/** * Create a new {@code Buffer} by copying the underlying {@link ByteBuffer} into a newly-allocated * {@code Buffer}. * * @return the new {@code Buffer} */ public Buffer copy() { snapshot(); Buffer b = new Buffer(buffer.remaining(), false); b.append(buffer); reset(); return b.flip(); }
/** * Append the given {@link Buffer} to this {@literal Buffer}. * * @param buffers The {@link Buffer Buffers} to append. * @return {@literal this} */ public Buffer append(Buffer... buffers) { for (Buffer b : buffers) { int pos = (null == buffer ? 0 : buffer.position()); int len = b.remaining(); ensureCapacity(len); buffer.put(b.byteBuffer()); buffer.position(pos + len); } return this; }
/** * Very efficient method for parsing an {@link Integer} from the given {@literal Buffer} range. * Much faster than {@link Integer#parseInt(String)}. * * @param b The {@literal Buffer} to slice. * @param start start of the range. * @param end end of the range. * @return The int value or {@literal null} if the {@literal Buffer} could not be read. */ public static Integer parseInt(Buffer b, int start, int end) { b.snapshot(); b.buffer.limit(end); b.buffer.position(start); Integer i = parseInt(b); b.reset(); return i; }
/** * Split this buffer on the given delimiter. Save memory by reusing the provided {@code List}. The * delimiter is stripped from the end of the segment if {@code stripDelimiter} is {@code true}. * * @param views The already-allocated List to reuse. * @param delimiter The multi-byte delimiter. * @param stripDelimiter {@literal true} to ignore the delimiter, {@literal false} to leave it in * the returned data. * @return An {@link Iterable} of {@link View Views} that point to the segments of this buffer. */ public Iterable<View> split(List<View> views, Buffer delimiter, boolean stripDelimiter) { snapshot(); byte[] delimBytes = delimiter.asBytes(); if (delimBytes.length == 0) { return Collections.emptyList(); } int start = this.position; for (byte b : this) { if (b != delimBytes[0]) { continue; } int end = -1; for (int i = 1; i < delimBytes.length; i++) { if (read() == delimBytes[i]) { end = stripDelimiter ? buffer.position() - delimBytes.length : buffer.position(); } else { end = -1; break; } } if (end > 0) { views.add(createView(start, end)); start = end + (stripDelimiter ? delimBytes.length : 0); } } if (start != buffer.position()) { buffer.position(start); } reset(); return views; }
/** * Very efficient method for parsing an {@link Integer} from the given {@literal Buffer}. Much * faster than {@link Integer#parseInt(String)}. * * @param b The {@literal Buffer} to slice. * @return The int value or {@literal null} if the {@literal Buffer} could not be read. */ public static Integer parseInt(Buffer b) { if (b.remaining() == 0) { return null; } b.snapshot(); int len = b.remaining(); int num = 0; int dec = 1; for (int i = (b.position + len); i > b.position; ) { char c = (char) b.buffer.get(--i); num += Character.getNumericValue(c) * dec; dec *= 10; } b.reset(); return num; }
/** * Very efficient method for parsing a {@link Long} from the given {@literal Buffer}. Much faster * than {@link Long#parseLong(String)}. * * @param b The {@literal Buffer} to slice. * @return The long value or {@literal null} if the {@literal Buffer} could not be read. */ public static Long parseLong(Buffer b) { if (b.remaining() == 0) { return null; } ByteBuffer bb = b.buffer; int origPos = bb.position(); int len = bb.remaining(); long num = 0; int dec = 1; for (int i = len; i > 0; ) { char c = (char) bb.get(--i); num += Character.getNumericValue(c) * dec; dec *= 10; } bb.position(origPos); return num; }