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