| | |
| | | * (the "License"). You may not use this file except in compliance |
| | | * with the License. |
| | | * |
| | | * You can obtain a copy of the license at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt |
| | | * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt |
| | | * or http://forgerock.org/license/CDDLv1.0.html. |
| | | * See the License for the specific language governing permissions |
| | | * and limitations under the License. |
| | | * |
| | | * When distributing Covered Code, include this CDDL HEADER in each |
| | | * file and include the License file at |
| | | * trunk/opendj3/legal-notices/CDDLv1_0.txt. If applicable, |
| | | * add the following below this CDDL HEADER, with the fields enclosed |
| | | * by brackets "[]" replaced with your own identifying information: |
| | | * file and include the License file at legal-notices/CDDLv1_0.txt. |
| | | * If applicable, add the following below this CDDL HEADER, with the |
| | | * fields enclosed by brackets "[]" replaced with your own identifying |
| | | * information: |
| | | * Portions Copyright [yyyy] [name of copyright owner] |
| | | * |
| | | * CDDL HEADER END |
| | |
| | | */ |
| | | package org.forgerock.opendj.ldap; |
| | | |
| | | |
| | | |
| | | /** |
| | | * An interface for iteratively reading date from a {@link ByteSequence} . |
| | | * {@code ByteSequenceReader} must be created using the associated {@code |
| | | * ByteSequence}'s {@code asReader()} method. |
| | | * {@code ByteSequenceReader} must be created using the associated |
| | | * {@code ByteSequence}'s {@code asReader()} method. |
| | | */ |
| | | public final class ByteSequenceReader |
| | | { |
| | | public final class ByteSequenceReader { |
| | | |
| | | // The current position in the byte sequence. |
| | | private int pos = 0; |
| | | // The current position in the byte sequence. |
| | | private int pos = 0; |
| | | |
| | | // The underlying byte sequence. |
| | | private final ByteSequence sequence; |
| | | // The underlying byte sequence. |
| | | private final ByteSequence sequence; |
| | | |
| | | |
| | | |
| | | /** |
| | | * Creates a new byte sequence reader whose source is the provided byte |
| | | * sequence. |
| | | * <p> |
| | | * <b>NOTE:</b> any concurrent changes to the underlying byte sequence (if |
| | | * mutable) may cause subsequent reads to overrun and fail. |
| | | * <p> |
| | | * This constructor is package private: construction must be performed using |
| | | * {@link ByteSequence#asReader()}. |
| | | * |
| | | * @param sequence |
| | | * The byte sequence to be read. |
| | | */ |
| | | ByteSequenceReader(final ByteSequence sequence) |
| | | { |
| | | this.sequence = sequence; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative get method. Reads the byte at the current position. |
| | | * |
| | | * @return The byte at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < 1}. |
| | | */ |
| | | public byte get() |
| | | { |
| | | final byte b = sequence.byteAt(pos); |
| | | pos++; |
| | | return b; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative bulk get method. This method transfers bytes from this reader into |
| | | * the given destination array. An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.get(b); |
| | | * </pre> |
| | | * |
| | | * Behaves in exactly the same way as the invocation: |
| | | * |
| | | * <pre> |
| | | * src.get(b, 0, b.length); |
| | | * </pre> |
| | | * |
| | | * @param b |
| | | * The byte array into which bytes are to be written. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < b.length}. |
| | | */ |
| | | public void get(final byte[] b) |
| | | { |
| | | get(b, 0, b.length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative bulk get method. Copies {@code length} bytes from this reader into |
| | | * the given array, starting at the current position of this reader and at the |
| | | * given {@code offset} in the array. The position of this reader is then |
| | | * incremented by {@code length}. In other words, an invocation of this method |
| | | * of the form: |
| | | * |
| | | * <pre> |
| | | * src.get(b, offset, length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as the loop: |
| | | * |
| | | * <pre> |
| | | * for (int i = offset; i < offset + length; i++) |
| | | * b[i] = src.get(); |
| | | * </pre> |
| | | * |
| | | * Except that it first checks that there are sufficient bytes in this buffer |
| | | * and it is potentially much more efficient. |
| | | * |
| | | * @param b |
| | | * The byte array into which bytes are to be written. |
| | | * @param offset |
| | | * The offset within the array of the first byte to be written; must |
| | | * be non-negative and no larger than {@code b.length}. |
| | | * @param length |
| | | * The number of bytes to be written to the given array; must be |
| | | * non-negative and no larger than {@code b.length} . |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public void get(final byte[] b, final int offset, final int length) |
| | | { |
| | | if (offset < 0 || length < 0 || offset + length > b.length |
| | | || length > remaining()) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | /** |
| | | * Creates a new byte sequence reader whose source is the provided byte |
| | | * sequence. |
| | | * <p> |
| | | * <b>NOTE:</b> any concurrent changes to the underlying byte sequence (if |
| | | * mutable) may cause subsequent reads to overrun and fail. |
| | | * <p> |
| | | * This constructor is package private: construction must be performed using |
| | | * {@link ByteSequence#asReader()}. |
| | | * |
| | | * @param sequence |
| | | * The byte sequence to be read. |
| | | */ |
| | | ByteSequenceReader(final ByteSequence sequence) { |
| | | this.sequence = sequence; |
| | | } |
| | | |
| | | sequence.subSequence(pos, pos + length).copyTo(b, offset); |
| | | pos += length; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative get method for reading a multi-byte BER length. Reads the next one |
| | | * to five bytes at this reader's current position, composing them into a |
| | | * integer value and then increments the position by the number of bytes read. |
| | | * |
| | | * @return The integer value representing the length at this reader's current |
| | | * position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request. |
| | | */ |
| | | public int getBERLength() |
| | | { |
| | | // Make sure we have at least one byte to read. |
| | | int newPos = pos + 1; |
| | | if (newPos > sequence.length()) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | /** |
| | | * Relative get method. Reads the byte at the current position. |
| | | * |
| | | * @return The byte at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < 1}. |
| | | */ |
| | | public byte get() { |
| | | final byte b = sequence.byteAt(pos); |
| | | pos++; |
| | | return b; |
| | | } |
| | | |
| | | int length = sequence.byteAt(pos) & 0x7F; |
| | | if (length != sequence.byteAt(pos)) |
| | | { |
| | | // Its a multi-byte length |
| | | final int numLengthBytes = length; |
| | | newPos = pos + 1 + numLengthBytes; |
| | | // Make sure we have the bytes needed |
| | | if (numLengthBytes > 4 || newPos > sequence.length()) |
| | | { |
| | | // Shouldn't have more than 4 bytes |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | length = 0x00; |
| | | for (int i = pos + 1; i < newPos; i++) |
| | | { |
| | | length = length << 8 | sequence.byteAt(i) & 0xFF; |
| | | } |
| | | /** |
| | | * Relative bulk get method. This method transfers bytes from this reader |
| | | * into the given destination array. An invocation of this method of the |
| | | * form: |
| | | * |
| | | * <pre> |
| | | * src.get(b); |
| | | * </pre> |
| | | * |
| | | * Behaves in exactly the same way as the invocation: |
| | | * |
| | | * <pre> |
| | | * src.get(b, 0, b.length); |
| | | * </pre> |
| | | * |
| | | * @param b |
| | | * The byte array into which bytes are to be written. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < b.length}. |
| | | */ |
| | | public void get(final byte[] b) { |
| | | get(b, 0, b.length); |
| | | } |
| | | |
| | | pos = newPos; |
| | | return length; |
| | | } |
| | | /** |
| | | * Relative bulk get method. Copies {@code length} bytes from this reader |
| | | * into the given array, starting at the current position of this reader and |
| | | * at the given {@code offset} in the array. The position of this reader is |
| | | * then incremented by {@code length}. In other words, an invocation of this |
| | | * method of the form: |
| | | * |
| | | * <pre> |
| | | * src.get(b, offset, length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as the loop: |
| | | * |
| | | * <pre> |
| | | * for (int i = offset; i < offset + length; i++) |
| | | * b[i] = src.get(); |
| | | * </pre> |
| | | * |
| | | * Except that it first checks that there are sufficient bytes in this |
| | | * buffer and it is potentially much more efficient. |
| | | * |
| | | * @param b |
| | | * The byte array into which bytes are to be written. |
| | | * @param offset |
| | | * The offset within the array of the first byte to be written; |
| | | * must be non-negative and no larger than {@code b.length}. |
| | | * @param length |
| | | * The number of bytes to be written to the given array; must be |
| | | * non-negative and no larger than {@code b.length} . |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public void get(final byte[] b, final int offset, final int length) { |
| | | if (offset < 0 || length < 0 || offset + length > b.length || length > remaining()) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative bulk get method. Returns a {@link ByteSequence} whose content is |
| | | * the next {@code length} bytes from this reader, starting at the current |
| | | * position of this reader. The position of this reader is then incremented by |
| | | * {@code length}. |
| | | * <p> |
| | | * <b>NOTE:</b> The value returned from this method should NEVER be cached as |
| | | * it prevents the contents of the underlying byte stream from being garbage |
| | | * collected. |
| | | * |
| | | * @param length |
| | | * The length of the byte sequence to be returned. |
| | | * @return The byte sequence whose content is the next {@code length} bytes |
| | | * from this reader. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public ByteSequence getByteSequence(final int length) |
| | | { |
| | | final int newPos = pos + length; |
| | | final ByteSequence subSequence = sequence.subSequence(pos, newPos); |
| | | pos = newPos; |
| | | return subSequence; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative bulk get method. Returns a {@link ByteString} whose content is the |
| | | * next {@code length} bytes from this reader, starting at the current |
| | | * position of this reader. The position of this reader is then incremented by |
| | | * {@code length}. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.getByteString(length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.getByteSequence(length).toByteString(); |
| | | * </pre> |
| | | * |
| | | * <b>NOTE:</b> The value returned from this method should NEVER be cached as |
| | | * it prevents the contents of the underlying byte stream from being garbage |
| | | * collected. |
| | | * |
| | | * @param length |
| | | * The length of the byte string to be returned. |
| | | * @return The byte string whose content is the next {@code length} bytes from |
| | | * this reader. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public ByteString getByteString(final int length) |
| | | { |
| | | return getByteSequence(length).toByteString(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative get method for reading an integer value. Reads the next four bytes |
| | | * at this reader's current position, composing them into an integer value |
| | | * according to big-endian byte order, and then increments the position by |
| | | * four. |
| | | * |
| | | * @return The integer value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < 4}. |
| | | */ |
| | | public int getInt() |
| | | { |
| | | if (remaining() < 4) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | sequence.subSequence(pos, pos + length).copyTo(b, offset); |
| | | pos += length; |
| | | } |
| | | |
| | | int v = 0; |
| | | for (int i = 0; i < 4; i++) |
| | | { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | /** |
| | | * Relative get method for reading a multi-byte BER length. Reads the next |
| | | * one to five bytes at this reader's current position, composing them into |
| | | * a integer value and then increments the position by the number of bytes |
| | | * read. |
| | | * |
| | | * @return The integer value representing the length at this reader's |
| | | * current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request. |
| | | */ |
| | | public int getBERLength() { |
| | | // Make sure we have at least one byte to read. |
| | | int newPos = pos + 1; |
| | | if (newPos > sequence.length()) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | int length = sequence.byteAt(pos) & 0x7F; |
| | | if (length != sequence.byteAt(pos)) { |
| | | // Its a multi-byte length |
| | | final int numLengthBytes = length; |
| | | newPos = pos + 1 + numLengthBytes; |
| | | // Make sure we have the bytes needed |
| | | if (numLengthBytes > 4 || newPos > sequence.length()) { |
| | | // Shouldn't have more than 4 bytes |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | length = 0x00; |
| | | for (int i = pos + 1; i < newPos; i++) { |
| | | length = length << 8 | sequence.byteAt(i) & 0xFF; |
| | | } |
| | | } |
| | | |
| | | pos = newPos; |
| | | return length; |
| | | } |
| | | |
| | | return v; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Relative get method for reading a long value. Reads the next eight bytes at |
| | | * this reader's current position, composing them into a long value according |
| | | * to big-endian byte order, and then increments the position by eight. |
| | | * |
| | | * @return The long value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < 8}. |
| | | */ |
| | | public long getLong() |
| | | { |
| | | if (remaining() < 8) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | /** |
| | | * Relative bulk get method. Returns a {@link ByteSequence} whose content is |
| | | * the next {@code length} bytes from this reader, starting at the current |
| | | * position of this reader. The position of this reader is then incremented |
| | | * by {@code length}. |
| | | * <p> |
| | | * <b>NOTE:</b> The value returned from this method should NEVER be cached |
| | | * as it prevents the contents of the underlying byte stream from being |
| | | * garbage collected. |
| | | * |
| | | * @param length |
| | | * The length of the byte sequence to be returned. |
| | | * @return The byte sequence whose content is the next {@code length} bytes |
| | | * from this reader. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public ByteSequence getByteSequence(final int length) { |
| | | final int newPos = pos + length; |
| | | final ByteSequence subSequence = sequence.subSequence(pos, newPos); |
| | | pos = newPos; |
| | | return subSequence; |
| | | } |
| | | |
| | | long v = 0; |
| | | for (int i = 0; i < 8; i++) |
| | | { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | /** |
| | | * Relative bulk get method. Returns a {@link ByteString} whose content is |
| | | * the next {@code length} bytes from this reader, starting at the current |
| | | * position of this reader. The position of this reader is then incremented |
| | | * by {@code length}. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.getByteString(length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.getByteSequence(length).toByteString(); |
| | | * </pre> |
| | | * |
| | | * <b>NOTE:</b> The value returned from this method should NEVER be cached |
| | | * as it prevents the contents of the underlying byte stream from being |
| | | * garbage collected. |
| | | * |
| | | * @param length |
| | | * The length of the byte string to be returned. |
| | | * @return The byte string whose content is the next {@code length} bytes |
| | | * from this reader. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public ByteString getByteString(final int length) { |
| | | return getByteSequence(length).toByteString(); |
| | | } |
| | | |
| | | return v; |
| | | } |
| | | /** |
| | | * Relative get method for reading an integer value. Reads the next four |
| | | * bytes at this reader's current position, composing them into an integer |
| | | * value according to big-endian byte order, and then increments the |
| | | * position by four. |
| | | * |
| | | * @return The integer value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < 4}. |
| | | */ |
| | | public int getInt() { |
| | | if (remaining() < 4) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | int v = 0; |
| | | for (int i = 0; i < 4; i++) { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Relative get method for reading an short value. Reads the next 2 bytes at |
| | | * this reader's current position, composing them into an short value |
| | | * according to big-endian byte order, and then increments the position by |
| | | * two. |
| | | * |
| | | * @return The integer value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < 2}. |
| | | */ |
| | | public short getShort() |
| | | { |
| | | if (remaining() < 2) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | return v; |
| | | } |
| | | |
| | | short v = 0; |
| | | for (int i = 0; i < 2; i++) |
| | | { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | /** |
| | | * Relative get method for reading a long value. Reads the next eight bytes |
| | | * at this reader's current position, composing them into a long value |
| | | * according to big-endian byte order, and then increments the position by |
| | | * eight. |
| | | * |
| | | * @return The long value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < 8}. |
| | | */ |
| | | public long getLong() { |
| | | if (remaining() < 8) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | long v = 0; |
| | | for (int i = 0; i < 8; i++) { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | } |
| | | |
| | | return v; |
| | | } |
| | | |
| | | return v; |
| | | } |
| | | /** |
| | | * Relative get method for reading an short value. Reads the next 2 bytes at |
| | | * this reader's current position, composing them into an short value |
| | | * according to big-endian byte order, and then increments the position by |
| | | * two. |
| | | * |
| | | * @return The integer value at this reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < 2}. |
| | | */ |
| | | public short getShort() { |
| | | if (remaining() < 2) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | short v = 0; |
| | | for (int i = 0; i < 2; i++) { |
| | | v <<= 8; |
| | | v |= sequence.byteAt(pos++) & 0xFF; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Relative get method for reading a UTF-8 encoded string. Reads the next |
| | | * number of specified bytes at this reader's current position, decoding them |
| | | * into a string using UTF-8 and then increments the position by the number of |
| | | * bytes read. If UTF-8 decoding fails, the platform's default encoding will |
| | | * be used. |
| | | * |
| | | * @param length |
| | | * The number of bytes to read and decode. |
| | | * @return The string value at the reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public String getString(final int length) |
| | | { |
| | | if (remaining() < length) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | return v; |
| | | } |
| | | |
| | | final int newPos = pos + length; |
| | | final String str = sequence.subSequence(pos, pos + length).toString(); |
| | | pos = newPos; |
| | | return str; |
| | | } |
| | | /** |
| | | * Relative get method for reading a UTF-8 encoded string. Reads the next |
| | | * number of specified bytes at this reader's current position, decoding |
| | | * them into a string using UTF-8 and then increments the position by the |
| | | * number of bytes read. If UTF-8 decoding fails, the platform's default |
| | | * encoding will be used. |
| | | * |
| | | * @param length |
| | | * The number of bytes to read and decode. |
| | | * @return The string value at the reader's current position. |
| | | * @throws IndexOutOfBoundsException |
| | | * If there are fewer bytes remaining in this reader than are |
| | | * required to satisfy the request, that is, if |
| | | * {@code remaining() |
| | | * < length}. |
| | | */ |
| | | public String getString(final int length) { |
| | | if (remaining() < length) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Returns this reader's position. |
| | | * |
| | | * @return The position of this reader. |
| | | */ |
| | | public int position() |
| | | { |
| | | return pos; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Sets this reader's position. |
| | | * |
| | | * @param pos |
| | | * The new position value; must be non-negative and no larger than |
| | | * the length of the underlying byte sequence. |
| | | * @throws IndexOutOfBoundsException |
| | | * If the position is negative or larger than the length of the |
| | | * underlying byte sequence. |
| | | */ |
| | | public void position(final int pos) |
| | | { |
| | | if (pos > sequence.length() || pos < 0) |
| | | { |
| | | throw new IndexOutOfBoundsException(); |
| | | final int newPos = pos + length; |
| | | final String str = sequence.subSequence(pos, pos + length).toString(); |
| | | pos = newPos; |
| | | return str; |
| | | } |
| | | |
| | | this.pos = pos; |
| | | } |
| | | /** |
| | | * Returns this reader's position. |
| | | * |
| | | * @return The position of this reader. |
| | | */ |
| | | public int position() { |
| | | return pos; |
| | | } |
| | | |
| | | /** |
| | | * Sets this reader's position. |
| | | * |
| | | * @param pos |
| | | * The new position value; must be non-negative and no larger |
| | | * than the length of the underlying byte sequence. |
| | | * @throws IndexOutOfBoundsException |
| | | * If the position is negative or larger than the length of the |
| | | * underlying byte sequence. |
| | | */ |
| | | public void position(final int pos) { |
| | | if (pos > sequence.length() || pos < 0) { |
| | | throw new IndexOutOfBoundsException(); |
| | | } |
| | | |
| | | this.pos = pos; |
| | | } |
| | | |
| | | /** |
| | | * Returns the number of bytes between the current position and the end of the |
| | | * underlying byte sequence. |
| | | * |
| | | * @return The number of bytes between the current position and the end of the |
| | | * underlying byte sequence. |
| | | */ |
| | | public int remaining() |
| | | { |
| | | return sequence.length() - pos; |
| | | } |
| | | /** |
| | | * Returns the number of bytes between the current position and the end of |
| | | * the underlying byte sequence. |
| | | * |
| | | * @return The number of bytes between the current position and the end of |
| | | * the underlying byte sequence. |
| | | */ |
| | | public int remaining() { |
| | | return sequence.length() - pos; |
| | | } |
| | | |
| | | /** |
| | | * Rewinds this reader's position to zero. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.rewind(); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.position(0); |
| | | * </pre> |
| | | */ |
| | | public void rewind() { |
| | | position(0); |
| | | } |
| | | |
| | | /** |
| | | * Skips the given number of bytes. Negative values are allowed. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.skip(length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.position(position() + length); |
| | | * </pre> |
| | | * |
| | | * @param length |
| | | * The number of bytes to skip. |
| | | * @throws IndexOutOfBoundsException |
| | | * If the new position is less than 0 or greater than the length |
| | | * of the underlying byte sequence. |
| | | */ |
| | | public void skip(final int length) { |
| | | position(pos + length); |
| | | } |
| | | |
| | | /** |
| | | * Rewinds this reader's position to zero. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.rewind(); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.position(0); |
| | | * </pre> |
| | | */ |
| | | public void rewind() |
| | | { |
| | | position(0); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * Skips the given number of bytes. Negative values are allowed. |
| | | * <p> |
| | | * An invocation of this method of the form: |
| | | * |
| | | * <pre> |
| | | * src.skip(length); |
| | | * </pre> |
| | | * |
| | | * Has exactly the same effect as: |
| | | * |
| | | * <pre> |
| | | * src.position(position() + length); |
| | | * </pre> |
| | | * |
| | | * @param length |
| | | * The number of bytes to skip. |
| | | * @throws IndexOutOfBoundsException |
| | | * If the new position is less than 0 or greater than the length of |
| | | * the underlying byte sequence. |
| | | */ |
| | | public void skip(final int length) |
| | | { |
| | | position(pos + length); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() |
| | | { |
| | | return sequence.toString(); |
| | | } |
| | | /** |
| | | * {@inheritDoc} |
| | | */ |
| | | @Override |
| | | public String toString() { |
| | | return sequence.toString(); |
| | | } |
| | | } |