aboutsummaryrefslogtreecommitdiffhomepage
path: root/java/src/main/java/com/google/protobuf/LiteralByteString.java
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/main/java/com/google/protobuf/LiteralByteString.java')
-rw-r--r--java/src/main/java/com/google/protobuf/LiteralByteString.java213
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.
*