From 263d085885df024dca9250cc03c807912b0a7662 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 24 Apr 2012 22:33:21 +0000
Subject: [PATCH] Reformat to comply with new Checkstyle rules.
---
opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java | 1990 +++++++++++++++++++++++++--------------------------------
1 files changed, 874 insertions(+), 1,116 deletions(-)
diff --git a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
index f709bf3..6ecfd05 100755
--- a/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
+++ b/opendj3/opendj-ldap-sdk/src/main/java/org/forgerock/opendj/ldap/ByteStringBuilder.java
@@ -6,17 +6,16 @@
* (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
@@ -27,8 +26,6 @@
*/
package org.forgerock.opendj.ldap;
-
-
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -39,1146 +36,907 @@
import com.forgerock.opendj.util.StaticUtils;
-
-
/**
* A mutable sequence of bytes backed by a byte array.
*/
-public final class ByteStringBuilder implements ByteSequence
-{
-
- /**
- * A sub-sequence of the parent byte string builder. The sub-sequence will be
- * robust against all updates to the byte string builder except for
- * invocations of the method {@code clear()}.
- */
- private final class SubSequence implements ByteSequence
- {
-
- // The length of the sub-sequence.
- private final int subLength;
-
- // The offset of the sub-sequence.
- private final int subOffset;
-
-
+public final class ByteStringBuilder implements ByteSequence {
/**
- * Creates a new sub-sequence.
+ * A sub-sequence of the parent byte string builder. The sub-sequence will
+ * be robust against all updates to the byte string builder except for
+ * invocations of the method {@code clear()}.
+ */
+ private final class SubSequence implements ByteSequence {
+
+ // The length of the sub-sequence.
+ private final int subLength;
+
+ // The offset of the sub-sequence.
+ private final int subOffset;
+
+ /**
+ * Creates a new sub-sequence.
+ *
+ * @param offset
+ * The offset of the sub-sequence.
+ * @param length
+ * The length of the sub-sequence.
+ */
+ private SubSequence(final int offset, final int length) {
+ this.subOffset = offset;
+ this.subLength = length;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteSequenceReader asReader() {
+ return new ByteSequenceReader(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte byteAt(final int index) {
+ if (index >= subLength || index < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // Protect against reallocation: use builder's buffer.
+ return buffer[subOffset + index];
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(final byte[] b, final int offset, final int length) {
+ ByteString.checkArrayBounds(b, offset, length);
+
+ // Protect against reallocation: use builder's buffer.
+ return ByteString.compareTo(buffer, subOffset, subLength, b, offset, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(final ByteSequence o) {
+ if (this == o) {
+ return 0;
+ }
+
+ // Protect against reallocation: use builder's buffer.
+ return -o.compareTo(buffer, subOffset, subLength);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] copyTo(final byte[] b) {
+ copyTo(b, 0);
+ return b;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] copyTo(final byte[] b, final int offset) {
+ if (offset < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ // Protect against reallocation: use builder's buffer.
+ System.arraycopy(buffer, subOffset, b, offset, Math.min(subLength, b.length - offset));
+ return b;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteStringBuilder copyTo(final ByteStringBuilder builder) {
+ // Protect against reallocation: use builder's buffer.
+ return builder.append(buffer, subOffset, subLength);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OutputStream copyTo(final OutputStream stream) throws IOException {
+ // Protect against reallocation: use builder's buffer.
+ stream.write(buffer, subOffset, subLength);
+ return stream;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(final byte[] b, final int offset, final int length) {
+ ByteString.checkArrayBounds(b, offset, length);
+
+ // Protect against reallocation: use builder's buffer.
+ return ByteString.equals(buffer, subOffset, subLength, b, offset, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ } else if (o instanceof ByteSequence) {
+ final ByteSequence other = (ByteSequence) o;
+
+ // Protect against reallocation: use builder's buffer.
+ return other.equals(buffer, subOffset, subLength);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public int hashCode() {
+ // Protect against reallocation: use builder's buffer.
+ return ByteString.hashCode(buffer, subOffset, subLength);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int length() {
+ return subLength;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteSequence subSequence(final int start, final int end) {
+ if (start < 0 || start > end || end > subLength) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ return new SubSequence(subOffset + start, end - start);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] toByteArray() {
+ return copyTo(new byte[subLength]);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteString toByteString() {
+ // Protect against reallocation: use builder's buffer.
+ final byte[] b = new byte[subLength];
+ System.arraycopy(buffer, subOffset, b, 0, subLength);
+ return ByteString.wrap(b);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ // Protect against reallocation: use builder's buffer.
+ return ByteString.toString(buffer, subOffset, subLength);
+ }
+ }
+
+ // These are package private so that compression and crypto
+ // functionality may directly access the fields.
+
+ // The buffer where data is stored.
+ byte[] buffer;
+
+ // The number of bytes to expose from the buffer.
+ int length;
+
+ /**
+ * Creates a new byte string builder with an initial capacity of 32 bytes.
+ */
+ public ByteStringBuilder() {
+ // Initially create a 32 byte buffer.
+ this(32);
+ }
+
+ /**
+ * Creates a new byte string builder with the specified initial capacity.
*
- * @param offset
- * The offset of the sub-sequence.
- * @param length
- * The length of the sub-sequence.
+ * @param capacity
+ * The initial capacity.
+ * @throws IllegalArgumentException
+ * If the {@code capacity} is negative.
*/
- private SubSequence(final int offset, final int length)
- {
- this.subOffset = offset;
- this.subLength = length;
+ public ByteStringBuilder(final int capacity) {
+ if (capacity < 0) {
+ throw new IllegalArgumentException();
+ }
+
+ this.buffer = new byte[capacity];
+ this.length = 0;
}
-
-
/**
- * {@inheritDoc}
+ * Appends the provided byte to this byte string builder.
+ *
+ * @param b
+ * The byte to be appended to this byte string builder.
+ * @return This byte string builder.
*/
- public ByteSequenceReader asReader()
- {
- return new ByteSequenceReader(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte byteAt(final int index)
- {
- if (index >= subLength || index < 0)
- {
- throw new IndexOutOfBoundsException();
- }
-
- // Protect against reallocation: use builder's buffer.
- return buffer[subOffset + index];
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int compareTo(final byte[] b, final int offset, final int length)
- {
- ByteString.checkArrayBounds(b, offset, length);
-
- // Protect against reallocation: use builder's buffer.
- return ByteString.compareTo(buffer, subOffset, subLength, b, offset,
- length);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int compareTo(final ByteSequence o)
- {
- if (this == o)
- {
- return 0;
- }
-
- // Protect against reallocation: use builder's buffer.
- return -o.compareTo(buffer, subOffset, subLength);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte[] copyTo(final byte[] b)
- {
- copyTo(b, 0);
- return b;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte[] copyTo(final byte[] b, final int offset)
- {
- if (offset < 0)
- {
- throw new IndexOutOfBoundsException();
- }
-
- // Protect against reallocation: use builder's buffer.
- System.arraycopy(buffer, subOffset, b, offset, Math.min(subLength,
- b.length - offset));
- return b;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ByteStringBuilder copyTo(final ByteStringBuilder builder)
- {
- // Protect against reallocation: use builder's buffer.
- return builder.append(buffer, subOffset, subLength);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public OutputStream copyTo(final OutputStream stream) throws IOException
- {
- // Protect against reallocation: use builder's buffer.
- stream.write(buffer, subOffset, subLength);
- return stream;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean equals(final byte[] b, final int offset, final int length)
- {
- ByteString.checkArrayBounds(b, offset, length);
-
- // Protect against reallocation: use builder's buffer.
- return ByteString.equals(buffer, subOffset, subLength, b, offset, length);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public boolean equals(final Object o)
- {
- if (this == o)
- {
- return true;
- }
- else if (o instanceof ByteSequence)
- {
- final ByteSequence other = (ByteSequence) o;
-
- // Protect against reallocation: use builder's buffer.
- return other.equals(buffer, subOffset, subLength);
- }
- else
- {
- return false;
- }
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int hashCode()
- {
- // Protect against reallocation: use builder's buffer.
- return ByteString.hashCode(buffer, subOffset, subLength);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int length()
- {
- return subLength;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ByteSequence subSequence(final int start, final int end)
- {
- if (start < 0 || start > end || end > subLength)
- {
- throw new IndexOutOfBoundsException();
- }
-
- return new SubSequence(subOffset + start, end - start);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte[] toByteArray()
- {
- return copyTo(new byte[subLength]);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ByteString toByteString()
- {
- // Protect against reallocation: use builder's buffer.
- final byte[] b = new byte[subLength];
- System.arraycopy(buffer, subOffset, b, 0, subLength);
- return ByteString.wrap(b);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString()
- {
- // Protect against reallocation: use builder's buffer.
- return ByteString.toString(buffer, subOffset, subLength);
- }
- }
-
-
-
- // These are package private so that compression and crypto
- // functionality may directly access the fields.
-
- // The buffer where data is stored.
- byte[] buffer;
-
- // The number of bytes to expose from the buffer.
- int length;
-
-
-
- /**
- * Creates a new byte string builder with an initial capacity of 32 bytes.
- */
- public ByteStringBuilder()
- {
- // Initially create a 32 byte buffer.
- this(32);
- }
-
-
-
- /**
- * Creates a new byte string builder with the specified initial capacity.
- *
- * @param capacity
- * The initial capacity.
- * @throws IllegalArgumentException
- * If the {@code capacity} is negative.
- */
- public ByteStringBuilder(final int capacity)
- {
- if (capacity < 0)
- {
- throw new IllegalArgumentException();
- }
-
- this.buffer = new byte[capacity];
- this.length = 0;
- }
-
-
-
- /**
- * Appends the provided byte to this byte string builder.
- *
- * @param b
- * The byte to be appended to this byte string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final byte b)
- {
- ensureAdditionalCapacity(1);
- buffer[length++] = b;
- return this;
- }
-
-
-
- /**
- * Appends the provided byte array to this byte string builder.
- * <p>
- * An invocation of the form:
- *
- * <pre>
- * src.append(bytes)
- * </pre>
- *
- * Behaves in exactly the same way as the invocation:
- *
- * <pre>
- * src.append(bytes, 0, bytes.length);
- * </pre>
- *
- * @param bytes
- * The byte array to be appended to this byte string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final byte[] bytes)
- {
- return append(bytes, 0, bytes.length);
- }
-
-
-
- /**
- * Appends the provided byte array to this byte string builder.
- *
- * @param bytes
- * The byte array to be appended to this byte string builder.
- * @param offset
- * The offset of the byte array to be used; must be non-negative and
- * no larger than {@code bytes.length} .
- * @param length
- * The length of the byte array to be used; must be non-negative and
- * no larger than {@code bytes.length - offset}.
- * @return This byte string builder.
- * @throws IndexOutOfBoundsException
- * If {@code offset} is negative or if {@code length} is negative or
- * if {@code offset + length} is greater than {@code bytes.length}.
- */
- public ByteStringBuilder append(final byte[] bytes, final int offset,
- final int length)
- {
- ByteString.checkArrayBounds(bytes, offset, length);
-
- if (length != 0)
- {
- ensureAdditionalCapacity(length);
- System.arraycopy(bytes, offset, buffer, this.length, length);
- this.length += length;
- }
-
- return this;
- }
-
-
-
- /**
- * Appends the provided {@code ByteBuffer} to this byte string builder.
- *
- * @param buffer
- * The byte buffer to be appended to this byte string builder.
- * @param length
- * The number of bytes to be appended from {@code buffer}.
- * @return This byte string builder.
- * @throws IndexOutOfBoundsException
- * If {@code length} is less than zero or greater than {@code
- * buffer.remaining()}.
- */
- public ByteStringBuilder append(final ByteBuffer buffer, final int length)
- {
- if (length < 0 || length > buffer.remaining())
- {
- throw new IndexOutOfBoundsException();
- }
-
- if (length != 0)
- {
- ensureAdditionalCapacity(length);
- buffer.get(this.buffer, this.length, length);
- this.length += length;
- }
-
- return this;
- }
-
-
-
- /**
- * Appends the provided {@link ByteSequence} to this byte string builder.
- *
- * @param bytes
- * The byte sequence to be appended to this byte string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final ByteSequence bytes)
- {
- return bytes.copyTo(this);
- }
-
-
-
- /**
- * Appends the provided {@link ByteSequenceReader} to this byte string
- * builder.
- *
- * @param reader
- * The byte sequence reader to be appended to this byte string
- * builder.
- * @param length
- * The number of bytes to be appended from {@code reader}.
- * @return This byte string builder.
- * @throws IndexOutOfBoundsException
- * If {@code length} is less than zero or greater than {@code
- * reader.remaining()}.
- */
- public ByteStringBuilder append(final ByteSequenceReader reader,
- final int length)
- {
- if (length < 0 || length > reader.remaining())
- {
- throw new IndexOutOfBoundsException();
- }
-
- if (length != 0)
- {
- ensureAdditionalCapacity(length);
- reader.get(buffer, this.length, length);
- this.length += length;
- }
-
- return this;
- }
-
-
-
- /**
- * Appends the UTF-8 encoded bytes of the provided
- * char array to this byte string
- * builder.
- *
- * @param chars
- * The char array whose UTF-8 encoding is to be appended to this byte
- * string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final char[] chars)
- {
- if (chars == null)
- {
- return this;
- }
-
- // Assume that each char is 1 byte
- final int len = chars.length;
- ensureAdditionalCapacity(len);
-
- for (int i = 0; i < len; i++)
- {
- final char c = chars[i];
- final byte b = (byte) (c & 0x0000007F);
-
- if (c == b)
- {
- buffer[this.length + i] = b;
- }
- else
- {
- // There is a multi-byte char. Defer to JDK.
- final Charset utf8 = Charset.forName("UTF-8");
- final ByteBuffer byteBuffer = utf8.encode(CharBuffer.wrap(chars));
- final int remaining = byteBuffer.remaining();
- ensureAdditionalCapacity(remaining - len);
- byteBuffer.get(buffer, this.length, remaining);
- this.length += remaining;
+ public ByteStringBuilder append(final byte b) {
+ ensureAdditionalCapacity(1);
+ buffer[length++] = b;
return this;
- }
}
- // The 1 byte char assumption was correct
- this.length += len;
- return this;
-
- }
-
-
-
- /**
- * Appends the provided {@code InputStream} to this byte string builder.
- *
- * @param stream
- * The input stream to be appended to this byte string builder.
- * @param length
- * The maximum number of bytes to be appended from {@code buffer}.
- * @return The number of bytes read from the input stream, or {@code -1} if
- * the end of the input stream has been reached.
- * @throws IndexOutOfBoundsException
- * If {@code length} is less than zero.
- * @throws IOException
- * If an I/O error occurs.
- */
- public int append(final InputStream stream, final int length)
- throws IOException
- {
- if (length < 0)
- {
- throw new IndexOutOfBoundsException();
+ /**
+ * Appends the provided byte array to this byte string builder.
+ * <p>
+ * An invocation of the form:
+ *
+ * <pre>
+ * src.append(bytes)
+ * </pre>
+ *
+ * Behaves in exactly the same way as the invocation:
+ *
+ * <pre>
+ * src.append(bytes, 0, bytes.length);
+ * </pre>
+ *
+ * @param bytes
+ * The byte array to be appended to this byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final byte[] bytes) {
+ return append(bytes, 0, bytes.length);
}
- ensureAdditionalCapacity(length);
- final int bytesRead = stream.read(buffer, this.length, length);
- if (bytesRead > 0)
- {
- this.length += bytesRead;
- }
+ /**
+ * Appends the provided byte array to this byte string builder.
+ *
+ * @param bytes
+ * The byte array to be appended to this byte string builder.
+ * @param offset
+ * The offset of the byte array to be used; must be non-negative
+ * and no larger than {@code bytes.length} .
+ * @param length
+ * The length of the byte array to be used; must be non-negative
+ * and no larger than {@code bytes.length - offset}.
+ * @return This byte string builder.
+ * @throws IndexOutOfBoundsException
+ * If {@code offset} is negative or if {@code length} is
+ * negative or if {@code offset + length} is greater than
+ * {@code bytes.length}.
+ */
+ public ByteStringBuilder append(final byte[] bytes, final int offset, final int length) {
+ ByteString.checkArrayBounds(bytes, offset, length);
- return bytesRead;
- }
-
-
-
- /**
- * Appends the big-endian encoded bytes of the provided integer to this byte
- * string builder.
- *
- * @param i
- * The integer whose big-endian encoding is to be appended to this
- * byte string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(int i)
- {
- ensureAdditionalCapacity(4);
- for (int j = length + 3; j >= length; j--)
- {
- buffer[j] = (byte) (i & 0xFF);
- i >>>= 8;
- }
- length += 4;
- return this;
- }
-
-
-
- /**
- * Appends the big-endian encoded bytes of the provided long to this byte
- * string builder.
- *
- * @param l
- * The long whose big-endian encoding is to be appended to this byte
- * string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(long l)
- {
- ensureAdditionalCapacity(8);
- for (int i = length + 7; i >= length; i--)
- {
- buffer[i] = (byte) (l & 0xFF);
- l >>>= 8;
- }
- length += 8;
- return this;
- }
-
-
-
- /**
- * Appends the byte string representation of the provided object to this byte
- * string builder. The object is converted to a byte string as follows:
- * <ul>
- * <li>if the object is an instance of {@code ByteSequence} then this method
- * is equivalent to calling {@link #append(ByteSequence)}
- * <li>if the object is a {@code byte[]} then this method is equivalent to
- * calling {@link #append(byte[])}
- * <li>if the object is a {@code char[]} then this method is equivalent to
- * calling {@link #append(char[])}
- * <li>for all other types of object this method is equivalent to calling
- * {@link #append(String)} with the {@code toString()} representation of the
- * provided object.
- * </ul>
- * <b>Note:</b> this method treats {@code Long} and {@code Integer} objects
- * like any other type of {@code Object}. More specifically, the following
- * invocations are not equivalent:
- * <ul>
- * <li>{@code append(0)} is not equivalent to {@code append((Object) 0)}
- * <li>{@code append(0L)} is not equivalent to {@code append((Object) 0L)}
- * </ul>
- *
- * @param o
- * The object to be appended to this byte string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final Object o)
- {
- if (o == null)
- {
- return this;
- }
- else if (o instanceof ByteSequence)
- {
- return append((ByteSequence) o);
- }
- else if (o instanceof byte[])
- {
- return append((byte[]) o);
- }
- else if (o instanceof char[])
- {
- return append((char[]) o);
- }
- else
- {
- return append(o.toString());
- }
- }
-
-
-
- /**
- * Appends the big-endian encoded bytes of the provided short to this byte
- * string builder.
- *
- * @param i
- * The short whose big-endian encoding is to be appended to this byte
- * string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(short i)
- {
- ensureAdditionalCapacity(2);
- for (int j = length + 1; j >= length; j--)
- {
- buffer[j] = (byte) (i & 0xFF);
- i >>>= 8;
- }
- length += 2;
- return this;
- }
-
-
-
- /**
- * Appends the UTF-8 encoded bytes of the provided string to this byte string
- * builder.
- *
- * @param s
- * The string whose UTF-8 encoding is to be appended to this byte
- * string builder.
- * @return This byte string builder.
- */
- public ByteStringBuilder append(final String s)
- {
- if (s == null)
- {
- return this;
- }
-
- // Assume that each char is 1 byte
- final int len = s.length();
- ensureAdditionalCapacity(len);
-
- for (int i = 0; i < len; i++)
- {
- final char c = s.charAt(i);
- final byte b = (byte) (c & 0x0000007F);
-
- if (c == b)
- {
- buffer[this.length + i] = b;
- }
- else
- {
- // There is a multi-byte char. Defer to JDK
- try
- {
- return append(s.getBytes("UTF-8"));
+ if (length != 0) {
+ ensureAdditionalCapacity(length);
+ System.arraycopy(bytes, offset, buffer, this.length, length);
+ this.length += length;
}
- catch (final Exception e)
- {
- if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING))
- {
- StaticUtils.DEBUG_LOG.warning("Unable to encode String "
- + "to UTF-8 bytes: " + e.toString());
- }
- return append(s.getBytes());
+ return this;
+ }
+
+ /**
+ * Appends the provided {@code ByteBuffer} to this byte string builder.
+ *
+ * @param buffer
+ * The byte buffer to be appended to this byte string builder.
+ * @param length
+ * The number of bytes to be appended from {@code buffer}.
+ * @return This byte string builder.
+ * @throws IndexOutOfBoundsException
+ * If {@code length} is less than zero or greater than
+ * {@code buffer.remaining()}.
+ */
+ public ByteStringBuilder append(final ByteBuffer buffer, final int length) {
+ if (length < 0 || length > buffer.remaining()) {
+ throw new IndexOutOfBoundsException();
}
- }
+
+ if (length != 0) {
+ ensureAdditionalCapacity(length);
+ buffer.get(this.buffer, this.length, length);
+ this.length += length;
+ }
+
+ return this;
}
- // The 1 byte char assumption was correct
- this.length += len;
- return this;
- }
-
-
-
- /**
- * Appends the ASN.1 BER length encoding representation of the provided
- * integer to this byte string builder.
- *
- * @param length
- * The value to encode using the BER length encoding rules.
- * @return This byte string builder.
- */
- public ByteStringBuilder appendBERLength(final int length)
- {
- if ((length & 0x0000007F) == length)
- {
- ensureAdditionalCapacity(1);
-
- buffer[this.length++] = (byte) (length & 0xFF);
- }
- else if ((length & 0x000000FF) == length)
- {
- ensureAdditionalCapacity(2);
-
- buffer[this.length++] = (byte) 0x81;
- buffer[this.length++] = (byte) (length & 0xFF);
- }
- else if ((length & 0x0000FFFF) == length)
- {
- ensureAdditionalCapacity(3);
-
- buffer[this.length++] = (byte) 0x82;
- buffer[this.length++] = (byte) (length >> 8 & 0xFF);
- buffer[this.length++] = (byte) (length & 0xFF);
- }
- else if ((length & 0x00FFFFFF) == length)
- {
- ensureAdditionalCapacity(4);
-
- buffer[this.length++] = (byte) 0x83;
- buffer[this.length++] = (byte) (length >> 16 & 0xFF);
- buffer[this.length++] = (byte) (length >> 8 & 0xFF);
- buffer[this.length++] = (byte) (length & 0xFF);
- }
- else
- {
- ensureAdditionalCapacity(5);
-
- buffer[this.length++] = (byte) 0x84;
- buffer[this.length++] = (byte) (length >> 24 & 0xFF);
- buffer[this.length++] = (byte) (length >> 16 & 0xFF);
- buffer[this.length++] = (byte) (length >> 8 & 0xFF);
- buffer[this.length++] = (byte) (length & 0xFF);
- }
- return this;
- }
-
-
-
- /**
- * Returns a {@link ByteSequenceReader} which can be used to incrementally
- * read and decode data from this byte string builder.
- * <p>
- * <b>NOTE:</b> all concurrent updates to this byte string builder are
- * supported with the exception of {@link #clear()}. Any invocations of
- * {@link #clear()} must be accompanied by a subsequent call to {@code
- * ByteSequenceReader.rewind()}.
- *
- * @return The {@link ByteSequenceReader} which can be used to incrementally
- * read and decode data from this byte string builder.
- * @see #clear()
- */
- public ByteSequenceReader asReader()
- {
- return new ByteSequenceReader(this);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte byteAt(final int index)
- {
- if (index >= length || index < 0)
- {
- throw new IndexOutOfBoundsException();
- }
- return buffer[index];
- }
-
-
-
- /**
- * Sets the length of this byte string builder to zero.
- * <p>
- * <b>NOTE:</b> if this method is called, then {@code
- * ByteSequenceReader.rewind()} must also be called on any associated byte
- * sequence readers in order for them to remain valid.
- *
- * @return This byte string builder.
- * @see #asReader()
- */
- public ByteStringBuilder clear()
- {
- length = 0;
- return this;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int compareTo(final byte[] bytes, final int offset, final int length)
- {
- ByteString.checkArrayBounds(bytes, offset, length);
- return ByteString.compareTo(this.buffer, 0, this.length, bytes, offset,
- length);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int compareTo(final ByteSequence o)
- {
- if (this == o)
- {
- return 0;
- }
- return -o.compareTo(buffer, 0, length);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte[] copyTo(final byte[] bytes)
- {
- copyTo(bytes, 0);
- return bytes;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public byte[] copyTo(final byte[] bytes, final int offset)
- {
- if (offset < 0)
- {
- throw new IndexOutOfBoundsException();
- }
- System.arraycopy(buffer, 0, bytes, offset,
- Math.min(length, bytes.length - offset));
- return bytes;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public ByteStringBuilder copyTo(final ByteStringBuilder builder)
- {
- builder.append(buffer, 0, length);
- return builder;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public OutputStream copyTo(final OutputStream stream) throws IOException
- {
- stream.write(buffer, 0, length);
- return stream;
- }
-
-
-
- /**
- * Ensures that the specified number of additional bytes will fit in this byte
- * string builder and resizes it if necessary.
- *
- * @param size
- * The number of additional bytes.
- * @return This byte string builder.
- */
- public ByteStringBuilder ensureAdditionalCapacity(final int size)
- {
- final int newCount = this.length + size;
- if (newCount > buffer.length)
- {
- final byte[] newbuffer = new byte[Math.max(buffer.length << 1, newCount)];
- System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
- buffer = newbuffer;
- }
- return this;
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public boolean equals(final byte[] bytes, final int offset, final int length)
- {
- ByteString.checkArrayBounds(bytes, offset, length);
- return ByteString
- .equals(this.buffer, 0, this.length, bytes, offset, length);
- }
-
-
-
- /**
- * Indicates whether the provided object is equal to this byte string builder.
- * In order for it to be considered equal, the provided object must be a byte
- * sequence containing the same bytes in the same order.
- *
- * @param o
- * The object for which to make the determination.
- * @return {@code true} if the provided object is a byte sequence whose
- * content is equal to that of this byte string builder, or {@code
- * false} if not.
- */
- @Override
- public boolean equals(final Object o)
- {
- if (this == o)
- {
- return true;
- }
- else if (o instanceof ByteSequence)
- {
- final ByteSequence other = (ByteSequence) o;
- return other.equals(buffer, 0, length);
- }
- else
- {
- return false;
- }
- }
-
-
-
- /**
- * Returns the byte array that backs this byte string builder. Modifications
- * to this byte string builder's content may cause the returned array's
- * content to be modified, and vice versa.
- * <p>
- * Note that the length of the returned array is only guaranteed to be the
- * same as the length of this byte string builder immediately after a call to
- * {@link #trimToSize()}.
- * <p>
- * In addition, subsequent modifications to this byte string builder may cause
- * the backing byte array to be reallocated thus decoupling the returned byte
- * array from this byte string builder.
- *
- * @return The byte array that backs this byte string builder.
- */
- public byte[] getBackingArray()
- {
- return buffer;
- }
-
-
-
- /**
- * Returns a hash code for this byte string builder. It will be the sum of all
- * of the bytes contained in the byte string builder.
- * <p>
- * <b>NOTE:</b> subsequent changes to this byte string builder will invalidate
- * the returned hash code.
- *
- * @return A hash code for this byte string builder.
- */
- @Override
- public int hashCode()
- {
- return ByteString.hashCode(buffer, 0, length);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- public int length()
- {
- return length;
- }
-
-
-
- /**
- * Sets the length of this byte string builder.
- * <p>
- * If the <code>newLength</code> argument is less than the current length, the
- * length is changed to the specified length.
- * <p>
- * If the <code>newLength</code> argument is greater than or equal to the
- * current length, then the capacity is increased and sufficient null bytes
- * are appended so that length becomes the <code>newLength</code> argument.
- * <p>
- * The <code>newLength</code> argument must be greater than or equal to
- * <code>0</code>.
- *
- * @param newLength
- * The new length.
- * @return This byte string builder.
- * @throws IndexOutOfBoundsException
- * If the <code>newLength</code> argument is negative.
- */
- public ByteStringBuilder setLength(final int newLength)
- {
- if (newLength < 0)
- {
- throw new IndexOutOfBoundsException("Negative newLength: " + newLength);
+ /**
+ * Appends the provided {@link ByteSequence} to this byte string builder.
+ *
+ * @param bytes
+ * The byte sequence to be appended to this byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final ByteSequence bytes) {
+ return bytes.copyTo(this);
}
- if (newLength > length)
- {
- ensureAdditionalCapacity(newLength - length);
+ /**
+ * Appends the provided {@link ByteSequenceReader} to this byte string
+ * builder.
+ *
+ * @param reader
+ * The byte sequence reader to be appended to this byte string
+ * builder.
+ * @param length
+ * The number of bytes to be appended from {@code reader}.
+ * @return This byte string builder.
+ * @throws IndexOutOfBoundsException
+ * If {@code length} is less than zero or greater than
+ * {@code reader.remaining()}.
+ */
+ public ByteStringBuilder append(final ByteSequenceReader reader, final int length) {
+ if (length < 0 || length > reader.remaining()) {
+ throw new IndexOutOfBoundsException();
+ }
- // Pad with zeros.
- for (int i = length; i < newLength; i++)
- {
- buffer[i] = 0;
- }
- }
- length = newLength;
+ if (length != 0) {
+ ensureAdditionalCapacity(length);
+ reader.get(buffer, this.length, length);
+ this.length += length;
+ }
- return this;
- }
-
-
-
- /**
- * Returns a new byte sequence that is a subsequence of this byte sequence.
- * <p>
- * The subsequence starts with the byte value at the specified {@code start}
- * index and ends with the byte value at index {@code end - 1}. The length (in
- * bytes) of the returned sequence is {@code end - start}, so if {@code start
- * == end} then an empty sequence is returned.
- * <p>
- * <b>NOTE:</b> the returned sub-sequence will be robust against all updates
- * to the byte string builder except for invocations of the method
- * {@link #clear()}. If a permanent immutable byte sequence is required then
- * callers should invoke {@code toByteString()} on the returned byte sequence.
- *
- * @param start
- * The start index, inclusive.
- * @param end
- * The end index, exclusive.
- * @return The newly created byte subsequence.
- */
- public ByteSequence subSequence(final int start, final int end)
- {
- if (start < 0 || start > end || end > length)
- {
- throw new IndexOutOfBoundsException();
+ return this;
}
- return new SubSequence(start, end - start);
- }
+ /**
+ * Appends the UTF-8 encoded bytes of the provided char array to this byte
+ * string builder.
+ *
+ * @param chars
+ * The char array whose UTF-8 encoding is to be appended to this
+ * byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final char[] chars) {
+ if (chars == null) {
+ return this;
+ }
+ // Assume that each char is 1 byte
+ final int len = chars.length;
+ ensureAdditionalCapacity(len);
+ for (int i = 0; i < len; i++) {
+ final char c = chars[i];
+ final byte b = (byte) (c & 0x0000007F);
- /**
- * {@inheritDoc}
- */
- public byte[] toByteArray()
- {
- return copyTo(new byte[length]);
- }
+ if (c == b) {
+ buffer[this.length + i] = b;
+ } else {
+ // There is a multi-byte char. Defer to JDK.
+ final Charset utf8 = Charset.forName("UTF-8");
+ final ByteBuffer byteBuffer = utf8.encode(CharBuffer.wrap(chars));
+ final int remaining = byteBuffer.remaining();
+ ensureAdditionalCapacity(remaining - len);
+ byteBuffer.get(buffer, this.length, remaining);
+ this.length += remaining;
+ return this;
+ }
+ }
+ // The 1 byte char assumption was correct
+ this.length += len;
+ return this;
-
- /**
- * Returns the {@link ByteString} representation of this byte string builder.
- * Subsequent changes to this byte string builder will not modify the returned
- * {@link ByteString}.
- *
- * @return The {@link ByteString} representation of this byte sequence.
- */
- public ByteString toByteString()
- {
- final byte[] b = new byte[length];
- System.arraycopy(buffer, 0, b, 0, length);
- return ByteString.wrap(b);
- }
-
-
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String toString()
- {
- return ByteString.toString(buffer, 0, length);
- }
-
-
-
- /**
- * Attempts to reduce storage used for this byte string builder. If the buffer
- * is larger than necessary to hold its current sequence of bytes, then it may
- * be resized to become more space efficient.
- *
- * @return This byte string builder.
- */
- public ByteStringBuilder trimToSize()
- {
- if (buffer.length > length)
- {
- final byte[] newBuffer = new byte[length];
- System.arraycopy(buffer, 0, newBuffer, 0, length);
- buffer = newBuffer;
}
- return this;
- }
+
+ /**
+ * Appends the provided {@code InputStream} to this byte string builder.
+ *
+ * @param stream
+ * The input stream to be appended to this byte string builder.
+ * @param length
+ * The maximum number of bytes to be appended from {@code buffer}
+ * .
+ * @return The number of bytes read from the input stream, or {@code -1} if
+ * the end of the input stream has been reached.
+ * @throws IndexOutOfBoundsException
+ * If {@code length} is less than zero.
+ * @throws IOException
+ * If an I/O error occurs.
+ */
+ public int append(final InputStream stream, final int length) throws IOException {
+ if (length < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ ensureAdditionalCapacity(length);
+ final int bytesRead = stream.read(buffer, this.length, length);
+ if (bytesRead > 0) {
+ this.length += bytesRead;
+ }
+
+ return bytesRead;
+ }
+
+ /**
+ * Appends the big-endian encoded bytes of the provided integer to this byte
+ * string builder.
+ *
+ * @param i
+ * The integer whose big-endian encoding is to be appended to
+ * this byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(int i) {
+ ensureAdditionalCapacity(4);
+ for (int j = length + 3; j >= length; j--) {
+ buffer[j] = (byte) (i & 0xFF);
+ i >>>= 8;
+ }
+ length += 4;
+ return this;
+ }
+
+ /**
+ * Appends the big-endian encoded bytes of the provided long to this byte
+ * string builder.
+ *
+ * @param l
+ * The long whose big-endian encoding is to be appended to this
+ * byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(long l) {
+ ensureAdditionalCapacity(8);
+ for (int i = length + 7; i >= length; i--) {
+ buffer[i] = (byte) (l & 0xFF);
+ l >>>= 8;
+ }
+ length += 8;
+ return this;
+ }
+
+ /**
+ * Appends the byte string representation of the provided object to this
+ * byte string builder. The object is converted to a byte string as follows:
+ * <ul>
+ * <li>if the object is an instance of {@code ByteSequence} then this method
+ * is equivalent to calling {@link #append(ByteSequence)}
+ * <li>if the object is a {@code byte[]} then this method is equivalent to
+ * calling {@link #append(byte[])}
+ * <li>if the object is a {@code char[]} then this method is equivalent to
+ * calling {@link #append(char[])}
+ * <li>for all other types of object this method is equivalent to calling
+ * {@link #append(String)} with the {@code toString()} representation of the
+ * provided object.
+ * </ul>
+ * <b>Note:</b> this method treats {@code Long} and {@code Integer} objects
+ * like any other type of {@code Object}. More specifically, the following
+ * invocations are not equivalent:
+ * <ul>
+ * <li>{@code append(0)} is not equivalent to {@code append((Object) 0)}
+ * <li>{@code append(0L)} is not equivalent to {@code append((Object) 0L)}
+ * </ul>
+ *
+ * @param o
+ * The object to be appended to this byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final Object o) {
+ if (o == null) {
+ return this;
+ } else if (o instanceof ByteSequence) {
+ return append((ByteSequence) o);
+ } else if (o instanceof byte[]) {
+ return append((byte[]) o);
+ } else if (o instanceof char[]) {
+ return append((char[]) o);
+ } else {
+ return append(o.toString());
+ }
+ }
+
+ /**
+ * Appends the big-endian encoded bytes of the provided short to this byte
+ * string builder.
+ *
+ * @param i
+ * The short whose big-endian encoding is to be appended to this
+ * byte string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(short i) {
+ ensureAdditionalCapacity(2);
+ for (int j = length + 1; j >= length; j--) {
+ buffer[j] = (byte) (i & 0xFF);
+ i >>>= 8;
+ }
+ length += 2;
+ return this;
+ }
+
+ /**
+ * Appends the UTF-8 encoded bytes of the provided string to this byte
+ * string builder.
+ *
+ * @param s
+ * The string whose UTF-8 encoding is to be appended to this byte
+ * string builder.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder append(final String s) {
+ if (s == null) {
+ return this;
+ }
+
+ // Assume that each char is 1 byte
+ final int len = s.length();
+ ensureAdditionalCapacity(len);
+
+ for (int i = 0; i < len; i++) {
+ final char c = s.charAt(i);
+ final byte b = (byte) (c & 0x0000007F);
+
+ if (c == b) {
+ buffer[this.length + i] = b;
+ } else {
+ // There is a multi-byte char. Defer to JDK
+ try {
+ return append(s.getBytes("UTF-8"));
+ } catch (final Exception e) {
+ if (StaticUtils.DEBUG_LOG.isLoggable(Level.WARNING)) {
+ StaticUtils.DEBUG_LOG.warning("Unable to encode String "
+ + "to UTF-8 bytes: " + e.toString());
+ }
+
+ return append(s.getBytes());
+ }
+ }
+ }
+
+ // The 1 byte char assumption was correct
+ this.length += len;
+ return this;
+ }
+
+ /**
+ * Appends the ASN.1 BER length encoding representation of the provided
+ * integer to this byte string builder.
+ *
+ * @param length
+ * The value to encode using the BER length encoding rules.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder appendBERLength(final int length) {
+ if ((length & 0x0000007F) == length) {
+ ensureAdditionalCapacity(1);
+
+ buffer[this.length++] = (byte) (length & 0xFF);
+ } else if ((length & 0x000000FF) == length) {
+ ensureAdditionalCapacity(2);
+
+ buffer[this.length++] = (byte) 0x81;
+ buffer[this.length++] = (byte) (length & 0xFF);
+ } else if ((length & 0x0000FFFF) == length) {
+ ensureAdditionalCapacity(3);
+
+ buffer[this.length++] = (byte) 0x82;
+ buffer[this.length++] = (byte) (length >> 8 & 0xFF);
+ buffer[this.length++] = (byte) (length & 0xFF);
+ } else if ((length & 0x00FFFFFF) == length) {
+ ensureAdditionalCapacity(4);
+
+ buffer[this.length++] = (byte) 0x83;
+ buffer[this.length++] = (byte) (length >> 16 & 0xFF);
+ buffer[this.length++] = (byte) (length >> 8 & 0xFF);
+ buffer[this.length++] = (byte) (length & 0xFF);
+ } else {
+ ensureAdditionalCapacity(5);
+
+ buffer[this.length++] = (byte) 0x84;
+ buffer[this.length++] = (byte) (length >> 24 & 0xFF);
+ buffer[this.length++] = (byte) (length >> 16 & 0xFF);
+ buffer[this.length++] = (byte) (length >> 8 & 0xFF);
+ buffer[this.length++] = (byte) (length & 0xFF);
+ }
+ return this;
+ }
+
+ /**
+ * Returns a {@link ByteSequenceReader} which can be used to incrementally
+ * read and decode data from this byte string builder.
+ * <p>
+ * <b>NOTE:</b> all concurrent updates to this byte string builder are
+ * supported with the exception of {@link #clear()}. Any invocations of
+ * {@link #clear()} must be accompanied by a subsequent call to
+ * {@code ByteSequenceReader.rewind()}.
+ *
+ * @return The {@link ByteSequenceReader} which can be used to incrementally
+ * read and decode data from this byte string builder.
+ * @see #clear()
+ */
+ public ByteSequenceReader asReader() {
+ return new ByteSequenceReader(this);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte byteAt(final int index) {
+ if (index >= length || index < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ return buffer[index];
+ }
+
+ /**
+ * Sets the length of this byte string builder to zero.
+ * <p>
+ * <b>NOTE:</b> if this method is called, then
+ * {@code ByteSequenceReader.rewind()} must also be called on any associated
+ * byte sequence readers in order for them to remain valid.
+ *
+ * @return This byte string builder.
+ * @see #asReader()
+ */
+ public ByteStringBuilder clear() {
+ length = 0;
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(final byte[] bytes, final int offset, final int length) {
+ ByteString.checkArrayBounds(bytes, offset, length);
+ return ByteString.compareTo(this.buffer, 0, this.length, bytes, offset, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int compareTo(final ByteSequence o) {
+ if (this == o) {
+ return 0;
+ }
+ return -o.compareTo(buffer, 0, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] copyTo(final byte[] bytes) {
+ copyTo(bytes, 0);
+ return bytes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] copyTo(final byte[] bytes, final int offset) {
+ if (offset < 0) {
+ throw new IndexOutOfBoundsException();
+ }
+ System.arraycopy(buffer, 0, bytes, offset, Math.min(length, bytes.length - offset));
+ return bytes;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public ByteStringBuilder copyTo(final ByteStringBuilder builder) {
+ builder.append(buffer, 0, length);
+ return builder;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public OutputStream copyTo(final OutputStream stream) throws IOException {
+ stream.write(buffer, 0, length);
+ return stream;
+ }
+
+ /**
+ * Ensures that the specified number of additional bytes will fit in this
+ * byte string builder and resizes it if necessary.
+ *
+ * @param size
+ * The number of additional bytes.
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder ensureAdditionalCapacity(final int size) {
+ final int newCount = this.length + size;
+ if (newCount > buffer.length) {
+ final byte[] newbuffer = new byte[Math.max(buffer.length << 1, newCount)];
+ System.arraycopy(buffer, 0, newbuffer, 0, buffer.length);
+ buffer = newbuffer;
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public boolean equals(final byte[] bytes, final int offset, final int length) {
+ ByteString.checkArrayBounds(bytes, offset, length);
+ return ByteString.equals(this.buffer, 0, this.length, bytes, offset, length);
+ }
+
+ /**
+ * Indicates whether the provided object is equal to this byte string
+ * builder. In order for it to be considered equal, the provided object must
+ * be a byte sequence containing the same bytes in the same order.
+ *
+ * @param o
+ * The object for which to make the determination.
+ * @return {@code true} if the provided object is a byte sequence whose
+ * content is equal to that of this byte string builder, or
+ * {@code false} if not.
+ */
+ @Override
+ public boolean equals(final Object o) {
+ if (this == o) {
+ return true;
+ } else if (o instanceof ByteSequence) {
+ final ByteSequence other = (ByteSequence) o;
+ return other.equals(buffer, 0, length);
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns the byte array that backs this byte string builder. Modifications
+ * to this byte string builder's content may cause the returned array's
+ * content to be modified, and vice versa.
+ * <p>
+ * Note that the length of the returned array is only guaranteed to be the
+ * same as the length of this byte string builder immediately after a call
+ * to {@link #trimToSize()}.
+ * <p>
+ * In addition, subsequent modifications to this byte string builder may
+ * cause the backing byte array to be reallocated thus decoupling the
+ * returned byte array from this byte string builder.
+ *
+ * @return The byte array that backs this byte string builder.
+ */
+ public byte[] getBackingArray() {
+ return buffer;
+ }
+
+ /**
+ * Returns a hash code for this byte string builder. It will be the sum of
+ * all of the bytes contained in the byte string builder.
+ * <p>
+ * <b>NOTE:</b> subsequent changes to this byte string builder will
+ * invalidate the returned hash code.
+ *
+ * @return A hash code for this byte string builder.
+ */
+ @Override
+ public int hashCode() {
+ return ByteString.hashCode(buffer, 0, length);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public int length() {
+ return length;
+ }
+
+ /**
+ * Sets the length of this byte string builder.
+ * <p>
+ * If the <code>newLength</code> argument is less than the current length,
+ * the length is changed to the specified length.
+ * <p>
+ * If the <code>newLength</code> argument is greater than or equal to the
+ * current length, then the capacity is increased and sufficient null bytes
+ * are appended so that length becomes the <code>newLength</code> argument.
+ * <p>
+ * The <code>newLength</code> argument must be greater than or equal to
+ * <code>0</code>.
+ *
+ * @param newLength
+ * The new length.
+ * @return This byte string builder.
+ * @throws IndexOutOfBoundsException
+ * If the <code>newLength</code> argument is negative.
+ */
+ public ByteStringBuilder setLength(final int newLength) {
+ if (newLength < 0) {
+ throw new IndexOutOfBoundsException("Negative newLength: " + newLength);
+ }
+
+ if (newLength > length) {
+ ensureAdditionalCapacity(newLength - length);
+
+ // Pad with zeros.
+ for (int i = length; i < newLength; i++) {
+ buffer[i] = 0;
+ }
+ }
+ length = newLength;
+
+ return this;
+ }
+
+ /**
+ * Returns a new byte sequence that is a subsequence of this byte sequence.
+ * <p>
+ * The subsequence starts with the byte value at the specified {@code start}
+ * index and ends with the byte value at index {@code end - 1}. The length
+ * (in bytes) of the returned sequence is {@code end - start}, so if
+ * {@code start
+ * == end} then an empty sequence is returned.
+ * <p>
+ * <b>NOTE:</b> the returned sub-sequence will be robust against all updates
+ * to the byte string builder except for invocations of the method
+ * {@link #clear()}. If a permanent immutable byte sequence is required then
+ * callers should invoke {@code toByteString()} on the returned byte
+ * sequence.
+ *
+ * @param start
+ * The start index, inclusive.
+ * @param end
+ * The end index, exclusive.
+ * @return The newly created byte subsequence.
+ */
+ public ByteSequence subSequence(final int start, final int end) {
+ if (start < 0 || start > end || end > length) {
+ throw new IndexOutOfBoundsException();
+ }
+
+ return new SubSequence(start, end - start);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public byte[] toByteArray() {
+ return copyTo(new byte[length]);
+ }
+
+ /**
+ * Returns the {@link ByteString} representation of this byte string
+ * builder. Subsequent changes to this byte string builder will not modify
+ * the returned {@link ByteString}.
+ *
+ * @return The {@link ByteString} representation of this byte sequence.
+ */
+ public ByteString toByteString() {
+ final byte[] b = new byte[length];
+ System.arraycopy(buffer, 0, b, 0, length);
+ return ByteString.wrap(b);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return ByteString.toString(buffer, 0, length);
+ }
+
+ /**
+ * Attempts to reduce storage used for this byte string builder. If the
+ * buffer is larger than necessary to hold its current sequence of bytes,
+ * then it may be resized to become more space efficient.
+ *
+ * @return This byte string builder.
+ */
+ public ByteStringBuilder trimToSize() {
+ if (buffer.length > length) {
+ final byte[] newBuffer = new byte[length];
+ System.arraycopy(buffer, 0, newBuffer, 0, length);
+ buffer = newBuffer;
+ }
+ return this;
+ }
}
--
Gitblit v1.10.0