NioByteString.java
Go to the documentation of this file.
1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 // * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 // * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 package com.google.protobuf;
32 
33 import static com.google.protobuf.Internal.checkNotNull;
34 
35 import java.io.IOException;
36 import java.io.InputStream;
37 import java.io.InvalidObjectException;
38 import java.io.ObjectInputStream;
39 import java.io.OutputStream;
40 import java.nio.ByteBuffer;
41 import java.nio.ByteOrder;
42 import java.nio.InvalidMarkException;
43 import java.nio.charset.Charset;
44 import java.util.Collections;
45 import java.util.List;
46 
48 final class NioByteString extends ByteString.LeafByteString {
49  private final ByteBuffer buffer;
50 
51  NioByteString(ByteBuffer buffer) {
52  checkNotNull(buffer, "buffer");
53 
54  // Use native byte order for fast fixed32/64 operations.
55  this.buffer = buffer.slice().order(ByteOrder.nativeOrder());
56  }
57 
58  // =================================================================
59  // Serializable
60 
62  private Object writeReplace() {
63  return ByteString.copyFrom(buffer.slice());
64  }
65 
67  private void readObject(@SuppressWarnings("unused") ObjectInputStream in) throws IOException {
68  throw new InvalidObjectException("NioByteString instances are not to be serialized directly");
69  }
70 
71  // =================================================================
72 
73  @Override
74  public byte byteAt(int index) {
75  try {
76  return buffer.get(index);
77  } catch (ArrayIndexOutOfBoundsException e) {
78  throw e;
79  } catch (IndexOutOfBoundsException e) {
80  throw new ArrayIndexOutOfBoundsException(e.getMessage());
81  }
82  }
83 
84  @Override
85  public byte internalByteAt(int index) {
86  // it isn't possible to avoid the bounds checking inside of ByteBuffer, so just use the default
87  // implementation.
88  return byteAt(index);
89  }
90 
91  @Override
92  public int size() {
93  return buffer.remaining();
94  }
95 
96  @Override
97  public ByteString substring(int beginIndex, int endIndex) {
98  try {
99  ByteBuffer slice = slice(beginIndex, endIndex);
100  return new NioByteString(slice);
101  } catch (ArrayIndexOutOfBoundsException e) {
102  throw e;
103  } catch (IndexOutOfBoundsException e) {
104  throw new ArrayIndexOutOfBoundsException(e.getMessage());
105  }
106  }
107 
108  @Override
109  protected void copyToInternal(
110  byte[] target, int sourceOffset, int targetOffset, int numberToCopy) {
111  ByteBuffer slice = buffer.slice();
112  slice.position(sourceOffset);
113  slice.get(target, targetOffset, numberToCopy);
114  }
115 
116  @Override
117  public void copyTo(ByteBuffer target) {
118  target.put(buffer.slice());
119  }
120 
121  @Override
122  public void writeTo(OutputStream out) throws IOException {
123  out.write(toByteArray());
124  }
125 
126  @Override
127  boolean equalsRange(ByteString other, int offset, int length) {
128  return substring(0, length).equals(other.substring(offset, offset + length));
129  }
130 
131  @Override
132  void writeToInternal(OutputStream out, int sourceOffset, int numberToWrite) throws IOException {
133  if (buffer.hasArray()) {
134  // Optimized write for array-backed buffers.
135  // Note that we're taking the risk that a malicious OutputStream could modify the array.
136  int bufferOffset = buffer.arrayOffset() + buffer.position() + sourceOffset;
137  out.write(buffer.array(), bufferOffset, numberToWrite);
138  return;
139  }
140 
141  ByteBufferWriter.write(slice(sourceOffset, sourceOffset + numberToWrite), out);
142  }
143 
144  @Override
145  void writeTo(ByteOutput output) throws IOException {
146  output.writeLazy(buffer.slice());
147  }
148 
149  @Override
150  public ByteBuffer asReadOnlyByteBuffer() {
151  return buffer.asReadOnlyBuffer();
152  }
153 
154  @Override
155  public List<ByteBuffer> asReadOnlyByteBufferList() {
156  return Collections.singletonList(asReadOnlyByteBuffer());
157  }
158 
159  @Override
160  protected String toStringInternal(Charset charset) {
161  final byte[] bytes;
162  final int offset;
163  final int length;
164  if (buffer.hasArray()) {
165  bytes = buffer.array();
166  offset = buffer.arrayOffset() + buffer.position();
167  length = buffer.remaining();
168  } else {
169  // TODO(nathanmittler): Can we optimize this?
170  bytes = toByteArray();
171  offset = 0;
172  length = bytes.length;
173  }
174  return new String(bytes, offset, length, charset);
175  }
176 
177  @Override
178  public boolean isValidUtf8() {
179  return Utf8.isValidUtf8(buffer);
180  }
181 
182  @Override
183  protected int partialIsValidUtf8(int state, int offset, int length) {
184  return Utf8.partialIsValidUtf8(state, buffer, offset, offset + length);
185  }
186 
187  @Override
188  public boolean equals(Object other) {
189  if (other == this) {
190  return true;
191  }
192  if (!(other instanceof ByteString)) {
193  return false;
194  }
195  ByteString otherString = ((ByteString) other);
196  if (size() != otherString.size()) {
197  return false;
198  }
199  if (size() == 0) {
200  return true;
201  }
202  if (other instanceof NioByteString) {
203  return buffer.equals(((NioByteString) other).buffer);
204  }
205  if (other instanceof RopeByteString) {
206  return other.equals(this);
207  }
208  return buffer.equals(otherString.asReadOnlyByteBuffer());
209  }
210 
211  @Override
212  protected int partialHash(int h, int offset, int length) {
213  for (int i = offset; i < offset + length; i++) {
214  h = h * 31 + buffer.get(i);
215  }
216  return h;
217  }
218 
219  @Override
220  public InputStream newInput() {
221  return new InputStream() {
222  private final ByteBuffer buf = buffer.slice();
223 
224  @Override
225  public void mark(int readlimit) {
226  buf.mark();
227  }
228 
229  @Override
230  public boolean markSupported() {
231  return true;
232  }
233 
234  @Override
235  public void reset() throws IOException {
236  try {
237  buf.reset();
238  } catch (InvalidMarkException e) {
239  throw new IOException(e);
240  }
241  }
242 
243  @Override
244  public int available() throws IOException {
245  return buf.remaining();
246  }
247 
248  @Override
249  public int read() throws IOException {
250  if (!buf.hasRemaining()) {
251  return -1;
252  }
253  return buf.get() & 0xFF;
254  }
255 
256  @Override
257  public int read(byte[] bytes, int off, int len) throws IOException {
258  if (!buf.hasRemaining()) {
259  return -1;
260  }
261 
262  len = Math.min(len, buf.remaining());
263  buf.get(bytes, off, len);
264  return len;
265  }
266  };
267  }
268 
269  @Override
270  public CodedInputStream newCodedInput() {
271  return CodedInputStream.newInstance(buffer, true);
272  }
273 
281  private ByteBuffer slice(int beginIndex, int endIndex) {
282  if (beginIndex < buffer.position() || endIndex > buffer.limit() || beginIndex > endIndex) {
283  throw new IllegalArgumentException(
284  String.format("Invalid indices [%d, %d]", beginIndex, endIndex));
285  }
286 
287  ByteBuffer slice = buffer.slice();
288  slice.position(beginIndex - buffer.position());
289  slice.limit(endIndex - buffer.position());
290  return slice;
291  }
292 }
length
GLenum GLuint GLenum GLsizei length
Definition: glcorearb.h:2695
com.google.protobuf
Definition: ProtoCaliperBenchmark.java:2
target
GLenum target
Definition: glcorearb.h:3739
bytes
uint8 bytes[10]
Definition: coded_stream_unittest.cc:153
offset
GLintptr offset
Definition: glcorearb.h:2944
buffer
GLuint buffer
Definition: glcorearb.h:2939
size
#define size
Definition: glcorearb.h:2944
buffer
Definition: buffer_processor.h:43
buf
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glcorearb.h:4175
i
int i
Definition: gmock-matchers_test.cc:764
java
len
int len
Definition: php/ext/google/protobuf/map.c:206
com.google
com
com.google.protobuf.Internal
Definition: Internal.java:54
output
const upb_json_parsermethod const upb_symtab upb_sink * output
Definition: ruby/ext/google/protobuf_c/upb.h:10503
index
GLuint index
Definition: glcorearb.h:3055
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glcorearb.h:4147


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