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