예제 #1
0
  // strio_getline
  private IRubyObject getline(ThreadContext context, IRubyObject[] args) {
    Ruby runtime = context.runtime;

    IRubyObject str = context.nil;
    ;
    int n, limit = -1;

    switch (args.length) {
      case 0:
        str = runtime.getGlobalVariables().get("$/");
        break;

      case 1:
        {
          str = args[0];
          if (!str.isNil() && !(str instanceof RubyString)) {
            IRubyObject tmp = str.checkStringType19();
            if (tmp.isNil()) {
              limit = RubyNumeric.num2int(str);
              if (limit == 0) return runtime.newString();
              str = runtime.getGlobalVariables().get("$/");
            } else {
              str = tmp;
            }
          }
          break;
        }

      case 2:
        if (!args[0].isNil()) str = args[0].convertToString();
        // 2.0 ignores double nil, 1.9 raises
        if (runtime.is2_0()) {
          if (!args[1].isNil()) {
            limit = RubyNumeric.num2int(args[1]);
          }
        } else {
          limit = RubyNumeric.num2int(args[1]);
        }
        break;
    }

    if (isEndOfString()) {
      return context.nil;
    }

    ByteList dataByteList = ptr.string.getByteList();
    byte[] dataBytes = dataByteList.getUnsafeBytes();
    int begin = dataByteList.getBegin();
    int s = begin + ptr.pos;
    int e = begin + dataByteList.getRealSize();
    int p;

    if (limit > 0 && s + limit < e) {
      e = dataByteList.getEncoding().rightAdjustCharHead(dataBytes, s, s + limit, e);
    }
    if (str.isNil()) {
      str = strioSubstr(runtime, ptr.pos, e - s);
    } else if ((n = ((RubyString) str).size()) == 0) {
      // this is not an exact port; the original confused me
      p = s;
      // remove leading \n
      while (dataBytes[p] == '\n') {
        if (++p == e) {
          return context.nil;
        }
      }
      s = p;
      // find next \n or end; if followed by \n, include it too
      p = memchr(dataBytes, p, '\n', e - p);
      if (p != -1) {
        if (++p < e && dataBytes[p] == '\n') {
          e = p + 1;
        } else {
          e = p;
        }
      }
      str = strioSubstr(runtime, s - begin, e - s);
    } else if (n == 1) {
      RubyString strStr = (RubyString) str;
      ByteList strByteList = strStr.getByteList();
      if ((p = memchr(dataBytes, s, strByteList.get(0), e - s)) != -1) {
        e = p + 1;
      }
      str = strioSubstr(runtime, ptr.pos, e - s);
    } else {
      if (n < e - s) {
        RubyString strStr = (RubyString) str;
        ByteList strByteList = strStr.getByteList();
        byte[] strBytes = strByteList.getUnsafeBytes();

        int[] skip = new int[1 << CHAR_BIT];
        int pos;
        p = strByteList.getBegin();
        bm_init_skip(skip, strBytes, p, n);
        if ((pos = bm_search(strBytes, p, n, dataBytes, s, e - s, skip)) >= 0) {
          e = s + pos + n;
        }
      }
      str = strioSubstr(runtime, ptr.pos, e - s);
    }
    ptr.pos = e - begin;
    ptr.lineno++;
    return str;
  }
예제 #2
0
 private static void blockPostTrace(
     Ruby runtime, ThreadContext context, String name, RubyModule implClass) {
   if (runtime.hasEventHooks() && runtime.is2_0())
     context.trace(RubyEvent.B_RETURN, name, implClass);
 }