예제 #1
0
파일: RubyFloat.java 프로젝트: komax/jruby
  /** 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);
  }
예제 #2
0
  public synchronized int writenonblock(ByteList buf) throws IOException, BadDescriptorException {
    checkWritable();
    ensureWrite();

    // Ruby ignores empty syswrites
    if (buf == null || buf.length() == 0) return 0;

    if (buffer.position() != 0 && !flushWrite(false)) return 0;

    if (descriptor.getChannel() instanceof SelectableChannel) {
      SelectableChannel selectableChannel = (SelectableChannel) descriptor.getChannel();
      synchronized (selectableChannel.blockingLock()) {
        boolean oldBlocking = selectableChannel.isBlocking();
        try {
          if (oldBlocking) {
            selectableChannel.configureBlocking(false);
          }
          return descriptor.write(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin(), buf.length()));
        } finally {
          if (oldBlocking) {
            selectableChannel.configureBlocking(oldBlocking);
          }
        }
      }
    } else {
      // can't set nonblocking, so go ahead with it...not much else we can do
      return descriptor.write(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin(), buf.length()));
    }
  }
예제 #3
0
  @JRubyMethod
  public IRubyObject convert(ThreadContext context, IRubyObject srcBuffer) {
    if (!(srcBuffer instanceof RubyString)) {
      throw context.runtime.newTypeError(srcBuffer, context.runtime.getString());
    }

    RubyString srcString = (RubyString) srcBuffer;

    ByteList srcBL = srcString.getByteList();

    if (srcBL.getRealSize() == 0) return context.runtime.newSymbol("source_buffer_empty");

    ByteBuffer srcBB = ByteBuffer.wrap(srcBL.getUnsafeBytes(), srcBL.begin(), srcBL.getRealSize());
    try {
      CharBuffer srcCB =
          CharBuffer.allocate((int) (srcDecoder.maxCharsPerByte() * srcBL.getRealSize()) + 1);
      CoderResult decodeResult = srcDecoder.decode(srcBB, srcCB, true);
      srcCB.flip();

      ByteBuffer destBB =
          ByteBuffer.allocate((int) (destEncoder.maxBytesPerChar() * srcCB.limit()) + 1);
      CoderResult encodeResult = destEncoder.encode(srcCB, destBB, true);
      destBB.flip();

      byte[] destBytes = new byte[destBB.limit()];
      destBB.get(destBytes);

      srcDecoder.reset();
      destEncoder.reset();

      return context.runtime.newString(new ByteList(destBytes, destEncoding.getEncoding(), false));
    } catch (Exception e) {
      throw context.runtime.newRuntimeError(e.getLocalizedMessage());
    }
  }
예제 #4
0
 private int nameToBackrefNumber(RubyString str) {
   ByteList value = str.getByteList();
   try {
     return pattern.nameToBackrefNumber(
         value.getUnsafeBytes(), value.getBegin(), value.getBegin() + value.getRealSize(), regs);
   } catch (JOniException je) {
     throw getRuntime().newIndexError(je.getMessage());
   }
 }
예제 #5
0
 public static int getBackrefNumber(DynamicObject matchData, ByteList value) {
   assert RubyGuards.isRubyMatchData(matchData);
   return Layouts.REGEXP
       .getRegex(Layouts.MATCH_DATA.getFields(matchData).regexp)
       .nameToBackrefNumber(
           value.getUnsafeBytes(),
           value.getBegin(),
           value.getBegin() + value.getRealSize(),
           Layouts.MATCH_DATA.getFields(matchData).region);
 }
예제 #6
0
 @JRubyMethod(name = "ruby=", required = 1)
 public IRubyObject ruby_set(final ThreadContext ctx, IRubyObject arg) {
   RubyString string;
   try {
     string = arg.convertToString();
   } catch (RaiseException re) {
     throw newTypeError(ctx.runtime, arg.getMetaClass(), "String");
   }
   ByteList bytes = string.getByteList();
   value.set(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getRealSize());
   return arg;
 }
예제 #7
0
 public final void marshal(
     ThreadContext context, InvocationBuffer buffer, IRubyObject parameter) {
   if (parameter instanceof RubyString) {
     Util.checkStringSafety(context.getRuntime(), parameter);
     ByteList bl = ((RubyString) parameter).getByteList();
     buffer.putArray(
         bl.getUnsafeBytes(), bl.begin(), bl.length(), ArrayFlags.IN | ArrayFlags.NULTERMINATE);
   } else if (parameter.isNil()) {
     buffer.putAddress(0);
   } else {
     throw context.getRuntime().newArgumentError("Invalid string parameter");
   }
 }
예제 #8
0
  /**
   * Perform a low-level read of the specified number of bytes into the specified byte list. The
   * incoming bytes will be appended to the byte list. This is equivalent to the read(2) POSIX
   * function, and like that function it ignores read and write buffers defined elsewhere.
   *
   * @param number the number of bytes to read
   * @param byteList the byte list on which to append the incoming bytes
   * @return the number of bytes actually read
   * @throws java.io.IOException if there is an exception during IO
   * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed.
   * @see org.jruby.util.ByteList
   */
  public int read(int number, ByteList byteList) throws IOException, BadDescriptorException {
    checkOpen();

    byteList.ensure(byteList.length() + number);
    int bytesRead =
        read(
            ByteBuffer.wrap(
                byteList.getUnsafeBytes(), byteList.begin() + byteList.length(), number));
    if (bytesRead > 0) {
      byteList.length(byteList.length() + bytesRead);
    }
    return bytesRead;
  }
예제 #9
0
  private RubyString strioSubstr(Ruby runtime, int pos, int len) {
    RubyString str = ptr.string;
    ByteList strByteList = str.getByteList();
    byte[] strBytes = strByteList.getUnsafeBytes();
    Encoding enc = str.getEncoding();
    int rlen = str.size() - pos;

    if (len > rlen) len = rlen;
    if (len < 0) len = 0;

    if (len == 0) return RubyString.newEmptyString(runtime);
    return RubyString.newStringShared(runtime, strBytes, strByteList.getBegin() + pos, len, enc);
  }
예제 #10
0
    public final void marshal(
        ThreadContext context, InvocationBuffer buffer, IRubyObject parameter) {
      if (parameter instanceof Buffer) {
        addBufferParameter(buffer, parameter, flags);
      } else if (parameter instanceof Pointer) {
        buffer.putAddress(getAddress((Pointer) parameter));
      } else if (parameter instanceof Struct) {
        IRubyObject memory = ((Struct) parameter).getMemory();
        if (memory instanceof Buffer) {
          addBufferParameter(buffer, memory, flags);
        } else if (memory instanceof Pointer) {
          buffer.putAddress(getAddress((Pointer) memory));
        } else if (memory == null || memory.isNil()) {
          buffer.putAddress(0L);
        } else {
          throw context.getRuntime().newArgumentError("Invalid Struct memory");
        }
      } else if (parameter.isNil()) {
        buffer.putAddress(0L);
      } else if (parameter instanceof RubyString) {
        ByteList bl = ((RubyString) parameter).getByteList();
        buffer.putArray(
            bl.getUnsafeBytes(), bl.begin(), bl.length(), flags | ArrayFlags.NULTERMINATE);

      } else if (parameter.respondsTo("to_ptr")) {
        final int MAXRECURSE = 4;
        for (int depth = 0; depth < MAXRECURSE; ++depth) {
          IRubyObject ptr = parameter.callMethod(context, "to_ptr");
          if (ptr instanceof Pointer) {
            buffer.putAddress(getAddress((Pointer) ptr));
          } else if (ptr instanceof Buffer) {
            addBufferParameter(buffer, ptr, flags);
          } else if (ptr.isNil()) {
            buffer.putAddress(0L);
          } else if (depth < MAXRECURSE && ptr.respondsTo("to_ptr")) {
            parameter = ptr;
            continue;
          } else {
            throw context.getRuntime().newArgumentError("to_ptr returned an invalid pointer");
          }
          break;
        }

      } else if (parameter instanceof RubyInteger && acceptIntegerValues) {

        buffer.putAddress(((RubyInteger) parameter).getLongValue());

      } else {
        throw context.getRuntime().newArgumentError("Invalid buffer/pointer parameter");
      }
    }
예제 #11
0
 @JRubyMethod(name = "chr", compat = CompatVersion.RUBY1_9)
 public RubyString chr19(ThreadContext context, IRubyObject arg) {
   Ruby runtime = context.getRuntime();
   long value = getLongValue();
   Encoding enc = arg.convertToString().toEncoding(runtime);
   int n;
   if (value < 0 || (n = StringSupport.codeLength(runtime, enc, (int) value)) <= 0) {
     throw runtime.newRangeError(this.toString() + " out of char range");
   }
   ByteList bytes = new ByteList(n);
   enc.codeToMbc((int) value, bytes.getUnsafeBytes(), 0);
   bytes.setRealSize(n);
   return RubyString.newStringNoCopy(runtime, bytes, enc, 0);
 }
예제 #12
0
  private ByteList fromEncodedBytes(Ruby runtime, Encoding enc, int value) {
    int n;
    try {
      n = value < 0 ? 0 : enc.codeToMbcLength(value);
    } catch (EncodingException ee) {
      n = 0;
    }

    if (n <= 0) throw runtime.newRangeError(this.toString() + " out of char range");

    ByteList bytes = new ByteList(n);
    enc.codeToMbc(value, bytes.getUnsafeBytes(), 0);
    bytes.setRealSize(n);
    return bytes;
  }
예제 #13
0
  /**
   * @throws IOException
   * @throws BadDescriptorException
   */
  private int bufferedWrite(ByteList buf) throws IOException, BadDescriptorException {
    checkWritable();
    ensureWrite();

    // Ruby ignores empty syswrites
    if (buf == null || buf.length() == 0) return 0;

    if (buf.length() > buffer.capacity()) { // Doesn't fit in buffer. Write immediately.
      flushWrite(); // ensure nothing left to write

      int n = descriptor.write(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin(), buf.length()));
      if (n != buf.length()) {
        // TODO: check the return value here
      }
    } else {
      if (buf.length() > buffer.remaining()) flushWrite();

      buffer.put(buf.getUnsafeBytes(), buf.begin(), buf.length());
    }

    if (isSync()) flushWrite();

    return buf.getRealSize();
  }
예제 #14
0
  private void updatePairs(ByteList value, Encoding encoding, Pair[] pairs) {
    Arrays.sort(pairs);

    int length = pairs.length;
    byte[] bytes = value.getUnsafeBytes();
    int p = value.getBegin();
    int s = p;
    int c = 0;

    for (int i = 0; i < length; i++) {
      int q = s + pairs[i].bytePos;
      c += StringSupport.strLength(encoding, bytes, p, q);
      pairs[i].charPos = c;
      p = q;
    }
  }
예제 #15
0
  @JRubyMethod(name = "truncate", required = 1)
  public IRubyObject truncate(IRubyObject len) {
    checkWritable();

    int l = RubyFixnum.fix2int(len);
    int plen = ptr.string.size();
    if (l < 0) {
      throw getRuntime().newErrnoEINVALError("negative legnth");
    }
    ptr.string.resize(l);
    ByteList buf = ptr.string.getByteList();
    if (plen < l) {
      // zero the gap
      Arrays.fill(buf.getUnsafeBytes(), buf.getBegin() + plen, buf.getBegin() + l, (byte) 0);
    }
    return len;
  }
예제 #16
0
 @JRubyMethod(name = "ruby=")
 public IRubyObject ruby_set(final ThreadContext ctx, IRubyObject arg) {
   RubyString string;
   try {
     string = arg.convertToString();
   } catch (RaiseException re) {
     throw newTypeError(ctx.runtime, arg.getMetaClass(), "String");
   }
   if (string.getEncoding() == UTF8Encoding.INSTANCE
       || string.getEncoding() == USASCIIEncoding.INSTANCE) {
     ByteList bytes = string.getByteList();
     value.set(bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getRealSize());
   } else {
     value.set(string.toString());
   }
   return arg;
 }
예제 #17
0
  @JRubyMethod(
      name = {"write"},
      required = 1)
  public IRubyObject write(ThreadContext context, IRubyObject arg) {
    checkWritable();

    Ruby runtime = context.runtime;

    RubyString str = arg.asString();
    int len, olen;
    Encoding enc, enc2;

    enc = ptr.string.getEncoding();
    enc2 = str.getEncoding();
    if (enc != enc2
        && enc != EncodingUtils.ascii8bitEncoding(runtime)
        // this is a hack because we don't seem to handle incoming ASCII-8BIT properly in transcoder
        && enc2 != ASCIIEncoding.INSTANCE) {
      str = runtime.newString(Transcoder.strConvEnc(context, str.getByteList(), enc2, enc));
    }
    len = str.size();
    if (len == 0) return RubyFixnum.zero(runtime);
    checkModifiable();
    olen = ptr.string.size();
    if ((ptr.flags & OpenFile.APPEND) != 0) {
      ptr.pos = olen;
    }
    if (ptr.pos == olen
        // this is a hack because we don't seem to handle incoming ASCII-8BIT properly in transcoder
        && enc2 != ASCIIEncoding.INSTANCE) {
      EncodingUtils.encStrBufCat(runtime, ptr.string, str.getByteList(), enc);
    } else {
      strioExtend(ptr.pos, len);
      ByteList ptrByteList = ptr.string.getByteList();
      System.arraycopy(
          str.getByteList().getUnsafeBytes(),
          str.getByteList().getBegin(),
          ptrByteList.getUnsafeBytes(),
          ptrByteList.begin + ptr.pos,
          len);
      ptr.string.infectBy(str);
    }
    ptr.string.infectBy(this);
    ptr.pos += len;
    return RubyFixnum.newFixnum(runtime, len);
  }
예제 #18
0
    public void put(
        ThreadContext context,
        StructLayout.Storage cache,
        Member m,
        IRubyObject ptr,
        IRubyObject value) {

      if (isCharArray() && value instanceof RubyString) {
        ByteList bl = value.convertToString().getByteList();
        m.getMemoryIO(ptr)
            .putZeroTerminatedByteArray(
                m.offset,
                bl.getUnsafeBytes(),
                bl.begin(),
                Math.min(bl.length(), arrayType.length() - 1));

      } else if (false) {
        RubyArray ary = value.convertToArray();
        int count = ary.size();
        if (count > arrayType.length()) {
          throw context.getRuntime().newIndexError("array too big");
        }
        AbstractMemory memory = (AbstractMemory) ptr;

        // Clear any elements that will not be filled by the array
        if (count < arrayType.length()) {
          memory
              .getMemoryIO()
              .setMemory(
                  m.offset + (count * arrayType.getComponentType().getNativeSize()),
                  (arrayType.length() - count) * arrayType.getComponentType().getNativeSize(),
                  (byte) 0);
        }

        for (int i = 0; i < count; ++i) {
          op.put(
              context.getRuntime(),
              memory,
              m.offset + (i * arrayType.getComponentType().getNativeSize()),
              ary.entry(i));
        }
      } else {
        throw context.getRuntime().newNotImplementedError("cannot set array field");
      }
    }
예제 #19
0
  @JRubyMethod(name = "truncate", required = 1)
  @Override
  public IRubyObject truncate(IRubyObject arg) {
    checkWritable();

    int len = RubyFixnum.fix2int(arg);
    if (len < 0) {
      throw getRuntime().newErrnoEINVALError("negative legnth");
    }

    data.internal.modify();
    ByteList buf = data.internal.getByteList();
    if (len < buf.length()) {
      Arrays.fill(buf.getUnsafeBytes(), len, buf.length(), (byte) 0);
    }
    buf.length(len);
    return arg;
  }
예제 #20
0
  @JRubyMethod(frame = true)
  public IRubyObject marshal_load(ThreadContext context, IRubyObject str) {
    try {
      ByteList byteList = str.convertToString().getByteList();
      ByteArrayInputStream bais =
          new ByteArrayInputStream(
              byteList.getUnsafeBytes(), byteList.getBegin(), byteList.getRealSize());
      ObjectInputStream ois = new JRubyObjectInputStream(context.getRuntime(), bais);

      object = ois.readObject();

      return this;
    } catch (IOException ioe) {
      throw context.getRuntime().newIOErrorFromException(ioe);
    } catch (ClassNotFoundException cnfe) {
      throw context
          .getRuntime()
          .newTypeError("Class not found unmarshaling Java type: " + cnfe.getLocalizedMessage());
    }
  }
예제 #21
0
  private void strioExtend(int pos, int len) {
    int olen;

    checkModifiable();
    olen = ptr.string.size();
    if (pos + len > olen) {
      ptr.string.resize(pos + len);
      if (pos > olen) {
        ByteList ptrByteList = ptr.string.getByteList();
        // zero the gap
        Arrays.fill(
            ptrByteList.getUnsafeBytes(),
            ptrByteList.getBegin() + olen,
            ptrByteList.getBegin() + pos,
            (byte) 0);
      }
    } else {
      ptr.string.modify19();
    }
  }
예제 #22
0
    public void put(
        ThreadContext context,
        StructLayout.Storage cache,
        Member m,
        IRubyObject ptr,
        IRubyObject value) {
      ByteList bl = value.convertToString().getByteList();

      MemoryPointer mem = MemoryPointer.allocate(context.getRuntime(), 1, bl.length() + 1, false);
      //
      // Keep a reference to the temporary memory in the cache so it does
      // not get freed by the GC until the struct is freed
      //
      cache.putReference(m, mem);

      MemoryIO io = mem.getMemoryIO();
      io.put(0, bl.getUnsafeBytes(), bl.begin(), bl.length());
      io.putByte(bl.length(), (byte) 0);

      m.getMemoryIO(ptr).putMemoryIO(m.getOffset(ptr), io);
    }
예제 #23
0
  private void updatePairs(ByteList value, Encoding encoding, Pair[] pairs) {
    Arrays.sort(pairs);

    int length = pairs.length;
    byte[] bytes = value.getUnsafeBytes();
    int p = value.getBegin();
    int s = p;
    int c = 0;

    for (int i = 0; i < length; i++) {
      int q = s + pairs[i].bytePos;
      c += StringSupport.strLength(encoding, bytes, p, q);
      pairs[i].charPos = c;
      p = q;
    }

    Pair key = new Pair();
    key.bytePos = begin;
    charOffsets.beg[0] = pairs[Arrays.binarySearch(pairs, key)].charPos;
    key.bytePos = end;
    charOffsets.end[0] = pairs[Arrays.binarySearch(pairs, key)].charPos;
  }
예제 #24
0
  @Override
  public IRubyObject each_charInternal(final ThreadContext context, final Block block) {
    checkReadable();

    Ruby runtime = context.runtime;
    ByteList bytes = data.internal.getByteList();
    int len = bytes.getRealSize();
    int end = bytes.getBegin() + len;
    Encoding enc = runtime.is1_9() ? bytes.getEncoding() : runtime.getKCode().getEncoding();
    while (data.pos < len) {
      int pos = (int) data.pos;
      int n = StringSupport.length(enc, bytes.getUnsafeBytes(), pos, end);

      if (len < pos + n) n = len - pos;

      data.pos += n;

      block.yield(context, data.internal.makeShared19(runtime, pos, n));
    }

    return this;
  }
예제 #25
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;
  }
예제 #26
0
  /**
   * @deprecated readall do busy loop for the IO which has NONBLOCK bit. You should implement the
   *     logic by yourself with fread().
   */
  @Deprecated
  public synchronized ByteList readall() throws IOException, BadDescriptorException {
    final long fileSize =
        descriptor.isSeekable() && descriptor.getChannel() instanceof FileChannel
            ? ((FileChannel) descriptor.getChannel()).size()
            : 0;
    //
    // Check file size - special files in /proc have zero size and need to be
    // handled by the generic read path.
    //
    if (fileSize > 0) {
      ensureRead();

      FileChannel channel = (FileChannel) descriptor.getChannel();
      final long left = fileSize - channel.position() + bufferedInputBytesRemaining();
      if (left <= 0) {
        eof = true;
        return null;
      }

      if (left > Integer.MAX_VALUE) {
        if (getRuntime() != null) {
          throw getRuntime().newIOError("File too large");
        } else {
          throw new IOException("File too large");
        }
      }

      ByteList result = new ByteList((int) left);
      ByteBuffer buf = ByteBuffer.wrap(result.getUnsafeBytes(), result.begin(), (int) left);

      //
      // Copy any buffered data (including ungetc byte)
      //
      copyBufferedBytes(buf);

      //
      // Now read unbuffered directly from the file
      //
      while (buf.hasRemaining()) {
        final int MAX_READ_CHUNK = 1 * 1024 * 1024;
        //
        // When reading into a heap buffer, the jvm allocates a temporary
        // direct ByteBuffer of the requested size.  To avoid allocating
        // a huge direct buffer when doing ludicrous reads (e.g. 1G or more)
        // we split the read up into chunks of no more than 1M
        //
        ByteBuffer tmp = buf.duplicate();
        if (tmp.remaining() > MAX_READ_CHUNK) {
          tmp.limit(tmp.position() + MAX_READ_CHUNK);
        }
        int n = channel.read(tmp);
        if (n <= 0) {
          break;
        }
        buf.position(tmp.position());
      }
      eof = true;
      result.length(buf.position());
      return result;
    } else if (descriptor.isNull()) {
      return new ByteList(0);
    } else {
      checkReadable();

      ByteList byteList = new ByteList();
      ByteList read = fread(BUFSIZE);

      if (read == null) {
        eof = true;
        return byteList;
      }

      while (read != null) {
        byteList.append(read);
        read = fread(BUFSIZE);
      }

      return byteList;
    }
  }
예제 #27
0
  public synchronized ByteList fgets(ByteList separatorString)
      throws IOException, BadDescriptorException {
    checkReadable();
    ensureRead();

    if (separatorString == null) {
      return readall();
    }

    final ByteList separator =
        (separatorString == PARAGRAPH_DELIMETER) ? PARAGRAPH_SEPARATOR : separatorString;

    descriptor.checkOpen();

    if (feof()) {
      return null;
    }

    int c = read();

    if (c == -1) {
      return null;
    }

    // unread back
    buffer.position(buffer.position() - 1);

    ByteList buf = new ByteList(40);

    byte first = separator.getUnsafeBytes()[separator.getBegin()];

    LineLoop:
    while (true) {
      ReadLoop:
      while (true) {
        byte[] bytes = buffer.array();
        int offset = buffer.position();
        int max = buffer.limit();

        // iterate over remainder of buffer until we find a match
        for (int i = offset; i < max; i++) {
          c = bytes[i];
          if (c == first) {
            // terminate and advance buffer when we find our char
            buf.append(bytes, offset, i - offset);
            if (i >= max) {
              buffer.clear();
            } else {
              buffer.position(i + 1);
            }
            break ReadLoop;
          }
        }

        // no match, append remainder of buffer and continue with next block
        buf.append(bytes, offset, buffer.remaining());
        int read = refillBuffer();
        if (read == -1) break LineLoop;
      }

      // found a match above, check if remaining separator characters match, appending as we go
      for (int i = 0; i < separator.getRealSize(); i++) {
        if (c == -1) {
          break LineLoop;
        } else if (c != separator.getUnsafeBytes()[separator.getBegin() + i]) {
          buf.append(c);
          continue LineLoop;
        }
        buf.append(c);
        if (i < separator.getRealSize() - 1) {
          c = read();
        }
      }
      break;
    }

    if (separatorString == PARAGRAPH_DELIMETER) {
      while (c == separator.getUnsafeBytes()[separator.getBegin()]) {
        c = read();
      }
      ungetc(c);
    }

    return buf;
  }
예제 #28
0
  @JRubyMethod(name = "read", optional = 2)
  public IRubyObject read(ThreadContext context, IRubyObject[] args) {
    checkReadable();

    Ruby runtime = context.runtime;
    IRubyObject str = runtime.getNil();
    int len;
    boolean binary = false;

    switch (args.length) {
      case 2:
        str = args[1];
        if (!str.isNil()) {
          str = str.convertToString();
          ((RubyString) str).modify();
        }
      case 1:
        if (!args[0].isNil()) {
          len = RubyNumeric.fix2int(args[0]);

          if (len < 0) {
            throw getRuntime().newArgumentError("negative length " + len + " given");
          }
          if (len > 0 && isEndOfString()) {
            if (!str.isNil()) ((RubyString) str).resize(0);
            return getRuntime().getNil();
          }
          binary = true;
          break;
        }
      case 0:
        len = ptr.string.size();
        if (len <= ptr.pos) {
          if (str.isNil()) {
            str = runtime.newString();
          } else {
            ((RubyString) str).resize(0);
          }

          return str;
        } else {
          len -= ptr.pos;
        }
        break;
      default:
        throw getRuntime().newArgumentError(args.length, 0);
    }

    if (str.isNil()) {
      str = strioSubstr(runtime, ptr.pos, len);
      if (binary) ((RubyString) str).setEncoding(ASCIIEncoding.INSTANCE);
    } else {
      int rest = ptr.string.size() - ptr.pos;
      if (len > rest) len = rest;
      ((RubyString) str).resize(len);
      ByteList strByteList = ((RubyString) str).getByteList();
      byte[] strBytes = strByteList.getUnsafeBytes();
      ByteList dataByteList = ptr.string.getByteList();
      byte[] dataBytes = dataByteList.getUnsafeBytes();
      System.arraycopy(
          dataBytes, dataByteList.getBegin() + ptr.pos, strBytes, strByteList.getBegin(), len);
      if (binary) {
        ((RubyString) str).setEncoding(ASCIIEncoding.INSTANCE);
      } else {
        ((RubyString) str).setEncoding(ptr.string.getEncoding());
      }
    }
    ptr.pos += ((RubyString) str).size();
    return str;
  }
예제 #29
0
 public Entry findAliasEntry(ByteList bytes) {
   return aliases.get(
       bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
 }
예제 #30
0
 public Entry findEncodingEntry(ByteList bytes) {
   return encodings.get(
       bytes.getUnsafeBytes(), bytes.getBegin(), bytes.getBegin() + bytes.getRealSize());
 }