📄 bytebuffer.java
字号:
* This method is a shortcut for <tt>putPrefixedString(in, 2, 0, encoder)</tt>. * * @throws BufferOverflowException if the specified string doesn't fit */ public ByteBuffer putPrefixedString(CharSequence in, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, 2, 0, encoder); } /** * Writes the content of <code>in</code> into this buffer as a * string which has a 16-bit length field before the actual * encoded string, using the specified <code>encoder</code>. * This method is a shortcut for <tt>putPrefixedString(in, prefixLength, 0, encoder)</tt>. * * @param prefixLength the length of the length field (1, 2, or 4) * * @throws BufferOverflowException if the specified string doesn't fit */ public ByteBuffer putPrefixedString(CharSequence in, int prefixLength, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, 0, encoder); } /** * Writes the content of <code>in</code> into this buffer as a * string which has a 16-bit length field before the actual * encoded string, using the specified <code>encoder</code>. * This method is a shortcut for <tt>putPrefixedString(in, prefixLength, padding, ( byte ) 0, encoder)</tt>. * * @param prefixLength the length of the length field (1, 2, or 4) * @param padding the number of padded <tt>NUL</tt>s (1 (or 0), 2, or 4) * * @throws BufferOverflowException if the specified string doesn't fit */ public ByteBuffer putPrefixedString(CharSequence in, int prefixLength, int padding, CharsetEncoder encoder) throws CharacterCodingException { return putPrefixedString(in, prefixLength, padding, (byte) 0, encoder); } /** * Writes the content of <code>in</code> into this buffer as a * string which has a 16-bit length field before the actual * encoded string, using the specified <code>encoder</code>. * * @param prefixLength the length of the length field (1, 2, or 4) * @param padding the number of padded bytes (1 (or 0), 2, or 4) * @param padValue the value of padded bytes * * @throws BufferOverflowException if the specified string doesn't fit */ public ByteBuffer putPrefixedString(CharSequence val, int prefixLength, int padding, byte padValue, CharsetEncoder encoder) throws CharacterCodingException { int maxLength; switch (prefixLength) { case 1: maxLength = 255; break; case 2: maxLength = 65535; break; case 4: maxLength = Integer.MAX_VALUE; break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (val.length() > maxLength) { throw new IllegalArgumentException( "The specified string is too long."); } if (val.length() == 0) { switch (prefixLength) { case 1: put((byte) 0); break; case 2: putShort((short) 0); break; case 4: putInt(0); break; } return this; } int padMask; switch (padding) { case 0: case 1: padMask = 0; break; case 2: padMask = 1; break; case 4: padMask = 3; break; default: throw new IllegalArgumentException("padding: " + padding); } CharBuffer in = CharBuffer.wrap(val); int expectedLength = (int) (in.remaining() * encoder .averageBytesPerChar()) + 1; skip(prefixLength); // make a room for the length field int oldPos = position(); encoder.reset(); for (;;) { CoderResult cr; if (in.hasRemaining()) { cr = encoder.encode(in, buf(), true); } else { cr = encoder.flush(buf()); } if (position() - oldPos > maxLength) { throw new IllegalArgumentException( "The specified string is too long."); } if (cr.isUnderflow()) { break; } if (cr.isOverflow() && isAutoExpand()) { autoExpand(expectedLength); continue; } cr.throwException(); } // Write the length field fill(padValue, padding - ((position() - oldPos) & padMask)); int length = position() - oldPos; switch (prefixLength) { case 1: put(oldPos - 1, (byte) length); break; case 2: putShort(oldPos - 2, (short) length); break; case 4: putInt(oldPos - 4, length); break; } return this; } /** * Reads a Java object from the buffer using the context {@link ClassLoader} * of the current thread. */ public Object getObject() throws ClassNotFoundException { return getObject(Thread.currentThread().getContextClassLoader()); } /** * Reads a Java object from the buffer using the specified <tt>classLoader</tt>. */ public Object getObject(final ClassLoader classLoader) throws ClassNotFoundException { if (!prefixedDataAvailable(4)) { throw new BufferUnderflowException(); } int length = getInt(); if (length <= 4) { throw new BufferDataException( "Object length should be greater than 4: " + length); } int oldLimit = limit(); limit(position() + length); try { ObjectInputStream in = new ObjectInputStream(asInputStream()) { protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { String className = readUTF(); Class<?> clazz = Class .forName(className, true, classLoader); return ObjectStreamClass.lookup(clazz); } }; return in.readObject(); } catch (IOException e) { throw new BufferDataException(e); } finally { limit(oldLimit); } } /** * Writes the specified Java object to the buffer. */ public ByteBuffer putObject(Object o) { int oldPos = position(); skip(4); // Make a room for the length field. try { ObjectOutputStream out = new ObjectOutputStream(asOutputStream()) { protected void writeClassDescriptor(ObjectStreamClass desc) throws IOException { writeUTF(desc.getName()); } }; out.writeObject(o); out.flush(); } catch (IOException e) { throw new BufferDataException(e); } // Fill the length field int newPos = position(); position(oldPos); putInt(newPos - oldPos - 4); position(newPos); return this; } /** * Returns <tt>true</tt> if this buffer contains a data which has a data * length as a prefix and the buffer has remaining data as enough as * specified in the data length field. This method is identical with * <tt>prefixedDataAvailable( prefixLength, Integer.MAX_VALUE )</tt>. * Please not that using this method can allow DoS (Denial of Service) * attack in case the remote peer sends too big data length value. * It is recommended to use {@link #prefixedDataAvailable(int, int)} * instead. * * @param prefixLength the length of the prefix field (1, 2, or 4) * * @throws IllegalArgumentException if prefixLength is wrong * @throws BufferDataException if data length is negative */ public boolean prefixedDataAvailable(int prefixLength) { return prefixedDataAvailable(prefixLength, Integer.MAX_VALUE); } /** * Returns <tt>true</tt> if this buffer contains a data which has a data * length as a prefix and the buffer has remaining data as enough as * specified in the data length field. * * @param prefixLength the length of the prefix field (1, 2, or 4) * @param maxDataLength the allowed maximum of the read data length * * @throws IllegalArgumentException if prefixLength is wrong * @throws BufferDataException if data length is negative or greater then <tt>maxDataLength</tt> */ public boolean prefixedDataAvailable(int prefixLength, int maxDataLength) { if (remaining() < prefixLength) { return false; } int dataLength; switch (prefixLength) { case 1: dataLength = getUnsigned(position()); break; case 2: dataLength = getUnsignedShort(position()); break; case 4: dataLength = getInt(position()); break; default: throw new IllegalArgumentException("prefixLength: " + prefixLength); } if (dataLength < 0 || dataLength > maxDataLength) { throw new BufferDataException("dataLength: " + dataLength); } return remaining() - prefixLength >= dataLength; } ////////////////////////// // Skip or fill methods // ////////////////////////// /** * Forwards the position of this buffer as the specified <code>size</code> * bytes. */ public ByteBuffer skip(int size) { autoExpand(size); return position(position() + size); } /** * Fills this buffer with the specified value. * This method moves buffer position forward. */ public ByteBuffer fill(byte value, int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; if (q > 0) { int intValue = value | (value << 8) | (value << 16) | (value << 24); long longValue = intValue; longValue <<= 32; longValue |= intValue; for (int i = q; i > 0; i--) { putLong(longValue); } } q = r >>> 2; r = r & 3; if (q > 0) { int intValue = value | (value << 8) | (value << 16) | (value << 24); putInt(intValue); } q = r >> 1; r = r & 1; if (q > 0) { short shortValue = (short) (value | (value << 8)); putShort(shortValue); } if (r > 0) { put(value); } return this; } /** * Fills this buffer with the specified value. * This method does not change buffer position. */ public ByteBuffer fillAndReset(byte value, int size) { autoExpand(size); int pos = position(); try { fill(value, size); } finally { position(pos); } return this; } /** * Fills this buffer with <code>NUL (0x00)</code>. * This method moves buffer position forward. */ public ByteBuffer fill(int size) { autoExpand(size); int q = size >>> 3; int r = size & 7; for (int i = q; i > 0; i--) { putLong(0L); } q = r >>> 2; r = r & 3; if (q > 0) { putInt(0); } q = r >> 1; r = r & 1; if (q > 0) { putShort((short) 0); } if (r > 0) { put((byte) 0); } return this; } /** * Fills this buffer with <code>NUL (0x00)</code>. * This method does not change buffer position. */ public ByteBuffer fillAndReset(int size) { autoExpand(size); int pos = position(); try { fill(size); } finally { position(pos); } return this; } /** * This method forwards the call to {@link #expand(int)} only when * <tt>autoExpand</tt> property is <tt>true</tt>. */ protected ByteBuffer autoExpand(int expectedRemaining) { if (isAutoExpand()) { expand(expectedRemaining); } return this; } /** * This method forwards the call to {@link #expand(int)} only when * <tt>autoExpand</tt> property is <tt>true</tt>. */ protected ByteBuffer autoExpand(int pos, int expectedRemaining) { if (isAutoExpand()) { expand(pos, expectedRemaining); } return this; } private static void checkFieldSize(int fieldSize) { if (fieldSize < 0) { throw new IllegalArgumentException("fieldSize cannot be negative: " + fieldSize); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -