Пример #1
0
  /**
   * 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;
  }
Пример #2
0
 /**
  * Get the first {@code byte} from this {@literal Buffer}.
  *
  * @return The first {@code byte}.
  */
 public byte first() {
   snapshot();
   if (this.position > 0) {
     buffer.position(0); // got to the 1st position
   }
   byte b = buffer.get(); // get the 1st byte
   reset(); // go back to original pos
   return b;
 }
Пример #3
0
  /**
   * 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() {
    if (buffer == null) return new Buffer();
    snapshot();
    Buffer b = new Buffer(buffer.remaining(), false);
    b.append(buffer);
    reset();

    return b.flip();
  }
Пример #4
0
 /**
  * Create a copy of the given range.
  *
  * @param start start of the range.
  * @param len end of the range.
  * @return A new {@link Buffer}, constructed from the contents of the given range.
  */
 public Buffer slice(int start, int len) {
   snapshot();
   ByteBuffer bb = ByteBuffer.allocate(len);
   buffer.position(start);
   bb.put(buffer);
   reset();
   bb.flip();
   return new Buffer(bb);
 }
Пример #5
0
  /**
   * Slice a portion of this buffer and convert it to a String.
   *
   * @param start start of the range.
   * @param end end of the range.
   * @return The contents of the given range as a String.
   */
  public String substring(int start, int end) {
    snapshot();

    buffer.limit((end > start ? end : this.limit));
    buffer.position(start);
    String s = asString();

    reset();
    return s;
  }
Пример #6
0
 @Override
 public int read(ByteBuffer dst) throws IOException {
   snapshot();
   if (dst.remaining() < this.limit) {
     buffer.limit(dst.remaining());
   }
   int pos = dst.position();
   dst.put(buffer);
   buffer.limit(this.limit);
   return dst.position() - pos;
 }
Пример #7
0
 private void expand(int expandSize) {
   snapshot();
   ByteBuffer newBuff =
       (buffer.isDirect()
           ? ByteBuffer.allocateDirect(buffer.capacity() + expandSize)
           : ByteBuffer.allocate(buffer.capacity() + expandSize));
   buffer.flip();
   newBuff.put(buffer);
   buffer = newBuff;
   reset();
 }
Пример #8
0
 /**
  * Return the contents of this buffer copied into a {@code byte[]}.
  *
  * @return The contents of this buffer as a {@code byte[]}.
  */
 public byte[] asBytes() {
   if (null != buffer) {
     snapshot();
     byte[] b = new byte[buffer.remaining()];
     buffer.get(b);
     reset();
     return b;
   } else {
     return null;
   }
 }
Пример #9
0
  /**
   * 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;
  }
Пример #10
0
 /**
  * Search the buffer and find the position of the first occurrence of the given {@code byte}
  * staring at the start position and searching until (and including) the end position.
  *
  * @param b the {@code byte} to search for
  * @param start the position to start searching
  * @param end the position at which to stop searching
  * @return the position of the char in the buffer or {@code -1} if not found
  */
 public int indexOf(byte b, int start, int end) {
   snapshot();
   if (buffer.position() != start) {
     buffer.position(start);
   }
   int pos = -1;
   while (buffer.hasRemaining() && buffer.position() < end) {
     if (buffer.get() == b) {
       pos = buffer.position();
       break;
     }
   }
   reset();
   return pos;
 }
Пример #11
0
  /**
   * Slice this buffer at the given positions. Useful for extracting multiple segments of data from
   * a buffer when the exact indices of that data is already known.
   *
   * @param positions The start and end positions of the slices.
   * @return A list of {@link View Views} pointing to the slices.
   */
  public List<View> slice(int... positions) {
    Assert.notNull(positions, "Positions cannot be null.");
    if (positions.length == 0) {
      return Collections.emptyList();
    }

    snapshot();

    List<View> views = new ArrayList<View>();
    int len = positions.length;
    for (int i = 0; i < len; i++) {
      int start = positions[i];
      int end = (i + 1 < len ? positions[++i] : this.limit);
      views.add(createView(start, end));
      reset();
    }

    return views;
  }
Пример #12
0
  private void shift(int right) {
    ByteBuffer currentBuffer;
    if (null == buffer) {
      ensureCapacity(right);
      currentBuffer = buffer;
    } else {
      currentBuffer = buffer.slice();
    }

    int len = buffer.remaining();
    int pos = buffer.position();
    ensureCapacity(right + len);

    buffer.position(pos + right);
    buffer.put(currentBuffer);
    buffer.position(pos);

    snapshot();
  }
Пример #13
0
  /**
   * Split this buffer on the given delimiter, save memory by reusing the given {@link List}, and
   * optionally leave the delimiter intact rather than stripping it.
   *
   * @param views The list to store {@link View Views} in.
   * @param delimiter The delimiter on which to split this buffer.
   * @param stripDelimiter {@literal true} to ignore the delimiter, {@literal false} to leave it in
   *     the returned data.
   * @return A {@link List} of {@link View Views} that point to the segments of this buffer.
   */
  public List<View> split(List<View> views, int delimiter, boolean stripDelimiter) {
    snapshot();

    int start = this.position;
    for (byte b : this) {
      if (b == delimiter) {
        int end = stripDelimiter ? buffer.position() - 1 : buffer.position();
        views.add(createView(start, end));
        start = end + (stripDelimiter ? 1 : 0);
      }
    }
    if (start != buffer.position()) {
      buffer.position(start);
    }

    reset();

    return views;
  }
Пример #14
0
  /**
   * 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;
  }
Пример #15
0
  private String decode() {
    if (null == decoder) {
      decoder = UTF8.newDecoder();
    }
    snapshot();
    try {
      if (null == chars || chars.remaining() < buffer.remaining()) {
        chars = CharBuffer.allocate(buffer.remaining());
      } else {
        chars.rewind();
      }
      decoder.reset();
      CoderResult cr = decoder.decode(buffer.duplicate(), chars, true);
      if (cr.isUnderflow()) {
        decoder.flush(chars);
      }
      chars.flip();

      return chars.toString();
    } finally {
      reset();
    }
  }
Пример #16
0
 /**
  * Create a {@link View} of the current range of this {@link Buffer}.
  *
  * @return The view of the buffer
  * @see #position()
  * @see #limit()
  */
 public View createView() {
   snapshot();
   return new View(position, limit);
 }
Пример #17
0
 /**
  * Create a {@link View} of the given range of this {@literal Buffer}.
  *
  * @param start start of the range.
  * @param end end of the range.
  * @return A new {@link View} object that represents the given range.
  */
 public View createView(int start, int end) {
   snapshot();
   return new View(start, end);
 }