Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1023)

Side by Side Diff: third_party/protobuf/java/core/src/main/java/com/google/protobuf/CodedOutputStream.java

Issue 2599263002: third_party/protobuf: Update to HEAD (f52e188fe4) (Closed)
Patch Set: Address comments Created 3 years, 12 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // https://developers.google.com/protocol-buffers/ 3 // https://developers.google.com/protocol-buffers/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 12 matching lines...) Expand all
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 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. 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 30
31 package com.google.protobuf; 31 package com.google.protobuf;
32 32
33 import static com.google.protobuf.WireFormat.FIXED_32_SIZE;
34 import static com.google.protobuf.WireFormat.FIXED_64_SIZE;
35 import static com.google.protobuf.WireFormat.MAX_VARINT_SIZE;
33 import static java.lang.Math.max; 36 import static java.lang.Math.max;
34 37
35 import com.google.protobuf.Utf8.UnpairedSurrogateException; 38 import com.google.protobuf.Utf8.UnpairedSurrogateException;
36
37 import java.io.IOException; 39 import java.io.IOException;
38 import java.io.OutputStream; 40 import java.io.OutputStream;
39 import java.lang.reflect.Field;
40 import java.nio.BufferOverflowException; 41 import java.nio.BufferOverflowException;
41 import java.nio.ByteBuffer; 42 import java.nio.ByteBuffer;
42 import java.nio.ByteOrder; 43 import java.nio.ByteOrder;
43 import java.security.AccessController;
44 import java.security.PrivilegedExceptionAction;
45 import java.util.logging.Level; 44 import java.util.logging.Level;
46 import java.util.logging.Logger; 45 import java.util.logging.Logger;
47 46
48 /** 47 /**
49 * Encodes and writes protocol message fields. 48 * Encodes and writes protocol message fields.
50 * 49 *
51 * <p>This class contains two kinds of methods: methods that write specific 50 * <p>This class contains two kinds of methods: methods that write specific
52 * protocol message constructs and field types (e.g. {@link #writeTag} and 51 * protocol message constructs and field types (e.g. {@link #writeTag} and
53 * {@link #writeInt32}) and methods that write low-level values (e.g. 52 * {@link #writeInt32}) and methods that write low-level values (e.g.
54 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are 53 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are
55 * writing encoded protocol messages, you should use the former methods, but if 54 * writing encoded protocol messages, you should use the former methods, but if
56 * you are writing some other format of your own design, use the latter. 55 * you are writing some other format of your own design, use the latter.
57 * 56 *
58 * <p>This class is totally unsynchronized. 57 * <p>This class is totally unsynchronized.
59 */ 58 */
60 public abstract class CodedOutputStream extends ByteOutput { 59 public abstract class CodedOutputStream extends ByteOutput {
61 private static final Logger logger = Logger.getLogger(CodedOutputStream.class. getName()); 60 private static final Logger logger = Logger.getLogger(CodedOutputStream.class. getName());
62 private static final sun.misc.Unsafe UNSAFE = getUnsafe(); 61 private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsaf eArrayOperations();
63 private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArray Operations(); 62 private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset();
64 private static final long ARRAY_BASE_OFFSET = byteArrayBaseOffset();
65
66 private static final int FIXED_32_SIZE = 4;
67 private static final int FIXED_64_SIZE = 8;
68 private static final int MAX_VARINT_SIZE = 10;
69 63
70 /** 64 /**
71 * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. 65 * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead.
72 */ 66 */
73 @Deprecated 67 @Deprecated
74 public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE; 68 public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE;
75 69
76 /** 70 /**
77 * The buffer size used in {@link #newInstance(OutputStream)}. 71 * The buffer size used in {@link #newInstance(OutputStream)}.
78 */ 72 */
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 * byte array slice. If more bytes are written than fit in the slice, 125 * byte array slice. If more bytes are written than fit in the slice,
132 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 126 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat
133 * array is faster than writing to an {@code OutputStream}. See also 127 * array is faster than writing to an {@code OutputStream}. See also
134 * {@link ByteString#newCodedBuilder}. 128 * {@link ByteString#newCodedBuilder}.
135 */ 129 */
136 public static CodedOutputStream newInstance( 130 public static CodedOutputStream newInstance(
137 final byte[] flatArray, final int offset, final int length) { 131 final byte[] flatArray, final int offset, final int length) {
138 return new ArrayEncoder(flatArray, offset, length); 132 return new ArrayEncoder(flatArray, offset, length);
139 } 133 }
140 134
141 /** 135 /** Create a new {@code CodedOutputStream} that writes to the given {@link Byt eBuffer}. */
142 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte Buffer}. 136 public static CodedOutputStream newInstance(ByteBuffer buffer) {
143 */ 137 if (buffer.hasArray()) {
144 public static CodedOutputStream newInstance(ByteBuffer byteBuffer) { 138 return new HeapNioEncoder(buffer);
145 if (byteBuffer.hasArray()) {
146 return new NioHeapEncoder(byteBuffer);
147 } 139 }
148 return new NioEncoder(byteBuffer); 140 if (buffer.isDirect() && !buffer.isReadOnly()) {
141 return UnsafeDirectNioEncoder.isSupported()
142 ? newUnsafeInstance(buffer)
143 : newSafeInstance(buffer);
144 }
145 throw new IllegalArgumentException("ByteBuffer is read-only");
146 }
147
148 /** For testing purposes only. */
149 static CodedOutputStream newUnsafeInstance(ByteBuffer buffer) {
150 return new UnsafeDirectNioEncoder(buffer);
151 }
152
153 /** For testing purposes only. */
154 static CodedOutputStream newSafeInstance(ByteBuffer buffer) {
155 return new SafeDirectNioEncoder(buffer);
149 } 156 }
150 157
151 /** 158 /**
159 * Configures serialization to be deterministic.
160 *
161 * <p>The deterministic serialization guarantees that for a given binary, equa l (defined by the
162 * {@code equals()} methods in protos) messages will always be serialized to t he same bytes. This
163 * implies:
164 *
165 * <ul>
166 * <li>repeated serialization of a message will return the same bytes
167 * <li>different processes of the same binary (which may be executing on diffe rent machines) will
168 * serialize equal messages to the same bytes.
169 * </ul>
170 *
171 * <p>Note the deterministic serialization is NOT canonical across languages; it is also unstable
172 * across different builds with schema changes due to unknown fields. Users wh o need canonical
173 * serialization, e.g. persistent storage in a canonical form, fingerprinting, etc, should define
174 * their own canonicalization specification and implement the serializer using reflection APIs
175 * rather than relying on this API.
176 *
177 * <p> Once set, the serializer will: (Note this is an implementation detail and may subject to
178 * change in the future)
179 *
180 * <ul>
181 * <li> sort map entries by keys in lexicographical order or numerical order. Note: For string
182 * keys, the order is based on comparing the Unicode value of each charact er in the strings.
183 * The order may be different from the deterministic serialization in othe r languages where
184 * maps are sorted on the lexicographical order of the UTF8 encoded keys.
185 * </ul>
186 */
187 void useDeterministicSerialization() {
188 serializationDeterministic = true;
189 }
190
191 boolean isSerializationDeterministic() {
192 return serializationDeterministic;
193 }
194 private boolean serializationDeterministic;
195
196 /**
152 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte Buffer}. 197 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte Buffer}.
153 * 198 *
154 * @deprecated the size parameter is no longer used since use of an internal b uffer is useless 199 * @deprecated the size parameter is no longer used since use of an internal b uffer is useless
155 * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstanc e(ByteBuffer)} 200 * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstanc e(ByteBuffer)}
156 * instead. 201 * instead.
157 */ 202 */
158 @Deprecated 203 @Deprecated
159 public static CodedOutputStream newInstance(ByteBuffer byteBuffer, 204 public static CodedOutputStream newInstance(ByteBuffer byteBuffer,
160 @SuppressWarnings("unused") int unused) { 205 @SuppressWarnings("unused") int unused) {
161 return newInstance(byteBuffer); 206 return newInstance(byteBuffer);
(...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after
862 } 907 }
863 908
864 /** 909 /**
865 * Compute the number of bytes that would be needed to encode an embedded 910 * Compute the number of bytes that would be needed to encode an embedded
866 * message field. 911 * message field.
867 */ 912 */
868 public static int computeMessageSizeNoTag(final MessageLite value) { 913 public static int computeMessageSizeNoTag(final MessageLite value) {
869 return computeLengthDelimitedFieldSize(value.getSerializedSize()); 914 return computeLengthDelimitedFieldSize(value.getSerializedSize());
870 } 915 }
871 916
872 private static int computeLengthDelimitedFieldSize(int fieldLength) { 917 static int computeLengthDelimitedFieldSize(int fieldLength) {
873 return computeUInt32SizeNoTag(fieldLength) + fieldLength; 918 return computeUInt32SizeNoTag(fieldLength) + fieldLength;
874 } 919 }
875 920
876 /** 921 /**
877 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 922 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
878 * into values that can be efficiently encoded with varint. (Otherwise, 923 * into values that can be efficiently encoded with varint. (Otherwise,
879 * negative values must be sign-extended to 64 bits to be varint encoded, 924 * negative values must be sign-extended to 64 bits to be varint encoded,
880 * thus always taking 10 bytes on the wire.) 925 * thus always taking 10 bytes on the wire.)
881 * 926 *
882 * @param n A signed 32-bit integer. 927 * @param n A signed 32-bit integer.
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
938 public static class OutOfSpaceException extends IOException { 983 public static class OutOfSpaceException extends IOException {
939 private static final long serialVersionUID = -6947486886997889499L; 984 private static final long serialVersionUID = -6947486886997889499L;
940 985
941 private static final String MESSAGE = 986 private static final String MESSAGE =
942 "CodedOutputStream was writing to a flat byte array and ran out of space ."; 987 "CodedOutputStream was writing to a flat byte array and ran out of space .";
943 988
944 OutOfSpaceException() { 989 OutOfSpaceException() {
945 super(MESSAGE); 990 super(MESSAGE);
946 } 991 }
947 992
993 OutOfSpaceException(String explanationMessage) {
994 super(MESSAGE + ": " + explanationMessage);
995 }
996
948 OutOfSpaceException(Throwable cause) { 997 OutOfSpaceException(Throwable cause) {
949 super(MESSAGE, cause); 998 super(MESSAGE, cause);
950 } 999 }
1000
1001 OutOfSpaceException(String explanationMessage, Throwable cause) {
1002 super(MESSAGE + ": " + explanationMessage, cause);
1003 }
951 } 1004 }
952 1005
953 /** 1006 /**
954 * Get the total number of bytes successfully written to this stream. The 1007 * Get the total number of bytes successfully written to this stream. The
955 * returned value is not guaranteed to be accurate if exceptions have been 1008 * returned value is not guaranteed to be accurate if exceptions have been
956 * found in the middle of writing. 1009 * found in the middle of writing.
957 */ 1010 */
958 public abstract int getTotalBytesWritten(); 1011 public abstract int getTotalBytesWritten();
959 1012
960 // ================================================================= 1013 // =================================================================
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1243 public final void writeMessageNoTag(final MessageLite value) throws IOExcept ion { 1296 public final void writeMessageNoTag(final MessageLite value) throws IOExcept ion {
1244 writeUInt32NoTag(value.getSerializedSize()); 1297 writeUInt32NoTag(value.getSerializedSize());
1245 value.writeTo(this); 1298 value.writeTo(this);
1246 } 1299 }
1247 1300
1248 @Override 1301 @Override
1249 public final void write(byte value) throws IOException { 1302 public final void write(byte value) throws IOException {
1250 try { 1303 try {
1251 buffer[position++] = value; 1304 buffer[position++] = value;
1252 } catch (IndexOutOfBoundsException e) { 1305 } catch (IndexOutOfBoundsException e) {
1253 throw new OutOfSpaceException(new IndexOutOfBoundsException( 1306 throw new OutOfSpaceException(
1254 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); 1307 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e) ;
1255 } 1308 }
1256 } 1309 }
1257 1310
1258 @Override 1311 @Override
1259 public final void writeInt32NoTag(int value) throws IOException { 1312 public final void writeInt32NoTag(int value) throws IOException {
1260 if (value >= 0) { 1313 if (value >= 0) {
1261 writeUInt32NoTag(value); 1314 writeUInt32NoTag(value);
1262 } else { 1315 } else {
1263 // Must sign-extend. 1316 // Must sign-extend.
1264 writeUInt64NoTag(value); 1317 writeUInt64NoTag(value);
1265 } 1318 }
1266 } 1319 }
1267 1320
1268 @Override 1321 @Override
1269 public final void writeUInt32NoTag(int value) throws IOException { 1322 public final void writeUInt32NoTag(int value) throws IOException {
1270 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { 1323 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
1271 long pos = ARRAY_BASE_OFFSET + position; 1324 long pos = ARRAY_BASE_OFFSET + position;
1272 while (true) { 1325 while (true) {
1273 if ((value & ~0x7F) == 0) { 1326 if ((value & ~0x7F) == 0) {
1274 UNSAFE.putByte(buffer, pos++, (byte) value); 1327 UnsafeUtil.putByte(buffer, pos++, (byte) value);
1275 position++; 1328 position++;
1276 return; 1329 return;
1277 } else { 1330 } else {
1278 UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); 1331 UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
1279 position++; 1332 position++;
1280 value >>>= 7; 1333 value >>>= 7;
1281 } 1334 }
1282 } 1335 }
1283 } else { 1336 } else {
1284 try { 1337 try {
1285 while (true) { 1338 while (true) {
1286 if ((value & ~0x7F) == 0) { 1339 if ((value & ~0x7F) == 0) {
1287 buffer[position++] = (byte) value; 1340 buffer[position++] = (byte) value;
1288 return; 1341 return;
1289 } else { 1342 } else {
1290 buffer[position++] = (byte) ((value & 0x7F) | 0x80); 1343 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
1291 value >>>= 7; 1344 value >>>= 7;
1292 } 1345 }
1293 } 1346 }
1294 } catch (IndexOutOfBoundsException e) { 1347 } catch (IndexOutOfBoundsException e) {
1295 throw new OutOfSpaceException( 1348 throw new OutOfSpaceException(
1296 new IndexOutOfBoundsException( 1349 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
1297 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
1298 } 1350 }
1299 } 1351 }
1300 } 1352 }
1301 1353
1302 @Override 1354 @Override
1303 public final void writeFixed32NoTag(int value) throws IOException { 1355 public final void writeFixed32NoTag(int value) throws IOException {
1304 try { 1356 try {
1305 buffer[position++] = (byte) (value & 0xFF); 1357 buffer[position++] = (byte) (value & 0xFF);
1306 buffer[position++] = (byte) ((value >> 8) & 0xFF); 1358 buffer[position++] = (byte) ((value >> 8) & 0xFF);
1307 buffer[position++] = (byte) ((value >> 16) & 0xFF); 1359 buffer[position++] = (byte) ((value >> 16) & 0xFF);
1308 buffer[position++] = (byte) ((value >> 24) & 0xFF); 1360 buffer[position++] = (byte) ((value >> 24) & 0xFF);
1309 } catch (IndexOutOfBoundsException e) { 1361 } catch (IndexOutOfBoundsException e) {
1310 throw new OutOfSpaceException( 1362 throw new OutOfSpaceException(
1311 new IndexOutOfBoundsException( 1363 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e) ;
1312 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1) ));
1313 } 1364 }
1314 } 1365 }
1315 1366
1316 @Override 1367 @Override
1317 public final void writeUInt64NoTag(long value) throws IOException { 1368 public final void writeUInt64NoTag(long value) throws IOException {
1318 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { 1369 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) {
1319 long pos = ARRAY_BASE_OFFSET + position; 1370 long pos = ARRAY_BASE_OFFSET + position;
1320 while (true) { 1371 while (true) {
1321 if ((value & ~0x7FL) == 0) { 1372 if ((value & ~0x7FL) == 0) {
1322 UNSAFE.putByte(buffer, pos++, (byte) value); 1373 UnsafeUtil.putByte(buffer, pos++, (byte) value);
1323 position++; 1374 position++;
1324 return; 1375 return;
1325 } else { 1376 } else {
1326 UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); 1377 UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x8 0));
1327 position++; 1378 position++;
1328 value >>>= 7; 1379 value >>>= 7;
1329 } 1380 }
1330 } 1381 }
1331 } else { 1382 } else {
1332 try { 1383 try {
1333 while (true) { 1384 while (true) {
1334 if ((value & ~0x7FL) == 0) { 1385 if ((value & ~0x7FL) == 0) {
1335 buffer[position++] = (byte) value; 1386 buffer[position++] = (byte) value;
1336 return; 1387 return;
1337 } else { 1388 } else {
1338 buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); 1389 buffer[position++] = (byte) (((int) value & 0x7F) | 0x80);
1339 value >>>= 7; 1390 value >>>= 7;
1340 } 1391 }
1341 } 1392 }
1342 } catch (IndexOutOfBoundsException e) { 1393 } catch (IndexOutOfBoundsException e) {
1343 throw new OutOfSpaceException( 1394 throw new OutOfSpaceException(
1344 new IndexOutOfBoundsException( 1395 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e);
1345 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)));
1346 } 1396 }
1347 } 1397 }
1348 } 1398 }
1349 1399
1350 @Override 1400 @Override
1351 public final void writeFixed64NoTag(long value) throws IOException { 1401 public final void writeFixed64NoTag(long value) throws IOException {
1352 try { 1402 try {
1353 buffer[position++] = (byte) ((int) (value) & 0xFF); 1403 buffer[position++] = (byte) ((int) (value) & 0xFF);
1354 buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); 1404 buffer[position++] = (byte) ((int) (value >> 8) & 0xFF);
1355 buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); 1405 buffer[position++] = (byte) ((int) (value >> 16) & 0xFF);
1356 buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); 1406 buffer[position++] = (byte) ((int) (value >> 24) & 0xFF);
1357 buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); 1407 buffer[position++] = (byte) ((int) (value >> 32) & 0xFF);
1358 buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); 1408 buffer[position++] = (byte) ((int) (value >> 40) & 0xFF);
1359 buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); 1409 buffer[position++] = (byte) ((int) (value >> 48) & 0xFF);
1360 buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); 1410 buffer[position++] = (byte) ((int) (value >> 56) & 0xFF);
1361 } catch (IndexOutOfBoundsException e) { 1411 } catch (IndexOutOfBoundsException e) {
1362 throw new OutOfSpaceException( 1412 throw new OutOfSpaceException(
1363 new IndexOutOfBoundsException( 1413 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e) ;
1364 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1) ));
1365 } 1414 }
1366 } 1415 }
1367 1416
1368 @Override 1417 @Override
1369 public final void write(byte[] value, int offset, int length) throws IOExcep tion { 1418 public final void write(byte[] value, int offset, int length) throws IOExcep tion {
1370 try { 1419 try {
1371 System.arraycopy(value, offset, buffer, position, length); 1420 System.arraycopy(value, offset, buffer, position, length);
1372 position += length; 1421 position += length;
1373 } catch (IndexOutOfBoundsException e) { 1422 } catch (IndexOutOfBoundsException e) {
1374 throw new OutOfSpaceException( 1423 throw new OutOfSpaceException(
1375 new IndexOutOfBoundsException( 1424 String.format("Pos: %d, limit: %d, len: %d", position, limit, length ), e);
1376 String.format("Pos: %d, limit: %d, len: %d", position, limit, le ngth)));
1377 } 1425 }
1378 } 1426 }
1379 1427
1380 @Override 1428 @Override
1381 public final void writeLazy(byte[] value, int offset, int length) throws IOE xception { 1429 public final void writeLazy(byte[] value, int offset, int length) throws IOE xception {
1382 write(value, offset, length); 1430 write(value, offset, length);
1383 } 1431 }
1384 1432
1385 @Override 1433 @Override
1386 public final void write(ByteBuffer value) throws IOException { 1434 public final void write(ByteBuffer value) throws IOException {
1387 final int length = value.remaining(); 1435 final int length = value.remaining();
1388 try { 1436 try {
1389 value.get(buffer, position, length); 1437 value.get(buffer, position, length);
1390 position += length; 1438 position += length;
1391 } catch (IndexOutOfBoundsException e) { 1439 } catch (IndexOutOfBoundsException e) {
1392 throw new OutOfSpaceException( 1440 throw new OutOfSpaceException(
1393 new IndexOutOfBoundsException( 1441 String.format("Pos: %d, limit: %d, len: %d", position, limit, length ), e);
1394 String.format("Pos: %d, limit: %d, len: %d", position, limit, le ngth)));
1395 } 1442 }
1396 } 1443 }
1397 1444
1398 @Override 1445 @Override
1399 public final void writeLazy(ByteBuffer value) throws IOException { 1446 public final void writeLazy(ByteBuffer value) throws IOException {
1400 write(value); 1447 write(value);
1401 } 1448 }
1402 1449
1403 @Override 1450 @Override
1404 public final void writeStringNoTag(String value) throws IOException { 1451 public final void writeStringNoTag(String value) throws IOException {
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
1447 @Override 1494 @Override
1448 public final int getTotalBytesWritten() { 1495 public final int getTotalBytesWritten() {
1449 return position - offset; 1496 return position - offset;
1450 } 1497 }
1451 } 1498 }
1452 1499
1453 /** 1500 /**
1454 * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffe r}. Writes are 1501 * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffe r}. Writes are
1455 * done directly to the underlying array. The buffer position is only updated after a flush. 1502 * done directly to the underlying array. The buffer position is only updated after a flush.
1456 */ 1503 */
1457 private static final class NioHeapEncoder extends ArrayEncoder { 1504 private static final class HeapNioEncoder extends ArrayEncoder {
1458 private final ByteBuffer byteBuffer; 1505 private final ByteBuffer byteBuffer;
1459 private int initialPosition; 1506 private int initialPosition;
1460 1507
1461 NioHeapEncoder(ByteBuffer byteBuffer) { 1508 HeapNioEncoder(ByteBuffer byteBuffer) {
1462 super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position() , 1509 super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position() ,
1463 byteBuffer.remaining()); 1510 byteBuffer.remaining());
1464 this.byteBuffer = byteBuffer; 1511 this.byteBuffer = byteBuffer;
1465 this.initialPosition = byteBuffer.position(); 1512 this.initialPosition = byteBuffer.position();
1466 } 1513 }
1467 1514
1468 @Override 1515 @Override
1469 public void flush() { 1516 public void flush() {
1470 // Update the position on the buffer. 1517 // Update the position on the buffer.
1471 byteBuffer.position(initialPosition + getTotalBytesWritten()); 1518 byteBuffer.position(initialPosition + getTotalBytesWritten());
1472 } 1519 }
1473 } 1520 }
1474 1521
1475 /** 1522 /**
1476 * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}. 1523 * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuf fer}, using only
1524 * safe operations..
1477 */ 1525 */
1478 private static final class NioEncoder extends CodedOutputStream { 1526 private static final class SafeDirectNioEncoder extends CodedOutputStream {
1479 private final ByteBuffer originalBuffer; 1527 private final ByteBuffer originalBuffer;
1480 private final ByteBuffer buffer; 1528 private final ByteBuffer buffer;
1481 private final int initialPosition; 1529 private final int initialPosition;
1482 1530
1483 NioEncoder(ByteBuffer buffer) { 1531 SafeDirectNioEncoder(ByteBuffer buffer) {
1484 this.originalBuffer = buffer; 1532 this.originalBuffer = buffer;
1485 this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN); 1533 this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
1486 initialPosition = buffer.position(); 1534 initialPosition = buffer.position();
1487 } 1535 }
1488 1536
1489 @Override 1537 @Override
1490 public void writeTag(final int fieldNumber, final int wireType) throws IOExc eption { 1538 public void writeTag(final int fieldNumber, final int wireType) throws IOExc eption {
1491 writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); 1539 writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
1492 } 1540 }
1493 1541
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 private void encode(String value) throws IOException { 1824 private void encode(String value) throws IOException {
1777 try { 1825 try {
1778 Utf8.encodeUtf8(value, buffer); 1826 Utf8.encodeUtf8(value, buffer);
1779 } catch (IndexOutOfBoundsException e) { 1827 } catch (IndexOutOfBoundsException e) {
1780 throw new OutOfSpaceException(e); 1828 throw new OutOfSpaceException(e);
1781 } 1829 }
1782 } 1830 }
1783 } 1831 }
1784 1832
1785 /** 1833 /**
1834 * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuf fer} using {@code
1835 * sun.misc.Unsafe}.
1836 */
1837 private static final class UnsafeDirectNioEncoder extends CodedOutputStream {
1838 private final ByteBuffer originalBuffer;
1839 private final ByteBuffer buffer;
1840 private final long address;
1841 private final long initialPosition;
1842 private final long limit;
1843 private final long oneVarintLimit;
1844 private long position;
1845
1846 UnsafeDirectNioEncoder(ByteBuffer buffer) {
1847 this.originalBuffer = buffer;
1848 this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN);
1849 address = UnsafeUtil.addressOffset(buffer);
1850 initialPosition = address + buffer.position();
1851 limit = address + buffer.limit();
1852 oneVarintLimit = limit - MAX_VARINT_SIZE;
1853 position = initialPosition;
1854 }
1855
1856 static boolean isSupported() {
1857 return UnsafeUtil.hasUnsafeByteBufferOperations();
1858 }
1859
1860 @Override
1861 public void writeTag(int fieldNumber, int wireType) throws IOException {
1862 writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType));
1863 }
1864
1865 @Override
1866 public void writeInt32(int fieldNumber, int value) throws IOException {
1867 writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
1868 writeInt32NoTag(value);
1869 }
1870
1871 @Override
1872 public void writeUInt32(int fieldNumber, int value) throws IOException {
1873 writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
1874 writeUInt32NoTag(value);
1875 }
1876
1877 @Override
1878 public void writeFixed32(int fieldNumber, int value) throws IOException {
1879 writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED32);
1880 writeFixed32NoTag(value);
1881 }
1882
1883 @Override
1884 public void writeUInt64(int fieldNumber, long value) throws IOException {
1885 writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
1886 writeUInt64NoTag(value);
1887 }
1888
1889 @Override
1890 public void writeFixed64(int fieldNumber, long value) throws IOException {
1891 writeTag(fieldNumber, WireFormat.WIRETYPE_FIXED64);
1892 writeFixed64NoTag(value);
1893 }
1894
1895 @Override
1896 public void writeBool(int fieldNumber, boolean value) throws IOException {
1897 writeTag(fieldNumber, WireFormat.WIRETYPE_VARINT);
1898 write((byte) (value ? 1 : 0));
1899 }
1900
1901 @Override
1902 public void writeString(int fieldNumber, String value) throws IOException {
1903 writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
1904 writeStringNoTag(value);
1905 }
1906
1907 @Override
1908 public void writeBytes(int fieldNumber, ByteString value) throws IOException {
1909 writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
1910 writeBytesNoTag(value);
1911 }
1912
1913 @Override
1914 public void writeByteArray(int fieldNumber, byte[] value) throws IOException {
1915 writeByteArray(fieldNumber, value, 0, value.length);
1916 }
1917
1918 @Override
1919 public void writeByteArray(int fieldNumber, byte[] value, int offset, int le ngth)
1920 throws IOException {
1921 writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
1922 writeByteArrayNoTag(value, offset, length);
1923 }
1924
1925 @Override
1926 public void writeByteBuffer(int fieldNumber, ByteBuffer value) throws IOExce ption {
1927 writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
1928 writeUInt32NoTag(value.capacity());
1929 writeRawBytes(value);
1930 }
1931
1932 @Override
1933 public void writeMessage(int fieldNumber, MessageLite value) throws IOExcept ion {
1934 writeTag(fieldNumber, WireFormat.WIRETYPE_LENGTH_DELIMITED);
1935 writeMessageNoTag(value);
1936 }
1937
1938 @Override
1939 public void writeMessageSetExtension(int fieldNumber, MessageLite value) thr ows IOException {
1940 writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
1941 writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
1942 writeMessage(WireFormat.MESSAGE_SET_MESSAGE, value);
1943 writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
1944 }
1945
1946 @Override
1947 public void writeRawMessageSetExtension(int fieldNumber, ByteString value) t hrows IOException {
1948 writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_START_GROUP);
1949 writeUInt32(WireFormat.MESSAGE_SET_TYPE_ID, fieldNumber);
1950 writeBytes(WireFormat.MESSAGE_SET_MESSAGE, value);
1951 writeTag(WireFormat.MESSAGE_SET_ITEM, WireFormat.WIRETYPE_END_GROUP);
1952 }
1953
1954 @Override
1955 public void writeMessageNoTag(MessageLite value) throws IOException {
1956 writeUInt32NoTag(value.getSerializedSize());
1957 value.writeTo(this);
1958 }
1959
1960 @Override
1961 public void write(byte value) throws IOException {
1962 if (position >= limit) {
1963 throw new OutOfSpaceException(
1964 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
1965 }
1966 UnsafeUtil.putByte(position++, value);
1967 }
1968
1969 @Override
1970 public void writeBytesNoTag(ByteString value) throws IOException {
1971 writeUInt32NoTag(value.size());
1972 value.writeTo(this);
1973 }
1974
1975 @Override
1976 public void writeByteArrayNoTag(byte[] value, int offset, int length) throws IOException {
1977 writeUInt32NoTag(length);
1978 write(value, offset, length);
1979 }
1980
1981 @Override
1982 public void writeRawBytes(ByteBuffer value) throws IOException {
1983 if (value.hasArray()) {
1984 write(value.array(), value.arrayOffset(), value.capacity());
1985 } else {
1986 ByteBuffer duplicated = value.duplicate();
1987 duplicated.clear();
1988 write(duplicated);
1989 }
1990 }
1991
1992 @Override
1993 public void writeInt32NoTag(int value) throws IOException {
1994 if (value >= 0) {
1995 writeUInt32NoTag(value);
1996 } else {
1997 // Must sign-extend.
1998 writeUInt64NoTag(value);
1999 }
2000 }
2001
2002 @Override
2003 public void writeUInt32NoTag(int value) throws IOException {
2004 if (position <= oneVarintLimit) {
2005 // Optimization to avoid bounds checks on each iteration.
2006 while (true) {
2007 if ((value & ~0x7F) == 0) {
2008 UnsafeUtil.putByte(position++, (byte) value);
2009 return;
2010 } else {
2011 UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
2012 value >>>= 7;
2013 }
2014 }
2015 } else {
2016 while (position < limit) {
2017 if ((value & ~0x7F) == 0) {
2018 UnsafeUtil.putByte(position++, (byte) value);
2019 return;
2020 } else {
2021 UnsafeUtil.putByte(position++, (byte) ((value & 0x7F) | 0x80));
2022 value >>>= 7;
2023 }
2024 }
2025 throw new OutOfSpaceException(
2026 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
2027 }
2028 }
2029
2030 @Override
2031 public void writeFixed32NoTag(int value) throws IOException {
2032 buffer.putInt(bufferPos(position), value);
2033 position += FIXED_32_SIZE;
2034 }
2035
2036 @Override
2037 public void writeUInt64NoTag(long value) throws IOException {
2038 if (position <= oneVarintLimit) {
2039 // Optimization to avoid bounds checks on each iteration.
2040 while (true) {
2041 if ((value & ~0x7FL) == 0) {
2042 UnsafeUtil.putByte(position++, (byte) value);
2043 return;
2044 } else {
2045 UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80)) ;
2046 value >>>= 7;
2047 }
2048 }
2049 } else {
2050 while (position < limit) {
2051 if ((value & ~0x7FL) == 0) {
2052 UnsafeUtil.putByte(position++, (byte) value);
2053 return;
2054 } else {
2055 UnsafeUtil.putByte(position++, (byte) (((int) value & 0x7F) | 0x80)) ;
2056 value >>>= 7;
2057 }
2058 }
2059 throw new OutOfSpaceException(
2060 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1));
2061 }
2062 }
2063
2064 @Override
2065 public void writeFixed64NoTag(long value) throws IOException {
2066 buffer.putLong(bufferPos(position), value);
2067 position += FIXED_64_SIZE;
2068 }
2069
2070 @Override
2071 public void write(byte[] value, int offset, int length) throws IOException {
2072 if (value == null
2073 || offset < 0
2074 || length < 0
2075 || (value.length - length) < offset
2076 || (limit - length) < position) {
2077 if (value == null) {
2078 throw new NullPointerException("value");
2079 }
2080 throw new OutOfSpaceException(
2081 String.format("Pos: %d, limit: %d, len: %d", position, limit, length ));
2082 }
2083
2084 UnsafeUtil.copyMemory(
2085 value, UnsafeUtil.getArrayBaseOffset() + offset, null, position, lengt h);
2086 position += length;
2087 }
2088
2089 @Override
2090 public void writeLazy(byte[] value, int offset, int length) throws IOExcepti on {
2091 write(value, offset, length);
2092 }
2093
2094 @Override
2095 public void write(ByteBuffer value) throws IOException {
2096 try {
2097 int length = value.remaining();
2098 repositionBuffer(position);
2099 buffer.put(value);
2100 position += length;
2101 } catch (BufferOverflowException e) {
2102 throw new OutOfSpaceException(e);
2103 }
2104 }
2105
2106 @Override
2107 public void writeLazy(ByteBuffer value) throws IOException {
2108 write(value);
2109 }
2110
2111 @Override
2112 public void writeStringNoTag(String value) throws IOException {
2113 long prevPos = position;
2114 try {
2115 // UTF-8 byte length of the string is at least its UTF-16 code unit leng th (value.length()),
2116 // and at most 3 times of it. We take advantage of this in both branches below.
2117 int maxEncodedSize = value.length() * Utf8.MAX_BYTES_PER_CHAR;
2118 int maxLengthVarIntSize = computeUInt32SizeNoTag(maxEncodedSize);
2119 int minLengthVarIntSize = computeUInt32SizeNoTag(value.length());
2120 if (minLengthVarIntSize == maxLengthVarIntSize) {
2121 // Save the current position and increment past the length field. We'l l come back
2122 // and write the length field after the encoding is complete.
2123 int stringStart = bufferPos(position) + minLengthVarIntSize;
2124 buffer.position(stringStart);
2125
2126 // Encode the string.
2127 Utf8.encodeUtf8(value, buffer);
2128
2129 // Write the length and advance the position.
2130 int length = buffer.position() - stringStart;
2131 writeUInt32NoTag(length);
2132 position += length;
2133 } else {
2134 // Calculate and write the encoded length.
2135 int length = Utf8.encodedLength(value);
2136 writeUInt32NoTag(length);
2137
2138 // Write the string and advance the position.
2139 repositionBuffer(position);
2140 Utf8.encodeUtf8(value, buffer);
2141 position += length;
2142 }
2143 } catch (UnpairedSurrogateException e) {
2144 // Roll back the change and convert to an IOException.
2145 position = prevPos;
2146 repositionBuffer(position);
2147
2148 // TODO(nathanmittler): We should throw an IOException here instead.
2149 inefficientWriteStringNoTag(value, e);
2150 } catch (IllegalArgumentException e) {
2151 // Thrown by buffer.position() if out of range.
2152 throw new OutOfSpaceException(e);
2153 } catch (IndexOutOfBoundsException e) {
2154 throw new OutOfSpaceException(e);
2155 }
2156 }
2157
2158 @Override
2159 public void flush() {
2160 // Update the position of the original buffer.
2161 originalBuffer.position(bufferPos(position));
2162 }
2163
2164 @Override
2165 public int spaceLeft() {
2166 return (int) (limit - position);
2167 }
2168
2169 @Override
2170 public int getTotalBytesWritten() {
2171 return (int) (position - initialPosition);
2172 }
2173
2174 private void repositionBuffer(long pos) {
2175 buffer.position(bufferPos(pos));
2176 }
2177
2178 private int bufferPos(long pos) {
2179 return (int) (pos - address);
2180 }
2181 }
2182
2183 /**
1786 * Abstract base class for buffered encoders. 2184 * Abstract base class for buffered encoders.
1787 */ 2185 */
1788 private abstract static class AbstractBufferedEncoder extends CodedOutputStrea m { 2186 private abstract static class AbstractBufferedEncoder extends CodedOutputStrea m {
1789 final byte[] buffer; 2187 final byte[] buffer;
1790 final int limit; 2188 final int limit;
1791 int position; 2189 int position;
1792 int totalBytesWritten; 2190 int totalBytesWritten;
1793 2191
1794 AbstractBufferedEncoder(int bufferSize) { 2192 AbstractBufferedEncoder(int bufferSize) {
1795 if (bufferSize < 0) { 2193 if (bufferSize < 0) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1848 /** 2246 /**
1849 * This method does not perform bounds checking on the array. Checking array bounds is the 2247 * This method does not perform bounds checking on the array. Checking array bounds is the
1850 * responsibility of the caller. 2248 * responsibility of the caller.
1851 */ 2249 */
1852 final void bufferUInt32NoTag(int value) { 2250 final void bufferUInt32NoTag(int value) {
1853 if (HAS_UNSAFE_ARRAY_OPERATIONS) { 2251 if (HAS_UNSAFE_ARRAY_OPERATIONS) {
1854 final long originalPos = ARRAY_BASE_OFFSET + position; 2252 final long originalPos = ARRAY_BASE_OFFSET + position;
1855 long pos = originalPos; 2253 long pos = originalPos;
1856 while (true) { 2254 while (true) {
1857 if ((value & ~0x7F) == 0) { 2255 if ((value & ~0x7F) == 0) {
1858 UNSAFE.putByte(buffer, pos++, (byte) value); 2256 UnsafeUtil.putByte(buffer, pos++, (byte) value);
1859 break; 2257 break;
1860 } else { 2258 } else {
1861 UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); 2259 UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80));
1862 value >>>= 7; 2260 value >>>= 7;
1863 } 2261 }
1864 } 2262 }
1865 int delta = (int) (pos - originalPos); 2263 int delta = (int) (pos - originalPos);
1866 position += delta; 2264 position += delta;
1867 totalBytesWritten += delta; 2265 totalBytesWritten += delta;
1868 } else { 2266 } else {
1869 while (true) { 2267 while (true) {
1870 if ((value & ~0x7F) == 0) { 2268 if ((value & ~0x7F) == 0) {
1871 buffer[position++] = (byte) value; 2269 buffer[position++] = (byte) value;
(...skipping 11 matching lines...) Expand all
1883 /** 2281 /**
1884 * This method does not perform bounds checking on the array. Checking array bounds is the 2282 * This method does not perform bounds checking on the array. Checking array bounds is the
1885 * responsibility of the caller. 2283 * responsibility of the caller.
1886 */ 2284 */
1887 final void bufferUInt64NoTag(long value) { 2285 final void bufferUInt64NoTag(long value) {
1888 if (HAS_UNSAFE_ARRAY_OPERATIONS) { 2286 if (HAS_UNSAFE_ARRAY_OPERATIONS) {
1889 final long originalPos = ARRAY_BASE_OFFSET + position; 2287 final long originalPos = ARRAY_BASE_OFFSET + position;
1890 long pos = originalPos; 2288 long pos = originalPos;
1891 while (true) { 2289 while (true) {
1892 if ((value & ~0x7FL) == 0) { 2290 if ((value & ~0x7FL) == 0) {
1893 UNSAFE.putByte(buffer, pos++, (byte) value); 2291 UnsafeUtil.putByte(buffer, pos++, (byte) value);
1894 break; 2292 break;
1895 } else { 2293 } else {
1896 UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); 2294 UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x8 0));
1897 value >>>= 7; 2295 value >>>= 7;
1898 } 2296 }
1899 } 2297 }
1900 int delta = (int) (pos - originalPos); 2298 int delta = (int) (pos - originalPos);
1901 position += delta; 2299 position += delta;
1902 totalBytesWritten += delta; 2300 totalBytesWritten += delta;
1903 } else { 2301 } else {
1904 while (true) { 2302 while (true) {
1905 if ((value & ~0x7FL) == 0) { 2303 if ((value & ~0x7FL) == 0) {
1906 buffer[position++] = (byte) value; 2304 buffer[position++] = (byte) value;
(...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after
2593 if (limit - position < requiredSize) { 2991 if (limit - position < requiredSize) {
2594 doFlush(); 2992 doFlush();
2595 } 2993 }
2596 } 2994 }
2597 2995
2598 private void doFlush() throws IOException { 2996 private void doFlush() throws IOException {
2599 out.write(buffer, 0, position); 2997 out.write(buffer, 0, position);
2600 position = 0; 2998 position = 0;
2601 } 2999 }
2602 } 3000 }
2603
2604 /**
2605 * Gets the {@code sun.misc.Unsafe} instance, or {@code null} if not available on this
2606 * platform.
2607 */
2608 private static sun.misc.Unsafe getUnsafe() {
2609 sun.misc.Unsafe unsafe = null;
2610 try {
2611 unsafe = AccessController.doPrivileged(new PrivilegedExceptionAction<sun.m isc.Unsafe>() {
2612 @Override
2613 public sun.misc.Unsafe run() throws Exception {
2614 Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
2615
2616 for (Field f : k.getDeclaredFields()) {
2617 f.setAccessible(true);
2618 Object x = f.get(null);
2619 if (k.isInstance(x)) {
2620 return k.cast(x);
2621 }
2622 }
2623 // The sun.misc.Unsafe field does not exist.
2624 return null;
2625 }
2626 });
2627 } catch (Throwable e) {
2628 // Catching Throwable here due to the fact that Google AppEngine raises No ClassDefFoundError
2629 // for Unsafe.
2630 }
2631
2632 logger.log(Level.FINEST, "sun.misc.Unsafe: {}",
2633 unsafe != null ? "available" : "unavailable");
2634 return unsafe;
2635 }
2636
2637 /**
2638 * Indicates whether or not unsafe array operations are supported on this plat form.
2639 */
2640 // TODO(nathanmittler): Add support for Android's MemoryBlock.
2641 private static boolean supportsUnsafeArrayOperations() {
2642 boolean supported = false;
2643 if (UNSAFE != null) {
2644 try {
2645 UNSAFE.getClass().getMethod("arrayBaseOffset", Class.class);
2646 UNSAFE.getClass().getMethod("putByte", Object.class, long.class, byte.cl ass);
2647 supported = true;
2648 } catch (Throwable e) {
2649 // Do nothing.
2650 }
2651 }
2652 logger.log(Level.FINEST, "Unsafe array operations: {}",
2653 supported ? "available" : "unavailable");
2654 return supported;
2655 }
2656
2657 /**
2658 * Get the base offset for byte arrays, or {@code -1} if {@code sun.misc.Unsaf e} is not
2659 * available.
2660 */
2661 private static <T> int byteArrayBaseOffset() {
2662 return HAS_UNSAFE_ARRAY_OPERATIONS ? UNSAFE.arrayBaseOffset(byte[].class) : -1;
2663 }
2664 } 3001 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698