/**
   * 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;
  }
Exemple #2
0
  /**
   * Copies bytes from the channel buffer into a destination <tt>ByteBuffer</tt>
   *
   * @param dst A <tt>ByteList</tt> to place the data in.
   * @param len The maximum number of bytes to copy.
   * @return The number of bytes copied.
   */
  private final int copyBufferedBytes(ByteList dst, int len) {
    int bytesCopied = 0;

    dst.ensure(Math.min(len, bufferedInputBytesRemaining()));

    if (bytesCopied < len && ungotc != -1) {
      ++bytesCopied;
      dst.append((byte) ungotc);
      ungotc = -1;
    }

    //
    // Copy out any buffered bytes
    //
    if (bytesCopied < len && buffer.hasRemaining()) {
      int n = Math.min(buffer.remaining(), len - bytesCopied);
      dst.append(buffer, n);
      bytesCopied += n;
    }

    return bytesCopied;
  }
Exemple #3
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);
  }