1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 package com.google.protobuf;
33 import java.util.NoSuchElementException;
36 * This class is used to represent the substring of a {@link ByteString} over a
37 * single byte array. In terms of the public API of {@link ByteString}, you end
38 * up here by calling {@link ByteString#copyFrom(byte[])} followed by {@link
39 * ByteString#substring(int, int)}.
41 * <p>This class contains most of the overhead involved in creating a substring
42 * from a {@link LiteralByteString}. The overhead involves some range-checking
43 * and two extra fields.
45 * @author carlanton@google.com (Carl Haverl)
47 class BoundedByteString extends LiteralByteString {
49 private final int bytesOffset;
50 private final int bytesLength;
53 * Creates a {@code BoundedByteString} backed by the sub-range of given array,
56 * @param bytes array to wrap
57 * @param offset index to first byte to use in bytes
58 * @param length number of bytes to use from bytes
59 * @throws IllegalArgumentException if {@code offset < 0}, {@code length < 0},
60 * or if {@code offset + length >
63 BoundedByteString(byte[] bytes, int offset, int length) {
66 throw new IllegalArgumentException("Offset too small: " + offset);
69 throw new IllegalArgumentException("Length too small: " + offset);
71 if ((long) offset + length > bytes.length) {
72 throw new IllegalArgumentException(
73 "Offset+Length too large: " + offset + "+" + length);
76 this.bytesOffset = offset;
77 this.bytesLength = length;
81 * Gets the byte at the given index.
82 * Throws {@link ArrayIndexOutOfBoundsException}
83 * for backwards-compatibility reasons although it would more properly be
84 * {@link IndexOutOfBoundsException}.
86 * @param index index of byte
88 * @throws ArrayIndexOutOfBoundsException {@code index} is < 0 or >= size
91 public byte byteAt(int index) {
92 // We must check the index ourselves as we cannot rely on Java array index
93 // checking for substrings.
95 throw new ArrayIndexOutOfBoundsException("Index too small: " + index);
97 if (index >= size()) {
98 throw new ArrayIndexOutOfBoundsException(
99 "Index too large: " + index + ", " + size());
102 return bytes[bytesOffset + index];
111 protected int getOffsetIntoBytes() {
115 // =================================================================
116 // ByteString -> byte[]
119 protected void copyToInternal(byte[] target, int sourceOffset,
120 int targetOffset, int numberToCopy) {
121 System.arraycopy(bytes, getOffsetIntoBytes() + sourceOffset, target,
122 targetOffset, numberToCopy);
125 // =================================================================
129 public ByteIterator iterator() {
130 return new BoundedByteIterator();
133 private class BoundedByteIterator implements ByteIterator {
135 private int position;
136 private final int limit;
138 private BoundedByteIterator() {
139 position = getOffsetIntoBytes();
140 limit = position + size();
143 public boolean hasNext() {
144 return (position < limit);
148 // Boxing calls Byte.valueOf(byte), which does not instantiate.
152 public byte nextByte() {
153 if (position >= limit) {
154 throw new NoSuchElementException();
156 return bytes[position++];
159 public void remove() {
160 throw new UnsupportedOperationException();