CodedOutputStreamMicro.java revision e2d542951c059563a3b7f74c257dac4f222d9dc5
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 31package com.google.protobuf.micro; 32 33import java.io.OutputStream; 34import java.io.IOException; 35import 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 */ 51public 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 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 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 */ 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 */ 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 */ 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 */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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. */ 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 StringUtf8Micro} field, including tag, to the stream. */ 183 public void writeStringUtf8(final int fieldNumber, final StringUtf8Micro value) 184 throws IOException { 185 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 186 writeStringUtf8NoTag(value); 187 } 188 189 /** Write a {@code group} field, including tag, to the stream. */ 190 public void writeGroup(final int fieldNumber, final MessageMicro value) 191 throws IOException { 192 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_START_GROUP); 193 writeGroupNoTag(value); 194 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_END_GROUP); 195 } 196 197 /** Write an embedded message field, including tag, to the stream. */ 198 public void writeMessage(final int fieldNumber, final MessageMicro value) 199 throws IOException { 200 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 201 writeMessageNoTag(value); 202 } 203 204 /** Write a {@code bytes} field, including tag, to the stream. */ 205 public void writeBytes(final int fieldNumber, final ByteStringMicro value) 206 throws IOException { 207 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_LENGTH_DELIMITED); 208 writeBytesNoTag(value); 209 } 210 211 /** Write a {@code uint32} field, including tag, to the stream. */ 212 public void writeUInt32(final int fieldNumber, final int value) 213 throws IOException { 214 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 215 writeUInt32NoTag(value); 216 } 217 218 /** 219 * Write an enum field, including tag, to the stream. Caller is responsible 220 * for converting the enum value to its numeric value. 221 */ 222 public void writeEnum(final int fieldNumber, final int value) 223 throws IOException { 224 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 225 writeEnumNoTag(value); 226 } 227 228 /** Write an {@code sfixed32} field, including tag, to the stream. */ 229 public void writeSFixed32(final int fieldNumber, final int value) 230 throws IOException { 231 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED32); 232 writeSFixed32NoTag(value); 233 } 234 235 /** Write an {@code sfixed64} field, including tag, to the stream. */ 236 public void writeSFixed64(final int fieldNumber, final long value) 237 throws IOException { 238 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_FIXED64); 239 writeSFixed64NoTag(value); 240 } 241 242 /** Write an {@code sint32} field, including tag, to the stream. */ 243 public void writeSInt32(final int fieldNumber, final int value) 244 throws IOException { 245 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 246 writeSInt32NoTag(value); 247 } 248 249 /** Write an {@code sint64} field, including tag, to the stream. */ 250 public void writeSInt64(final int fieldNumber, final long value) 251 throws IOException { 252 writeTag(fieldNumber, WireFormatMicro.WIRETYPE_VARINT); 253 writeSInt64NoTag(value); 254 } 255 256 /** 257 * Write a MessageSet extension field to the stream. For historical reasons, 258 * the wire format differs from normal fields. 259 */ 260// public void writeMessageSetExtension(final int fieldNumber, 261// final MessageMicro value) 262// throws IOException { 263// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 264// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 265// writeMessage(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 266// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 267// } 268 269 /** 270 * Write an unparsed MessageSet extension field to the stream. For 271 * historical reasons, the wire format differs from normal fields. 272 */ 273// public void writeRawMessageSetExtension(final int fieldNumber, 274// final ByteStringMicro value) 275// throws IOException { 276// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_START_GROUP); 277// writeUInt32(WireFormatMicro.MESSAGE_SET_TYPE_ID, fieldNumber); 278// writeBytes(WireFormatMicro.MESSAGE_SET_MESSAGE, value); 279// writeTag(WireFormatMicro.MESSAGE_SET_ITEM, WireFormatMicro.WIRETYPE_END_GROUP); 280// } 281 282 // ----------------------------------------------------------------- 283 284 /** Write a {@code double} field to the stream. */ 285 public void writeDoubleNoTag(final double value) throws IOException { 286 writeRawLittleEndian64(Double.doubleToLongBits(value)); 287 } 288 289 /** Write a {@code float} field to the stream. */ 290 public void writeFloatNoTag(final float value) throws IOException { 291 writeRawLittleEndian32(Float.floatToIntBits(value)); 292 } 293 294 /** Write a {@code uint64} field to the stream. */ 295 public void writeUInt64NoTag(final long value) throws IOException { 296 writeRawVarint64(value); 297 } 298 299 /** Write an {@code int64} field to the stream. */ 300 public void writeInt64NoTag(final long value) throws IOException { 301 writeRawVarint64(value); 302 } 303 304 /** Write an {@code int32} field to the stream. */ 305 public void writeInt32NoTag(final int value) throws IOException { 306 if (value >= 0) { 307 writeRawVarint32(value); 308 } else { 309 // Must sign-extend. 310 writeRawVarint64(value); 311 } 312 } 313 314 /** Write a {@code fixed64} field to the stream. */ 315 public void writeFixed64NoTag(final long value) throws IOException { 316 writeRawLittleEndian64(value); 317 } 318 319 /** Write a {@code fixed32} field to the stream. */ 320 public void writeFixed32NoTag(final int value) throws IOException { 321 writeRawLittleEndian32(value); 322 } 323 324 /** Write a {@code bool} field to the stream. */ 325 public void writeBoolNoTag(final boolean value) throws IOException { 326 writeRawByte(value ? 1 : 0); 327 } 328 329 /** Write a {@code string} field to the stream. */ 330 public void writeStringNoTag(final String value) throws IOException { 331 // Unfortunately there does not appear to be any way to tell Java to encode 332 // UTF-8 directly into our buffer, so we have to let it create its own byte 333 // array and then copy. 334 final byte[] bytes = value.getBytes("UTF-8"); 335 writeRawVarint32(bytes.length); 336 writeRawBytes(bytes); 337 } 338 339 /** Write a {@code StringUtf8Micro} field to the stream. */ 340 public void writeStringUtf8NoTag(final StringUtf8Micro value) throws IOException { 341 final byte[] bytes = value.getBytes(); 342 writeRawVarint32(bytes.length); 343 writeRawBytes(bytes); 344 } 345 346 /** Write a {@code group} field to the stream. */ 347 public void writeGroupNoTag(final MessageMicro value) throws IOException { 348 value.writeTo(this); 349 } 350 351 /** Write an embedded message field to the stream. */ 352 public void writeMessageNoTag(final MessageMicro value) throws IOException { 353 writeRawVarint32(value.getCachedSize()); 354 value.writeTo(this); 355 } 356 357 /** Write a {@code bytes} field to the stream. */ 358 public void writeBytesNoTag(final ByteStringMicro value) throws IOException { 359 final byte[] bytes = value.toByteArray(); 360 writeRawVarint32(bytes.length); 361 writeRawBytes(bytes); 362 } 363 364 /** Write a {@code uint32} field to the stream. */ 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 */ 373 public void writeEnumNoTag(final int value) throws IOException { 374 writeRawVarint32(value); 375 } 376 377 /** Write an {@code sfixed32} field to the stream. */ 378 public void writeSFixed32NoTag(final int value) throws IOException { 379 writeRawLittleEndian32(value); 380 } 381 382 /** Write an {@code sfixed64} field to the stream. */ 383 public void writeSFixed64NoTag(final long value) throws IOException { 384 writeRawLittleEndian64(value); 385 } 386 387 /** Write an {@code sint32} field to the stream. */ 388 public void writeSInt32NoTag(final int value) throws IOException { 389 writeRawVarint32(encodeZigZag32(value)); 390 } 391 392 /** Write an {@code sint64} field to the stream. */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 StringUtf8Micro} field, including tag. 479 */ 480 public static int computeStringUtf8Size(final int fieldNumber, 481 final StringUtf8Micro value) { 482 return computeTagSize(fieldNumber) + computeStringUtf8SizeNoTag(value); 483 } 484 485 /** 486 * Compute the number of bytes that would be needed to encode a 487 * {@code group} field, including tag. 488 */ 489 public static int computeGroupSize(final int fieldNumber, 490 final MessageMicro value) { 491 return computeTagSize(fieldNumber) * 2 + computeGroupSizeNoTag(value); 492 } 493 494 /** 495 * Compute the number of bytes that would be needed to encode an 496 * embedded message field, including tag. 497 */ 498 public static int computeMessageSize(final int fieldNumber, 499 final MessageMicro value) { 500 return computeTagSize(fieldNumber) + computeMessageSizeNoTag(value); 501 } 502 503 /** 504 * Compute the number of bytes that would be needed to encode a 505 * {@code bytes} field, including tag. 506 */ 507 public static int computeBytesSize(final int fieldNumber, 508 final ByteStringMicro value) { 509 return computeTagSize(fieldNumber) + computeBytesSizeNoTag(value); 510 } 511 512 /** 513 * Compute the number of bytes that would be needed to encode a 514 * {@code uint32} field, including tag. 515 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 StringUtf8Micro} field. 675 */ 676 public static int computeStringUtf8SizeNoTag(final StringUtf8Micro value) { 677 final byte[] bytes = value.getBytes(); 678 return computeRawVarint32Size(bytes.length) + 679 bytes.length; 680 } 681 682 /** 683 * Compute the number of bytes that would be needed to encode a 684 * {@code group} field. 685 */ 686 public static int computeGroupSizeNoTag(final MessageMicro value) { 687 return value.getCachedSize(); 688 } 689 690 /** 691 * Compute the number of bytes that would be needed to encode an embedded 692 * message field. 693 */ 694 public static int computeMessageSizeNoTag(final MessageMicro value) { 695 final int size = value.getCachedSize(); 696 return computeRawVarint32Size(size) + size; 697 } 698 699 /** 700 * Compute the number of bytes that would be needed to encode a 701 * {@code bytes} field. 702 */ 703 public static int computeBytesSizeNoTag(final ByteStringMicro value) { 704 return computeRawVarint32Size(value.size()) + 705 value.size(); 706 } 707 708 /** 709 * Compute the number of bytes that would be needed to encode a 710 * {@code uint32} field. 711 */ 712 public static int computeUInt32SizeNoTag(final int value) { 713 return computeRawVarint32Size(value); 714 } 715 716 /** 717 * Compute the number of bytes that would be needed to encode an enum field. 718 * Caller is responsible for converting the enum value to its numeric value. 719 */ 720 public static int computeEnumSizeNoTag(final int value) { 721 return computeRawVarint32Size(value); 722 } 723 724 /** 725 * Compute the number of bytes that would be needed to encode an 726 * {@code sfixed32} field. 727 */ 728 public static int computeSFixed32SizeNoTag(final int value) { 729 return LITTLE_ENDIAN_32_SIZE; 730 } 731 732 /** 733 * Compute the number of bytes that would be needed to encode an 734 * {@code sfixed64} field. 735 */ 736 public static int computeSFixed64SizeNoTag(final long value) { 737 return LITTLE_ENDIAN_64_SIZE; 738 } 739 740 /** 741 * Compute the number of bytes that would be needed to encode an 742 * {@code sint32} field. 743 */ 744 public static int computeSInt32SizeNoTag(final int value) { 745 return computeRawVarint32Size(encodeZigZag32(value)); 746 } 747 748 /** 749 * Compute the number of bytes that would be needed to encode an 750 * {@code sint64} field. 751 */ 752 public static int computeSInt64SizeNoTag(final long value) { 753 return computeRawVarint64Size(encodeZigZag64(value)); 754 } 755 756 // ================================================================= 757 758 /** 759 * Internal helper that writes the current buffer to the output. The 760 * buffer position is reset to its initial value when this returns. 761 */ 762 private void refreshBuffer() throws IOException { 763 if (output == null) { 764 // We're writing to a single buffer. 765 throw new OutOfSpaceException(); 766 } 767 768 // Since we have an output stream, this is our buffer 769 // and buffer offset == 0 770 output.write(buffer, 0, position); 771 position = 0; 772 } 773 774 /** 775 * Flushes the stream and forces any buffered bytes to be written. This 776 * does not flush the underlying OutputStream. 777 */ 778 public void flush() throws IOException { 779 if (output != null) { 780 refreshBuffer(); 781 } 782 } 783 784 /** 785 * If writing to a flat array, return the space left in the array. 786 * Otherwise, throws {@code UnsupportedOperationException}. 787 */ 788 public int spaceLeft() { 789 if (output == null) { 790 return limit - position; 791 } else { 792 throw new UnsupportedOperationException( 793 "spaceLeft() can only be called on CodedOutputStreams that are " + 794 "writing to a flat array."); 795 } 796 } 797 798 /** 799 * Verifies that {@link #spaceLeft()} returns zero. It's common to create 800 * a byte array that is exactly big enough to hold a message, then write to 801 * it with a {@code CodedOutputStream}. Calling {@code checkNoSpaceLeft()} 802 * after writing verifies that the message was actually as big as expected, 803 * which can help catch bugs. 804 */ 805 public void checkNoSpaceLeft() { 806 if (spaceLeft() != 0) { 807 throw new IllegalStateException( 808 "Did not write as much data as expected."); 809 } 810 } 811 812 /** 813 * If you create a CodedOutputStream around a simple flat array, you must 814 * not attempt to write more bytes than the array has space. Otherwise, 815 * this exception will be thrown. 816 */ 817 public static class OutOfSpaceException extends IOException { 818 private static final long serialVersionUID = -6947486886997889499L; 819 820 OutOfSpaceException() { 821 super("CodedOutputStream was writing to a flat byte array and ran " + 822 "out of space."); 823 } 824 } 825 826 /** Write a single byte. */ 827 public void writeRawByte(final byte value) throws IOException { 828 if (position == limit) { 829 refreshBuffer(); 830 } 831 832 buffer[position++] = value; 833 } 834 835 /** Write a single byte, represented by an integer value. */ 836 public void writeRawByte(final int value) throws IOException { 837 writeRawByte((byte) value); 838 } 839 840 /** Write an array of bytes. */ 841 public void writeRawBytes(final byte[] value) throws IOException { 842 writeRawBytes(value, 0, value.length); 843 } 844 845 /** Write part of an array of bytes. */ 846 public void writeRawBytes(final byte[] value, int offset, int length) 847 throws IOException { 848 if (limit - position >= length) { 849 // We have room in the current buffer. 850 System.arraycopy(value, offset, buffer, position, length); 851 position += length; 852 } else { 853 // Write extends past current buffer. Fill the rest of this buffer and 854 // flush. 855 final int bytesWritten = limit - position; 856 System.arraycopy(value, offset, buffer, position, bytesWritten); 857 offset += bytesWritten; 858 length -= bytesWritten; 859 position = limit; 860 refreshBuffer(); 861 862 // Now deal with the rest. 863 // Since we have an output stream, this is our buffer 864 // and buffer offset == 0 865 if (length <= limit) { 866 // Fits in new buffer. 867 System.arraycopy(value, offset, buffer, 0, length); 868 position = length; 869 } else { 870 // Write is very big. Let's do it all at once. 871 output.write(value, offset, length); 872 } 873 } 874 } 875 876 /** Encode and write a tag. */ 877 public void writeTag(final int fieldNumber, final int wireType) 878 throws IOException { 879 writeRawVarint32(WireFormatMicro.makeTag(fieldNumber, wireType)); 880 } 881 882 /** Compute the number of bytes that would be needed to encode a tag. */ 883 public static int computeTagSize(final int fieldNumber) { 884 return computeRawVarint32Size(WireFormatMicro.makeTag(fieldNumber, 0)); 885 } 886 887 /** 888 * Encode and write a varint. {@code value} is treated as 889 * unsigned, so it won't be sign-extended if negative. 890 */ 891 public void writeRawVarint32(int value) throws IOException { 892 while (true) { 893 if ((value & ~0x7F) == 0) { 894 writeRawByte(value); 895 return; 896 } else { 897 writeRawByte((value & 0x7F) | 0x80); 898 value >>>= 7; 899 } 900 } 901 } 902 903 /** 904 * Compute the number of bytes that would be needed to encode a varint. 905 * {@code value} is treated as unsigned, so it won't be sign-extended if 906 * negative. 907 */ 908 public static int computeRawVarint32Size(final int value) { 909 if ((value & (0xffffffff << 7)) == 0) return 1; 910 if ((value & (0xffffffff << 14)) == 0) return 2; 911 if ((value & (0xffffffff << 21)) == 0) return 3; 912 if ((value & (0xffffffff << 28)) == 0) return 4; 913 return 5; 914 } 915 916 /** Encode and write a varint. */ 917 public void writeRawVarint64(long value) throws IOException { 918 while (true) { 919 if ((value & ~0x7FL) == 0) { 920 writeRawByte((int)value); 921 return; 922 } else { 923 writeRawByte(((int)value & 0x7F) | 0x80); 924 value >>>= 7; 925 } 926 } 927 } 928 929 /** Compute the number of bytes that would be needed to encode a varint. */ 930 public static int computeRawVarint64Size(final long value) { 931 if ((value & (0xffffffffffffffffL << 7)) == 0) return 1; 932 if ((value & (0xffffffffffffffffL << 14)) == 0) return 2; 933 if ((value & (0xffffffffffffffffL << 21)) == 0) return 3; 934 if ((value & (0xffffffffffffffffL << 28)) == 0) return 4; 935 if ((value & (0xffffffffffffffffL << 35)) == 0) return 5; 936 if ((value & (0xffffffffffffffffL << 42)) == 0) return 6; 937 if ((value & (0xffffffffffffffffL << 49)) == 0) return 7; 938 if ((value & (0xffffffffffffffffL << 56)) == 0) return 8; 939 if ((value & (0xffffffffffffffffL << 63)) == 0) return 9; 940 return 10; 941 } 942 943 /** Write a little-endian 32-bit integer. */ 944 public void writeRawLittleEndian32(final int value) throws IOException { 945 writeRawByte((value ) & 0xFF); 946 writeRawByte((value >> 8) & 0xFF); 947 writeRawByte((value >> 16) & 0xFF); 948 writeRawByte((value >> 24) & 0xFF); 949 } 950 951 public static final int LITTLE_ENDIAN_32_SIZE = 4; 952 953 /** Write a little-endian 64-bit integer. */ 954 public void writeRawLittleEndian64(final long value) throws IOException { 955 writeRawByte((int)(value ) & 0xFF); 956 writeRawByte((int)(value >> 8) & 0xFF); 957 writeRawByte((int)(value >> 16) & 0xFF); 958 writeRawByte((int)(value >> 24) & 0xFF); 959 writeRawByte((int)(value >> 32) & 0xFF); 960 writeRawByte((int)(value >> 40) & 0xFF); 961 writeRawByte((int)(value >> 48) & 0xFF); 962 writeRawByte((int)(value >> 56) & 0xFF); 963 } 964 965 public static final int LITTLE_ENDIAN_64_SIZE = 8; 966 967 /** 968 * Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers 969 * into values that can be efficiently encoded with varint. (Otherwise, 970 * negative values must be sign-extended to 64 bits to be varint encoded, 971 * thus always taking 10 bytes on the wire.) 972 * 973 * @param n A signed 32-bit integer. 974 * @return An unsigned 32-bit integer, stored in a signed int because 975 * Java has no explicit unsigned support. 976 */ 977 public static int encodeZigZag32(final int n) { 978 // Note: the right-shift must be arithmetic 979 return (n << 1) ^ (n >> 31); 980 } 981 982 /** 983 * Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers 984 * into values that can be efficiently encoded with varint. (Otherwise, 985 * negative values must be sign-extended to 64 bits to be varint encoded, 986 * thus always taking 10 bytes on the wire.) 987 * 988 * @param n A signed 64-bit integer. 989 * @return An unsigned 64-bit integer, stored in a signed int because 990 * Java has no explicit unsigned support. 991 */ 992 public static long encodeZigZag64(final long n) { 993 // Note: the right-shift must be arithmetic 994 return (n << 1) ^ (n >> 63); 995 } 996} 997