Example #1
0
  /** flo_to_s */
  @JRubyMethod(name = "to_s")
  @Override
  public IRubyObject to_s() {
    Ruby runtime = getRuntime();
    if (Double.isInfinite(value))
      return RubyString.newString(runtime, value < 0 ? "-Infinity" : "Infinity");
    if (Double.isNaN(value)) return RubyString.newString(runtime, "NaN");

    ByteList buf = new ByteList();
    // Under 1.9, use full-precision float formatting (JRUBY-4846).
    // Double-precision can represent around 16 decimal digits;
    // we use 20 to ensure full representation.
    Sprintf.sprintf(buf, Locale.US, "%#.20g", this);
    int e = buf.indexOf('e');
    if (e == -1) e = buf.getRealSize();
    ASCIIEncoding ascii = ASCIIEncoding.INSTANCE;

    if (!ascii.isDigit(buf.get(e - 1))) {
      buf.setRealSize(0);
      Sprintf.sprintf(buf, Locale.US, "%#.14e", this);
      e = buf.indexOf('e');
      if (e == -1) e = buf.getRealSize();
    }

    int p = e;
    while (buf.get(p - 1) == '0' && ascii.isDigit(buf.get(p - 2))) p--;
    System.arraycopy(buf.getUnsafeBytes(), e, buf.getUnsafeBytes(), p, buf.getRealSize() - e);
    buf.setRealSize(p + buf.getRealSize() - e);

    buf.setEncoding(USASCIIEncoding.INSTANCE);

    return runtime.newString(buf);
  }
Example #2
0
  // Make string based on internal data encoding (which ironically is its
  // external encoding.  This seems messy and we should consider a more
  // uniform method for makeing strings (we have a slightly different variant
  // of this in RubyIO.
  private RubyString makeString(Ruby runtime, ByteList buf, boolean setEncoding) {
    if (runtime.is1_9() && setEncoding) buf.setEncoding(ptr.string.getEncoding());

    RubyString str = RubyString.newString(runtime, buf);
    str.setTaint(true);

    return str;
  }
  // Make string based on internal data encoding (which ironically is its
  // external encoding.  This seems messy and we should consider a more
  // uniform method for makeing strings (we have a slightly different variant
  // of this in RubyIO.
  private RubyString makeString(Ruby runtime, ByteList buf) {
    if (runtime.is1_9()) buf.setEncoding(data.internal.getEncoding());

    RubyString str = RubyString.newString(runtime, buf);
    str.setTaint(true);

    return str;
  }
Example #4
0
  @Override
  public int parseString(RubyLexer lexer) throws java.io.IOException {
    ByteList str = null;
    ByteList eos = nd_lit;
    int len = nd_lit.length() - 1;
    boolean indent = (flags & STR_FUNC_INDENT) != 0;
    int c = lexer.nextc();

    if (c == EOF) return error(lexer, len, str, eos);

    // Found end marker for this heredoc
    if (lexer.was_bol() && lexer.whole_match_p(nd_lit, indent)) {
      lexer.heredoc_restore(this);
      return Tokens.tSTRING_END;
    }

    if ((flags & STR_FUNC_EXPAND) == 0) {
      do {
        ByteList lbuf = lexer.lex_lastline;
        int p = 0;
        int pend = lexer.lex_pend;
        if (pend > p) {
          switch (lexer.p(pend - 1)) {
            case '\n':
              pend--;
              if (pend == p || lexer.p(pend - 1) == '\r') {
                pend++;
                break;
              }
              break;
            case '\r':
              pend--;
              break;
          }
        }

        if (lexer.getHeredocIndent() > 0) {
          for (long i = 0; p + i < pend && lexer.update_heredoc_indent(lexer.p(p)); i++) {}
          lexer.setHeredocLineIndent(0);
        }

        if (str != null) {
          str.append(lbuf.makeShared(p, pend - p));
        } else {
          str = new ByteList(lbuf.makeShared(p, pend - p));
        }

        if (pend < lexer.lex_pend) str.append('\n');
        lexer.lex_goto_eol();

        if (lexer.getHeredocIndent() > 0) {
          lexer.setValue(str);
          return Tokens.tSTRING_CONTENT;
        }
        // MRI null checks str in this case but it is unconditionally non-null?
        if (lexer.nextc() == -1) return error(lexer, len, null, eos);
      } while (!lexer.whole_match_p(eos, indent));
    } else {
      ByteList tok = new ByteList();
      tok.setEncoding(lexer.getEncoding());
      if (c == '#') {
        switch (c = lexer.nextc()) {
          case '$':
          case '@':
            lexer.pushback(c);
            return Tokens.tSTRING_DVAR;
          case '{':
            lexer.commandStart = true;
            return Tokens.tSTRING_DBEG;
        }
        tok.append('#');
      }

      // MRI has extra pointer which makes our code look a little bit more strange in comparison
      do {
        lexer.pushback(c);

        Encoding enc[] = new Encoding[1];
        enc[0] = lexer.getEncoding();

        if ((c = new StringTerm(flags, '\0', '\n').parseStringIntoBuffer(lexer, tok, enc)) == EOF) {
          if (lexer.eofp) return error(lexer, len, str, eos);
          return restore(lexer);
        }
        if (c != '\n') {
          lexer.setValue(lexer.createStr(tok, 0));
          return Tokens.tSTRING_CONTENT;
        }
        tok.append(lexer.nextc());

        if (lexer.getHeredocIndent() > 0) {
          lexer.lex_goto_eol();
          lexer.setValue(lexer.createStr(tok, 0));
          return Tokens.tSTRING_CONTENT;
        }

        if ((c = lexer.nextc()) == EOF) return error(lexer, len, str, eos);
      } while (!lexer.whole_match_p(eos, indent));
      str = tok;
    }

    lexer.heredoc_restore(this);
    lexer.setStrTerm(new StringTerm(-1, '\0', '\0'));
    lexer.setValue(lexer.createStr(str, 0));
    return Tokens.tSTRING_CONTENT;
  }
Example #5
0
  @JRubyMethod(required = 2, optional = 4)
  public IRubyObject primitive_convert(ThreadContext context, IRubyObject[] args) {
    Ruby runtime = context.runtime;

    RubyString input;
    RubyString output;
    int outputByteoffset = -1;
    int outputBytesize = 0;
    int flags = 0;

    int hashArg = -1;

    if (args.length > 2 && !args[2].isNil()) {
      if (args.length == 3 && args[2] instanceof RubyHash) {
        hashArg = 2;
      } else {
        outputByteoffset = (int) args[2].convertToInteger().getLongValue();
        if (outputByteoffset < 0) throw runtime.newArgumentError("negative offset");
      }
    }

    if (args.length > 3 && !args[3].isNil()) {
      if (args.length == 4 && args[3] instanceof RubyHash) {
        hashArg = 3;
      } else {
        outputBytesize = (int) args[3].convertToInteger().getLongValue();
        if (outputBytesize < 0) throw runtime.newArgumentError("negative bytesize");
      }
    }

    if (args.length > 4 && !args[4].isNil()) {
      if (args.length > 5 && !args[5].isNil()) {
        throw runtime.newArgumentError(args.length, 5);
      }

      if (args[4] instanceof RubyHash) {
        hashArg = 4;
      } else {
        flags = (int) args[4].convertToInteger().getLongValue();
      }
    }

    IRubyObject opt = context.nil;
    if (hashArg != -1 && !(opt = TypeConverter.checkHashType(runtime, args[hashArg])).isNil()) {
      IRubyObject v = ((RubyHash) opt).op_aref(context, runtime.newSymbol("partial_input"));
      if (v.isTrue()) {
        flags |= EncodingUtils.ECONV_PARTIAL_INPUT;
      }
      v = ((RubyHash) opt).op_aref(context, runtime.newSymbol("after_output"));
      if (v.isTrue()) {
        flags |= EncodingUtils.ECONV_AFTER_OUTPUT;
      }
    } else {
      flags = 0;
    }

    ByteList inBytes;
    ByteList outBytes;

    if (args[0].isNil()) {
      inBytes = new ByteList();
    } else {
      input = args[0].convertToString();
      input.modify19();
      inBytes = input.getByteList();
    }

    output = args[1].convertToString();
    output.modify19();
    outBytes = output.getByteList();

    if (outputByteoffset == -1) {
      outputByteoffset = outBytes.getRealSize();
    } else if (outputByteoffset > outBytes.getRealSize()) {
      throw runtime.newArgumentError("offset too big");
    }

    int outputByteEnd = outputByteoffset + outputBytesize;

    if (outputByteEnd > outBytes.getRealSize()) {
      outBytes.ensure(outputByteEnd);
    }

    RubyCoderResult result =
        transcoder.primitiveConvert(
            context,
            inBytes,
            output.getByteList(),
            outputByteoffset,
            outputBytesize,
            inBytes.getEncoding(),
            inBytes.getEncoding().isAsciiCompatible(),
            flags);

    outBytes.setEncoding(
        transcoder.outEncoding != null ? transcoder.outEncoding : inBytes.getEncoding());

    return symbolFromResult(result, runtime, flags, context);
  }
  private IRubyObject internalGets(ThreadContext context, IRubyObject[] args) {
    Ruby runtime = context.runtime;

    if (!isEndOfString() && !data.eof) {
      boolean isParagraph = false;
      boolean is19 = runtime.is1_9();
      ByteList sep = ((RubyString) runtime.getGlobalVariables().get("$/")).getByteList();
      IRubyObject sepArg;
      int limit = -1;

      if (is19) {
        IRubyObject limitArg =
            (args.length > 1
                ? args[1]
                : (args.length > 0 && args[0] instanceof RubyFixnum ? args[0] : null));
        if (limitArg != null) {
          limit = RubyNumeric.fix2int(limitArg);
        }

        sepArg = (args.length > 0 && !(args[0] instanceof RubyFixnum) ? args[0] : null);
      } else {
        sepArg = (args.length > 0 ? args[0] : null);
      }

      if (sepArg != null) {
        if (sepArg.isNil()) {
          int bytesAvailable = data.internal.getByteList().getRealSize() - (int) data.pos;
          int bytesToUse = (limit < 0 || limit >= bytesAvailable ? bytesAvailable : limit);
          ByteList buf = data.internal.getByteList().makeShared((int) data.pos, bytesToUse);
          data.pos += buf.getRealSize();
          return makeString(runtime, buf);
        }

        sep = sepArg.convertToString().getByteList();
        if (sep.getRealSize() == 0) {
          isParagraph = true;
          sep = Stream.PARAGRAPH_SEPARATOR;
        }
      }

      ByteList ss = data.internal.getByteList();

      if (isParagraph) {
        swallowLF(ss);
        if (data.pos == ss.getRealSize()) {
          return runtime.getNil();
        }
      }

      int ix = ss.indexOf(sep, (int) data.pos);

      ByteList add;
      if (-1 == ix) {
        ix = data.internal.getByteList().getRealSize();
        add = ByteList.EMPTY_BYTELIST;
      } else {
        add = sep;
      }

      int bytes = ix - (int) data.pos;
      int bytesToUse = (limit < 0 || limit >= bytes ? bytes : limit);

      int bytesWithSep = ix - (int) data.pos + add.getRealSize();
      int bytesToUseWithSep = (limit < 0 || limit >= bytesWithSep ? bytesWithSep : limit);

      ByteList line = new ByteList(bytesToUseWithSep);
      if (is19) line.setEncoding(data.internal.getByteList().getEncoding());
      line.append(data.internal.getByteList(), (int) data.pos, bytesToUse);
      data.pos += bytesToUse;

      int sepBytesToUse = bytesToUseWithSep - bytesToUse;
      line.append(add, 0, sepBytesToUse);
      data.pos += sepBytesToUse;

      if (sepBytesToUse >= add.getRealSize()) {
        data.lineno++;
      }

      return makeString(runtime, line);
    }
    return runtime.getNil();
  }
Example #7
0
  // FIXME: We are assuming that original string will be raw bytes.  If -Ku is provided
  // this will not be true, but that is ok for now.  Deal with that when someone needs it.
  private IRubyObject _iconv(RubyString str, int start, int length) {
    if (fromEncoding == null) {
      throw getRuntime().newArgumentError("closed iconv");
    }

    ByteList bytes = str.getByteList();

    // treat start and end as start...end for end >= 0, start..end for end < 0
    if (start < 0) {
      start += bytes.length();
    }

    if (start < 0 || start > bytes.length()) { // invalid ranges result in an empty string
      return RubyString.newEmptyString(getRuntime());
    }

    if (length < 0 || length > bytes.length() - start) {
      length = bytes.length() - start;
    }

    ByteBuffer buf = ByteBuffer.wrap(bytes.getUnsafeBytes(), bytes.begin() + start, length);

    try {
      CharBuffer cbuf = fromEncoding.decode(buf);
      buf = toEncoding.encode(cbuf);
    } catch (MalformedInputException e) {
      throw getRuntime().newIllegalSequence(str.toString());
    } catch (UnmappableCharacterException e) {
      throw getRuntime().newIllegalSequence(str.toString());
    } catch (CharacterCodingException e) {
      throw getRuntime().newInvalidEncoding("invalid sequence");
    } catch (IllegalStateException e) {
      throw getRuntime().newIllegalSequence(str.toString());
    }
    byte[] arr = buf.array();

    start = 0;
    String displayName = toEncoding.charset().displayName();

    if (arr.length >= 2) { // minimum Byte Order Mark (BOM) length
      if (displayName.toLowerCase().startsWith("utf-16")) {
        if ((arr[0] == (byte) 0xfe && arr[1] == (byte) 0xff)) {
          if (count > 0) start = 2;
          endian = "BE";
        } else if (arr[0] == (byte) 0xff && arr[1] == (byte) 0xfe) {
          if (count > 0) start = 2;
          endian = "LE";
        }
      } else if (displayName.toLowerCase().startsWith("utf-32") && arr.length >= 4) {
        if (arr[0] == (byte) 0x00
            && arr[1] == (byte) 0x00
            && arr[2] == (byte) 0xfe
            && arr[3] == (byte) 0xff) {
          if (count > 0) start = 4;
          endian = "BE";
        } else if (arr[0] == (byte) 0xff
            && arr[1] == (byte) 0xfe
            && arr[2] == (byte) 0x00
            && arr[3] == (byte) 0x00) {
          if (count > 0) start = 4;
          endian = "LE";
        }
      }
    }

    count++;

    if (displayName.equalsIgnoreCase("utf-16") || displayName.equalsIgnoreCase("utf-32")) {
      displayName += endian;
    }

    ByteList r = new ByteList(arr, start, buf.limit() - start);

    EncodingDB.Entry entry = EncodingDB.getEncodings().get(displayName.getBytes());
    if (entry != null) {
      Encoding charset = entry.getEncoding();
      r.setEncoding(charset);
    }

    return getRuntime().newString(r);
  }