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();
  }