| OLD | NEW |
| 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 Loading... |
| 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; | |
| 36 import static java.lang.Math.max; | 33 import static java.lang.Math.max; |
| 37 | 34 |
| 38 import com.google.protobuf.Utf8.UnpairedSurrogateException; | 35 import com.google.protobuf.Utf8.UnpairedSurrogateException; |
| 36 |
| 39 import java.io.IOException; | 37 import java.io.IOException; |
| 40 import java.io.OutputStream; | 38 import java.io.OutputStream; |
| 39 import java.lang.reflect.Field; |
| 41 import java.nio.BufferOverflowException; | 40 import java.nio.BufferOverflowException; |
| 42 import java.nio.ByteBuffer; | 41 import java.nio.ByteBuffer; |
| 43 import java.nio.ByteOrder; | 42 import java.nio.ByteOrder; |
| 43 import java.security.AccessController; |
| 44 import java.security.PrivilegedExceptionAction; |
| 44 import java.util.logging.Level; | 45 import java.util.logging.Level; |
| 45 import java.util.logging.Logger; | 46 import java.util.logging.Logger; |
| 46 | 47 |
| 47 /** | 48 /** |
| 48 * Encodes and writes protocol message fields. | 49 * Encodes and writes protocol message fields. |
| 49 * | 50 * |
| 50 * <p>This class contains two kinds of methods: methods that write specific | 51 * <p>This class contains two kinds of methods: methods that write specific |
| 51 * protocol message constructs and field types (e.g. {@link #writeTag} and | 52 * protocol message constructs and field types (e.g. {@link #writeTag} and |
| 52 * {@link #writeInt32}) and methods that write low-level values (e.g. | 53 * {@link #writeInt32}) and methods that write low-level values (e.g. |
| 53 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are | 54 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are |
| 54 * writing encoded protocol messages, you should use the former methods, but if | 55 * writing encoded protocol messages, you should use the former methods, but if |
| 55 * you are writing some other format of your own design, use the latter. | 56 * you are writing some other format of your own design, use the latter. |
| 56 * | 57 * |
| 57 * <p>This class is totally unsynchronized. | 58 * <p>This class is totally unsynchronized. |
| 58 */ | 59 */ |
| 59 public abstract class CodedOutputStream extends ByteOutput { | 60 public abstract class CodedOutputStream extends ByteOutput { |
| 60 private static final Logger logger = Logger.getLogger(CodedOutputStream.class.
getName()); | 61 private static final Logger logger = Logger.getLogger(CodedOutputStream.class.
getName()); |
| 61 private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = UnsafeUtil.hasUnsaf
eArrayOperations(); | 62 private static final sun.misc.Unsafe UNSAFE = getUnsafe(); |
| 62 private static final long ARRAY_BASE_OFFSET = UnsafeUtil.getArrayBaseOffset(); | 63 private static final boolean HAS_UNSAFE_ARRAY_OPERATIONS = supportsUnsafeArray
Operations(); |
| 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; |
| 63 | 69 |
| 64 /** | 70 /** |
| 65 * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. | 71 * @deprecated Use {@link #computeFixed32SizeNoTag(int)} instead. |
| 66 */ | 72 */ |
| 67 @Deprecated | 73 @Deprecated |
| 68 public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE; | 74 public static final int LITTLE_ENDIAN_32_SIZE = FIXED_32_SIZE; |
| 69 | 75 |
| 70 /** | 76 /** |
| 71 * The buffer size used in {@link #newInstance(OutputStream)}. | 77 * The buffer size used in {@link #newInstance(OutputStream)}. |
| 72 */ | 78 */ |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 125 * byte array slice. If more bytes are written than fit in the slice, | 131 * byte array slice. If more bytes are written than fit in the slice, |
| 126 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat | 132 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat |
| 127 * array is faster than writing to an {@code OutputStream}. See also | 133 * array is faster than writing to an {@code OutputStream}. See also |
| 128 * {@link ByteString#newCodedBuilder}. | 134 * {@link ByteString#newCodedBuilder}. |
| 129 */ | 135 */ |
| 130 public static CodedOutputStream newInstance( | 136 public static CodedOutputStream newInstance( |
| 131 final byte[] flatArray, final int offset, final int length) { | 137 final byte[] flatArray, final int offset, final int length) { |
| 132 return new ArrayEncoder(flatArray, offset, length); | 138 return new ArrayEncoder(flatArray, offset, length); |
| 133 } | 139 } |
| 134 | 140 |
| 135 /** Create a new {@code CodedOutputStream} that writes to the given {@link Byt
eBuffer}. */ | 141 /** |
| 136 public static CodedOutputStream newInstance(ByteBuffer buffer) { | 142 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte
Buffer}. |
| 137 if (buffer.hasArray()) { | 143 */ |
| 138 return new HeapNioEncoder(buffer); | 144 public static CodedOutputStream newInstance(ByteBuffer byteBuffer) { |
| 145 if (byteBuffer.hasArray()) { |
| 146 return new NioHeapEncoder(byteBuffer); |
| 139 } | 147 } |
| 140 if (buffer.isDirect() && !buffer.isReadOnly()) { | 148 return new NioEncoder(byteBuffer); |
| 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); | |
| 156 } | 149 } |
| 157 | 150 |
| 158 /** | 151 /** |
| 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 /** | |
| 197 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte
Buffer}. | 152 * Create a new {@code CodedOutputStream} that writes to the given {@link Byte
Buffer}. |
| 198 * | 153 * |
| 199 * @deprecated the size parameter is no longer used since use of an internal b
uffer is useless | 154 * @deprecated the size parameter is no longer used since use of an internal b
uffer is useless |
| 200 * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstanc
e(ByteBuffer)} | 155 * (and wasteful) when writing to a {@link ByteBuffer}. Use {@link #newInstanc
e(ByteBuffer)} |
| 201 * instead. | 156 * instead. |
| 202 */ | 157 */ |
| 203 @Deprecated | 158 @Deprecated |
| 204 public static CodedOutputStream newInstance(ByteBuffer byteBuffer, | 159 public static CodedOutputStream newInstance(ByteBuffer byteBuffer, |
| 205 @SuppressWarnings("unused") int unused) { | 160 @SuppressWarnings("unused") int unused) { |
| 206 return newInstance(byteBuffer); | 161 return newInstance(byteBuffer); |
| (...skipping 700 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 907 } | 862 } |
| 908 | 863 |
| 909 /** | 864 /** |
| 910 * Compute the number of bytes that would be needed to encode an embedded | 865 * Compute the number of bytes that would be needed to encode an embedded |
| 911 * message field. | 866 * message field. |
| 912 */ | 867 */ |
| 913 public static int computeMessageSizeNoTag(final MessageLite value) { | 868 public static int computeMessageSizeNoTag(final MessageLite value) { |
| 914 return computeLengthDelimitedFieldSize(value.getSerializedSize()); | 869 return computeLengthDelimitedFieldSize(value.getSerializedSize()); |
| 915 } | 870 } |
| 916 | 871 |
| 917 static int computeLengthDelimitedFieldSize(int fieldLength) { | 872 private static int computeLengthDelimitedFieldSize(int fieldLength) { |
| 918 return computeUInt32SizeNoTag(fieldLength) + fieldLength; | 873 return computeUInt32SizeNoTag(fieldLength) + fieldLength; |
| 919 } | 874 } |
| 920 | 875 |
| 921 /** | 876 /** |
| 922 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers | 877 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers |
| 923 * into values that can be efficiently encoded with varint. (Otherwise, | 878 * into values that can be efficiently encoded with varint. (Otherwise, |
| 924 * negative values must be sign-extended to 64 bits to be varint encoded, | 879 * negative values must be sign-extended to 64 bits to be varint encoded, |
| 925 * thus always taking 10 bytes on the wire.) | 880 * thus always taking 10 bytes on the wire.) |
| 926 * | 881 * |
| 927 * @param n A signed 32-bit integer. | 882 * @param n A signed 32-bit integer. |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 983 public static class OutOfSpaceException extends IOException { | 938 public static class OutOfSpaceException extends IOException { |
| 984 private static final long serialVersionUID = -6947486886997889499L; | 939 private static final long serialVersionUID = -6947486886997889499L; |
| 985 | 940 |
| 986 private static final String MESSAGE = | 941 private static final String MESSAGE = |
| 987 "CodedOutputStream was writing to a flat byte array and ran out of space
."; | 942 "CodedOutputStream was writing to a flat byte array and ran out of space
."; |
| 988 | 943 |
| 989 OutOfSpaceException() { | 944 OutOfSpaceException() { |
| 990 super(MESSAGE); | 945 super(MESSAGE); |
| 991 } | 946 } |
| 992 | 947 |
| 993 OutOfSpaceException(String explanationMessage) { | |
| 994 super(MESSAGE + ": " + explanationMessage); | |
| 995 } | |
| 996 | |
| 997 OutOfSpaceException(Throwable cause) { | 948 OutOfSpaceException(Throwable cause) { |
| 998 super(MESSAGE, cause); | 949 super(MESSAGE, cause); |
| 999 } | 950 } |
| 1000 | |
| 1001 OutOfSpaceException(String explanationMessage, Throwable cause) { | |
| 1002 super(MESSAGE + ": " + explanationMessage, cause); | |
| 1003 } | |
| 1004 } | 951 } |
| 1005 | 952 |
| 1006 /** | 953 /** |
| 1007 * Get the total number of bytes successfully written to this stream. The | 954 * Get the total number of bytes successfully written to this stream. The |
| 1008 * returned value is not guaranteed to be accurate if exceptions have been | 955 * returned value is not guaranteed to be accurate if exceptions have been |
| 1009 * found in the middle of writing. | 956 * found in the middle of writing. |
| 1010 */ | 957 */ |
| 1011 public abstract int getTotalBytesWritten(); | 958 public abstract int getTotalBytesWritten(); |
| 1012 | 959 |
| 1013 // ================================================================= | 960 // ================================================================= |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1296 public final void writeMessageNoTag(final MessageLite value) throws IOExcept
ion { | 1243 public final void writeMessageNoTag(final MessageLite value) throws IOExcept
ion { |
| 1297 writeUInt32NoTag(value.getSerializedSize()); | 1244 writeUInt32NoTag(value.getSerializedSize()); |
| 1298 value.writeTo(this); | 1245 value.writeTo(this); |
| 1299 } | 1246 } |
| 1300 | 1247 |
| 1301 @Override | 1248 @Override |
| 1302 public final void write(byte value) throws IOException { | 1249 public final void write(byte value) throws IOException { |
| 1303 try { | 1250 try { |
| 1304 buffer[position++] = value; | 1251 buffer[position++] = value; |
| 1305 } catch (IndexOutOfBoundsException e) { | 1252 } catch (IndexOutOfBoundsException e) { |
| 1306 throw new OutOfSpaceException( | 1253 throw new OutOfSpaceException(new IndexOutOfBoundsException( |
| 1307 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e)
; | 1254 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1))); |
| 1308 } | 1255 } |
| 1309 } | 1256 } |
| 1310 | 1257 |
| 1311 @Override | 1258 @Override |
| 1312 public final void writeInt32NoTag(int value) throws IOException { | 1259 public final void writeInt32NoTag(int value) throws IOException { |
| 1313 if (value >= 0) { | 1260 if (value >= 0) { |
| 1314 writeUInt32NoTag(value); | 1261 writeUInt32NoTag(value); |
| 1315 } else { | 1262 } else { |
| 1316 // Must sign-extend. | 1263 // Must sign-extend. |
| 1317 writeUInt64NoTag(value); | 1264 writeUInt64NoTag(value); |
| 1318 } | 1265 } |
| 1319 } | 1266 } |
| 1320 | 1267 |
| 1321 @Override | 1268 @Override |
| 1322 public final void writeUInt32NoTag(int value) throws IOException { | 1269 public final void writeUInt32NoTag(int value) throws IOException { |
| 1323 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { | 1270 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { |
| 1324 long pos = ARRAY_BASE_OFFSET + position; | 1271 long pos = ARRAY_BASE_OFFSET + position; |
| 1325 while (true) { | 1272 while (true) { |
| 1326 if ((value & ~0x7F) == 0) { | 1273 if ((value & ~0x7F) == 0) { |
| 1327 UnsafeUtil.putByte(buffer, pos++, (byte) value); | 1274 UNSAFE.putByte(buffer, pos++, (byte) value); |
| 1328 position++; | 1275 position++; |
| 1329 return; | 1276 return; |
| 1330 } else { | 1277 } else { |
| 1331 UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); | 1278 UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); |
| 1332 position++; | 1279 position++; |
| 1333 value >>>= 7; | 1280 value >>>= 7; |
| 1334 } | 1281 } |
| 1335 } | 1282 } |
| 1336 } else { | 1283 } else { |
| 1337 try { | 1284 try { |
| 1338 while (true) { | 1285 while (true) { |
| 1339 if ((value & ~0x7F) == 0) { | 1286 if ((value & ~0x7F) == 0) { |
| 1340 buffer[position++] = (byte) value; | 1287 buffer[position++] = (byte) value; |
| 1341 return; | 1288 return; |
| 1342 } else { | 1289 } else { |
| 1343 buffer[position++] = (byte) ((value & 0x7F) | 0x80); | 1290 buffer[position++] = (byte) ((value & 0x7F) | 0x80); |
| 1344 value >>>= 7; | 1291 value >>>= 7; |
| 1345 } | 1292 } |
| 1346 } | 1293 } |
| 1347 } catch (IndexOutOfBoundsException e) { | 1294 } catch (IndexOutOfBoundsException e) { |
| 1348 throw new OutOfSpaceException( | 1295 throw new OutOfSpaceException( |
| 1349 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1),
e); | 1296 new IndexOutOfBoundsException( |
| 1297 String.format("Pos: %d, limit: %d, len: %d", position, limit,
1))); |
| 1350 } | 1298 } |
| 1351 } | 1299 } |
| 1352 } | 1300 } |
| 1353 | 1301 |
| 1354 @Override | 1302 @Override |
| 1355 public final void writeFixed32NoTag(int value) throws IOException { | 1303 public final void writeFixed32NoTag(int value) throws IOException { |
| 1356 try { | 1304 try { |
| 1357 buffer[position++] = (byte) (value & 0xFF); | 1305 buffer[position++] = (byte) (value & 0xFF); |
| 1358 buffer[position++] = (byte) ((value >> 8) & 0xFF); | 1306 buffer[position++] = (byte) ((value >> 8) & 0xFF); |
| 1359 buffer[position++] = (byte) ((value >> 16) & 0xFF); | 1307 buffer[position++] = (byte) ((value >> 16) & 0xFF); |
| 1360 buffer[position++] = (byte) ((value >> 24) & 0xFF); | 1308 buffer[position++] = (byte) ((value >> 24) & 0xFF); |
| 1361 } catch (IndexOutOfBoundsException e) { | 1309 } catch (IndexOutOfBoundsException e) { |
| 1362 throw new OutOfSpaceException( | 1310 throw new OutOfSpaceException( |
| 1363 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e)
; | 1311 new IndexOutOfBoundsException( |
| 1312 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)
)); |
| 1364 } | 1313 } |
| 1365 } | 1314 } |
| 1366 | 1315 |
| 1367 @Override | 1316 @Override |
| 1368 public final void writeUInt64NoTag(long value) throws IOException { | 1317 public final void writeUInt64NoTag(long value) throws IOException { |
| 1369 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { | 1318 if (HAS_UNSAFE_ARRAY_OPERATIONS && spaceLeft() >= MAX_VARINT_SIZE) { |
| 1370 long pos = ARRAY_BASE_OFFSET + position; | 1319 long pos = ARRAY_BASE_OFFSET + position; |
| 1371 while (true) { | 1320 while (true) { |
| 1372 if ((value & ~0x7FL) == 0) { | 1321 if ((value & ~0x7FL) == 0) { |
| 1373 UnsafeUtil.putByte(buffer, pos++, (byte) value); | 1322 UNSAFE.putByte(buffer, pos++, (byte) value); |
| 1374 position++; | 1323 position++; |
| 1375 return; | 1324 return; |
| 1376 } else { | 1325 } else { |
| 1377 UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x8
0)); | 1326 UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); |
| 1378 position++; | 1327 position++; |
| 1379 value >>>= 7; | 1328 value >>>= 7; |
| 1380 } | 1329 } |
| 1381 } | 1330 } |
| 1382 } else { | 1331 } else { |
| 1383 try { | 1332 try { |
| 1384 while (true) { | 1333 while (true) { |
| 1385 if ((value & ~0x7FL) == 0) { | 1334 if ((value & ~0x7FL) == 0) { |
| 1386 buffer[position++] = (byte) value; | 1335 buffer[position++] = (byte) value; |
| 1387 return; | 1336 return; |
| 1388 } else { | 1337 } else { |
| 1389 buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); | 1338 buffer[position++] = (byte) (((int) value & 0x7F) | 0x80); |
| 1390 value >>>= 7; | 1339 value >>>= 7; |
| 1391 } | 1340 } |
| 1392 } | 1341 } |
| 1393 } catch (IndexOutOfBoundsException e) { | 1342 } catch (IndexOutOfBoundsException e) { |
| 1394 throw new OutOfSpaceException( | 1343 throw new OutOfSpaceException( |
| 1395 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1),
e); | 1344 new IndexOutOfBoundsException( |
| 1345 String.format("Pos: %d, limit: %d, len: %d", position, limit,
1))); |
| 1396 } | 1346 } |
| 1397 } | 1347 } |
| 1398 } | 1348 } |
| 1399 | 1349 |
| 1400 @Override | 1350 @Override |
| 1401 public final void writeFixed64NoTag(long value) throws IOException { | 1351 public final void writeFixed64NoTag(long value) throws IOException { |
| 1402 try { | 1352 try { |
| 1403 buffer[position++] = (byte) ((int) (value) & 0xFF); | 1353 buffer[position++] = (byte) ((int) (value) & 0xFF); |
| 1404 buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); | 1354 buffer[position++] = (byte) ((int) (value >> 8) & 0xFF); |
| 1405 buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); | 1355 buffer[position++] = (byte) ((int) (value >> 16) & 0xFF); |
| 1406 buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); | 1356 buffer[position++] = (byte) ((int) (value >> 24) & 0xFF); |
| 1407 buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); | 1357 buffer[position++] = (byte) ((int) (value >> 32) & 0xFF); |
| 1408 buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); | 1358 buffer[position++] = (byte) ((int) (value >> 40) & 0xFF); |
| 1409 buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); | 1359 buffer[position++] = (byte) ((int) (value >> 48) & 0xFF); |
| 1410 buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); | 1360 buffer[position++] = (byte) ((int) (value >> 56) & 0xFF); |
| 1411 } catch (IndexOutOfBoundsException e) { | 1361 } catch (IndexOutOfBoundsException e) { |
| 1412 throw new OutOfSpaceException( | 1362 throw new OutOfSpaceException( |
| 1413 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1), e)
; | 1363 new IndexOutOfBoundsException( |
| 1364 String.format("Pos: %d, limit: %d, len: %d", position, limit, 1)
)); |
| 1414 } | 1365 } |
| 1415 } | 1366 } |
| 1416 | 1367 |
| 1417 @Override | 1368 @Override |
| 1418 public final void write(byte[] value, int offset, int length) throws IOExcep
tion { | 1369 public final void write(byte[] value, int offset, int length) throws IOExcep
tion { |
| 1419 try { | 1370 try { |
| 1420 System.arraycopy(value, offset, buffer, position, length); | 1371 System.arraycopy(value, offset, buffer, position, length); |
| 1421 position += length; | 1372 position += length; |
| 1422 } catch (IndexOutOfBoundsException e) { | 1373 } catch (IndexOutOfBoundsException e) { |
| 1423 throw new OutOfSpaceException( | 1374 throw new OutOfSpaceException( |
| 1424 String.format("Pos: %d, limit: %d, len: %d", position, limit, length
), e); | 1375 new IndexOutOfBoundsException( |
| 1376 String.format("Pos: %d, limit: %d, len: %d", position, limit, le
ngth))); |
| 1425 } | 1377 } |
| 1426 } | 1378 } |
| 1427 | 1379 |
| 1428 @Override | 1380 @Override |
| 1429 public final void writeLazy(byte[] value, int offset, int length) throws IOE
xception { | 1381 public final void writeLazy(byte[] value, int offset, int length) throws IOE
xception { |
| 1430 write(value, offset, length); | 1382 write(value, offset, length); |
| 1431 } | 1383 } |
| 1432 | 1384 |
| 1433 @Override | 1385 @Override |
| 1434 public final void write(ByteBuffer value) throws IOException { | 1386 public final void write(ByteBuffer value) throws IOException { |
| 1435 final int length = value.remaining(); | 1387 final int length = value.remaining(); |
| 1436 try { | 1388 try { |
| 1437 value.get(buffer, position, length); | 1389 value.get(buffer, position, length); |
| 1438 position += length; | 1390 position += length; |
| 1439 } catch (IndexOutOfBoundsException e) { | 1391 } catch (IndexOutOfBoundsException e) { |
| 1440 throw new OutOfSpaceException( | 1392 throw new OutOfSpaceException( |
| 1441 String.format("Pos: %d, limit: %d, len: %d", position, limit, length
), e); | 1393 new IndexOutOfBoundsException( |
| 1394 String.format("Pos: %d, limit: %d, len: %d", position, limit, le
ngth))); |
| 1442 } | 1395 } |
| 1443 } | 1396 } |
| 1444 | 1397 |
| 1445 @Override | 1398 @Override |
| 1446 public final void writeLazy(ByteBuffer value) throws IOException { | 1399 public final void writeLazy(ByteBuffer value) throws IOException { |
| 1447 write(value); | 1400 write(value); |
| 1448 } | 1401 } |
| 1449 | 1402 |
| 1450 @Override | 1403 @Override |
| 1451 public final void writeStringNoTag(String value) throws IOException { | 1404 public final void writeStringNoTag(String value) throws IOException { |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1494 @Override | 1447 @Override |
| 1495 public final int getTotalBytesWritten() { | 1448 public final int getTotalBytesWritten() { |
| 1496 return position - offset; | 1449 return position - offset; |
| 1497 } | 1450 } |
| 1498 } | 1451 } |
| 1499 | 1452 |
| 1500 /** | 1453 /** |
| 1501 * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffe
r}. Writes are | 1454 * A {@link CodedOutputStream} that writes directly to a heap {@link ByteBuffe
r}. Writes are |
| 1502 * done directly to the underlying array. The buffer position is only updated
after a flush. | 1455 * done directly to the underlying array. The buffer position is only updated
after a flush. |
| 1503 */ | 1456 */ |
| 1504 private static final class HeapNioEncoder extends ArrayEncoder { | 1457 private static final class NioHeapEncoder extends ArrayEncoder { |
| 1505 private final ByteBuffer byteBuffer; | 1458 private final ByteBuffer byteBuffer; |
| 1506 private int initialPosition; | 1459 private int initialPosition; |
| 1507 | 1460 |
| 1508 HeapNioEncoder(ByteBuffer byteBuffer) { | 1461 NioHeapEncoder(ByteBuffer byteBuffer) { |
| 1509 super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position()
, | 1462 super(byteBuffer.array(), byteBuffer.arrayOffset() + byteBuffer.position()
, |
| 1510 byteBuffer.remaining()); | 1463 byteBuffer.remaining()); |
| 1511 this.byteBuffer = byteBuffer; | 1464 this.byteBuffer = byteBuffer; |
| 1512 this.initialPosition = byteBuffer.position(); | 1465 this.initialPosition = byteBuffer.position(); |
| 1513 } | 1466 } |
| 1514 | 1467 |
| 1515 @Override | 1468 @Override |
| 1516 public void flush() { | 1469 public void flush() { |
| 1517 // Update the position on the buffer. | 1470 // Update the position on the buffer. |
| 1518 byteBuffer.position(initialPosition + getTotalBytesWritten()); | 1471 byteBuffer.position(initialPosition + getTotalBytesWritten()); |
| 1519 } | 1472 } |
| 1520 } | 1473 } |
| 1521 | 1474 |
| 1522 /** | 1475 /** |
| 1523 * A {@link CodedOutputStream} that writes directly to a direct {@link ByteBuf
fer}, using only | 1476 * A {@link CodedOutputStream} that writes directly to a {@link ByteBuffer}. |
| 1524 * safe operations.. | |
| 1525 */ | 1477 */ |
| 1526 private static final class SafeDirectNioEncoder extends CodedOutputStream { | 1478 private static final class NioEncoder extends CodedOutputStream { |
| 1527 private final ByteBuffer originalBuffer; | 1479 private final ByteBuffer originalBuffer; |
| 1528 private final ByteBuffer buffer; | 1480 private final ByteBuffer buffer; |
| 1529 private final int initialPosition; | 1481 private final int initialPosition; |
| 1530 | 1482 |
| 1531 SafeDirectNioEncoder(ByteBuffer buffer) { | 1483 NioEncoder(ByteBuffer buffer) { |
| 1532 this.originalBuffer = buffer; | 1484 this.originalBuffer = buffer; |
| 1533 this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN); | 1485 this.buffer = buffer.duplicate().order(ByteOrder.LITTLE_ENDIAN); |
| 1534 initialPosition = buffer.position(); | 1486 initialPosition = buffer.position(); |
| 1535 } | 1487 } |
| 1536 | 1488 |
| 1537 @Override | 1489 @Override |
| 1538 public void writeTag(final int fieldNumber, final int wireType) throws IOExc
eption { | 1490 public void writeTag(final int fieldNumber, final int wireType) throws IOExc
eption { |
| 1539 writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); | 1491 writeUInt32NoTag(WireFormat.makeTag(fieldNumber, wireType)); |
| 1540 } | 1492 } |
| 1541 | 1493 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1824 private void encode(String value) throws IOException { | 1776 private void encode(String value) throws IOException { |
| 1825 try { | 1777 try { |
| 1826 Utf8.encodeUtf8(value, buffer); | 1778 Utf8.encodeUtf8(value, buffer); |
| 1827 } catch (IndexOutOfBoundsException e) { | 1779 } catch (IndexOutOfBoundsException e) { |
| 1828 throw new OutOfSpaceException(e); | 1780 throw new OutOfSpaceException(e); |
| 1829 } | 1781 } |
| 1830 } | 1782 } |
| 1831 } | 1783 } |
| 1832 | 1784 |
| 1833 /** | 1785 /** |
| 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 /** | |
| 2184 * Abstract base class for buffered encoders. | 1786 * Abstract base class for buffered encoders. |
| 2185 */ | 1787 */ |
| 2186 private abstract static class AbstractBufferedEncoder extends CodedOutputStrea
m { | 1788 private abstract static class AbstractBufferedEncoder extends CodedOutputStrea
m { |
| 2187 final byte[] buffer; | 1789 final byte[] buffer; |
| 2188 final int limit; | 1790 final int limit; |
| 2189 int position; | 1791 int position; |
| 2190 int totalBytesWritten; | 1792 int totalBytesWritten; |
| 2191 | 1793 |
| 2192 AbstractBufferedEncoder(int bufferSize) { | 1794 AbstractBufferedEncoder(int bufferSize) { |
| 2193 if (bufferSize < 0) { | 1795 if (bufferSize < 0) { |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2246 /** | 1848 /** |
| 2247 * This method does not perform bounds checking on the array. Checking array
bounds is the | 1849 * This method does not perform bounds checking on the array. Checking array
bounds is the |
| 2248 * responsibility of the caller. | 1850 * responsibility of the caller. |
| 2249 */ | 1851 */ |
| 2250 final void bufferUInt32NoTag(int value) { | 1852 final void bufferUInt32NoTag(int value) { |
| 2251 if (HAS_UNSAFE_ARRAY_OPERATIONS) { | 1853 if (HAS_UNSAFE_ARRAY_OPERATIONS) { |
| 2252 final long originalPos = ARRAY_BASE_OFFSET + position; | 1854 final long originalPos = ARRAY_BASE_OFFSET + position; |
| 2253 long pos = originalPos; | 1855 long pos = originalPos; |
| 2254 while (true) { | 1856 while (true) { |
| 2255 if ((value & ~0x7F) == 0) { | 1857 if ((value & ~0x7F) == 0) { |
| 2256 UnsafeUtil.putByte(buffer, pos++, (byte) value); | 1858 UNSAFE.putByte(buffer, pos++, (byte) value); |
| 2257 break; | 1859 break; |
| 2258 } else { | 1860 } else { |
| 2259 UnsafeUtil.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); | 1861 UNSAFE.putByte(buffer, pos++, (byte) ((value & 0x7F) | 0x80)); |
| 2260 value >>>= 7; | 1862 value >>>= 7; |
| 2261 } | 1863 } |
| 2262 } | 1864 } |
| 2263 int delta = (int) (pos - originalPos); | 1865 int delta = (int) (pos - originalPos); |
| 2264 position += delta; | 1866 position += delta; |
| 2265 totalBytesWritten += delta; | 1867 totalBytesWritten += delta; |
| 2266 } else { | 1868 } else { |
| 2267 while (true) { | 1869 while (true) { |
| 2268 if ((value & ~0x7F) == 0) { | 1870 if ((value & ~0x7F) == 0) { |
| 2269 buffer[position++] = (byte) value; | 1871 buffer[position++] = (byte) value; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 2281 /** | 1883 /** |
| 2282 * This method does not perform bounds checking on the array. Checking array
bounds is the | 1884 * This method does not perform bounds checking on the array. Checking array
bounds is the |
| 2283 * responsibility of the caller. | 1885 * responsibility of the caller. |
| 2284 */ | 1886 */ |
| 2285 final void bufferUInt64NoTag(long value) { | 1887 final void bufferUInt64NoTag(long value) { |
| 2286 if (HAS_UNSAFE_ARRAY_OPERATIONS) { | 1888 if (HAS_UNSAFE_ARRAY_OPERATIONS) { |
| 2287 final long originalPos = ARRAY_BASE_OFFSET + position; | 1889 final long originalPos = ARRAY_BASE_OFFSET + position; |
| 2288 long pos = originalPos; | 1890 long pos = originalPos; |
| 2289 while (true) { | 1891 while (true) { |
| 2290 if ((value & ~0x7FL) == 0) { | 1892 if ((value & ~0x7FL) == 0) { |
| 2291 UnsafeUtil.putByte(buffer, pos++, (byte) value); | 1893 UNSAFE.putByte(buffer, pos++, (byte) value); |
| 2292 break; | 1894 break; |
| 2293 } else { | 1895 } else { |
| 2294 UnsafeUtil.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x8
0)); | 1896 UNSAFE.putByte(buffer, pos++, (byte) (((int) value & 0x7F) | 0x80)); |
| 2295 value >>>= 7; | 1897 value >>>= 7; |
| 2296 } | 1898 } |
| 2297 } | 1899 } |
| 2298 int delta = (int) (pos - originalPos); | 1900 int delta = (int) (pos - originalPos); |
| 2299 position += delta; | 1901 position += delta; |
| 2300 totalBytesWritten += delta; | 1902 totalBytesWritten += delta; |
| 2301 } else { | 1903 } else { |
| 2302 while (true) { | 1904 while (true) { |
| 2303 if ((value & ~0x7FL) == 0) { | 1905 if ((value & ~0x7FL) == 0) { |
| 2304 buffer[position++] = (byte) value; | 1906 buffer[position++] = (byte) value; |
| (...skipping 686 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2991 if (limit - position < requiredSize) { | 2593 if (limit - position < requiredSize) { |
| 2992 doFlush(); | 2594 doFlush(); |
| 2993 } | 2595 } |
| 2994 } | 2596 } |
| 2995 | 2597 |
| 2996 private void doFlush() throws IOException { | 2598 private void doFlush() throws IOException { |
| 2997 out.write(buffer, 0, position); | 2599 out.write(buffer, 0, position); |
| 2998 position = 0; | 2600 position = 0; |
| 2999 } | 2601 } |
| 3000 } | 2602 } |
| 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 } |
| 3001 } | 2664 } |
| OLD | NEW |