/** * Write the byte represented by the specified int to the associated channel. * * @param c The byte to write * @return 1 if the byte was written, 0 if not and -1 if there was an error (@see * java.nio.channels.WritableByteChannel.write(java.nio.ByteBuffer)) * @throws java.io.IOException If there was an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed */ public int write(int c) throws IOException, BadDescriptorException { checkOpen(); ByteBuffer buf = ByteBuffer.allocate(1); buf.put((byte) c); buf.flip(); return internalWrite(buf); }
/** * Perform a low-level read of the remaining number of bytes into the specified byte buffer. The * incoming bytes will be used to fill the remaining space in the target byte buffer. This is * equivalent to the read(2) POSIX function, and like that function it ignores read and write * buffers defined elsewhere. * * @param buffer the java.nio.ByteBuffer in which to put 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 java.nio.ByteBuffer */ public int read(ByteBuffer buffer) throws IOException, BadDescriptorException { checkOpen(); // TODO: It would be nice to throw a better error for this if (!isReadable()) { throw new BadDescriptorException(); } ReadableByteChannel readChannel = (ReadableByteChannel) channel; int bytesRead = 0; bytesRead = readChannel.read(buffer); return bytesRead; }
/** * 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; }
public synchronized int read() throws IOException, BadDescriptorException { try { descriptor.checkOpen(); if (ungotc >= 0) { int c = ungotc; ungotc = -1; return c; } return bufferedRead(); } catch (EOFException e) { eof = true; return -1; } }
public synchronized int getline(ByteList dst, byte terminator, long limit) throws IOException, BadDescriptorException { checkReadable(); ensureRead(); descriptor.checkOpen(); int totalRead = 0; boolean found = false; if (ungotc != -1) { dst.append((byte) ungotc); found = ungotc == terminator; ungotc = -1; limit--; ++totalRead; } while (!found) { final byte[] bytes = buffer.array(); final int begin = buffer.arrayOffset() + buffer.position(); final int end = begin + buffer.remaining(); int len = 0; for (int i = begin; i < end && limit-- > 0 && !found; ++i) { found = bytes[i] == terminator; ++len; } if (limit < 1) found = true; if (len > 0) { dst.append(buffer, len); totalRead += len; } if (!found) { int n = refillBuffer(); if (n <= 0) { if (n < 0 && totalRead < 1) { return -1; } break; } } } return totalRead; }
/** * Write the bytes in the specified byte list to the associated channel. * * @param buffer the byte list containing the bytes to be written * @return the number of bytes actually written * @throws java.io.IOException if there is an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed */ public int internalWrite(ByteBuffer buffer) throws IOException, BadDescriptorException { checkOpen(); // TODO: It would be nice to throw a better error for this if (!isWritable()) { throw new BadDescriptorException(); } WritableByteChannel writeChannel = (WritableByteChannel) channel; // if appendable, we always seek to the end before writing if (isSeekable() && originalModes.isAppendable()) { // if already in append mode, we don't do our own seeking if (!isInAppendMode) { FileChannel fileChannel = (FileChannel) channel; fileChannel.position(fileChannel.size()); } } return writeChannel.write(buffer); }
/** * Perform a low-level seek operation on the associated channel if it is instanceof FileChannel, * or raise PipeException if it is not a FileChannel. Calls checkOpen to confirm the target * channel is open. This is equivalent to the lseek(2) POSIX function, and like that function it * bypasses any buffer flushing or invalidation as in ChannelStream.fseek. * * @param offset the offset value to use * @param whence whence to seek * @throws java.io.IOException If there is an exception while seeking * @throws org.jruby.util.io.InvalidValueException If the value specified for offset or whence is * invalid * @throws org.jruby.util.io.PipeException If the target channel is not seekable * @throws org.jruby.util.io.BadDescriptorException If the target channel is already closed. * @return the new offset into the FileChannel. */ public long lseek(long offset, int whence) throws IOException, InvalidValueException, PipeException, BadDescriptorException { if (seekableChannel) { checkOpen(); FileChannel fileChannel = (FileChannel) channel; try { long pos; switch (whence) { case Stream.SEEK_SET: pos = offset; fileChannel.position(pos); break; case Stream.SEEK_CUR: pos = fileChannel.position() + offset; fileChannel.position(pos); break; case Stream.SEEK_END: pos = fileChannel.size() + offset; fileChannel.position(pos); break; default: throw new InvalidValueException(); } return pos; } catch (IllegalArgumentException e) { throw new InvalidValueException(); } catch (IOException ioe) { // "invalid seek" means it's an ESPIPE, so we rethrow as a PipeException() if (ioe.getMessage().equals("Illegal seek")) { throw new PipeException(); } throw ioe; } } else { throw new PipeException(); } }
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; }
/** * Write the bytes in the specified byte list to the associated channel. * * @param buf the byte list containing the bytes to be written * @param offset the offset to start at. this is relative to the begin variable in the but * @param len the amount of bytes to write. this should not be longer than the buffer * @return the number of bytes actually written * @throws java.io.IOException if there is an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed */ public int write(ByteList buf, int offset, int len) throws IOException, BadDescriptorException { checkOpen(); return internalWrite(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin() + offset, len)); }
/** * Write the bytes in the specified byte list to the associated channel. * * @param buf the byte list containing the bytes to be written * @return the number of bytes actually written * @throws java.io.IOException if there is an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed */ public int write(ByteList buf) throws IOException, BadDescriptorException { checkOpen(); return internalWrite(ByteBuffer.wrap(buf.getUnsafeBytes(), buf.begin(), buf.length())); }
/** * Write the bytes in the specified byte list to the associated channel. * * @param buffer the byte list containing the bytes to be written * @return the number of bytes actually written * @throws java.io.IOException if there is an exception during IO * @throws org.jruby.util.io.BadDescriptorException if the associated channel is already closed */ public int write(ByteBuffer buffer) throws IOException, BadDescriptorException { checkOpen(); return internalWrite(buffer); }