| Index: third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
|
| ===================================================================
|
| --- third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java (revision 0)
|
| +++ third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java (revision 0)
|
| @@ -0,0 +1,349 @@
|
| +// Protocol Buffers - Google's data interchange format
|
| +// Copyright 2008 Google Inc. All rights reserved.
|
| +// http://code.google.com/p/protobuf/
|
| +//
|
| +// Redistribution and use in source and binary forms, with or without
|
| +// modification, are permitted provided that the following conditions are
|
| +// met:
|
| +//
|
| +// * Redistributions of source code must retain the above copyright
|
| +// notice, this list of conditions and the following disclaimer.
|
| +// * Redistributions in binary form must reproduce the above
|
| +// copyright notice, this list of conditions and the following disclaimer
|
| +// in the documentation and/or other materials provided with the
|
| +// distribution.
|
| +// * Neither the name of Google Inc. nor the names of its
|
| +// contributors may be used to endorse or promote products derived from
|
| +// this software without specific prior written permission.
|
| +//
|
| +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
| +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
| +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
| +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
| +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
| +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
| +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
| +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
| +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| +
|
| +package com.google.protobuf;
|
| +
|
| +import java.io.ByteArrayInputStream;
|
| +import java.io.IOException;
|
| +import java.io.InputStream;
|
| +import java.io.OutputStream;
|
| +import java.io.UnsupportedEncodingException;
|
| +import java.nio.ByteBuffer;
|
| +import java.util.ArrayList;
|
| +import java.util.List;
|
| +import java.util.NoSuchElementException;
|
| +
|
| +/**
|
| + * This class implements a {@link com.google.protobuf.ByteString} backed by a
|
| + * single array of bytes, contiguous in memory. It supports substring by
|
| + * pointing to only a sub-range of the underlying byte array, meaning that a
|
| + * substring will reference the full byte-array of the string it's made from,
|
| + * exactly as with {@link String}.
|
| + *
|
| + * @author carlanton@google.com (Carl Haverl)
|
| + */
|
| +class LiteralByteString extends ByteString {
|
| +
|
| + protected final byte[] bytes;
|
| +
|
| + /**
|
| + * Creates a {@code LiteralByteString} backed by the given array, without
|
| + * copying.
|
| + *
|
| + * @param bytes array to wrap
|
| + */
|
| + LiteralByteString(byte[] bytes) {
|
| + this.bytes = bytes;
|
| + }
|
| +
|
| + @Override
|
| + public byte byteAt(int index) {
|
| + // Unlike most methods in this class, this one is a direct implementation
|
| + // ignoring the potential offset because we need to do range-checking in the
|
| + // substring case anyway.
|
| + return bytes[index];
|
| + }
|
| +
|
| + @Override
|
| + public int size() {
|
| + return bytes.length;
|
| + }
|
| +
|
| + // =================================================================
|
| + // 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);
|
| + }
|
| +
|
| + ByteString result;
|
| + if (substringLength == 0) {
|
| + result = ByteString.EMPTY;
|
| + } else {
|
| + result = new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex,
|
| + substringLength);
|
| + }
|
| + return result;
|
| + }
|
| +
|
| + // =================================================================
|
| + // ByteString -> byte[]
|
| +
|
| + @Override
|
| + 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.
|
| + System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
|
| + }
|
| +
|
| + @Override
|
| + public void copyTo(ByteBuffer target) {
|
| + target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
|
| + }
|
| +
|
| + @Override
|
| + public ByteBuffer asReadOnlyByteBuffer() {
|
| + ByteBuffer byteBuffer =
|
| + ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size());
|
| + return byteBuffer.asReadOnlyBuffer();
|
| + }
|
| +
|
| + @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 {
|
| + outputStream.write(toByteArray());
|
| + }
|
| +
|
| + @Override
|
| + public String toString(String charsetName)
|
| + throws UnsupportedEncodingException {
|
| + return new String(bytes, getOffsetIntoBytes(), size(), charsetName);
|
| + }
|
| +
|
| + // =================================================================
|
| + // UTF-8 decoding
|
| +
|
| + @Override
|
| + public boolean isValidUtf8() {
|
| + int offset = getOffsetIntoBytes();
|
| + return Utf8.isValidUtf8(bytes, offset, offset + size());
|
| + }
|
| +
|
| + @Override
|
| + protected int partialIsValidUtf8(int state, int offset, int length) {
|
| + int index = getOffsetIntoBytes() + offset;
|
| + return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
|
| + }
|
| +
|
| + // =================================================================
|
| + // equals() and hashCode()
|
| +
|
| + @Override
|
| + public boolean equals(Object other) {
|
| + if (other == this) {
|
| + return true;
|
| + }
|
| + if (!(other instanceof ByteString)) {
|
| + return false;
|
| + }
|
| +
|
| + if (size() != ((ByteString) other).size()) {
|
| + return false;
|
| + }
|
| + if (size() == 0) {
|
| + return true;
|
| + }
|
| +
|
| + if (other instanceof LiteralByteString) {
|
| + 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());
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * Check equality of the substring of given length of this object starting at
|
| + * zero with another {@code LiteralByteString} substring starting at offset.
|
| + *
|
| + * @param other what to compare a substring in
|
| + * @param offset offset into other
|
| + * @param length number of bytes to compare
|
| + * @return true for equality of substrings, else false.
|
| + */
|
| + boolean equalsRange(LiteralByteString other, int offset, int length) {
|
| + if (length > other.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());
|
| + }
|
| +
|
| + 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;
|
| + }
|
| + hash = h;
|
| + }
|
| + return h;
|
| + }
|
| +
|
| + @Override
|
| + protected int peekCachedHashCode() {
|
| + return hash;
|
| + }
|
| +
|
| + @Override
|
| + protected int partialHash(int h, int offset, int length) {
|
| + byte[] thisBytes = bytes;
|
| + for (int i = getOffsetIntoBytes() + offset, limit = i + length; i < limit;
|
| + i++) {
|
| + h = h * 31 + thisBytes[i];
|
| + }
|
| + return h;
|
| + }
|
| +
|
| + // =================================================================
|
| + // Input stream
|
| +
|
| + @Override
|
| + public InputStream newInput() {
|
| + return new ByteArrayInputStream(bytes, getOffsetIntoBytes(),
|
| + size()); // No copy
|
| + }
|
| +
|
| + @Override
|
| + public CodedInputStream newCodedInput() {
|
| + // We trust CodedInputStream not to modify the bytes, or to give anyone
|
| + // else access to them.
|
| + return CodedInputStream
|
| + .newInstance(bytes, getOffsetIntoBytes(), size()); // No copy
|
| + }
|
| +
|
| + // =================================================================
|
| + // 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.
|
| + *
|
| + * @return always 0 for this class
|
| + */
|
| + protected int getOffsetIntoBytes() {
|
| + return 0;
|
| + }
|
| +}
|
|
|
| Property changes on: third_party/protobuf/java/src/main/java/com/google/protobuf/LiteralByteString.java
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|