1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // http://code.google.com/p/protobuf/ 4 // 5 // Redistribution and use in source and binary forms, with or without 6 // modification, are permitted provided that the following conditions are 7 // met: 8 // 9 // * Redistributions of source code must retain the above copyright 10 // notice, this list of conditions and the following disclaimer. 11 // * Redistributions in binary form must reproduce the above 12 // copyright notice, this list of conditions and the following disclaimer 13 // in the documentation and/or other materials provided with the 14 // distribution. 15 // * Neither the name of Google Inc. nor the names of its 16 // contributors may be used to endorse or promote products derived from 17 // this software without specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31 package com.google.protobuf.micro; 32 33 import java.io.OutputStream; 34 import java.io.IOException; 35 import java.io.UnsupportedEncodingException; 36 37 /** 38 * Encodes and writes protocol message fields. 39 * 40 * <p>This class contains two kinds of methods: methods that write specific 41 * protocol message constructs and field types (e.g. {@link #writeTag} and 42 * {@link #writeInt32}) and methods that write low-level values (e.g. 43 * {@link #writeRawVarint32} and {@link #writeRawBytes}). If you are 44 * writing encoded protocol messages, you should use the former methods, but if 45 * you are writing some other format of your own design, use the latter. 46 * 47 * <p>This class is totally unsynchronized. 48 * 49 * @author kneton@google.com Kenton Varda 50 */ 51 public final class CodedOutputStreamMicro { 52 private final byte[] buffer; 53 private final int limit; 54 private int position; 55 56 private final OutputStream output; 57 58 /** 59 * The buffer size used in {@link #newInstance(OutputStream)}. 60 */ 61 public static final int DEFAULT_BUFFER_SIZE = 4096; 62 CodedOutputStreamMicro(final byte[] buffer, final int offset, final int length)63 private CodedOutputStreamMicro(final byte[] buffer, final int offset, 64 final int length) { 65 output = null; 66 this.buffer = buffer; 67 position = offset; 68 limit = offset + length; 69 } 70 CodedOutputStreamMicro(final OutputStream output, final byte[] buffer)71 private CodedOutputStreamMicro(final OutputStream output, final byte[] buffer) { 72 this.output = output; 73 this.buffer = buffer; 74 position = 0; 75 limit = buffer.length; 76 } 77 78 /** 79 * Create a new {@code CodedOutputStream} wrapping the given 80 * {@code OutputStream}. 81 */ newInstance(final OutputStream output)82 public static CodedOutputStreamMicro newInstance(final OutputStream output) { 83 return newInstance(output, DEFAULT_BUFFER_SIZE); 84 } 85 86 /** 87 * Create a new {@code CodedOutputStream} wrapping the given 88 * {@code OutputStream} with a given buffer size. 89 */ newInstance(final OutputStream output, final int bufferSize)90 public static CodedOutputStreamMicro newInstance(final OutputStream output, 91 final int bufferSize) { 92 return new CodedOutputStreamMicro(output, new byte[bufferSize]); 93 } 94 95 /** 96 * Create a new {@code CodedOutputStream} that writes directly to the given 97 * byte array. If more bytes are written than fit in the array, 98 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 99 * array is faster than writing to an {@code OutputStream}. 100 */ newInstance(final byte[] flatArray)101 public static CodedOutputStreamMicro newInstance(final byte[] flatArray) { 102 return newInstance(flatArray, 0, flatArray.length); 103 } 104 105 /** 106 * Create a new {@code CodedOutputStream} that writes directly to the given 107 * byte array slice. If more bytes are written than fit in the slice, 108 * {@link OutOfSpaceException} will be thrown. Writing directly to a flat 109 * array is faster than writing to an {@code OutputStream}. 110 */ newInstance(final byte[] flatArray, final int offset, final int length)111 public static CodedOutputStreamMicro newInstance(final byte[] flatArray, 112 final int offset, 113 final int length) { 114 return new CodedOutputStreamMicro(flatArray, offset, length); 115 } 116 117 // ----------------------------------------------------------------- 118 119 /** Write a {@code double} field, including tag, to the stream. */ writeDouble(final int fieldNumber, final double value)120 public void writeDouble(final int fieldNumber, final double value) 121 throws IOException { 122 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64); 123 writeDoubleNoTag(value); 124 } 125 126 /** Write a {@code float} field, including tag, to the stream. */ writeFloat(final int fieldNumber, final float value)127 public void writeFloat(final int fieldNumber, final float value) 128 throws IOException { 129 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32); 130 writeFloatNoTag(value); 131 } 132 133 /** Write a {@code uint64} field, including tag, to the stream. */ writeUInt64(final int fieldNumber, final long value)134 public void writeUInt64(final int fieldNumber, final long value) 135 throws IOException { 136 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 137 writeUInt64NoTag(value); 138 } 139 140 /** Write an {@code int64} field, including tag, to the stream. */ writeInt64(final int fieldNumber, final long value)141 public void writeInt64(final int fieldNumber, final long value) 142 throws IOException { 143 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 144 writeInt64NoTag(value); 145 } 146 147 /** Write an {@code int32} field, including tag, to the stream. */ writeInt32(final int fieldNumber, final int value)148 public void writeInt32(final int fieldNumber, final int value) 149 throws IOException { 150 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 151 writeInt32NoTag(value); 152 } 153 154 /** Write a {@code fixed64} field, including tag, to the stream. */ writeFixed64(final int fieldNumber, final long value)155 public void writeFixed64(final int fieldNumber, final long value) 156 throws IOException { 157 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64); 158 writeFixed64NoTag(value); 159 } 160 161 /** Write a {@code fixed32} field, including tag, to the stream. */ writeFixed32(final int fieldNumber, final int value)162 public void writeFixed32(final int fieldNumber, final int value) 163 throws IOException { 164 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32); 165 writeFixed32NoTag(value); 166 } 167 168 /** Write a {@code bool} field, including tag, to the stream. */ writeBool(final int fieldNumber, final boolean value)169 public void writeBool(final int fieldNumber, final boolean value) 170 throws IOException { 171 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 172 writeBoolNoTag(value); 173 } 174 175 /** Write a {@code string} field, including tag, to the stream. */ writeString(final int fieldNumber, final String value)176 public void writeString(final int fieldNumber, final String value) 177 throws IOException { 178 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 179 writeStringNoTag(value); 180 } 181 182 /** Write a {@code group} field, including tag, to the stream. */ writeGroup(final int fieldNumber, final MessageMicro value)183 public void writeGroup(final int fieldNumber, final MessageMicro value) 184 throws IOException { 185 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_START_GROUP); 186 writeGroupNoTag(value); 187 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP); 188 } 189 190 /** Write an embedded message field, including tag, to the stream. */ writeMessage(final int fieldNumber, final MessageMicro value)191 public void writeMessage(final int fieldNumber, final MessageMicro value) 192 throws IOException { 193 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 194 writeMessageNoTag(value); 195 } 196 197 /** Write a {@code bytes} field, including tag, to the stream. */ writeBytes(final int fieldNumber, final ByteStringMicro value)198 public void writeBytes(final int fieldNumber, final ByteStringMicro value) 199 throws IOException { 200 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 201 writeBytesNoTag(value); 202 } 203 204 /** Write a {@code byte} field, including tag, to the stream. */ writeByteArray(final int fieldNumber, final byte[] value)205 public void writeByteArray(final int fieldNumber, final byte[] value) 206 throws IOException { 207 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 208 writeByteArrayNoTag(value); 209 } 210 211 212 /** Write a {@code uint32} field, including tag, to the stream. */ writeUInt32(final int fieldNumber, final int value)213 public void writeUInt32(final int fieldNumber, final int value) 214 throws IOException { 215 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 216 writeUInt32NoTag(value); 217 } 218 219 /** 220 * Write an enum field, including tag, to the stream. Caller is responsible 221 * for converting the enum value to its numeric value. 222 */ writeEnum(final int fieldNumber, final int value)223 public void writeEnum(final int fieldNumber, final int value) 224 throws IOException { 225 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 226 writeEnumNoTag(value); 227 } 228 229 /** Write an {@code sfixed32} field, including tag, to the stream. */ writeSFixed32(final int fieldNumber, final int value)230 public void writeSFixed32(final int fieldNumber, final int value) 231 throws IOException { 232 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32); 233 writeSFixed32NoTag(value); 234 } 235 236 /** Write an {@code sfixed64} field, including tag, to the stream. */ writeSFixed64(final int fieldNumber, final long value)237 public void writeSFixed64(final int fieldNumber, final long value) 238 throws IOException { 239 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64); 240 writeSFixed64NoTag(value); 241 } 242 243 /** Write an {@code sint32} field, including tag, to the stream. */ writeSInt32(final int fieldNumber, final int value)244 public void writeSInt32(final int fieldNumber, final int value) 245 throws IOException { 246 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 247 writeSInt32NoTag(value); 248 } 249 250 /** Write an {@code sint64} field, including tag, to the stream. */ writeSInt64(final int fieldNumber, final long value)251 public void writeSInt64(final int fieldNumber, final long value) 252 throws IOException { 253 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 254 writeSInt64NoTag(value); 255 } 256 257 /** 258 * Write a MessageSet extension field to the stream. For historical reasons, 259 * the wire format differs from normal fields. 260 */ 261 // public void writeMessageSetExtension(final int fieldNumber, 262 // final MessageMicro value) 263 // throws IOException { 264 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 265 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 266 // writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 267 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 268 // } 269 270 /** 271 * Write an unparsed MessageSet extension field to the stream. For 272 * historical reasons, the wire format differs from normal fields. 273 */ 274 // public void writeRawMessageSetExtension(final int fieldNumber, 275 // final ByteStringMicro value) 276 // throws IOException { 277 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 278 // writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 279 // writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 280 // writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 281 // } 282 283 // ----------------------------------------------------------------- 284 285 /** Write a {@code double} field to the stream. */ writeDoubleNoTag(final double value)286 public void writeDoubleNoTag(final double value) throws IOException { 287 writeRawLittleEndian64(Double.doubleToLongBits(value)); 288 } 289 290 /** Write a {@code float} field to the stream. */ writeFloatNoTag(final float value)291 public void writeFloatNoTag(final float value) throws IOException { 292 writeRawLittleEndian32(Float.floatToIntBits(value)); 293 } 294 295 /** Write a {@code uint64} field to the stream. */ writeUInt64NoTag(final long value)296 public void writeUInt64NoTag(final long value) throws IOException { 297 writeRawVarint64(value); 298 } 299 300 /** Write an {@code int64} field to the stream. */ writeInt64NoTag(final long value)301 public void writeInt64NoTag(final long value) throws IOException { 302 writeRawVarint64(value); 303 } 304 305 /** Write an {@code int32} field to the stream. */ writeInt32NoTag(final int value)306 public void writeInt32NoTag(final int value) throws IOException { 307 if (value >= 0) { 308 writeRawVarint32(value); 309 } else { 310 // Must sign-extend. 311 writeRawVarint64(value); 312 } 313 } 314 315 /** Write a {@code fixed64} field to the stream. */ writeFixed64NoTag(final long value)316 public void writeFixed64NoTag(final long value) throws IOException { 317 writeRawLittleEndian64(value); 318 } 319 320 /** Write a {@code fixed32} field to the stream. */ writeFixed32NoTag(final int value)321 public void writeFixed32NoTag(final int value) throws IOException { 322 writeRawLittleEndian32(value); 323 } 324 325 /** Write a {@code bool} field to the stream. */ writeBoolNoTag(final boolean value)326 public void writeBoolNoTag(final boolean value) throws IOException { 327 writeRawByte(value ? 1 : 0); 328 } 329 330 /** Write a {@code string} field to the stream. */ writeStringNoTag(final String value)331 public void writeStringNoTag(final String value) throws IOException { 332 // Unfortunately there does not appear to be any way to tell Java to encode 333 // UTF-8 directly into our buffer, so we have to let it create its own byte 334 // array and then copy. 335 final byte[] bytes = value.getBytes("UTF-8"); 336 writeRawVarint32(bytes.length); 337 writeRawBytes(bytes); 338 } 339 340 /** Write a {@code group} field to the stream. */ writeGroupNoTag(final MessageMicro value)341 public void writeGroupNoTag(final MessageMicro value) throws IOException { 342 value.writeTo(this); 343 } 344 345 /** Write an embedded message field to the stream. */ writeMessageNoTag(final MessageMicro value)346 public void writeMessageNoTag(final MessageMicro value) throws IOException { 347 writeRawVarint32(value.getCachedSize()); 348 value.writeTo(this); 349 } 350 351 /** Write a {@code bytes} field to the stream. */ writeBytesNoTag(final ByteStringMicro value)352 public void writeBytesNoTag(final ByteStringMicro value) throws IOException { 353 final byte[] bytes = value.toByteArray(); 354 writeRawVarint32(bytes.length); 355 writeRawBytes(bytes); 356 } 357 358 /** Write a {@code byte[]} field to the stream. */ writeByteArrayNoTag(final byte [] value)359 public void writeByteArrayNoTag(final byte [] value) throws IOException { 360 writeRawVarint32(value.length); 361 writeRawBytes(value); 362 } 363 364 /** Write a {@code uint32} field to the stream. */ writeUInt32NoTag(final int value)365 public void writeUInt32NoTag(final int value) throws IOException { 366 writeRawVarint32(value); 367 } 368 369 /** 370 * Write an enum field to the stream. Caller is responsible 371 * for converting the enum value to its numeric value. 372 */ writeEnumNoTag(final int value)373 public void writeEnumNoTag(final int value) throws IOException { 374 writeRawVarint32(value); 375 } 376 377 /** Write an {@code sfixed32} field to the stream. */ writeSFixed32NoTag(final int value)378 public void writeSFixed32NoTag(final int value) throws IOException { 379 writeRawLittleEndian32(value); 380 } 381 382 /** Write an {@code sfixed64} field to the stream. */ writeSFixed64NoTag(final long value)383 public void writeSFixed64NoTag(final long value) throws IOException { 384 writeRawLittleEndian64(value); 385 } 386 387 /** Write an {@code sint32} field to the stream. */ writeSInt32NoTag(final int value)388 public void writeSInt32NoTag(final int value) throws IOException { 389 writeRawVarint32(encodeZigZag32(value)); 390 } 391 392 /** Write an {@code sint64} field to the stream. */ writeSInt64NoTag(final long value)393 public void writeSInt64NoTag(final long value) throws IOException { 394 writeRawVarint64(encodeZigZag64(value)); 395 } 396 397 // ================================================================= 398 399 /** 400 * Compute the number of bytes that would be needed to encode a 401 * {@code double} field, including tag. 402 */ computeDoubleSize(final int fieldNumber, final double value)403 public static int computeDoubleSize(final int fieldNumber, 404 final double value) { 405 return computeTagSize(fieldNumber) + computeDoubleSizeNoTag(value); 406 } 407 408 /** 409 * Compute the number of bytes that would be needed to encode a 410 * {@code float} field, including tag. 411 */ computeFloatSize(final int fieldNumber, final float value)412 public static int computeFloatSize(final int fieldNumber, final float value) { 413 return computeTagSize(fieldNumber) + computeFloatSizeNoTag(value); 414 } 415 416 /** 417 * Compute the number of bytes that would be needed to encode a 418 * {@code uint64} field, including tag. 419 */ computeUInt64Size(final int fieldNumber, final long value)420 public static int computeUInt64Size(final int fieldNumber, final long value) { 421 return computeTagSize(fieldNumber) + computeUInt64SizeNoTag(value); 422 } 423 424 /** 425 * Compute the number of bytes that would be needed to encode an 426 * {@code int64} field, including tag. 427 */ computeInt64Size(final int fieldNumber, final long value)428 public static int computeInt64Size(final int fieldNumber, final long value) { 429 return computeTagSize(fieldNumber) + computeInt64SizeNoTag(value); 430 } 431 432 /** 433 * Compute the number of bytes that would be needed to encode an 434 * {@code int32} field, including tag. 435 */ computeInt32Size(final int fieldNumber, final int value)436 public static int computeInt32Size(final int fieldNumber, final int value) { 437 return computeTagSize(fieldNumber) + computeInt32SizeNoTag(value); 438 } 439 440 /** 441 * Compute the number of bytes that would be needed to encode a 442 * {@code fixed64} field, including tag. 443 */ computeFixed64Size(final int fieldNumber, final long value)444 public static int computeFixed64Size(final int fieldNumber, 445 final long value) { 446 return computeTagSize(fieldNumber) + computeFixed64SizeNoTag(value); 447 } 448 449 /** 450 * Compute the number of bytes that would be needed to encode a 451 * {@code fixed32} field, including tag. 452 */ computeFixed32Size(final int fieldNumber, final int value)453 public static int computeFixed32Size(final int fieldNumber, 454 final int value) { 455 return computeTagSize(fieldNumber) + computeFixed32SizeNoTag(value); 456 } 457 458 /** 459 * Compute the number of bytes that would be needed to encode a 460 * {@code bool} field, including tag. 461 */ computeBoolSize(final int fieldNumber, final boolean value)462 public static int computeBoolSize(final int fieldNumber, 463 final boolean value) { 464 return computeTagSize(fieldNumber) + computeBoolSizeNoTag(value); 465 } 466 467 /** 468 * Compute the number of bytes that would be needed to encode a 469 * {@code string} field, including tag. 470 */ computeStringSize(final int fieldNumber, final String value)471 public static int computeStringSize(final int fieldNumber, 472 final String value) { 473 return computeTagSize(fieldNumber) + computeStringSizeNoTag(value); 474 } 475 476 /** 477 * Compute the number of bytes that would be needed to encode a 478 * {@code group} field, including tag. 479 */ computeGroupSize(final int fieldNumber, final MessageMicro value)480 public static int computeGroupSize(final int fieldNumber, 481 final MessageMicro value) { 482 return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); 483 } 484 485 /** 486 * Compute the number of bytes that would be needed to encode an 487 * embedded message field, including tag. 488 */ computeMessageSize(final int fieldNumber, final MessageMicro value)489 public static int computeMessageSize(final int fieldNumber, 490 final MessageMicro value) { 491 return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); 492 } 493 494 /** 495 * Compute the number of bytes that would be needed to encode a 496 * {@code bytes} field, including tag. 497 */ computeBytesSize(final int fieldNumber, final ByteStringMicro value)498 public static int computeBytesSize(final int fieldNumber, 499 final ByteStringMicro value) { 500 return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); 501 } 502 503 /** 504 * Compute the number of bytes that would be needed to encode a 505 * {@code byte[]} field, including tag. 506 */ computeByteArraySize(final int fieldNumber, final byte[] value)507 public static int computeByteArraySize(final int fieldNumber, 508 final byte[] value) { 509 return computeTagSize(fieldNumber) + computeByteArraySizeNoTag(value); 510 } 511 512 /** 513 * Compute the number of bytes that would be needed to encode a 514 * {@code uint32} field, including tag. 515 */ computeUInt32Size(final int fieldNumber, final int value)516 public static int computeUInt32Size(final int fieldNumber, final int value) { 517 return computeTagSize(fieldNumber) + computeUInt32SizeNoTag(value); 518 } 519 520 /** 521 * Compute the number of bytes that would be needed to encode an 522 * enum field, including tag. Caller is responsible for converting the 523 * enum value to its numeric value. 524 */ computeEnumSize(final int fieldNumber, final int value)525 public static int computeEnumSize(final int fieldNumber, final int value) { 526 return computeTagSize(fieldNumber) + computeEnumSizeNoTag(value); 527 } 528 529 /** 530 * Compute the number of bytes that would be needed to encode an 531 * {@code sfixed32} field, including tag. 532 */ computeSFixed32Size(final int fieldNumber, final int value)533 public static int computeSFixed32Size(final int fieldNumber, 534 final int value) { 535 return computeTagSize(fieldNumber) + computeSFixed32SizeNoTag(value); 536 } 537 538 /** 539 * Compute the number of bytes that would be needed to encode an 540 * {@code sfixed64} field, including tag. 541 */ computeSFixed64Size(final int fieldNumber, final long value)542 public static int computeSFixed64Size(final int fieldNumber, 543 final long value) { 544 return computeTagSize(fieldNumber) + computeSFixed64SizeNoTag(value); 545 } 546 547 /** 548 * Compute the number of bytes that would be needed to encode an 549 * {@code sint32} field, including tag. 550 */ computeSInt32Size(final int fieldNumber, final int value)551 public static int computeSInt32Size(final int fieldNumber, final int value) { 552 return computeTagSize(fieldNumber) + computeSInt32SizeNoTag(value); 553 } 554 555 /** 556 * Compute the number of bytes that would be needed to encode an 557 * {@code sint64} field, including tag. 558 */ computeSInt64Size(final int fieldNumber, final long value)559 public static int computeSInt64Size(final int fieldNumber, final long value) { 560 return computeTagSize(fieldNumber) + computeSInt64SizeNoTag(value); 561 } 562 563 /** 564 * Compute the number of bytes that would be needed to encode a 565 * MessageSet extension to the stream. For historical reasons, 566 * the wire format differs from normal fields. 567 */ 568 // public static int computeMessageSetExtensionSize( 569 // final int fieldNumber, final MessageMicro value) { 570 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 571 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 572 // computeMessageSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 573 // } 574 575 /** 576 * Compute the number of bytes that would be needed to encode an 577 * unparsed MessageSet extension field to the stream. For 578 * historical reasons, the wire format differs from normal fields. 579 */ 580 // public static int computeRawMessageSetExtensionSize( 581 // final int fieldNumber, final ByteStringMicro value) { 582 // return computeTagSize(WireFormatMicro.MESSAGE_SET_ITEM) * 2 + 583 // computeUInt32Size(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber) + 584 // computeBytesSize(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 585 // } 586 587 // ----------------------------------------------------------------- 588 589 /** 590 * Compute the number of bytes that would be needed to encode a 591 * {@code double} field, including tag. 592 */ computeDoubleSizeNoTag(final double value)593 public static int computeDoubleSizeNoTag(final double value) { 594 return LITTLE_ENDIAN_64_SIZE; 595 } 596 597 /** 598 * Compute the number of bytes that would be needed to encode a 599 * {@code float} field, including tag. 600 */ computeFloatSizeNoTag(final float value)601 public static int computeFloatSizeNoTag(final float value) { 602 return LITTLE_ENDIAN_32_SIZE; 603 } 604 605 /** 606 * Compute the number of bytes that would be needed to encode a 607 * {@code uint64} field, including tag. 608 */ computeUInt64SizeNoTag(final long value)609 public static int computeUInt64SizeNoTag(final long value) { 610 return computeRawVarint64Size(value); 611 } 612 613 /** 614 * Compute the number of bytes that would be needed to encode an 615 * {@code int64} field, including tag. 616 */ computeInt64SizeNoTag(final long value)617 public static int computeInt64SizeNoTag(final long value) { 618 return computeRawVarint64Size(value); 619 } 620 621 /** 622 * Compute the number of bytes that would be needed to encode an 623 * {@code int32} field, including tag. 624 */ computeInt32SizeNoTag(final int value)625 public static int computeInt32SizeNoTag(final int value) { 626 if (value >= 0) { 627 return computeRawVarint32Size(value); 628 } else { 629 // Must sign-extend. 630 return 10; 631 } 632 } 633 634 /** 635 * Compute the number of bytes that would be needed to encode a 636 * {@code fixed64} field. 637 */ computeFixed64SizeNoTag(final long value)638 public static int computeFixed64SizeNoTag(final long value) { 639 return LITTLE_ENDIAN_64_SIZE; 640 } 641 642 /** 643 * Compute the number of bytes that would be needed to encode a 644 * {@code fixed32} field. 645 */ computeFixed32SizeNoTag(final int value)646 public static int computeFixed32SizeNoTag(final int value) { 647 return LITTLE_ENDIAN_32_SIZE; 648 } 649 650 /** 651 * Compute the number of bytes that would be needed to encode a 652 * {@code bool} field. 653 */ computeBoolSizeNoTag(final boolean value)654 public static int computeBoolSizeNoTag(final boolean value) { 655 return 1; 656 } 657 658 /** 659 * Compute the number of bytes that would be needed to encode a 660 * {@code string} field. 661 */ computeStringSizeNoTag(final String value)662 public static int computeStringSizeNoTag(final String value) { 663 try { 664 final byte[] bytes = value.getBytes("UTF-8"); 665 return computeRawVarint32Size(bytes.length) + 666 bytes.length; 667 } catch (UnsupportedEncodingException e) { 668 throw new RuntimeException("UTF-8 not supported."); 669 } 670 } 671 672 /** 673 * Compute the number of bytes that would be needed to encode a 674 * {@code group} field. 675 */ computeGroupSizeNoTag(final MessageMicro value)676 public static int computeGroupSizeNoTag(final MessageMicro value) { 677 return value.getSerializedSize(); 678 } 679 680 /** 681 * Compute the number of bytes that would be needed to encode an embedded 682 * message field. 683 */ computeMessageSizeNoTag(final MessageMicro value)684 public static int computeMessageSizeNoTag(final MessageMicro value) { 685 final int size = value.getSerializedSize(); 686 return computeRawVarint32Size(size) + size; 687 } 688 689 /** 690 * Compute the number of bytes that would be needed to encode a 691 * {@code bytes} field. 692 */ computeBytesSizeNoTag(final ByteStringMicro value)693 public static int computeBytesSizeNoTag(final ByteStringMicro value) { 694 return computeRawVarint32Size(value.size()) + value.size(); 695 } 696 697 /** 698 * Compute the number of bytes that would be needed to encode a 699 * {@code byte[]} field. 700 */ computeByteArraySizeNoTag(final byte[] value)701 public static int computeByteArraySizeNoTag(final byte[] value) { 702 return computeRawVarint32Size(value.length) + value.length; 703 } 704 705 /** 706 * Compute the number of bytes that would be needed to encode a 707 * {@code uint32} field. 708 */ computeUInt32SizeNoTag(final int value)709 public static int computeUInt32SizeNoTag(final int value) { 710 return computeRawVarint32Size(value); 711 } 712 713 /** 714 * Compute the number of bytes that would be needed to encode an enum field. 715 * Caller is responsible for converting the enum value to its numeric value. 716 */ computeEnumSizeNoTag(final int value)717 public static int computeEnumSizeNoTag(final int value) { 718 return computeRawVarint32Size(value); 719 } 720 721 /** 722 * Compute the number of bytes that would be needed to encode an 723 * {@code sfixed32} field. 724 */ computeSFixed32SizeNoTag(final int value)725 public static int computeSFixed32SizeNoTag(final int value) { 726 return LITTLE_ENDIAN_32_SIZE; 727 } 728 729 /** 730 * Compute the number of bytes that would be needed to encode an 731 * {@code sfixed64} field. 732 */ computeSFixed64SizeNoTag(final long value)733 public static int computeSFixed64SizeNoTag(final long value) { 734 return LITTLE_ENDIAN_64_SIZE; 735 } 736 737 /** 738 * Compute the number of bytes that would be needed to encode an 739 * {@code sint32} field. 740 */ computeSInt32SizeNoTag(final int value)741 public static int computeSInt32SizeNoTag(final int value) { 742 return computeRawVarint32Size(encodeZigZag32(value)); 743 } 744 745 /** 746 * Compute the number of bytes that would be needed to encode an 747 * {@code sint64} field. 748 */ computeSInt64SizeNoTag(final long value)749 public static int computeSInt64SizeNoTag(final long value) { 750 return computeRawVarint64Size(encodeZigZag64(value)); 751 } 752 753 // ================================================================= 754 755 /** 756 * Internal helper that writes the current buffer to the output. The 757 * buffer position is reset to its initial value when this returns. 758 */ refreshBuffer()759 private void refreshBuffer() throws IOException { 760 if (output == null) { 761 // We're writing to a single buffer. 762 throw new OutOfSpaceException(); 763 } 764 765 // Since we have an output stream, this is our buffer 766 // and buffer offset == 0 767 output.write(buffer, 0, position); 768 position = 0; 769 } 770 771 /** 772 * Flushes the stream and forces any buffered bytes to be written. This 773 * does not flush the underlying OutputStream. 774 */ flush()775 public void flush() throws IOException { 776 if (output != null) { 777 refreshBuffer(); 778 } 779 } 780 781 /** 782 * If writing to a flat array, return the space left in the array. 783 * Otherwise, throws {@code UnsupportedOperationException}. 784 */ spaceLeft()785 public int spaceLeft() { 786 if (output == null) { 787 return limit - position; 788 } else { 789 throw new UnsupportedOperationException( 790 "spaceLeft() can only be called on CodedOutputStreams that are " + 791 "writing to a flat array."); 792 } 793 } 794 795 /** 796 * Verifies that {@link #spaceLeft()} returns zero. It's common to create 797 * a byte array that is exactly big enough to hold a message, then write to 798 * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} 799 * after writing verifies that the message was actually as big as expected, 800 * which can help catch bugs. 801 */ checkNoSpaceLeft()802 public void checkNoSpaceLeft() { 803 if (spaceLeft() != 0) { 804 throw new IllegalStateException( 805 "Did not write as much data as expected."); 806 } 807 } 808 809 /** 810 * If you create a CodedOutputStream around a simple flat array, you must 811 * not attempt to write more bytes than the array has space. Otherwise, 812 * this exception will be thrown. 813 */ 814 public static class OutOfSpaceException extends IOException { 815 private static final long serialVersionUID = -6947486886997889499L; 816 OutOfSpaceException()817 OutOfSpaceException() { 818 super("CodedOutputStream was writing to a flat byte array and ran " + 819 "out of space."); 820 } 821 } 822 823 /** Write a single byte. */ writeRawByte(final byte value)824 public void writeRawByte(final byte value) throws IOException { 825 if (position == limit) { 826 refreshBuffer(); 827 } 828 829 buffer[position++] = value; 830 } 831 832 /** Write a single byte, represented by an integer value. */ writeRawByte(final int value)833 public void writeRawByte(final int value) throws IOException { 834 writeRawByte((byte) value); 835 } 836 837 /** Write an array of bytes. */ writeRawBytes(final byte[] value)838 public void writeRawBytes(final byte[] value) throws IOException { 839 writeRawBytes(value, 0, value.length); 840 } 841 842 /** Write part of an array of bytes. */ writeRawBytes(final byte[] value, int offset, int length)843 public void writeRawBytes(final byte[] value, int offset, int length) 844 throws IOException { 845 if (limit - position >= length) { 846 // We have room in the current buffer. 847 System.arraycopy(value, offset, buffer, position, length); 848 position += length; 849 } else { 850 // Write extends past current buffer. Fill the rest of this buffer and 851 // flush. 852 final int bytesWritten = limit - position; 853 System.arraycopy(value, offset, buffer, position, bytesWritten); 854 offset += bytesWritten; 855 length -= bytesWritten; 856 position = limit; 857 refreshBuffer(); 858 859 // Now deal with the rest. 860 // Since we have an output stream, this is our buffer 861 // and buffer offset == 0 862 if (length <= limit) { 863 // Fits in new buffer. 864 System.arraycopy(value, offset, buffer, 0, length); 865 position = length; 866 } else { 867 // Write is very big. Let's do it all at once. 868 output.write(value, offset, length); 869 } 870 } 871 } 872 873 /** Encode and write a tag. */ writeTag(final int fieldNumber, final int wireType)874 public void writeTag(final int fieldNumber, final int wireType) 875 throws IOException { 876 writeRawVarint32(WireFormatMicro.makeTag(fieldNumber, wireType)); 877 } 878 879 /** Compute the number of bytes that would be needed to encode a tag. */ computeTagSize(final int fieldNumber)880 public static int computeTagSize(final int fieldNumber) { 881 return computeRawVarint32Size(WireFormatMicro.makeTag(fieldNumber, 0)); 882 } 883 884 /** 885 * Encode and write a varint. {@code value} is treated as 886 * unsigned, so it won't be sign-extended if negative. 887 */ writeRawVarint32(int value)888 public void writeRawVarint32(int value) throws IOException { 889 while (true) { 890 if ((value & ~0x7F) == 0) { 891 writeRawByte(value); 892 return; 893 } else { 894 writeRawByte((value & 0x7F) | 0x80); 895 value >>>= 7; 896 } 897 } 898 } 899 900 /** 901 * Compute the number of bytes that would be needed to encode a varint. 902 * {@code value} is treated as unsigned, so it won't be sign-extended if 903 * negative. 904 */ computeRawVarint32Size(final int value)905 public static int computeRawVarint32Size(final int value) { 906 if ((value & (0xffffffff << 7)) == 0) return 1; 907 if ((value & (0xffffffff << 14)) == 0) return 2; 908 if ((value & (0xffffffff << 21)) == 0) return 3; 909 if ((value & (0xffffffff << 28)) == 0) return 4; 910 return 5; 911 } 912 913 /** Encode and write a varint. */ writeRawVarint64(long value)914 public void writeRawVarint64(long value) throws IOException { 915 while (true) { 916 if ((value & ~0x7FL) == 0) { 917 writeRawByte((int)value); 918 return; 919 } else { 920 writeRawByte(((int)value & 0x7F) | 0x80); 921 value >>>= 7; 922 } 923 } 924 } 925 926 /** Compute the number of bytes that would be needed to encode a varint. */ computeRawVarint64Size(final long value)927 public static int computeRawVarint64Size(final long value) { 928 if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; 929 if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; 930 if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; 931 if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; 932 if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; 933 if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; 934 if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; 935 if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; 936 if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; 937 return 10; 938 } 939 940 /** Write a little-endian 32-bit integer. */ writeRawLittleEndian32(final int value)941 public void writeRawLittleEndian32(final int value) throws IOException { 942 writeRawByte((value ) & 0xFF); 943 writeRawByte((value >> 8) & 0xFF); 944 writeRawByte((value >> 16) & 0xFF); 945 writeRawByte((value >> 24) & 0xFF); 946 } 947 948 public static final int LITTLE_ENDIAN_32_SIZE = 4; 949 950 /** Write a little-endian 64-bit integer. */ writeRawLittleEndian64(final long value)951 public void writeRawLittleEndian64(final long value) throws IOException { 952 writeRawByte((int)(value ) & 0xFF); 953 writeRawByte((int)(value >> 8) & 0xFF); 954 writeRawByte((int)(value >> 16) & 0xFF); 955 writeRawByte((int)(value >> 24) & 0xFF); 956 writeRawByte((int)(value >> 32) & 0xFF); 957 writeRawByte((int)(value >> 40) & 0xFF); 958 writeRawByte((int)(value >> 48) & 0xFF); 959 writeRawByte((int)(value >> 56) & 0xFF); 960 } 961 962 public static final int LITTLE_ENDIAN_64_SIZE = 8; 963 964 /** 965 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 966 * into values that can be efficiently encoded with varint. (Otherwise, 967 * negative values must be sign-extended to 64 bits to be varint encoded, 968 * thus always taking 10 bytes on the wire.) 969 * 970 * @param n A signed 32-bit integer. 971 * @return An unsigned 32-bit integer, stored in a signed int because 972 * Java has no explicit unsigned support. 973 */ encodeZigZag32(final int n)974 public static int encodeZigZag32(final int n) { 975 // Note: the right-shift must be arithmetic 976 return (n << 1) ^ (n >> 31); 977 } 978 979 /** 980 * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 981 * into values that can be efficiently encoded with varint. (Otherwise, 982 * negative values must be sign-extended to 64 bits to be varint encoded, 983 * thus always taking 10 bytes on the wire.) 984 * 985 * @param n A signed 64-bit integer. 986 * @return An unsigned 64-bit integer, stored in a signed int because 987 * Java has no explicit unsigned support. 988 */ encodeZigZag64(final long n)989 public static long encodeZigZag64(final long n) { 990 // Note: the right-shift must be arithmetic 991 return (n << 1) ^ (n >> 63); 992 } 993 } 994