diff options
Diffstat (limited to 'java/src/main/java/com/google/protobuf/LiteralByteString.java')
-rw-r--r-- | java/src/main/java/com/google/protobuf/LiteralByteString.java | 213 |
1 files changed, 54 insertions, 159 deletions
diff --git a/java/src/main/java/com/google/protobuf/LiteralByteString.java b/java/src/main/java/com/google/protobuf/LiteralByteString.java index c5a8512a..a18c2792 100644 --- a/java/src/main/java/com/google/protobuf/LiteralByteString.java +++ b/java/src/main/java/com/google/protobuf/LiteralByteString.java @@ -36,9 +36,8 @@ import java.io.InputStream; import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.charset.Charset; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.NoSuchElementException; /** * This class implements a {@link com.google.protobuf.ByteString} backed by a @@ -49,8 +48,7 @@ import java.util.NoSuchElementException; * * @author carlanton@google.com (Carl Haverl) */ -class LiteralByteString extends ByteString { - +class LiteralByteString extends ByteString.LeafByteString { private static final long serialVersionUID = 1L; protected final byte[] bytes; @@ -82,77 +80,56 @@ class LiteralByteString extends ByteString { // ByteString -> substring @Override - public ByteString substring(int beginIndex, int endIndex) { - if (beginIndex < 0) { - throw new IndexOutOfBoundsException( - "Beginning index: " + beginIndex + " < 0"); - } - if (endIndex > size()) { - throw new IndexOutOfBoundsException("End index: " + endIndex + " > " + - size()); - } - int substringLength = endIndex - beginIndex; - if (substringLength < 0) { - throw new IndexOutOfBoundsException( - "Beginning index larger than ending index: " + beginIndex + ", " - + endIndex); - } + public final ByteString substring(int beginIndex, int endIndex) { + final int length = checkRange(beginIndex, endIndex, size()); - ByteString result; - if (substringLength == 0) { - result = ByteString.EMPTY; - } else { - result = new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, - substringLength); + if (length == 0) { + return ByteString.EMPTY; } - return result; + + return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length); } // ================================================================= // ByteString -> byte[] @Override - protected void copyToInternal(byte[] target, int sourceOffset, - int targetOffset, int numberToCopy) { + protected void copyToInternal( + byte[] target, int sourceOffset, int targetOffset, int numberToCopy) { // Optimized form, not for subclasses, since we don't call // getOffsetIntoBytes() or check the 'numberToCopy' parameter. + // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much? System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy); } @Override - public void copyTo(ByteBuffer target) { - target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes + public final void copyTo(ByteBuffer target) { + target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes + } + + @Override + public final ByteBuffer asReadOnlyByteBuffer() { + return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer(); } @Override - public ByteBuffer asReadOnlyByteBuffer() { - ByteBuffer byteBuffer = - ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()); - return byteBuffer.asReadOnlyBuffer(); + public final List<ByteBuffer> asReadOnlyByteBufferList() { + return Collections.singletonList(asReadOnlyByteBuffer()); } @Override - public List<ByteBuffer> asReadOnlyByteBufferList() { - // Return the ByteBuffer generated by asReadOnlyByteBuffer() as a singleton - List<ByteBuffer> result = new ArrayList<ByteBuffer>(1); - result.add(asReadOnlyByteBuffer()); - return result; - } - - @Override - public void writeTo(OutputStream outputStream) throws IOException { + public final void writeTo(OutputStream outputStream) throws IOException { outputStream.write(toByteArray()); } @Override - void writeToInternal(OutputStream outputStream, int sourceOffset, - int numberToWrite) throws IOException { - outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, - numberToWrite); + final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite) + throws IOException { + outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite); } @Override - protected String toStringInternal(Charset charset) { + protected final String toStringInternal(Charset charset) { return new String(bytes, getOffsetIntoBytes(), size(), charset); } @@ -160,13 +137,13 @@ class LiteralByteString extends ByteString { // UTF-8 decoding @Override - public boolean isValidUtf8() { + public final boolean isValidUtf8() { int offset = getOffsetIntoBytes(); return Utf8.isValidUtf8(bytes, offset, offset + size()); } @Override - protected int partialIsValidUtf8(int state, int offset, int length) { + protected final int partialIsValidUtf8(int state, int offset, int length) { int index = getOffsetIntoBytes() + offset; return Utf8.partialIsValidUtf8(state, bytes, index, index + length); } @@ -175,7 +152,7 @@ class LiteralByteString extends ByteString { // equals() and hashCode() @Override - public boolean equals(Object other) { + public final boolean equals(Object other) { if (other == this) { return true; } @@ -194,19 +171,16 @@ class LiteralByteString extends ByteString { LiteralByteString otherAsLiteral = (LiteralByteString) other; // If we know the hash codes and they are not equal, we know the byte // strings are not equal. - if (hash != 0 - && otherAsLiteral.hash != 0 - && hash != otherAsLiteral.hash) { + int thisHash = peekCachedHashCode(); + int thatHash = otherAsLiteral.peekCachedHashCode(); + if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) { return false; } return equalsRange((LiteralByteString) other, 0, size()); - } else if (other instanceof RopeByteString) { - return other.equals(this); } else { - throw new IllegalArgumentException( - "Has a new type of ByteString been created? Found " - + other.getClass()); + // RopeByteString and NioByteString. + return other.equals(this); } } @@ -219,65 +193,36 @@ class LiteralByteString extends ByteString { * @param length number of bytes to compare * @return true for equality of substrings, else false. */ - boolean equalsRange(LiteralByteString other, int offset, int length) { + @Override + final boolean equalsRange(ByteString other, int offset, int length) { if (length > other.size()) { - throw new IllegalArgumentException( - "Length too large: " + length + size()); + throw new IllegalArgumentException("Length too large: " + length + size()); } if (offset + length > other.size()) { throw new IllegalArgumentException( - "Ran off end of other: " + offset + ", " + length + ", " + - other.size()); + "Ran off end of other: " + offset + ", " + length + ", " + other.size()); } - byte[] thisBytes = bytes; - byte[] otherBytes = other.bytes; - int thisLimit = getOffsetIntoBytes() + length; - for (int thisIndex = getOffsetIntoBytes(), otherIndex = - other.getOffsetIntoBytes() + offset; - (thisIndex < thisLimit); ++thisIndex, ++otherIndex) { - if (thisBytes[thisIndex] != otherBytes[otherIndex]) { - return false; - } - } - return true; - } - - /** - * Cached hash value. Intentionally accessed via a data race, which - * is safe because of the Java Memory Model's "no out-of-thin-air values" - * guarantees for ints. - */ - private int hash = 0; - - /** - * Compute the hashCode using the traditional algorithm from {@link - * ByteString}. - * - * @return hashCode value - */ - @Override - public int hashCode() { - int h = hash; - - if (h == 0) { - int size = size(); - h = partialHash(size, 0, size); - if (h == 0) { - h = 1; + if (other instanceof LiteralByteString) { + LiteralByteString lbsOther = (LiteralByteString) other; + byte[] thisBytes = bytes; + byte[] otherBytes = lbsOther.bytes; + int thisLimit = getOffsetIntoBytes() + length; + for ( + int thisIndex = getOffsetIntoBytes(), otherIndex = lbsOther.getOffsetIntoBytes() + offset; + (thisIndex < thisLimit); ++thisIndex, ++otherIndex) { + if (thisBytes[thisIndex] != otherBytes[otherIndex]) { + return false; + } } - hash = h; + return true; } - return h; - } - @Override - protected int peekCachedHashCode() { - return hash; + return other.substring(offset, offset + length).equals(substring(0, length)); } @Override - protected int partialHash(int h, int offset, int length) { + protected final int partialHash(int h, int offset, int length) { return hashCode(h, bytes, getOffsetIntoBytes() + offset, length); } @@ -297,70 +242,20 @@ class LiteralByteString extends ByteString { // Input stream @Override - public InputStream newInput() { - return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), - size()); // No copy + public final InputStream newInput() { + return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy } @Override - public CodedInputStream newCodedInput() { + public final CodedInputStream newCodedInput() { // We trust CodedInputStream not to modify the bytes, or to give anyone // else access to them. return CodedInputStream.newInstance(this); } // ================================================================= - // ByteIterator - - @Override - public ByteIterator iterator() { - return new LiteralByteIterator(); - } - - private class LiteralByteIterator implements ByteIterator { - private int position; - private final int limit; - - private LiteralByteIterator() { - position = 0; - limit = size(); - } - - public boolean hasNext() { - return (position < limit); - } - - public Byte next() { - // Boxing calls Byte.valueOf(byte), which does not instantiate. - return nextByte(); - } - - public byte nextByte() { - try { - return bytes[position++]; - } catch (ArrayIndexOutOfBoundsException e) { - throw new NoSuchElementException(e.getMessage()); - } - } - - public void remove() { - throw new UnsupportedOperationException(); - } - } - - // ================================================================= // Internal methods - @Override - protected int getTreeDepth() { - return 0; - } - - @Override - protected boolean isBalanced() { - return true; - } - /** * Offset into {@code bytes[]} to use, non-zero for substrings. * |