1fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Protocol Buffers - Google's data interchange format
2fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Copyright 2008 Google Inc.  All rights reserved.
3afb4b72037e3f13db208590fc782c4bc8e27f862Jeff Davidson// https://developers.google.com/protocol-buffers/
4fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
5fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// Redistribution and use in source and binary forms, with or without
6fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// modification, are permitted provided that the following conditions are
7fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// met:
8fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
9fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions of source code must retain the above copyright
10fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// notice, this list of conditions and the following disclaimer.
11fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Redistributions in binary form must reproduce the above
12fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// copyright notice, this list of conditions and the following disclaimer
13fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// in the documentation and/or other materials provided with the
14fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// distribution.
15fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//     * Neither the name of Google Inc. nor the names of its
16fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// contributors may be used to endorse or promote products derived from
17fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// this software without specific prior written permission.
18fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville//
19fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
31fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savillepackage com.google.protobuf;
32fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
33b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.ByteArrayInputStream;
34fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.io.ByteArrayOutputStream;
35a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.io.IOException;
36a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.io.InputStream;
37b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.InvalidObjectException;
38b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.ObjectInputStream;
39a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.io.OutputStream;
40b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.io.Serializable;
41fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.io.UnsupportedEncodingException;
42fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Savilleimport java.nio.ByteBuffer;
43b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.charset.Charset;
44b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.nio.charset.UnsupportedCharsetException;
45a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.ArrayList;
46b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Arrays;
47a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.Collection;
48b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerimport java.util.Collections;
49a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.Iterator;
50d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Savilleimport java.util.List;
51a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidsonimport java.util.NoSuchElementException;
52fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
53fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville/**
54a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * Immutable sequence of bytes.  Substring is supported by sharing the reference
55a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * to the immutable underlying bytes, as with {@link String}.  Concatenation is
56a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * likewise supported without copying (long strings) by building a tree of
57a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * pieces in {@link RopeByteString}.
58a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * <p>
59a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * Like {@link String}, the contents of a {@link ByteString} can never be
60a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * observed to change, not even in the presence of a data race or incorrect
61a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * API usage in the client code.
62fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville *
63fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @author crazybob@google.com Bob Lee
64fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville * @author kenton@google.com Kenton Varda
65a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * @author carlanton@google.com Carl Haverl
66a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson * @author martinrb@google.com Martin Buchholz
67fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville */
68b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammerpublic abstract class ByteString implements Iterable<Byte>, Serializable {
69fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
70a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
71a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * When two strings to be concatenated have a combined length shorter than
72a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * this, we just copy their bytes on {@link #concat(ByteString)}.
73a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * The trade-off is copy size versus the overhead of creating tree nodes
74a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * in {@link RopeByteString}.
75a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
76a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  static final int CONCATENATE_BY_COPY_SIZE = 128;
77a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
78a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
79a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * When copying an InputStream into a ByteString with .readFrom(),
80a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * the chunks in the underlying rope start at 256 bytes, but double
81a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * each iteration up to 8192 bytes.
82a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
83a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  static final int MIN_READ_FROM_CHUNK_SIZE = 0x100;  // 256b
84a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  static final int MAX_READ_FROM_CHUNK_SIZE = 0x2000;  // 8k
85fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
86fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
87a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Empty {@code ByteString}.
88a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
89b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public static final ByteString EMPTY = new LiteralByteString(Internal.EMPTY_BYTE_ARRAY);
90b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
91b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
92b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * An interface to efficiently copy {@code byte[]}.
93b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
94b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>One of the noticable costs of copying a byte[] into a new array using
95b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@code System.arraycopy} is nullification of a new buffer before the copy. It has been shown
96b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the Hotspot VM is capable to intrisicfy {@code Arrays.copyOfRange} operation to avoid this
97b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * expensive nullification and provide substantial performance gain. Unfortunately this does not
98b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * hold on Android runtimes and could make the copy slightly slower due to additional code in
99b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the {@code Arrays.copyOfRange}. Thus we provide two different implementation for array copier
100b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * for Hotspot and Android runtimes.
101b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
102b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private interface ByteArrayCopier {
103b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
104b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Copies the specified range of the specified array into a new array
105b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
106b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    byte[] copyFrom(byte[] bytes, int offset, int size);
107b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
108b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
109b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /** Implementation of {@code ByteArrayCopier} which uses {@link System#arraycopy}. */
110b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final class SystemByteArrayCopier implements ByteArrayCopier {
111b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
112b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public byte[] copyFrom(byte[] bytes, int offset, int size) {
113b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      byte[] copy = new byte[size];
114b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      System.arraycopy(bytes, offset, copy, 0, size);
115b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return copy;
116b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
117b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
118b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
119b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /** Implementation of {@code ByteArrayCopier} which uses {@link Arrays#copyOfRange}. */
120b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final class ArraysByteArrayCopier implements ByteArrayCopier {
121b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
122b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public byte[] copyFrom(byte[] bytes, int offset, int size) {
123b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return Arrays.copyOfRange(bytes, offset, offset + size);
124b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
125b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
126b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
127b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final ByteArrayCopier byteArrayCopier;
128b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static {
129b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    boolean isAndroid = true;
130b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    try {
131b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      Class.forName("android.content.Context");
132b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } catch (ClassNotFoundException e) {
133b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      isAndroid = false;
134b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
135b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
136b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    byteArrayCopier = isAndroid ? new SystemByteArrayCopier() : new ArraysByteArrayCopier();
137b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
138b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
139b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
140b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Cached hash value. Intentionally accessed via a data race, which
141b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * is safe because of the Java Memory Model's "no out-of-thin-air values"
142b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * guarantees for ints. A value of 0 implies that the hash has not been set.
143b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
144b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private int hash = 0;
145a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
146a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // This constructor is here to prevent subclassing outside of this package,
147a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  ByteString() {}
148a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
149a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
150a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Gets the byte at the given index. This method should be used only for
151a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * random access to individual bytes. To access bytes sequentially, use the
152a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@link ByteIterator} returned by {@link #iterator()}, and call {@link
153a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * #substring(int, int)} first if necessary.
154fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
155a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param index index of byte
156a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return the value
157b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @throws IndexOutOfBoundsException {@code index < 0 or index >= size}
158fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
159a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract byte byteAt(int index);
160a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
161a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
162a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return a {@link ByteString.ByteIterator} over the bytes in the ByteString.
163a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * To avoid auto-boxing, you may get the iterator manually and call
164a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@link ByteIterator#nextByte()}.
165a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
166a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return the iterator
167a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  @Override
169b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final ByteIterator iterator() {
170b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new ByteIterator() {
171b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      private int position = 0;
172b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      private final int limit = size();
173b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
174b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      @Override
175b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      public boolean hasNext() {
176b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return position < limit;
177b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
178b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
179b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      @Override
180b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      public Byte next() {
181b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        // Boxing calls Byte.valueOf(byte), which does not instantiate.
182b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return nextByte();
183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      @Override
186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      public byte nextByte() {
187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        try {
188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return byteAt(position++);
189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        } catch (IndexOutOfBoundsException e) {
190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          throw new NoSuchElementException(e.getMessage());
191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      @Override
195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      public void remove() {
196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new UnsupportedOperationException();
197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    };
199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
200a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
201a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
202a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * This interface extends {@code Iterator<Byte>}, so that we can return an
203a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * unboxed {@code byte}.
204a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
205a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public interface ByteIterator extends Iterator<Byte> {
206a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
207a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * An alternative to {@link Iterator#next()} that returns an
208a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * unboxed primitive {@code byte}.
209a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     *
210a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @return the next {@code byte} in the iteration
211a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @throws NoSuchElementException if the iteration has no more elements
212a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
213a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    byte nextByte();
214fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
215fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
216fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
217fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Gets the number of bytes.
218a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
219a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return size in bytes
220fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
221a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract int size();
222fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
223fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
224fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Returns {@code true} if the size is {@code 0}, {@code false} otherwise.
225a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
226a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return true if this is zero bytes long
227fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
228b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final boolean isEmpty() {
229a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return size() == 0;
230fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
231fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
232fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
233a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // ByteString -> substring
234a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
235a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
236a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return the substring from {@code beginIndex}, inclusive, to the end of the
237a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * string.
238a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
239a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param beginIndex start at this index
240a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return substring sharing underlying data
241a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IndexOutOfBoundsException if {@code beginIndex < 0} or
242a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     {@code beginIndex > size()}.
243a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final ByteString substring(int beginIndex) {
245a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return substring(beginIndex, size());
246a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
247a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
248a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
249a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return the substring from {@code beginIndex}, inclusive, to {@code
250a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * endIndex}, exclusive.
251a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
252a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param beginIndex start at this index
253a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param endIndex   the last character is the one before this index
254a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return substring sharing underlying data
255a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IndexOutOfBoundsException if {@code beginIndex < 0},
256a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     {@code endIndex > size()}, or {@code beginIndex > endIndex}.
257a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
258a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract ByteString substring(int beginIndex, int endIndex);
259fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
260fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
261a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Tests if this bytestring starts with the specified prefix.
262a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Similar to {@link String#startsWith(String)}
263a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
264a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param prefix the prefix.
265a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return <code>true</code> if the byte sequence represented by the
266a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         argument is a prefix of the byte sequence represented by
267a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         this string; <code>false</code> otherwise.
268fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final boolean startsWith(ByteString prefix) {
270a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return size() >= prefix.size() &&
271a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson           substring(0, prefix.size()).equals(prefix);
272a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
273a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
274a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
275a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Tests if this bytestring ends with the specified suffix.
276a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Similar to {@link String#endsWith(String)}
277a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
278a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param suffix the suffix.
279a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return <code>true</code> if the byte sequence represented by the
280a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         argument is a suffix of the byte sequence represented by
281a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *         this string; <code>false</code> otherwise.
282a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final boolean endsWith(ByteString suffix) {
284a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return size() >= suffix.size() &&
285a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        substring(size() - suffix.size()).equals(suffix);
286a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
287a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
288a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // =================================================================
289a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // byte[] -> ByteString
290fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
291fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
292fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Copies the given bytes into a {@code ByteString}.
293a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
294a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param bytes source array
295a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param offset offset in source array
296a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param size number of bytes to copy
297a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
298fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
299a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(byte[] bytes, int offset, int size) {
300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new LiteralByteString(byteArrayCopier.copyFrom(bytes, offset, size));
301fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
302fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
303fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
304fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Copies the given bytes into a {@code ByteString}.
305a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
306a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param bytes to copy
307a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
308fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
309a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(byte[] bytes) {
310fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return copyFrom(bytes, 0, bytes.length);
311fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Wraps the given bytes into a {@code ByteString}. Intended for internal only
315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * usage to force a classload of ByteString before LiteralByteString.
316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static ByteString wrap(byte[] bytes) {
318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new LiteralByteString(bytes);
320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Wraps the given bytes into a {@code ByteString}. Intended for internal only
324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * usage to force a classload of ByteString before BoundedByteString and
325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * LiteralByteString.
326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static ByteString wrap(byte[] bytes, int offset, int length) {
328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new BoundedByteString(bytes, offset, length);
329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
330fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
331fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
332a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Copies the next {@code size} bytes from a {@code java.nio.ByteBuffer} into
333d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * a {@code ByteString}.
334a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
335a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param bytes source buffer
336a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param size number of bytes to copy
337a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
338d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   */
339a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(ByteBuffer bytes, int size) {
340a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    byte[] copy = new byte[size];
341d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    bytes.get(copy);
342a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return new LiteralByteString(copy);
343d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
344d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
345d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  /**
346d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * Copies the remaining bytes from a {@code java.nio.ByteBuffer} into
347d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * a {@code ByteString}.
348a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
349a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param bytes sourceBuffer
350a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
351d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   */
352a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(ByteBuffer bytes) {
353d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    return copyFrom(bytes, bytes.remaining());
354d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
355d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
356d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  /**
357fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Encodes {@code text} into a sequence of bytes using the named charset
358fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * and returns the result as a {@code ByteString}.
359a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
360a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param text source string
361a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param charsetName encoding to use
362a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
363a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws UnsupportedEncodingException if the encoding isn't found
364fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
365a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(String text, String charsetName)
366fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      throws UnsupportedEncodingException {
367a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return new LiteralByteString(text.getBytes(charsetName));
368fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
369fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
370fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Encodes {@code text} into a sequence of bytes using the named charset
372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * and returns the result as a {@code ByteString}.
373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param text source string
375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param charset encode using this charset
376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return new {@code ByteString}
377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public static ByteString copyFrom(String text, Charset charset) {
379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new LiteralByteString(text.getBytes(charset));
380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
383fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Encodes {@code text} into a sequence of UTF-8 bytes and returns the
384fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * result as a {@code ByteString}.
385a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
386a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param text source string
387a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
388fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
389a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFromUtf8(String text) {
390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return new LiteralByteString(text.getBytes(Internal.UTF_8));
391fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
392fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
393a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // =================================================================
394a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // InputStream -> ByteString
395a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
396a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
397a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Completely reads the given stream's bytes into a
398a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@code ByteString}, blocking if necessary until all bytes are
399a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * read through to the end of the stream.
400a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
401a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <b>Performance notes:</b> The returned {@code ByteString} is an
402a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * immutable tree of byte arrays ("chunks") of the stream data.  The
403a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * first chunk is small, with subsequent chunks each being double
404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * the size, up to 8K.
405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>Each byte read from the input stream will be copied twice to ensure
407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * that the resulting ByteString is truly immutable.
408a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
409a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param streamToDrain The source stream, which is read completely
410a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     but not closed.
411a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return A new {@code ByteString} which is made up of chunks of
412a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     various sizes, depending on the behavior of the underlying
413a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     stream.
414a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IOException IOException is thrown if there is a problem
415a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     reading the underlying stream.
416a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
417a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString readFrom(InputStream streamToDrain)
418a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return readFrom(streamToDrain, MIN_READ_FROM_CHUNK_SIZE, MAX_READ_FROM_CHUNK_SIZE);
420a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
421a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
422a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
423a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Completely reads the given stream's bytes into a
424a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@code ByteString}, blocking if necessary until all bytes are
425a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * read through to the end of the stream.
426a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
427a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <b>Performance notes:</b> The returned {@code ByteString} is an
428a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * immutable tree of byte arrays ("chunks") of the stream data.  The
429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * chunkSize parameter sets the size of these byte arrays.
430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>Each byte read from the input stream will be copied twice to ensure
432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * that the resulting ByteString is truly immutable.
433a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
434a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param streamToDrain The source stream, which is read completely
435a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     but not closed.
436a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param chunkSize The size of the chunks in which to read the
437a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     stream.
438a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return A new {@code ByteString} which is made up of chunks of
439a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     the given size.
440a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IOException IOException is thrown if there is a problem
441a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     reading the underlying stream.
442a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
443a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString readFrom(InputStream streamToDrain, int chunkSize)
444a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
445a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return readFrom(streamToDrain, chunkSize, chunkSize);
446a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
447a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
448a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Helper method that takes the chunk size range as a parameter.
449a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString readFrom(InputStream streamToDrain, int minChunkSize,
450a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int maxChunkSize) throws IOException {
451a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Collection<ByteString> results = new ArrayList<ByteString>();
452a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
453a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // copy the inbound bytes into a list of chunks; the chunk size
454a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // grows exponentially to support both short and long streams.
455a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    int chunkSize = minChunkSize;
456a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    while (true) {
457a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteString chunk = readChunk(streamToDrain, chunkSize);
458a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (chunk == null) {
459a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        break;
460a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
461a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      results.add(chunk);
462a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      chunkSize = Math.min(chunkSize * 2, maxChunkSize);
463a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
464a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
465a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return ByteString.copyFrom(results);
466a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
467a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
468a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
469a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Blocks until a chunk of the given size can be made from the
470a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * stream, or EOF is reached.  Calls read() repeatedly in case the
471a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * given stream implementation doesn't completely fill the given
472a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * buffer in one read() call.
473a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
474a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return A chunk of the desired size, or else a chunk as large as
475a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * was available when end of stream was reached. Returns null if the
476a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * given stream had no more data in it.
477a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
478a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  private static ByteString readChunk(InputStream in, final int chunkSize)
479a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
480a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      final byte[] buf = new byte[chunkSize];
481a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int bytesRead = 0;
482a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      while (bytesRead < chunkSize) {
483a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        final int count = in.read(buf, bytesRead, chunkSize - bytesRead);
484a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (count == -1) {
485a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          break;
486a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
487a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bytesRead += count;
488a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
489a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
490a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bytesRead == 0) {
491a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        return null;
492a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Always make a copy since InputStream could steal a reference to buf.
495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return ByteString.copyFrom(buf, 0, bytesRead);
496a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
497a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
498a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // =================================================================
499a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Multiple ByteStrings -> One ByteString
500a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
501a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
502a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Concatenate the given {@code ByteString} to this one. Short concatenations,
503a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * of total size smaller than {@link ByteString#CONCATENATE_BY_COPY_SIZE}, are
504a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * produced by copying the underlying bytes (as per Rope.java, <a
505a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * href="http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol25/issue12/spe986.pdf">
506a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * BAP95 </a>. In general, the concatenate involves no copying.
507a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
508a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param other string to concatenate
509a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return a new {@code ByteString} instance
510a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final ByteString concat(ByteString other) {
512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (Integer.MAX_VALUE - size() < other.size()) {
513a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throw new IllegalArgumentException("ByteString would be too long: " +
514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          size() + "+" + other.size());
515a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
516a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
517a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return RopeByteString.concatenate(this, other);
518a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
519a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
520d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  /**
521a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Concatenates all byte strings in the iterable and returns the result.
522a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * This is designed to run in O(list size), not O(total bytes).
523d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   *
524d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * <p>The returned {@code ByteString} is not necessarily a unique object.
525d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * If the list is empty, the returned object is the singleton empty
526d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * {@code ByteString}.  If the list has only one element, that
527d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   * {@code ByteString} will be returned without copying.
528a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
529a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param byteStrings strings to be concatenated
530a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new {@code ByteString}
531d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville   */
532a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static ByteString copyFrom(Iterable<ByteString> byteStrings) {
533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // Determine the size;
534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final int size;
535a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (!(byteStrings instanceof Collection)) {
536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int tempSize = 0;
537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      for (Iterator<ByteString> iter = byteStrings.iterator(); iter.hasNext();
538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          iter.next(), ++tempSize) {
539a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size = tempSize;
541a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      size = ((Collection<ByteString>) byteStrings).size();
543d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
544b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
545b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (size == 0) {
546b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return EMPTY;
547d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
548b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
549b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return balancedConcat(byteStrings.iterator(), size);
550a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
551a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
552a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Internal function used by copyFrom(Iterable<ByteString>).
553a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Create a balanced concatenation of the next "length" elements from the
554a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // iterable.
555b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static ByteString balancedConcat(Iterator<ByteString> iterator, int length) {
556a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    assert length >= 1;
557a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    ByteString result;
558a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (length == 1) {
559a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      result = iterator.next();
560a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    } else {
561a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int halfLength = length >>> 1;
562a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteString left = balancedConcat(iterator, halfLength);
563a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteString right = balancedConcat(iterator, length - halfLength);
564a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      result = left.concat(right);
565d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville    }
566a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
567d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville  }
568d0332953cda33fb4f8e24ebff9c49159b69c43d6Wink Saville
569fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
570fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // ByteString -> byte[]
571fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
572fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
573fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Copies bytes into a buffer at the given offset.
574fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
575fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param target buffer to copy into
576fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param offset in the target buffer
577a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IndexOutOfBoundsException if the offset is negative or too large
578fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
579a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public void copyTo(byte[] target, int offset) {
580a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    copyTo(target, 0, offset, size());
581fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
582fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
583fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
584fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Copies bytes into a buffer.
585fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
586a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param target       buffer to copy into
587fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param sourceOffset offset within these bytes
588fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * @param targetOffset offset within the target buffer
589a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param numberToCopy number of bytes to copy
590a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IndexOutOfBoundsException if an offset or size is negative or too
591a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     large
592fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
593b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final void copyTo(byte[] target, int sourceOffset, int targetOffset,
594a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int numberToCopy) {
595b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkRange(sourceOffset, sourceOffset + numberToCopy, size());
596b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkRange(targetOffset, targetOffset + numberToCopy, target.length);
597a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (numberToCopy > 0) {
598a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      copyToInternal(target, sourceOffset, targetOffset, numberToCopy);
599a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
600fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
601fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
602fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
603a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Internal (package private) implementation of
604b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@link #copyTo(byte[],int,int,int)}.
605b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * It assumes that all error checking has already been performed and that
606b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@code numberToCopy > 0}.
607a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
608a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  protected abstract void copyToInternal(byte[] target, int sourceOffset,
609a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int targetOffset, int numberToCopy);
610a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
611a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
612a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Copies bytes into a ByteBuffer.
613a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
614a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param target ByteBuffer to copy into.
615a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws java.nio.ReadOnlyBufferException if the {@code target} is read-only
616a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws java.nio.BufferOverflowException if the {@code target}'s
617a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     remaining() space is not large enough to hold the data.
618a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
619a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract void copyTo(ByteBuffer target);
620a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
621a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
622fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Copies bytes to a {@code byte[]}.
623a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
624a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return copied bytes
625fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
626b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final byte[] toByteArray() {
627b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final int size = size();
628a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (size == 0) {
629a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return Internal.EMPTY_BYTE_ARRAY;
630a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
631a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    byte[] result = new byte[size];
632a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    copyToInternal(result, 0, 0, size);
633a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return result;
634fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
635fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
636fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
637b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Writes a copy of the contents of this byte string to the specified output stream argument.
638a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
639a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param  out  the output stream to which to write the data.
640a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IOException  if an I/O error occurs.
641fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
642a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract void writeTo(OutputStream out) throws IOException;
643b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
644a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
645a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Writes a specified part of this byte string to an output stream.
646a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
647a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param  out  the output stream to which to write the data.
648a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param  sourceOffset offset within these bytes
649a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param  numberToWrite number of bytes to write
650a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws IOException  if an I/O error occurs.
651b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @throws IndexOutOfBoundsException if an offset or size is negative or too large
652a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
653b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  final void writeTo(OutputStream out, int sourceOffset, int numberToWrite)
654a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      throws IOException {
655b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    checkRange(sourceOffset, sourceOffset + numberToWrite, size());
656a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    if (numberToWrite > 0) {
657a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      writeToInternal(out, sourceOffset, numberToWrite);
658a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
659fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
660fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
661fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
662a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Internal version of {@link #writeTo(OutputStream,int,int)} that assumes
663a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * all error checking has already been done.
664a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
665b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  abstract void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite)
666b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throws IOException;
667b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
668b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
669b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Writes this {@link ByteString} to the provided {@link ByteOutput}. Calling
670b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * this method may result in multiple operations on the target {@link ByteOutput}.
671b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
672b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>This method may expose internal backing buffers of the {@link ByteString} to the {@link
673b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * ByteOutput} in order to avoid additional copying overhead. It would be possible for a malicious
674b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@link ByteOutput} to corrupt the {@link ByteString}. Use with caution!
675b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
676b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param  byteOutput  the output target to receive the bytes
677b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @throws IOException  if an I/O error occurs
678b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @see UnsafeByteOperations#unsafeWriteTo(ByteString, ByteOutput)
679b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
680b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  abstract void writeTo(ByteOutput byteOutput) throws IOException;
681a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
682a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
683a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Constructs a read-only {@code java.nio.ByteBuffer} whose content
684a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * is equal to the contents of this byte string.
685a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * The result uses the same backing array as the byte string, if possible.
686a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
687a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return wrapped bytes
688a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
689a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract ByteBuffer asReadOnlyByteBuffer();
690a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
691a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
692a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Constructs a list of read-only {@code java.nio.ByteBuffer} objects
693a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * such that the concatenation of their contents is equal to the contents
694a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * of this byte string.  The result uses the same backing arrays as the
695a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * byte string.
696a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>
697a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * By returning a list, implementations of this method may be able to avoid
698a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * copying even when there are multiple backing arrays.
699b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
700a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return a list of wrapped bytes
701a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
702a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract List<ByteBuffer> asReadOnlyByteBufferList();
703a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
704a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
705fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Constructs a new {@code String} by decoding the bytes using the
706fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * specified charset.
707a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
708a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param charsetName encode using this charset
709a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new string
710a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @throws UnsupportedEncodingException if charset isn't recognized
711fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
712b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final String toString(String charsetName)
713b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throws UnsupportedEncodingException {
714b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    try {
715b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return toString(Charset.forName(charsetName));
716b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    } catch (UnsupportedCharsetException e) {
717b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      UnsupportedEncodingException exception = new UnsupportedEncodingException(charsetName);
718b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      exception.initCause(e);
719b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw exception;
720b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
721b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
722b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
723b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
724b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Constructs a new {@code String} by decoding the bytes using the
725b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * specified charset. Returns the same empty String if empty.
726b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
727b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param charset encode using this charset
728b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return new string
729b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
730b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final String toString(Charset charset) {
731b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return size() == 0 ? "" : toStringInternal(charset);
732b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
733b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
734b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
735b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Constructs a new {@code String} by decoding the bytes using the
736b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * specified charset.
737b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
738b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param charset encode using this charset
739b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return new string
740b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
741b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  protected abstract String toStringInternal(Charset charset);
742a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
743a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // =================================================================
744a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // UTF-8 decoding
745fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
746fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
747fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Constructs a new {@code String} by decoding the bytes as UTF-8.
748a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
749a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return new string using UTF-8 encoding
750fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
751b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final String toStringUtf8() {
752b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return toString(Internal.UTF_8);
753fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
754fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
755a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
756a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Tells whether this {@code ByteString} represents a well-formed UTF-8
757a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * byte sequence, such that the original bytes can be converted to a
758a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * String object and then round tripped back to bytes without loss.
759a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
760a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>More precisely, returns {@code true} whenever: <pre> {@code
761a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Arrays.equals(byteString.toByteArray(),
762a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     new String(byteString.toByteArray(), "UTF-8").getBytes("UTF-8"))
763a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * }</pre>
764a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
765a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>This method returns {@code false} for "overlong" byte sequences,
766a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * as well as for 3-byte sequences that would map to a surrogate
767a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * character, in accordance with the restricted definition of UTF-8
768a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * introduced in Unicode 3.1.  Note that the UTF-8 decoder included in
769a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Oracle's JDK has been modified to also reject "overlong" byte
770a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * sequences, but (as of 2011) still accepts 3-byte surrogate
771a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * character byte sequences.
772a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
773b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>See the Unicode Standard,<br>
774b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Table 3-6. <em>UTF-8 Bit Distribution</em>,<br>
775a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Table 3-7. <em>Well Formed UTF-8 Byte Sequences</em>.
776a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
777a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return whether the bytes in this {@code ByteString} are a
778a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * well-formed UTF-8 byte sequence
779a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
780a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract boolean isValidUtf8();
781a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
782a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
783a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Tells whether the given byte sequence is a well-formed, malformed, or
784a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * incomplete UTF-8 byte sequence.  This method accepts and returns a partial
785a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * state result, allowing the bytes for a complete UTF-8 byte sequence to be
786a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * composed from multiple {@code ByteString} segments.
787a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
788a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param state either {@code 0} (if this is the initial decoding operation)
789a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     or the value returned from a call to a partial decoding method for the
790a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     previous bytes
791a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param offset offset of the first byte to check
792a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param length number of bytes to check
793a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
794a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return {@code -1} if the partial byte sequence is definitely malformed,
795a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@code 0} if it is well-formed (no additional input needed), or, if the
796a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * byte sequence is "incomplete", i.e. apparently terminated in the middle of
797a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * a character, an opaque integer "state" value containing enough information
798a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * to decode the character when passed to a subsequent invocation of a
799a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * partial decoding method.
800a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
801a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  protected abstract int partialIsValidUtf8(int state, int offset, int length);
802a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
803fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
804fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // equals() and hashCode()
805fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
806fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  @Override
807a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract boolean equals(Object o);
808fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
809a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
810b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Base class for leaf {@link ByteString}s (i.e. non-ropes).
811b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
812b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  abstract static class LeafByteString extends ByteString {
813b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
814b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final int getTreeDepth() {
815b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return 0;
816b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
817b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
818b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
819b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final boolean isBalanced() {
820b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return true;
821b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
822b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
823b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
824b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Check equality of the substring of given length of this object starting at
825b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * zero with another {@code ByteString} substring starting at offset.
826b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
827b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param other  what to compare a substring in
828b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param offset offset into other
829b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param length number of bytes to compare
830b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @return true for equality of substrings, else false.
831b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
832b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    abstract boolean equalsRange(ByteString other, int offset, int length);
833b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
834b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
835b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
836b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Compute the hashCode using the traditional algorithm from {@link
837b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * ByteString}.
838a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
839b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return hashCode value
840a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
841fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  @Override
842b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final int hashCode() {
843b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    int h = hash;
844b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
845b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if (h == 0) {
846b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int size = size();
847b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      h = partialHash(size, 0, size);
848b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (h == 0) {
849b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        h = 1;
850b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
851b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      hash = h;
852b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
853b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return h;
854b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
855fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
856fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
857fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Input stream
858fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
859fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
860fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Creates an {@code InputStream} which can be used to read the bytes.
861a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>
862a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * The {@link InputStream} returned by this method is guaranteed to be
863a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * completely non-blocking.  The method {@link InputStream#available()}
864a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * returns the number of bytes remaining in the stream. The methods
865b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@link InputStream#read(byte[])}, {@link InputStream#read(byte[],int,int)}
866a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * and {@link InputStream#skip(long)} will read/skip as many bytes as are
867b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * available.  The method {@link InputStream#markSupported()} returns
868b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * {@code true}.
869a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>
870a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * The methods in the returned {@link InputStream} might <b>not</b> be
871a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * thread safe.
872a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
873a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return an input stream that returns the bytes of this byte string.
874fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
875a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract InputStream newInput();
876fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
877fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
878fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Creates a {@link CodedInputStream} which can be used to read the bytes.
879a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Using this is often more efficient than creating a {@link CodedInputStream}
880a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * that wraps the result of {@link #newInput()}.
881a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
882a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return stream based on wrapped data
883fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
884a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public abstract CodedInputStream newCodedInput();
885fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
886fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // =================================================================
887fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  // Output stream
888fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
889fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
890a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Creates a new {@link Output} with the given initial capacity. Call {@link
891a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Output#toByteString()} to create the {@code ByteString} instance.
892a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>
893a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * A {@link ByteString.Output} offers the same functionality as a
894a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
895a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * rather than a {@code byte} array.
896a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
897a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param initialCapacity estimate of number of bytes to be written
898a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return {@code OutputStream} for building a {@code ByteString}
899fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
900a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static Output newOutput(int initialCapacity) {
901a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return new Output(initialCapacity);
902fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
903fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
904fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
905a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Creates a new {@link Output}. Call {@link Output#toByteString()} to create
906a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * the {@code ByteString} instance.
907a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * <p>
908a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * A {@link ByteString.Output} offers the same functionality as a
909a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * {@link ByteArrayOutputStream}, except that it returns a {@link ByteString}
910a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * rather than a {@code byte array}.
911a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
912a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return {@code OutputStream} for building a {@code ByteString}
913fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
914fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  public static Output newOutput() {
915a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return new Output(CONCATENATE_BY_COPY_SIZE);
916fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
917fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
918fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
919fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Outputs to a {@code ByteString} instance. Call {@link #toByteString()} to
920fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * create the {@code ByteString} instance.
921fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
922a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  public static final class Output extends OutputStream {
923a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Implementation note.
924a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // The public methods of this class must be synchronized.  ByteStrings
925a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // are guaranteed to be immutable.  Without some sort of locking, it could
926a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // be possible for one thread to call toByteSring(), while another thread
927a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // is still modifying the underlying byte array.
928a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
929a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
930a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // argument passed by user, indicating initial capacity.
931a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private final int initialCapacity;
932a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // ByteStrings to be concatenated to create the result
933a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private final ArrayList<ByteString> flushedBuffers;
934a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Total number of bytes in the ByteStrings of flushedBuffers
935a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private int flushedBuffersTotalBytes;
936a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Current buffer to which we are writing
937a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private byte[] buffer;
938a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    // Location in buffer[] to which we write the next byte.
939a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private int bufferPos;
940fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
941fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    /**
942a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Creates a new ByteString output stream with the specified
943a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * initial capacity.
944a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     *
945a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @param initialCapacity  the initial capacity of the output stream.
946fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville     */
947a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    Output(int initialCapacity) {
948a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (initialCapacity < 0) {
949a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        throw new IllegalArgumentException("Buffer size < 0");
950a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
951a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      this.initialCapacity = initialCapacity;
952a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      this.flushedBuffers = new ArrayList<ByteString>();
953a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      this.buffer = new byte[initialCapacity];
954a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
955a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
956a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
957a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public synchronized void write(int b) {
958a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bufferPos == buffer.length) {
959a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        flushFullBuffer(1);
960a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
961a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      buffer[bufferPos++] = (byte)b;
962a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
963a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
964a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
965a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public synchronized void write(byte[] b, int offset, int length)  {
966a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (length <= buffer.length - bufferPos) {
967a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // The bytes can fit into the current buffer.
968a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        System.arraycopy(b, offset, buffer, bufferPos, length);
969a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferPos += length;
970a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
971a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Use up the current buffer
972a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        int copySize  = buffer.length - bufferPos;
973a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        System.arraycopy(b, offset, buffer, bufferPos, copySize);
974a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        offset += copySize;
975a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        length -= copySize;
976a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Flush the buffer, and get a new buffer at least big enough to cover
977a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // what we still need to output
978a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        flushFullBuffer(length);
979a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        System.arraycopy(b, offset, buffer, 0 /* count */, length);
980a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        bufferPos = length;
981a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
982fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
983fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
984fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    /**
985a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Creates a byte string. Its size is the current size of this output
986a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * stream and its output has been copied to it.
987a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     *
988a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @return  the current contents of this output stream, as a byte string.
989fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville     */
990a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public synchronized ByteString toByteString() {
991a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushLastBuffer();
992a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return ByteString.copyFrom(flushedBuffers);
993a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
994b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
995a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
996a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Implement java.util.Arrays.copyOf() for jdk 1.5.
997a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
998a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private byte[] copyArray(byte[] buffer, int length) {
999a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      byte[] result = new byte[length];
1000a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
1001a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return result;
1002a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1003a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1004a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
1005a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Writes the complete contents of this byte array output stream to
1006a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * the specified output stream argument.
1007a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     *
1008a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @param out the output stream to which to write the data.
1009a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @throws IOException  if an I/O error occurs.
1010a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
1011a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public void writeTo(OutputStream out) throws IOException {
1012a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      ByteString[] cachedFlushBuffers;
1013a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      byte[] cachedBuffer;
1014a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int cachedBufferPos;
1015a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      synchronized (this) {
1016a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Copy the information we need into local variables so as to hold
1017a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // the lock for as short a time as possible.
1018a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        cachedFlushBuffers =
1019a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson            flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
1020a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        cachedBuffer = buffer;
1021a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        cachedBufferPos = bufferPos;
1022a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
1023a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      for (ByteString byteString : cachedFlushBuffers) {
1024a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        byteString.writeTo(out);
1025a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
1026a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1027a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      out.write(copyArray(cachedBuffer, cachedBufferPos));
1028a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1029a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1030a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
1031a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Returns the current size of the output stream.
1032a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     *
1033a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * @return  the current size of the output stream
1034a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
1035a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public synchronized int size() {
1036a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return flushedBuffersTotalBytes + bufferPos;
1037a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1038a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1039a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
1040a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Resets this stream, so that all currently accumulated output in the
1041a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * output stream is discarded. The output stream can be used again,
1042a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * reusing the already allocated buffer space.
1043a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
1044a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public synchronized void reset() {
1045a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushedBuffers.clear();
1046a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushedBuffersTotalBytes = 0;
1047a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = 0;
1048a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1049a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1050a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    @Override
1051a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    public String toString() {
1052a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return String.format("<ByteString.Output@%s size=%d>",
1053a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          Integer.toHexString(System.identityHashCode(this)), size());
1054a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1055a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1056a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
1057a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Internal function used by writers.  The current buffer is full, and the
1058a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * writer needs a new buffer whose size is at least the specified minimum
1059a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * size.
1060a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
1061a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private void flushFullBuffer(int minSize)  {
1062a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushedBuffers.add(new LiteralByteString(buffer));
1063a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushedBuffersTotalBytes += buffer.length;
1064a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // We want to increase our total capacity by 50%, but as a minimum,
1065a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // the new buffer should also at least be >= minSize and
1066a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      // >= initial Capacity.
1067a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      int newSize = Math.max(initialCapacity,
1068a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          Math.max(minSize, flushedBuffersTotalBytes >>> 1));
1069a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      buffer = new byte[newSize];
1070a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = 0;
1071a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    }
1072a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1073a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    /**
1074a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * Internal function used by {@link #toByteString()}. The current buffer may
1075a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     * or may not be full, but it needs to be flushed.
1076a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson     */
1077a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private void flushLastBuffer()  {
1078a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      if (bufferPos < buffer.length) {
1079a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        if (bufferPos > 0) {
1080a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          byte[] bufferCopy = copyArray(buffer, bufferPos);
1081a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson          flushedBuffers.add(new LiteralByteString(bufferCopy));
1082a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        }
1083a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // We reuse this buffer for further writes.
1084a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      } else {
1085a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // Buffer is completely full.  Huzzah.
1086a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        flushedBuffers.add(new LiteralByteString(buffer));
1087a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // 99% of the time, we're not going to use this OutputStream again.
1088a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // We set buffer to an empty byte stream so that we're handling this
1089a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // case without wasting space.  In the rare case that more writes
1090a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // *do* occur, this empty buffer will be flushed and an appropriately
1091a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        // sized new buffer will be created.
1092a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        buffer = EMPTY_BYTE_ARRAY;
1093a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      }
1094a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      flushedBuffersTotalBytes += bufferPos;
1095a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      bufferPos = 0;
1096fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1097fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1098fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1099fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /**
1100a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Constructs a new {@code ByteString} builder, which allows you to
1101a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * efficiently construct a {@code ByteString} by writing to a {@link
1102a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * CodedOutputStream}. Using this is much more efficient than calling {@code
1103a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * newOutput()} and wrapping that in a {@code CodedOutputStream}.
1104fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1105fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * <p>This is package-private because it's a somewhat confusing interface.
1106fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * Users can call {@link Message#toByteString()} instead of calling this
1107fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   * directly.
1108fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   *
1109a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param size The target byte size of the {@code ByteString}.  You must write
1110a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *     exactly this many bytes before building the result.
1111a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return the builder
1112fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville   */
1113a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  static CodedBuilder newCodedBuilder(int size) {
1114fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    return new CodedBuilder(size);
1115fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1116fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1117fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  /** See {@link ByteString#newCodedBuilder(int)}. */
1118fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  static final class CodedBuilder {
1119fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    private final CodedOutputStream output;
1120fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    private final byte[] buffer;
1121fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1122a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    private CodedBuilder(int size) {
1123fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      buffer = new byte[size];
1124fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      output = CodedOutputStream.newInstance(buffer);
1125fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1126fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1127fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    public ByteString build() {
1128fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      output.checkNoSpaceLeft();
1129fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1130fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // We can be confident that the CodedOutputStream will not modify the
1131fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // underlying bytes anymore because it already wrote all of them.  So,
1132fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      // no need to make a copy.
1133a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson      return new LiteralByteString(buffer);
1134fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1135fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville
1136fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    public CodedOutputStream getCodedOutput() {
1137fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville      return output;
1138fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville    }
1139fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville  }
1140a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1141a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // =================================================================
1142a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // Methods {@link RopeByteString} needs on instances, which aren't part of the
1143a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  // public API.
1144a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1145a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1146a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return the depth of the tree representing this {@code ByteString}, if any,
1147a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * whose root is this node. If this is a leaf node, return 0.
1148a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1149a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return tree depth or zero
1150a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1151a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  protected abstract int getTreeDepth();
1152a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1153a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1154a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return {@code true} if this ByteString is literal (a leaf node) or a
1155a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * flat-enough tree in the sense of {@link RopeByteString}.
1156a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1157a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return true if the tree is flat enough
1158a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1159a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  protected abstract boolean isBalanced();
1160a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1161a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1162a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Return the cached hash code if available.
1163a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1164a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return value of cached hash code or 0 if not computed yet
1165a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1166b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  protected final int peekCachedHashCode() {
1167b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return hash;
1168b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1169a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1170a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  /**
1171a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * Compute the hash across the value bytes starting with the given hash, and
1172a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * return the result.  This is used to compute the hash across strings
1173a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * represented as a set of pieces by allowing the hash computation to be
1174a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * continued from piece to piece.
1175a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   *
1176a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param h starting hash value
1177a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param offset offset into this value to start looking at data values
1178a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @param length number of data values to include in the hash computation
1179a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   * @return ending hash value
1180a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson   */
1181a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  protected abstract int partialHash(int h, int offset, int length);
1182a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson
1183b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
1184b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Checks that the given index falls within the specified array size.
1185b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1186b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param index the index position to be tested
1187b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param size the length of the array
1188b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @throws IndexOutOfBoundsException if the index does not fall within the array.
1189b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
1190b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static void checkIndex(int index, int size) {
1191b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if ((index | (size - (index + 1))) < 0) {
1192b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (index < 0) {
1193b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new ArrayIndexOutOfBoundsException("Index < 0: " + index);
1194b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1195b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new ArrayIndexOutOfBoundsException("Index > length: " + index + ", " + size);
1196b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1197b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1198b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1199b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
1200b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * Checks that the given range falls within the bounds of an array
1201b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1202b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param startIndex the start index of the range (inclusive)
1203b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param endIndex the end index of the range (exclusive)
1204b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @param size the size of the array.
1205b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @return the length of the range.
1206b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @throws IndexOutOfBoundsException some or all of the range falls outside of the array.
1207b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
1208b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  static int checkRange(int startIndex, int endIndex, int size) {
1209b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final int length = endIndex - startIndex;
1210b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    if ((startIndex | endIndex | length | (size - endIndex)) < 0) {
1211b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (startIndex < 0) {
1212b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new IndexOutOfBoundsException("Beginning index: " + startIndex + " < 0");
1213b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1214b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (endIndex < startIndex) {
1215b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new IndexOutOfBoundsException(
1216b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            "Beginning index larger than ending index: " + startIndex + ", " + endIndex);
1217b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1218b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // endIndex >= size
1219b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new IndexOutOfBoundsException("End index: " + endIndex + " >= " + size);
1220b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1221b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    return length;
1222b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1223b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1224a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  @Override
1225b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  public final String toString() {
1226a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson    return String.format("<ByteString@%s size=%d>",
1227a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson        Integer.toHexString(System.identityHashCode(this)), size());
1228a3b2a6da25a76f17c73d31def3952feb0fd2296eJeff Davidson  }
1229b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1230b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
1231b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * This class implements a {@link com.google.protobuf.ByteString} backed by a
1232b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * single array of bytes, contiguous in memory. It supports substring by
1233b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * pointing to only a sub-range of the underlying byte array, meaning that a
1234b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * substring will reference the full byte-array of the string it's made from,
1235b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * exactly as with {@link String}.
1236b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1237b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @author carlanton@google.com (Carl Haverl)
1238b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
1239b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1240b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // static initializer loads LiteralByteString and another thread loads LiteralByteString.
1241b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static class LiteralByteString extends ByteString.LeafByteString {
1242b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private static final long serialVersionUID = 1L;
1243b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1244b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final byte[] bytes;
1245b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1246b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
1247b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Creates a {@code LiteralByteString} backed by the given array, without
1248b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * copying.
1249b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
1250b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param bytes array to wrap
1251b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
1252b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    LiteralByteString(byte[] bytes) {
1253b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      this.bytes = bytes;
1254b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1255b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1256b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1257b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public byte byteAt(int index) {
1258b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Unlike most methods in this class, this one is a direct implementation
1259b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // ignoring the potential offset because we need to do range-checking in the
1260b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // substring case anyway.
1261b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return bytes[index];
1262b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1263b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1264b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1265b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public int size() {
1266b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return bytes.length;
1267b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1268b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1269b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1270b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // ByteString -> substring
1271b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1272b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1273b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final ByteString substring(int beginIndex, int endIndex) {
1274b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      final int length = checkRange(beginIndex, endIndex, size());
1275b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1276b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (length == 0) {
1277b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return ByteString.EMPTY;
1278b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1279b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1280b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return new BoundedByteString(bytes, getOffsetIntoBytes() + beginIndex, length);
1281b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1282b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1283b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1284b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // ByteString -> byte[]
1285b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1286b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1287b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected void copyToInternal(
1288b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
1289b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // Optimized form, not for subclasses, since we don't call
1290b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // getOffsetIntoBytes() or check the 'numberToCopy' parameter.
1291b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // TODO(nathanmittler): Is not calling getOffsetIntoBytes really saving that much?
1292b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      System.arraycopy(bytes, sourceOffset, target, targetOffset, numberToCopy);
1293b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1294b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1295b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1296b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final void copyTo(ByteBuffer target) {
1297b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      target.put(bytes, getOffsetIntoBytes(), size()); // Copies bytes
1298b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1299b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1300b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1301b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final ByteBuffer asReadOnlyByteBuffer() {
1302b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return ByteBuffer.wrap(bytes, getOffsetIntoBytes(), size()).asReadOnlyBuffer();
1303b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1304b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1305b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1306b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final List<ByteBuffer> asReadOnlyByteBufferList() {
1307b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return Collections.singletonList(asReadOnlyByteBuffer());
1308b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1309b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1310b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1311b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final void writeTo(OutputStream outputStream) throws IOException {
1312b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      outputStream.write(toByteArray());
1313b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1314b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1315b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1316b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final void writeToInternal(OutputStream outputStream, int sourceOffset, int numberToWrite)
1317b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throws IOException {
1318b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      outputStream.write(bytes, getOffsetIntoBytes() + sourceOffset, numberToWrite);
1319b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1320b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1321b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1322b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final void writeTo(ByteOutput output) throws IOException {
1323b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      output.writeLazy(bytes, getOffsetIntoBytes(), size());
1324b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1325b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1326b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1327b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final String toStringInternal(Charset charset) {
1328b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return new String(bytes, getOffsetIntoBytes(), size(), charset);
1329b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1330b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1331b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1332b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // UTF-8 decoding
1333b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1334b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1335b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final boolean isValidUtf8() {
1336b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int offset = getOffsetIntoBytes();
1337b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return Utf8.isValidUtf8(bytes, offset, offset + size());
1338b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1339b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1340b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1341b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final int partialIsValidUtf8(int state, int offset, int length) {
1342b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      int index = getOffsetIntoBytes() + offset;
1343b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return Utf8.partialIsValidUtf8(state, bytes, index, index + length);
1344b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1345b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1346b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1347b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // equals() and hashCode()
1348b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1349b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1350b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final boolean equals(Object other) {
1351b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (other == this) {
1352b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
1353b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1354b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (!(other instanceof ByteString)) {
1355b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
1356b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1357b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1358b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (size() != ((ByteString) other).size()) {
1359b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return false;
1360b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1361b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (size() == 0) {
1362b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
1363b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1364b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1365b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (other instanceof LiteralByteString) {
1366b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        LiteralByteString otherAsLiteral = (LiteralByteString) other;
1367b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        // If we know the hash codes and they are not equal, we know the byte
1368b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        // strings are not equal.
1369b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        int thisHash = peekCachedHashCode();
1370b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        int thatHash = otherAsLiteral.peekCachedHashCode();
1371b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        if (thisHash != 0 && thatHash != 0 && thisHash != thatHash) {
1372b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          return false;
1373b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
1374b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1375b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return equalsRange((LiteralByteString) other, 0, size());
1376b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      } else {
1377b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        // RopeByteString and NioByteString.
1378b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return other.equals(this);
1379b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1380b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1381b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1382b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
1383b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Check equality of the substring of given length of this object starting at
1384b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * zero with another {@code LiteralByteString} substring starting at offset.
1385b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
1386b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param other  what to compare a substring in
1387b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param offset offset into other
1388b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param length number of bytes to compare
1389b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @return true for equality of substrings, else false.
1390b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
1391b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1392b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    final boolean equalsRange(ByteString other, int offset, int length) {
1393b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (length > other.size()) {
1394b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new IllegalArgumentException("Length too large: " + length + size());
1395b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1396b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (offset + length > other.size()) {
1397b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        throw new IllegalArgumentException(
1398b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            "Ran off end of other: " + offset + ", " + length + ", " + other.size());
1399b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1400b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1401b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      if (other instanceof LiteralByteString) {
1402b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        LiteralByteString lbsOther = (LiteralByteString) other;
1403b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        byte[] thisBytes = bytes;
1404b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        byte[] otherBytes = lbsOther.bytes;
1405b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        int thisLimit = getOffsetIntoBytes() + length;
1406b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        for (
1407b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            int thisIndex = getOffsetIntoBytes(),
1408b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer                otherIndex = lbsOther.getOffsetIntoBytes() + offset;
1409b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            (thisIndex < thisLimit); ++thisIndex, ++otherIndex) {
1410b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          if (thisBytes[thisIndex] != otherBytes[otherIndex]) {
1411b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer            return false;
1412b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          }
1413b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        }
1414b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        return true;
1415b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      }
1416b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1417b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return other.substring(offset, offset + length).equals(substring(0, length));
1418b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1419b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1420b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1421b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected final int partialHash(int h, int offset, int length) {
1422b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return Internal.partialHash(h, bytes, getOffsetIntoBytes() + offset, length);
1423b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1424b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1425b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1426b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // Input stream
1427b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1428b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1429b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final InputStream newInput() {
1430b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return new ByteArrayInputStream(bytes, getOffsetIntoBytes(), size()); // No copy
1431b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1432b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1433b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1434b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public final CodedInputStream newCodedInput() {
1435b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // We trust CodedInputStream not to modify the bytes, or to give anyone
1436b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // else access to them.
1437b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return CodedInputStream.newInstance(
1438b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          bytes, getOffsetIntoBytes(), size(), true /* bufferIsImmutable */);
1439b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1440b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1441b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1442b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // Internal methods
1443b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1444b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
1445b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Offset into {@code bytes[]} to use, non-zero for substrings.
1446b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
1447b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @return always 0 for this class
1448b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
1449b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected int getOffsetIntoBytes() {
1450b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return 0;
1451b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1452b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1453b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1454b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  /**
1455b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * This class is used to represent the substring of a {@link ByteString} over a
1456b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * single byte array. In terms of the public API of {@link ByteString}, you end
1457b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
1458b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * ByteString#substring(int, int)}.
1459b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1460b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * <p>This class contains most of the overhead involved in creating a substring
1461b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * from a {@link LiteralByteString}.  The overhead involves some range-checking
1462b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * and two extra fields.
1463b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   *
1464b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   * @author carlanton@google.com (Carl Haverl)
1465b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer   */
1466b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
1467b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  // static initializer loads LiteralByteString and another thread loads BoundedByteString.
1468b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  private static final class BoundedByteString extends LiteralByteString {
1469b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1470b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private final int bytesOffset;
1471b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private final int bytesLength;
1472b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1473b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
1474b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Creates a {@code BoundedByteString} backed by the sub-range of given array,
1475b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * without copying.
1476b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
1477b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param bytes  array to wrap
1478b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param offset index to first byte to use in bytes
1479b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param length number of bytes to use from bytes
1480b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
1481b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *                                  or if {@code offset + length >
1482b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *                                  bytes.length}.
1483b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
1484b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    BoundedByteString(byte[] bytes, int offset, int length) {
1485b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      super(bytes);
1486b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      checkRange(offset, offset + length, bytes.length);
1487b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1488b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      this.bytesOffset = offset;
1489b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      this.bytesLength = length;
1490b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1491b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1492b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    /**
1493b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Gets the byte at the given index.
1494b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * Throws {@link ArrayIndexOutOfBoundsException}
1495b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * for backwards-compatibility reasons although it would more properly be
1496b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * {@link IndexOutOfBoundsException}.
1497b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     *
1498b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @param index index of byte
1499b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @return the value
1500b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
1501b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer     */
1502b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1503b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public byte byteAt(int index) {
1504b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // We must check the index ourselves as we cannot rely on Java array index
1505b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      // checking for substrings.
1506b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      checkIndex(index, size());
1507b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return bytes[bytesOffset + index];
1508b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1509b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1510b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1511b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    public int size() {
1512b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return bytesLength;
1513b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1514b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1515b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1516b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected int getOffsetIntoBytes() {
1517b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return bytesOffset;
1518b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1519b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1520b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1521b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // ByteString -> byte[]
1522b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1523b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    @Override
1524b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    protected void copyToInternal(byte[] target, int sourceOffset, int targetOffset,
1525b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer        int numberToCopy) {
1526b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
1527b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          targetOffset, numberToCopy);
1528b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1529b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1530b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // =================================================================
1531b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    // Serializable
1532b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1533b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private static final long serialVersionUID = 1L;
1534b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1535b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    Object writeReplace() {
1536b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      return ByteString.wrap(toByteArray());
1537b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1538b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer
1539b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
1540b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer      throw new InvalidObjectException(
1541b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer          "BoundedByteStream instances are not to be serialized directly");
1542b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer    }
1543b0575e93e4c39dec69365b850088a1eb7f82c5b3Tamas Berghammer  }
1544fbaaef999ba563838ebd00874ed8a1c01fbf286dWink Saville}
1545