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())); } }
/** * 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; }
@JRubyMethod(name = "ungetc", required = 1) public IRubyObject ungetc(IRubyObject arg) { checkReadable(); int c = RubyNumeric.num2int(arg); if (pos == 0) return getRuntime().getNil(); internal.modify(); pos--; ByteList bytes = internal.getByteList(); if (bytes.length() <= pos) { bytes.length((int) pos + 1); } bytes.set((int) pos, c); return getRuntime().getNil(); }
@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; }
private void ungetcCommon(int c) { data.internal.modify(); data.pos--; ByteList bytes = data.internal.getByteList(); if (isEndOfString()) bytes.length((int) data.pos + 1); bytes.set((int) data.pos, c); }
public SymbolNode(ISourcePosition position, ByteList value) { super(position, false); this.name = value.toString().intern(); // FIXME: A full scan to determine whether we should back off to US-ASCII. Lexer should just do // this properly. if (value.lengthEnc() == value.length()) { this.encoding = USASCIIEncoding.INSTANCE; } else { this.encoding = value.getEncoding(); } }
private IRubyObject internalGets(ThreadContext context, IRubyObject[] args) { Ruby runtime = context.getRuntime(); if (pos < internal.getByteList().realSize && !eof) { boolean isParagraph = false; ByteList sep; if (args.length > 0) { if (args[0].isNil()) { ByteList buf = internal .getByteList() .makeShared((int) pos, internal.getByteList().realSize - (int) pos); pos += buf.realSize; return RubyString.newString(runtime, buf); } sep = args[0].convertToString().getByteList(); if (sep.realSize == 0) { isParagraph = true; sep = Stream.PARAGRAPH_SEPARATOR; } } else { sep = ((RubyString) runtime.getGlobalVariables().get("$/")).getByteList(); } ByteList ss = internal.getByteList(); if (isParagraph) { swallowLF(ss); if (pos == ss.realSize) { return runtime.getNil(); } } int ix = ss.indexOf(sep, (int) pos); ByteList add; if (-1 == ix) { ix = internal.getByteList().realSize; add = ByteList.EMPTY_BYTELIST; } else { add = isParagraph ? NEWLINE : sep; } ByteList line = new ByteList(ix - (int) pos + add.length()); line.append(internal.getByteList(), (int) pos, ix - (int) pos); line.append(add); pos = ix + add.realSize; lineno++; return RubyString.newString(runtime, line); } return runtime.getNil(); }
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); }
@JRubyMethod(name = "putc", required = 1) @Override public IRubyObject putc(IRubyObject obj) { checkWritable(); byte c = RubyNumeric.num2chr(obj); checkFrozen(); data.internal.modify(); ByteList bytes = data.internal.getByteList(); if (data.modes.isAppendable()) { data.pos = bytes.length(); bytes.append(c); } else { if (isEndOfString()) bytes.length((int) data.pos + 1); bytes.set((int) data.pos, c); data.pos++; } return obj; }
@Override public IRubyObject each_byte(ThreadContext context, Block block) { checkReadable(); Ruby runtime = context.runtime; ByteList bytes = data.internal.getByteList(); // Check the length every iteration, since // the block can modify this string. while (data.pos < bytes.length()) { block.yield(context, runtime.newFixnum(bytes.get((int) data.pos++) & 0xFF)); } return this; }
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.unsafeBytes(), bl.begin(), bl.length(), ArrayFlags.IN | ArrayFlags.NULTERMINATE); } else if (parameter.isNil()) { buffer.putAddress(0); } else { throw context.getRuntime().newArgumentError("Invalid string parameter"); } }
@JRubyMethod(name = "putc", required = 1) public IRubyObject putc(IRubyObject obj) { checkWritable(); byte c = RubyNumeric.num2chr(obj); checkFrozen(); internal.modify(); ByteList bytes = internal.getByteList(); if (modes.isAppendable()) { pos = bytes.length(); bytes.append(c); } else { if (pos >= bytes.length()) { bytes.length((int) pos + 1); } bytes.set((int) pos, c); pos++; } return obj; }
@JRubyMethod(name = "each_byte", frame = true) public IRubyObject each_byte(ThreadContext context, Block block) { checkReadable(); Ruby runtime = context.getRuntime(); ByteList bytes = internal.getByteList(); // Check the length every iteration, since // the block can modify this string. while (pos < bytes.length()) { block.yield(context, runtime.newFixnum(bytes.get((int) pos++) & 0xFF)); } return runtime.getNil(); }
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"); } }
public static final void checkStringSafety(Ruby runtime, IRubyObject value) { RubyString s = value.asString(); if (runtime.getSafeLevel() > 0 && s.isTaint()) { throw runtime.newSecurityError("Unsafe string parameter"); } ByteList bl = s.getByteList(); final byte[] array = bl.unsafeBytes(); final int end = bl.length(); for (int i = bl.begin(); i < end; ++i) { if (array[i] == (byte) 0) { throw runtime.newSecurityError("string contains null byte"); } } }
private void ungetbyteCommon(int c) { ptr.string.modify(); ptr.pos--; ByteList bytes = ptr.string.getByteList(); if (isEndOfString()) bytes.length((int) ptr.pos + 1); if (ptr.pos == -1) { bytes.prepend((byte) c); ptr.pos = 0; } else { bytes.set((int) ptr.pos, c); } }
@JRubyMethod(name = {"each_byte", "bytes"}) public IRubyObject each_byte(ThreadContext context, Block block) { if (!block.isGiven()) return enumeratorize(context.runtime, this, "each_byte"); checkReadable(); Ruby runtime = context.runtime; ByteList bytes = ptr.string.getByteList(); // Check the length every iteration, since // the block can modify this string. while (ptr.pos < bytes.length()) { block.yield(context, runtime.newFixnum(bytes.get((int) ptr.pos++) & 0xFF)); } return this; }
@JRubyMethod(name = "crc32", optional = 2, module = true, visibility = Visibility.PRIVATE) public static IRubyObject crc32(IRubyObject recv, IRubyObject[] args) throws Exception { args = Arity.scanArgs(recv.getRuntime(), args, 0, 2); long crc = 0; ByteList bytes = null; if (!args[0].isNil()) bytes = args[0].convertToString().getByteList(); if (!args[1].isNil()) crc = RubyNumeric.num2long(args[1]); CRC32Ext ext = new CRC32Ext((int) crc); if (bytes != null) { ext.update(bytes.unsafeBytes(), bytes.begin(), bytes.length()); } return recv.getRuntime().newFixnum(ext.getValue()); }
private IRubyObject internalSepGets(ByteList sep) throws IOException { ByteList result = new ByteList(); int ce = io.read(); while (ce != -1 && sep.indexOf(ce) == -1) { result.append((byte) ce); ce = io.read(); } // io.available() only returns 0 after EOF is encountered // so we need to differentiate between the empty string and EOF if (0 == result.length() && -1 == ce) { return getRuntime().getNil(); } line++; result.append(sep); return RubyString.newString(getRuntime(), result); }
@JRubyMethod(name = "adler32", optional = 2, module = true, visibility = Visibility.PRIVATE) public static IRubyObject adler32(IRubyObject recv, IRubyObject[] args) throws Exception { args = Arity.scanArgs(recv.getRuntime(), args, 0, 2); int adler = 1; ByteList bytes = null; if (!args[0].isNil()) bytes = args[0].convertToString().getByteList(); if (!args[1].isNil()) adler = RubyNumeric.fix2int(args[1]); Adler32Ext ext = new Adler32Ext(adler); if (bytes != null) { ext.update( bytes.unsafeBytes(), bytes.begin(), bytes.length()); // it's safe since adler.update doesn't modify the array } return recv.getRuntime().newFixnum(ext.getValue()); }
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"); } }
public static IRubyObject pack_sockaddr_un(ThreadContext context, IRubyObject filename) { ByteList str = filename.convertToString().getByteList(); AddressFamily af = AddressFamily.AF_UNIX; int high = (af.intValue() & 0xff00) >> 8; int low = af.intValue() & 0xff; ByteList bl = new ByteList(); bl.append((byte) high); bl.append((byte) low); bl.append(str); for (int i = str.length(); i < 104; i++) { bl.append((byte) 0); } return context.runtime.newString(bl); }
private void ungetbyteCommon(RubyString ungetBytes) { ByteList ungetByteList = ungetBytes.getByteList(); int len = ungetByteList.getRealSize(); int start = ptr.pos; if (len == 0) return; ptr.string.modify(); if (len > ptr.pos) { start = 0; } else { start = ptr.pos - len; } ByteList bytes = ptr.string.getByteList(); if (isEndOfString()) bytes.length(Math.max(ptr.pos, len)); bytes.replace(start, ptr.pos - start, ungetBytes.getByteList()); ptr.pos = start; }
/** * @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(); }
@Override public int parseString(RubyLexer lexer) throws java.io.IOException { ByteList str = null; ByteList eos = nd_lit; int len = nd_lit.length() - 1; boolean indent = (flags & STR_FUNC_INDENT) != 0; int c = lexer.nextc(); if (c == EOF) return error(lexer, len, str, eos); // Found end marker for this heredoc if (lexer.was_bol() && lexer.whole_match_p(nd_lit, indent)) { lexer.heredoc_restore(this); return Tokens.tSTRING_END; } if ((flags & STR_FUNC_EXPAND) == 0) { do { ByteList lbuf = lexer.lex_lastline; int p = 0; int pend = lexer.lex_pend; if (pend > p) { switch (lexer.p(pend - 1)) { case '\n': pend--; if (pend == p || lexer.p(pend - 1) == '\r') { pend++; break; } break; case '\r': pend--; break; } } if (lexer.getHeredocIndent() > 0) { for (long i = 0; p + i < pend && lexer.update_heredoc_indent(lexer.p(p)); i++) {} lexer.setHeredocLineIndent(0); } if (str != null) { str.append(lbuf.makeShared(p, pend - p)); } else { str = new ByteList(lbuf.makeShared(p, pend - p)); } if (pend < lexer.lex_pend) str.append('\n'); lexer.lex_goto_eol(); if (lexer.getHeredocIndent() > 0) { lexer.setValue(str); return Tokens.tSTRING_CONTENT; } // MRI null checks str in this case but it is unconditionally non-null? if (lexer.nextc() == -1) return error(lexer, len, null, eos); } while (!lexer.whole_match_p(eos, indent)); } else { ByteList tok = new ByteList(); tok.setEncoding(lexer.getEncoding()); if (c == '#') { switch (c = lexer.nextc()) { case '$': case '@': lexer.pushback(c); return Tokens.tSTRING_DVAR; case '{': lexer.commandStart = true; return Tokens.tSTRING_DBEG; } tok.append('#'); } // MRI has extra pointer which makes our code look a little bit more strange in comparison do { lexer.pushback(c); Encoding enc[] = new Encoding[1]; enc[0] = lexer.getEncoding(); if ((c = new StringTerm(flags, '\0', '\n').parseStringIntoBuffer(lexer, tok, enc)) == EOF) { if (lexer.eofp) return error(lexer, len, str, eos); return restore(lexer); } if (c != '\n') { lexer.setValue(lexer.createStr(tok, 0)); return Tokens.tSTRING_CONTENT; } tok.append(lexer.nextc()); if (lexer.getHeredocIndent() > 0) { lexer.lex_goto_eol(); lexer.setValue(lexer.createStr(tok, 0)); return Tokens.tSTRING_CONTENT; } if ((c = lexer.nextc()) == EOF) return error(lexer, len, str, eos); } while (!lexer.whole_match_p(eos, indent)); str = tok; } lexer.heredoc_restore(this); lexer.setStrTerm(new StringTerm(-1, '\0', '\0')); lexer.setValue(lexer.createStr(str, 0)); return Tokens.tSTRING_CONTENT; }
/** * @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; } }
protected boolean isEmpty(ByteList bytes) { return bytes.length() == 0; }
@SuppressWarnings("fallthrough") @JRubyMethod(name = "read", optional = 2) public IRubyObject read(IRubyObject[] args) { checkReadable(); ByteList buf = null; int length = 0; int oldLength = 0; RubyString originalString = null; switch (args.length) { case 2: originalString = args[1].convertToString(); // must let original string know we're modifying, so shared buffers aren't damaged originalString.modify(); buf = originalString.getByteList(); case 1: if (!args[0].isNil()) { length = RubyNumeric.fix2int(args[0]); oldLength = length; if (length < 0) { throw getRuntime().newArgumentError("negative length " + length + " given"); } if (length > 0 && pos >= internal.getByteList().length()) { eof = true; if (buf != null) buf.realSize = 0; return getRuntime().getNil(); } else if (eof) { if (buf != null) buf.realSize = 0; return getRuntime().getNil(); } break; } case 0: oldLength = -1; length = internal.getByteList().length(); if (length <= pos) { eof = true; if (buf == null) { buf = new ByteList(); } else { buf.realSize = 0; } return getRuntime().newString(buf); } else { length -= pos; } break; default: getRuntime().newArgumentError(args.length, 0); } if (buf == null) { int internalLength = internal.getByteList().length(); if (internalLength > 0) { if (internalLength >= pos + length) { buf = new ByteList(internal.getByteList(), (int) pos, length); } else { int rest = (int) (internal.getByteList().length() - pos); if (length > rest) length = rest; buf = new ByteList(internal.getByteList(), (int) pos, length); } } } else { int rest = (int) (internal.getByteList().length() - pos); if (length > rest) length = rest; // Yow...this is still ugly byte[] target = buf.bytes; if (target.length > length) { System.arraycopy(internal.getByteList().bytes, (int) pos, target, 0, length); buf.begin = 0; buf.realSize = length; } else { target = new byte[length]; System.arraycopy(internal.getByteList().bytes, (int) pos, target, 0, length); buf.begin = 0; buf.realSize = length; buf.bytes = target; } } if (buf == null) { if (!eof) buf = new ByteList(); length = 0; } else { length = buf.length(); pos += length; } if (oldLength < 0 || oldLength > length) eof = true; return originalString != null ? originalString : getRuntime().newString(buf); }
// FIXME: We are assuming that original string will be raw bytes. If -Ku is provided // this will not be true, but that is ok for now. Deal with that when someone needs it. private IRubyObject _iconv(RubyString str, int start, int length) { if (fromEncoding == null) { throw getRuntime().newArgumentError("closed iconv"); } ByteList bytes = str.getByteList(); // treat start and end as start...end for end >= 0, start..end for end < 0 if (start < 0) { start += bytes.length(); } if (start < 0 || start > bytes.length()) { // invalid ranges result in an empty string return RubyString.newEmptyString(getRuntime()); } if (length < 0 || length > bytes.length() - start) { length = bytes.length() - start; } ByteBuffer buf = ByteBuffer.wrap(bytes.getUnsafeBytes(), bytes.begin() + start, length); try { CharBuffer cbuf = fromEncoding.decode(buf); buf = toEncoding.encode(cbuf); } catch (MalformedInputException e) { throw getRuntime().newIllegalSequence(str.toString()); } catch (UnmappableCharacterException e) { throw getRuntime().newIllegalSequence(str.toString()); } catch (CharacterCodingException e) { throw getRuntime().newInvalidEncoding("invalid sequence"); } catch (IllegalStateException e) { throw getRuntime().newIllegalSequence(str.toString()); } byte[] arr = buf.array(); start = 0; String displayName = toEncoding.charset().displayName(); if (arr.length >= 2) { // minimum Byte Order Mark (BOM) length if (displayName.toLowerCase().startsWith("utf-16")) { if ((arr[0] == (byte) 0xfe && arr[1] == (byte) 0xff)) { if (count > 0) start = 2; endian = "BE"; } else if (arr[0] == (byte) 0xff && arr[1] == (byte) 0xfe) { if (count > 0) start = 2; endian = "LE"; } } else if (displayName.toLowerCase().startsWith("utf-32") && arr.length >= 4) { if (arr[0] == (byte) 0x00 && arr[1] == (byte) 0x00 && arr[2] == (byte) 0xfe && arr[3] == (byte) 0xff) { if (count > 0) start = 4; endian = "BE"; } else if (arr[0] == (byte) 0xff && arr[1] == (byte) 0xfe && arr[2] == (byte) 0x00 && arr[3] == (byte) 0x00) { if (count > 0) start = 4; endian = "LE"; } } } count++; if (displayName.equalsIgnoreCase("utf-16") || displayName.equalsIgnoreCase("utf-32")) { displayName += endian; } ByteList r = new ByteList(arr, start, buf.limit() - start); EncodingDB.Entry entry = EncodingDB.getEncodings().get(displayName.getBytes()); if (entry != null) { Encoding charset = entry.getEncoding(); r.setEncoding(charset); } return getRuntime().newString(r); }
@JRubyMethod(name = "write", required = 1) public IRubyObject write(IRubyObject p1) throws IOException { ByteList bytes = p1.convertToString().getByteList(); io.write(bytes.unsafeBytes(), bytes.begin(), bytes.length()); return getRuntime().newFixnum(bytes.length()); }