ByteString.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import java.io.ByteArrayInputStream;
34 import java.io.ByteArrayOutputStream;
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InvalidObjectException;
38 import java.io.ObjectInputStream;
39 import java.io.OutputStream;
40 import java.io.Serializable;
41 import java.io.UnsupportedEncodingException;
42 import java.nio.ByteBuffer;
43 import java.nio.charset.Charset;
44 import java.nio.charset.UnsupportedCharsetException;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collection;
48 import java.util.Collections;
49 import java.util.Comparator;
50 import java.util.Iterator;
51 import java.util.List;
52 import java.util.NoSuchElementException;
53 
67 public abstract class ByteString implements Iterable<Byte>, Serializable {
68 
74  static final int CONCATENATE_BY_COPY_SIZE = 128;
75 
80  static final int MIN_READ_FROM_CHUNK_SIZE = 0x100; // 256b
81 
82  static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000; // 8k
83 
85  public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
86 
98  private interface ByteArrayCopier {
100  byte[] copyFrom(byte[] bytes, int offset, int size);
101  }
102 
104  private static final class SystemByteArrayCopier implements ByteArrayCopier {
105  @Override
106  public byte[] copyFrom(byte[] bytes, int offset, int size) {
107  byte[] copy = new byte[size];
108  System.arraycopy(bytes, offset, copy, 0, size);
109  return copy;
110  }
111  }
112 
114  private static final class ArraysByteArrayCopier implements ByteArrayCopier {
115  @Override
116  public byte[] copyFrom(byte[] bytes, int offset, int size) {
117  return Arrays.copyOfRange(bytes, offset, offset + size);
118  }
119  }
120 
121  private static final ByteArrayCopier byteArrayCopier;
122 
123  static {
125  Android.isOnAndroidDevice() ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
126  }
127 
133  private int hash = 0;
134 
135  // This constructor is here to prevent subclassing outside of this package,
136  ByteString() {}
137 
147  public abstract byte byteAt(int index);
148 
156  abstract byte internalByteAt(int index);
157 
164  @Override
166  return new AbstractByteIterator() {
167  private int position = 0;
168  private final int limit = size();
169 
170  @Override
171  public boolean hasNext() {
172  return position < limit;
173  }
174 
175  @Override
176  public byte nextByte() {
177  int currentPos = position;
178  if (currentPos >= limit) {
179  throw new NoSuchElementException();
180  }
181  position = currentPos + 1;
182  return internalByteAt(currentPos);
183  }
184  };
185  }
186 
190  public interface ByteIterator extends Iterator<Byte> {
197  byte nextByte();
198  }
199 
200  abstract static class AbstractByteIterator implements ByteIterator {
201  @Override
202  public final Byte next() {
203  // Boxing calls Byte.valueOf(byte), which does not instantiate.
204  return nextByte();
205  }
206 
207  @Override
208  public final void remove() {
209  throw new UnsupportedOperationException();
210  }
211  }
212 
218  public abstract int size();
219 
225  public final boolean isEmpty() {
226  return size() == 0;
227  }
228 
229  // =================================================================
230  // Comparison
231 
232  private static final int UNSIGNED_BYTE_MASK = 0xFF;
233 
242  private static int toInt(byte value) {
243  return value & UNSIGNED_BYTE_MASK;
244  }
245 
253  private static final Comparator<ByteString> UNSIGNED_LEXICOGRAPHICAL_COMPARATOR =
254  new Comparator<ByteString>() {
255  @Override
256  public int compare(ByteString former, ByteString latter) {
257  ByteIterator formerBytes = former.iterator();
258  ByteIterator latterBytes = latter.iterator();
259 
260  while (formerBytes.hasNext() && latterBytes.hasNext()) {
261  // Note: This code was copied from com.google.common.primitives.UnsignedBytes#compare,
262  // as Guava libraries cannot be used in the {@code com.google.protobuf} package.
263  int result =
264  Integer.compare(toInt(formerBytes.nextByte()), toInt(latterBytes.nextByte()));
265  if (result != 0) {
266  return result;
267  }
268  }
269 
270  return Integer.compare(former.size(), latter.size());
271  }
272  };
273 
286  public static Comparator<ByteString> unsignedLexicographicalComparator() {
288  }
289 
290  // =================================================================
291  // ByteString -> substring
292 
300  public final ByteString substring(int beginIndex) {
301  return substring(beginIndex, size());
302  }
303 
313  public abstract ByteString substring(int beginIndex, int endIndex);
314 
323  public final boolean startsWith(ByteString prefix) {
324  return size() >= prefix.size() && substring(0, prefix.size()).equals(prefix);
325  }
326 
335  public final boolean endsWith(ByteString suffix) {
336  return size() >= suffix.size() && substring(size() - suffix.size()).equals(suffix);
337  }
338 
339  // =================================================================
340  // byte[] -> ByteString
341 
351  public static ByteString copyFrom(byte[] bytes, int offset, int size) {
352  checkRange(offset, offset + size, bytes.length);
353  return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
354  }
355 
362  public static ByteString copyFrom(byte[] bytes) {
363  return copyFrom(bytes, 0, bytes.length);
364  }
365 
367  static ByteString wrap(ByteBuffer buffer) {
368  if (buffer.hasArray()) {
369  final int offset = buffer.arrayOffset();
370  return ByteString.wrap(buffer.array(), offset + buffer.position(), buffer.remaining());
371  } else {
372  return new NioByteString(buffer);
373  }
374  }
375 
380  static ByteString wrap(byte[] bytes) {
381  // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
382  return new LiteralByteString(bytes);
383  }
384 
389  static ByteString wrap(byte[] bytes, int offset, int length) {
390  return new BoundedByteString(bytes, offset, length);
391  }
392 
402  public static ByteString copyFrom(ByteBuffer bytes, int size) {
403  checkRange(0, size, bytes.remaining());
404  byte[] copy = new byte[size];
405  bytes.get(copy);
406  return new LiteralByteString(copy);
407  }
408 
415  public static ByteString copyFrom(ByteBuffer bytes) {
416  return copyFrom(bytes, bytes.remaining());
417  }
418 
428  public static ByteString copyFrom(String text, String charsetName)
429  throws UnsupportedEncodingException {
430  return new LiteralByteString(text.getBytes(charsetName));
431  }
432 
441  public static ByteString copyFrom(String text, Charset charset) {
442  return new LiteralByteString(text.getBytes(charset));
443  }
444 
452  public static ByteString copyFromUtf8(String text) {
453  return new LiteralByteString(text.getBytes(Internal.UTF_8));
454  }
455 
456  // =================================================================
457  // InputStream -> ByteString
458 
475  public static ByteString readFrom(InputStream streamToDrain) throws IOException {
476  return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
477  }
478 
495  public static ByteString readFrom(InputStream streamToDrain, int chunkSize) throws IOException {
496  return readFrom(streamToDrain, chunkSize, chunkSize);
497  }
498 
499  // Helper method that takes the chunk size range as a parameter.
500  public static ByteString readFrom(InputStream streamToDrain, int minChunkSize, int maxChunkSize)
501  throws IOException {
502  Collection<ByteString> results = new ArrayList<ByteString>();
503 
504  // copy the inbound bytes into a list of chunks; the chunk size
505  // grows exponentially to support both short and long streams.
506  int chunkSize = minChunkSize;
507  while (true) {
508  ByteString chunk = readChunk(streamToDrain, chunkSize);
509  if (chunk == null) {
510  break;
511  }
512  results.add(chunk);
513  chunkSize = Math.min(chunkSize * 2, maxChunkSize);
514  }
515 
516  return ByteString.copyFrom(results);
517  }
518 
527  private static ByteString readChunk(InputStream in, final int chunkSize) throws IOException {
528  final byte[] buf = new byte[chunkSize];
529  int bytesRead = 0;
530  while (bytesRead < chunkSize) {
531  final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
532  if (count == -1) {
533  break;
534  }
535  bytesRead += count;
536  }
537 
538  if (bytesRead == 0) {
539  return null;
540  }
541 
542  // Always make a copy since InputStream could steal a reference to buf.
543  return ByteString.copyFrom(buf, 0, bytesRead);
544  }
545 
546  // =================================================================
547  // Multiple ByteStrings -> One ByteString
548 
559  public final ByteString concat(ByteString other) {
560  if (Integer.MAX_VALUE - size() < other.size()) {
561  throw new IllegalArgumentException(
562  "ByteString would be too long: " + size() + "+" + other.size());
563  }
564 
565  return RopeByteString.concatenate(this, other);
566  }
567 
579  public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
580  // Determine the size;
581  final int size;
582  if (!(byteStrings instanceof Collection)) {
583  int tempSize = 0;
584  for (Iterator<ByteString> iter = byteStrings.iterator();
585  iter.hasNext();
586  iter.next(), ++tempSize) {}
587  size = tempSize;
588  } else {
589  size = ((Collection<ByteString>) byteStrings).size();
590  }
591 
592  if (size == 0) {
593  return EMPTY;
594  }
595 
596  return balancedConcat(byteStrings.iterator(), size);
597  }
598 
599  // Internal function used by copyFrom(Iterable<ByteString>).
600  // Create a balanced concatenation of the next "length" elements from the
601  // iterable.
602  private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
603  if (length < 1) {
604  throw new IllegalArgumentException(String.format("length (%s) must be >= 1", length));
605  }
606  ByteString result;
607  if (length == 1) {
608  result = iterator.next();
609  } else {
610  int halfLength = length >>> 1;
611  ByteString left = balancedConcat(iterator, halfLength);
612  ByteString right = balancedConcat(iterator, length - halfLength);
613  result = left.concat(right);
614  }
615  return result;
616  }
617 
618  // =================================================================
619  // ByteString -> byte[]
620 
631  public void copyTo(byte[] target, int offset) {
632  copyTo(target, 0, offset, size());
633  }
634 
646  @Deprecated
647  public final void copyTo(byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
648  checkRange(sourceOffset, sourceOffset + numberToCopy, size());
649  checkRange(targetOffset, targetOffset + numberToCopy, target.length);
650  if (numberToCopy > 0) {
651  copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
652  }
653  }
654 
659  protected abstract void copyToInternal(
660  byte[] target, int sourceOffset, int targetOffset, int numberToCopy);
661 
673  public abstract void copyTo(ByteBuffer target);
674 
680  public final byte[] toByteArray() {
681  final int size = size();
682  if (size == 0) {
683  return Internal.EMPTY_BYTE_ARRAY;
684  }
685  byte[] result = new byte[size];
686  copyToInternal(result, 0, 0, size);
687  return result;
688  }
689 
696  public abstract void writeTo(OutputStream out) throws IOException;
697 
707  final void writeTo(OutputStream out, int sourceOffset, int numberToWrite) throws IOException {
708  checkRange(sourceOffset, sourceOffset + numberToWrite, size());
709  if (numberToWrite > 0) {
710  writeToInternal(out, sourceOffset, numberToWrite);
711  }
712  }
713 
718  abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)
719  throws IOException;
720 
733  abstract void writeTo(ByteOutput byteOutput) throws IOException;
734 
744  abstract void writeToReverse(ByteOutput byteOutput) throws IOException;
745 
752  public abstract ByteBuffer asReadOnlyByteBuffer();
753 
764  public abstract List<ByteBuffer> asReadOnlyByteBufferList();
765 
773  public final String toString(String charsetName) throws UnsupportedEncodingException {
774  try {
775  return toString(Charset.forName(charsetName));
776  } catch (UnsupportedCharsetException e) {
777  UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName);
778  exception.initCause(e);
779  throw exception;
780  }
781  }
782 
790  public final String toString(Charset charset) {
791  return size() == 0 ? "" : toStringInternal(charset);
792  }
793 
800  protected abstract String toStringInternal(Charset charset);
801 
802  // =================================================================
803  // UTF-8 decoding
804 
810  public final String toStringUtf8() {
811  return toString(Internal.UTF_8);
812  }
813 
838  public abstract boolean isValidUtf8();
839 
855  protected abstract int partialIsValidUtf8(int state, int offset, int length);
856 
857  // =================================================================
858  // equals() and hashCode()
859 
860  @Override
861  public abstract boolean equals(Object o);
862 
864  abstract static class LeafByteString extends ByteString {
865  @Override
866  protected final int getTreeDepth() {
867  return 0;
868  }
869 
870  @Override
871  protected final boolean isBalanced() {
872  return true;
873  }
874 
875  @Override
876  void writeToReverse(ByteOutput byteOutput) throws IOException {
877  writeTo(byteOutput);
878  }
879 
889  abstract boolean equalsRange(ByteString other, int offset, int length);
890  }
891 
897  @Override
898  public final int hashCode() {
899  int h = hash;
900 
901  if (h == 0) {
902  int size = size();
903  h = partialHash(size, 0, size);
904  if (h == 0) {
905  h = 1;
906  }
907  hash = h;
908  }
909  return h;
910  }
911 
912  // =================================================================
913  // Input stream
914 
928  public abstract InputStream newInput();
929 
937  public abstract CodedInputStream newCodedInput();
938 
939  // =================================================================
940  // Output stream
941 
953  public static Output newOutput(int initialCapacity) {
954  return new Output(initialCapacity);
955  }
956 
967  public static Output newOutput() {
968  return new Output(CONCATENATE_BY_COPY_SIZE);
969  }
970 
975  public static final class Output extends OutputStream {
976  // Implementation note.
977  // The public methods of this class must be synchronized. ByteStrings
978  // are guaranteed to be immutable. Without some sort of locking, it could
979  // be possible for one thread to call toByteSring(), while another thread
980  // is still modifying the underlying byte array.
981 
982  private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
983  // argument passed by user, indicating initial capacity.
984  private final int initialCapacity;
985  // ByteStrings to be concatenated to create the result
986  private final ArrayList<ByteString> flushedBuffers;
987  // Total number of bytes in the ByteStrings of flushedBuffers
988  private int flushedBuffersTotalBytes;
989  // Current buffer to which we are writing
990  private byte[] buffer;
991  // Location in buffer[] to which we write the next byte.
992  private int bufferPos;
993 
999  Output(int initialCapacity) {
1000  if (initialCapacity < 0) {
1001  throw new IllegalArgumentException("Buffer size < 0");
1002  }
1003  this.initialCapacity = initialCapacity;
1004  this.flushedBuffers = new ArrayList<ByteString>();
1005  this.buffer = new byte[initialCapacity];
1006  }
1007 
1008  @Override
1009  public synchronized void write(int b) {
1010  if (bufferPos == buffer.length) {
1011  flushFullBuffer(1);
1012  }
1013  buffer[bufferPos++] = (byte) b;
1014  }
1015 
1016  @Override
1017  public synchronized void write(byte[] b, int offset, int length) {
1018  if (length <= buffer.length - bufferPos) {
1019  // The bytes can fit into the current buffer.
1020  System.arraycopy(b, offset, buffer, bufferPos, length);
1021  bufferPos += length;
1022  } else {
1023  // Use up the current buffer
1024  int copySize = buffer.length - bufferPos;
1025  System.arraycopy(b, offset, buffer, bufferPos, copySize);
1026  offset += copySize;
1027  length -= copySize;
1028  // Flush the buffer, and get a new buffer at least big enough to cover
1029  // what we still need to output
1030  flushFullBuffer(length);
1031  System.arraycopy(b, offset, buffer, /* count= */ 0, length);
1032  bufferPos = length;
1033  }
1034  }
1035 
1042  public synchronized ByteString toByteString() {
1043  flushLastBuffer();
1044  return ByteString.copyFrom(flushedBuffers);
1045  }
1046 
1048  private byte[] copyArray(byte[] buffer, int length) {
1049  byte[] result = new byte[length];
1050  System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
1051  return result;
1052  }
1053 
1061  public void writeTo(OutputStream out) throws IOException {
1062  ByteString[] cachedFlushBuffers;
1063  byte[] cachedBuffer;
1064  int cachedBufferPos;
1065  synchronized (this) {
1066  // Copy the information we need into local variables so as to hold
1067  // the lock for as short a time as possible.
1068  cachedFlushBuffers = flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
1069  cachedBuffer = buffer;
1070  cachedBufferPos = bufferPos;
1071  }
1072  for (ByteString byteString : cachedFlushBuffers) {
1073  byteString.writeTo(out);
1074  }
1075 
1076  out.write(copyArray(cachedBuffer, cachedBufferPos));
1077  }
1078 
1084  public synchronized int size() {
1085  return flushedBuffersTotalBytes + bufferPos;
1086  }
1087 
1092  public synchronized void reset() {
1093  flushedBuffers.clear();
1094  flushedBuffersTotalBytes = 0;
1095  bufferPos = 0;
1096  }
1097 
1098  @Override
1099  public String toString() {
1100  return String.format(
1101  "<ByteString.Output@%s size=%d>",
1102  Integer.toHexString(System.identityHashCode(this)), size());
1103  }
1104 
1109  private void flushFullBuffer(int minSize) {
1110  flushedBuffers.add(new LiteralByteString(buffer));
1111  flushedBuffersTotalBytes += buffer.length;
1112  // We want to increase our total capacity by 50%, but as a minimum,
1113  // the new buffer should also at least be >= minSize and
1114  // >= initial Capacity.
1115  int newSize = Math.max(initialCapacity, Math.max(minSize, flushedBuffersTotalBytes >>> 1));
1116  buffer = new byte[newSize];
1117  bufferPos = 0;
1118  }
1119 
1124  private void flushLastBuffer() {
1125  if (bufferPos < buffer.length) {
1126  if (bufferPos > 0) {
1127  byte[] bufferCopy = copyArray(buffer, bufferPos);
1128  flushedBuffers.add(new LiteralByteString(bufferCopy));
1129  }
1130  // We reuse this buffer for further writes.
1131  } else {
1132  // Buffer is completely full. Huzzah.
1133  flushedBuffers.add(new LiteralByteString(buffer));
1134  // 99% of the time, we're not going to use this OutputStream again.
1135  // We set buffer to an empty byte stream so that we're handling this
1136  // case without wasting space. In the rare case that more writes
1137  // *do* occur, this empty buffer will be flushed and an appropriately
1138  // sized new buffer will be created.
1139  buffer = EMPTY_BYTE_ARRAY;
1140  }
1141  flushedBuffersTotalBytes += bufferPos;
1142  bufferPos = 0;
1143  }
1144  }
1145 
1158  static CodedBuilder newCodedBuilder(int size) {
1159  return new CodedBuilder(size);
1160  }
1161 
1163  static final class CodedBuilder {
1164  private final CodedOutputStream output;
1165  private final byte[] buffer;
1166 
1167  private CodedBuilder(int size) {
1168  buffer = new byte[size];
1169  output = CodedOutputStream.newInstance(buffer);
1170  }
1171 
1172  public ByteString build() {
1173  output.checkNoSpaceLeft();
1174 
1175  // We can be confident that the CodedOutputStream will not modify the
1176  // underlying bytes anymore because it already wrote all of them. So,
1177  // no need to make a copy.
1178  return new LiteralByteString(buffer);
1179  }
1180 
1181  public CodedOutputStream getCodedOutput() {
1182  return output;
1183  }
1184  }
1185 
1186  // =================================================================
1187  // Methods {@link RopeByteString} needs on instances, which aren't part of the
1188  // public API.
1189 
1196  protected abstract int getTreeDepth();
1197 
1204  protected abstract boolean isBalanced();
1205 
1211  protected final int peekCachedHashCode() {
1212  return hash;
1213  }
1214 
1225  protected abstract int partialHash(int h, int offset, int length);
1226 
1234  static void checkIndex(int index, int size) {
1235  if ((index | (size - (index + 1))) < 0) {
1236  if (index < 0) {
1237  throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
1238  }
1239  throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size);
1240  }
1241  }
1242 
1252  static int checkRange(int startIndex, int endIndex, int size) {
1253  final int length = endIndex - startIndex;
1254  if ((startIndex | endIndex | length | (size - endIndex)) < 0) {
1255  if (startIndex < 0) {
1256  throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0");
1257  }
1258  if (endIndex < startIndex) {
1259  throw new IndexOutOfBoundsException(
1260  "Beginning index larger than ending index: " + startIndex + ", " + endIndex);
1261  }
1262  // endIndex >= size
1263  throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size);
1264  }
1265  return length;
1266  }
1267 
1268  @Override
1269  public final String toString() {
1270  return String.format(
1271  "<ByteString@%s size=%d>", Integer.toHexString(System.identityHashCode(this)), size());
1272  }
1273 
1282  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1283  // static initializer loads LiteralByteString and another thread loads LiteralByteString.
1284  private static class LiteralByteString extends ByteString.LeafByteString {
1285  private static final long serialVersionUID = 1L;
1286 
1287  protected final byte[] bytes;
1288 
1294  LiteralByteString(byte[] bytes) {
1295  if (bytes == null) {
1296  throw new NullPointerException();
1297  }
1298  this.bytes = bytes;
1299  }
1300 
1301  @Override
1302  public byte byteAt(int index) {
1303  // Unlike most methods in this class, this one is a direct implementation
1304  // ignoring the potential offset because we need to do range-checking in the
1305  // substring case anyway.
1306  return bytes[index];
1307  }
1308 
1309  @Override
1310  byte internalByteAt(int index) {
1311  return bytes[index];
1312  }
1313 
1314  @Override
1315  public int size() {
1316  return bytes.length;
1317  }
1318 
1319  // =================================================================
1320  // ByteString -> substring
1321 
1322  @Override
1323  public final ByteString substring(int beginIndex, int endIndex) {
1324  final int length = checkRange(beginIndex, endIndex, size());
1325 
1326  if (length == 0) {
1327  return ByteString.EMPTY;
1328  }
1329 
1330  return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
1331  }
1332 
1333  // =================================================================
1334  // ByteString -> byte[]
1335 
1336  @Override
1337  protected void copyToInternal(
1338  byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
1339  // Optimized form, not for subclasses, since we don't call
1340  // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
1341  // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
1342  System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
1343  }
1344 
1345  @Override
1346  public final void copyTo(ByteBuffer target) {
1347  target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
1348  }
1349 
1350  @Override
1351  public final ByteBuffer asReadOnlyByteBuffer() {
1352  return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
1353  }
1354 
1355  @Override
1356  public final List<ByteBuffer> asReadOnlyByteBufferList() {
1357  return Collections.singletonList(asReadOnlyByteBuffer());
1358  }
1359 
1360  @Override
1361  public final void writeTo(OutputStream outputStream) throws IOException {
1362  outputStream.write(toByteArray());
1363  }
1364 
1365  @Override
1366  final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
1367  throws IOException {
1368  outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
1369  }
1370 
1371  @Override
1372  final void writeTo(ByteOutput output) throws IOException {
1373  output.writeLazy(bytes, getOffsetIntoBytes(), size());
1374  }
1375 
1376  @Override
1377  protected final String toStringInternal(Charset charset) {
1378  return new String(bytes, getOffsetIntoBytes(), size(), charset);
1379  }
1380 
1381  // =================================================================
1382  // UTF-8 decoding
1383 
1384  @Override
1385  public final boolean isValidUtf8() {
1386  int offset = getOffsetIntoBytes();
1387  return Utf8.isValidUtf8(bytes, offset, offset + size());
1388  }
1389 
1390  @Override
1391  protected final int partialIsValidUtf8(int state, int offset, int length) {
1392  int index = getOffsetIntoBytes() + offset;
1393  return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
1394  }
1395 
1396  // =================================================================
1397  // equals() and hashCode()
1398 
1399  @Override
1400  public final boolean equals(Object other) {
1401  if (other == this) {
1402  return true;
1403  }
1404  if (!(other instanceof ByteString)) {
1405  return false;
1406  }
1407 
1408  if (size() != ((ByteString) other).size()) {
1409  return false;
1410  }
1411  if (size() == 0) {
1412  return true;
1413  }
1414 
1415  if (other instanceof LiteralByteString) {
1416  LiteralByteString otherAsLiteral = (LiteralByteString) other;
1417  // If we know the hash codes and they are not equal, we know the byte
1418  // strings are not equal.
1419  int thisHash = peekCachedHashCode();
1420  int thatHash = otherAsLiteral.peekCachedHashCode();
1421  if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
1422  return false;
1423  }
1424 
1425  return equalsRange((LiteralByteString) other, 0, size());
1426  } else {
1427  // RopeByteString and NioByteString.
1428  return other.equals(this);
1429  }
1430  }
1431 
1441  @Override
1442  final boolean equalsRange(ByteString other, int offset, int length) {
1443  if (length > other.size()) {
1444  throw new IllegalArgumentException("Length too large: " + length + size());
1445  }
1446  if (offset + length > other.size()) {
1447  throw new IllegalArgumentException(
1448  "Ran off end of other: " + offset + ", " + length + ", " + other.size());
1449  }
1450 
1451  if (other instanceof LiteralByteString) {
1452  LiteralByteString lbsOther = (LiteralByteString) other;
1453  byte[] thisBytes = bytes;
1454  byte[] otherBytes = lbsOther.bytes;
1455  int thisLimit = getOffsetIntoBytes() + length;
1456  for (int thisIndex = getOffsetIntoBytes(),
1457  otherIndex = lbsOther.getOffsetIntoBytes() + offset;
1458  (thisIndex < thisLimit);
1459  ++thisIndex, ++otherIndex) {
1460  if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
1461  return false;
1462  }
1463  }
1464  return true;
1465  }
1466 
1467  return other.substring(offset, offset + length).equals(substring(0, length));
1468  }
1469 
1470  @Override
1471  protected final int partialHash(int h, int offset, int length) {
1472  return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length);
1473  }
1474 
1475  // =================================================================
1476  // Input stream
1477 
1478  @Override
1479  public final InputStream newInput() {
1480  return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
1481  }
1482 
1483  @Override
1484  public final CodedInputStream newCodedInput() {
1485  // We trust CodedInputStream not to modify the bytes, or to give anyone
1486  // else access to them.
1487  return CodedInputStream.newInstance(
1488  bytes, getOffsetIntoBytes(), size(), /* bufferIsImmutable= */ true);
1489  }
1490 
1491  // =================================================================
1492  // Internal methods
1493 
1499  protected int getOffsetIntoBytes() {
1500  return 0;
1501  }
1502  }
1503 
1514  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1515  // static initializer loads LiteralByteString and another thread loads BoundedByteString.
1516  private static final class BoundedByteString extends LiteralByteString {
1517 
1518  private final int bytesOffset;
1519  private final int bytesLength;
1520 
1530  BoundedByteString(byte[] bytes, int offset, int length) {
1531  super(bytes);
1532  checkRange(offset, offset + length, bytes.length);
1533 
1534  this.bytesOffset = offset;
1535  this.bytesLength = length;
1536  }
1537 
1547  @Override
1548  public byte byteAt(int index) {
1549  // We must check the index ourselves as we cannot rely on Java array index
1550  // checking for substrings.
1551  checkIndex(index, size());
1552  return bytes[bytesOffset + index];
1553  }
1554 
1555  @Override
1556  byte internalByteAt(int index) {
1557  return bytes[bytesOffset + index];
1558  }
1559 
1560  @Override
1561  public int size() {
1562  return bytesLength;
1563  }
1564 
1565  @Override
1566  protected int getOffsetIntoBytes() {
1567  return bytesOffset;
1568  }
1569 
1570  // =================================================================
1571  // ByteString -> byte[]
1572 
1573  @Override
1574  protected void copyToInternal(
1575  byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
1576  System.arraycopy(
1577  bytes, getOffsetIntoBytes() + sourceOffset, target, targetOffset, numberToCopy);
1578  }
1579 
1580  // =================================================================
1581  // Serializable
1582 
1583  private static final long serialVersionUID = 1L;
1584 
1585  Object writeReplace() {
1586  return ByteString.wrap(toByteArray());
1587  }
1588 
1589  private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
1590  throw new InvalidObjectException(
1591  "BoundedByteStream instances are not to be serialized directly");
1592  }
1593  }
1594 }
com.google.protobuf.ByteString.UNSIGNED_BYTE_MASK
static final int UNSIGNED_BYTE_MASK
Definition: ByteString.java:232
com.google.protobuf.Internal.EMPTY_BYTE_ARRAY
static final byte[] EMPTY_BYTE_ARRAY
Definition: Internal.java:375
length
GLenum GLuint GLenum GLsizei length
Definition: glcorearb.h:2695
com.google.protobuf.ByteString.ByteIterator.nextByte
byte nextByte()
left
GLint left
Definition: glcorearb.h:4150
com.google.protobuf.ByteString.ArraysByteArrayCopier
Definition: ByteString.java:114
target
GLenum target
Definition: glcorearb.h:3739
com.google.protobuf.ByteString.ByteArrayCopier.copyFrom
byte[] copyFrom(byte[] bytes, int offset, int size)
com.google.protobuf.ByteString.EMPTY
static final ByteString EMPTY
Definition: ByteString.java:85
bytes
uint8 bytes[10]
Definition: coded_stream_unittest.cc:153
b
GLboolean GLboolean GLboolean b
Definition: glcorearb.h:3228
com.google.protobuf.ByteString.SystemByteArrayCopier.copyFrom
byte[] copyFrom(byte[] bytes, int offset, int size)
Definition: ByteString.java:106
com.google.protobuf.ByteString.isEmpty
final boolean isEmpty()
Definition: ByteString.java:225
com.google.protobuf.ByteString.ArraysByteArrayCopier.copyFrom
byte[] copyFrom(byte[] bytes, int offset, int size)
Definition: ByteString.java:116
benchmarks.python.py_benchmark.results
list results
Definition: py_benchmark.py:145
prefix
static const char prefix[]
Definition: test_pair_ipc.cpp:26
offset
GLintptr offset
Definition: glcorearb.h:2944
buffer
GLuint buffer
Definition: glcorearb.h:2939
com.google.protobuf.ByteString.toInt
static int toInt(byte value)
Definition: ByteString.java:242
buffer::length
size_t length
Definition: buffer_processor.h:45
com.google.protobuf.ByteString.UNSIGNED_LEXICOGRAPHICAL_COMPARATOR
static final Comparator< ByteString > UNSIGNED_LEXICOGRAPHICAL_COMPARATOR
Definition: ByteString.java:253
com.google.protobuf.ByteString.byteAt
abstract byte byteAt(int index)
buffer
Definition: buffer_processor.h:43
byte
SETUP_TEARDOWN_TESTCONTEXT typedef uint8_t byte
Definition: test_stream.cpp:12
position
intern position
Definition: array.c:487
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:4175
java
com.google.protobuf.ByteString.byteArrayCopier
static final ByteArrayCopier byteArrayCopier
Definition: ByteString.java:121
com.google.protobuf.ByteString.SystemByteArrayCopier
Definition: ByteString.java:104
size
GLsizeiptr size
Definition: glcorearb.h:2943
com.google.protobuf.ByteString.iterator
ByteIterator iterator()
Definition: ByteString.java:165
Output
Output
com.google.protobuf.Internal
Definition: Internal.java:54
com.google.protobuf.ByteString.hash
int hash
Definition: ByteString.java:133
next
static size_t next(const upb_table *t, size_t i)
Definition: php/ext/google/protobuf/upb.c:4889
value
GLsizei const GLfloat * value
Definition: glcorearb.h:3093
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
count
GLint GLsizei count
Definition: glcorearb.h:2830
index
GLuint index
Definition: glcorearb.h:3055
com.google.protobuf.ByteString.size
abstract int size()
com.google.protobuf.ByteString.ByteArrayCopier
Definition: ByteString.java:98
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:4147
com.google.protobuf.ByteString
Definition: ByteString.java:67
com.google.protobuf.ByteString.ByteIterator
Definition: ByteString.java:190


libaditof
Author(s):
autogenerated on Wed May 21 2025 02:06:48