Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.ProtobufCS/2.4.1/ProtobufCS/src/ProtocolBuffers/CodedOutputStream.cs @ 8295

Last change on this file since 8295 was 8295, checked in by abeham, 12 years ago

#1897:

  • Removed protocol buffers 0.9.1
  • Added protocol buffers 2.4.1
  • Updated proto processing command
File size: 47.2 KB
Line 
1#region Copyright notice and license
2
3// Protocol Buffers - Google's data interchange format
4// Copyright 2008 Google Inc.  All rights reserved.
5// http://github.com/jskeet/dotnet-protobufs/
6// Original C++/Java/Python code:
7// http://code.google.com/p/protobuf/
8//
9// Redistribution and use in source and binary forms, with or without
10// modification, are permitted provided that the following conditions are
11// met:
12//
13//     * Redistributions of source code must retain the above copyright
14// notice, this list of conditions and the following disclaimer.
15//     * Redistributions in binary form must reproduce the above
16// copyright notice, this list of conditions and the following disclaimer
17// in the documentation and/or other materials provided with the
18// distribution.
19//     * Neither the name of Google Inc. nor the names of its
20// contributors may be used to endorse or promote products derived from
21// this software without specific prior written permission.
22//
23// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
26// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
27// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
30// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
31// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
33// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35#endregion
36
37using System;
38using System.Collections;
39using System.Collections.Generic;
40using System.IO;
41using System.Text;
42using Google.ProtocolBuffers.Collections;
43using Google.ProtocolBuffers.Descriptors;
44
45namespace Google.ProtocolBuffers
46{
47    /// <summary>
48    /// Encodes and writes protocol message fields.
49    /// </summary>
50    /// <remarks>
51    /// This class contains two kinds of methods:  methods that write specific
52    /// protocol message constructs and field types (e.g. WriteTag and
53    /// WriteInt32) and methods that write low-level values (e.g.
54    /// WriteRawVarint32 and WriteRawBytes).  If you are writing encoded protocol
55    /// messages, you should use the former methods, but if you are writing some
56    /// other format of your own design, use the latter. The names of the former
57    /// methods are taken from the protocol buffer type names, not .NET types.
58    /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
59    /// </remarks>
60    public sealed partial class CodedOutputStream : ICodedOutputStream
61    {
62        /// <summary>
63        /// The buffer size used by CreateInstance(Stream).
64        /// </summary>
65        public static readonly int DefaultBufferSize = 4096;
66
67        private readonly byte[] buffer;
68        private readonly int limit;
69        private int position;
70        private readonly Stream output;
71
72        #region Construction
73
74        private CodedOutputStream(byte[] buffer, int offset, int length)
75        {
76            this.output = null;
77            this.buffer = buffer;
78            this.position = offset;
79            this.limit = offset + length;
80        }
81
82        private CodedOutputStream(Stream output, byte[] buffer)
83        {
84            this.output = output;
85            this.buffer = buffer;
86            this.position = 0;
87            this.limit = buffer.Length;
88        }
89
90        /// <summary>
91        /// Creates a new CodedOutputStream which write to the given stream.
92        /// </summary>
93        public static CodedOutputStream CreateInstance(Stream output)
94        {
95            return CreateInstance(output, DefaultBufferSize);
96        }
97
98        /// <summary>
99        /// Creates a new CodedOutputStream which write to the given stream and uses
100        /// the specified buffer size.
101        /// </summary>
102        public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
103        {
104            return new CodedOutputStream(output, new byte[bufferSize]);
105        }
106
107        /// <summary>
108        /// Creates a new CodedOutputStream that writes directly to the given
109        /// byte array. If more bytes are written than fit in the array,
110        /// OutOfSpaceException will be thrown.
111        /// </summary>
112        public static CodedOutputStream CreateInstance(byte[] flatArray)
113        {
114            return CreateInstance(flatArray, 0, flatArray.Length);
115        }
116
117        /// <summary>
118        /// Creates a new CodedOutputStream that writes directly to the given
119        /// byte array slice. If more bytes are written than fit in the array,
120        /// OutOfSpaceException will be thrown.
121        /// </summary>
122        public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
123        {
124            return new CodedOutputStream(flatArray, offset, length);
125        }
126
127        #endregion
128       
129        void ICodedOutputStream.WriteMessageStart() { }
130        void ICodedOutputStream.WriteMessageEnd() { Flush(); }
131
132        #region Writing of unknown fields
133
134        [Obsolete]
135        public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
136        {
137            WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
138            value.WriteTo(this);
139            WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
140        }
141
142        public void WriteUnknownBytes(int fieldNumber, ByteString value)
143        {
144            WriteBytes(fieldNumber, null /*not used*/, value);
145        }
146
147        [CLSCompliant(false)]
148        public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
149        {
150            if (wireType == WireFormat.WireType.Varint)
151            {
152                WriteUInt64(fieldNumber, null /*not used*/, value);
153            }
154            else if (wireType == WireFormat.WireType.Fixed32)
155            {
156                WriteFixed32(fieldNumber, null /*not used*/, (uint) value);
157            }
158            else if (wireType == WireFormat.WireType.Fixed64)
159            {
160                WriteFixed64(fieldNumber, null /*not used*/, value);
161            }
162            else
163            {
164                throw InvalidProtocolBufferException.InvalidWireType();
165            }
166        }
167
168        #endregion
169
170        #region Writing of tags and fields
171
172        public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
173        {
174            switch (fieldType)
175            {
176                case FieldType.String:
177                    WriteString(fieldNumber, fieldName, (string) value);
178                    break;
179                case FieldType.Message:
180                    WriteMessage(fieldNumber, fieldName, (IMessageLite) value);
181                    break;
182                case FieldType.Group:
183                    WriteGroup(fieldNumber, fieldName, (IMessageLite) value);
184                    break;
185                case FieldType.Bytes:
186                    WriteBytes(fieldNumber, fieldName, (ByteString) value);
187                    break;
188                case FieldType.Bool:
189                    WriteBool(fieldNumber, fieldName, (bool) value);
190                    break;
191                case FieldType.Enum:
192                    if (value is Enum)
193                    {
194                        WriteEnum(fieldNumber, fieldName, (int) value, null /*not used*/);
195                    }
196                    else
197                    {
198                        WriteEnum(fieldNumber, fieldName, ((IEnumLite) value).Number, null /*not used*/);
199                    }
200                    break;
201                case FieldType.Int32:
202                    WriteInt32(fieldNumber, fieldName, (int) value);
203                    break;
204                case FieldType.Int64:
205                    WriteInt64(fieldNumber, fieldName, (long) value);
206                    break;
207                case FieldType.UInt32:
208                    WriteUInt32(fieldNumber, fieldName, (uint) value);
209                    break;
210                case FieldType.UInt64:
211                    WriteUInt64(fieldNumber, fieldName, (ulong) value);
212                    break;
213                case FieldType.SInt32:
214                    WriteSInt32(fieldNumber, fieldName, (int) value);
215                    break;
216                case FieldType.SInt64:
217                    WriteSInt64(fieldNumber, fieldName, (long) value);
218                    break;
219                case FieldType.Fixed32:
220                    WriteFixed32(fieldNumber, fieldName, (uint) value);
221                    break;
222                case FieldType.Fixed64:
223                    WriteFixed64(fieldNumber, fieldName, (ulong) value);
224                    break;
225                case FieldType.SFixed32:
226                    WriteSFixed32(fieldNumber, fieldName, (int) value);
227                    break;
228                case FieldType.SFixed64:
229                    WriteSFixed64(fieldNumber, fieldName, (long) value);
230                    break;
231                case FieldType.Double:
232                    WriteDouble(fieldNumber, fieldName, (double) value);
233                    break;
234                case FieldType.Float:
235                    WriteFloat(fieldNumber, fieldName, (float) value);
236                    break;
237            }
238        }
239
240        /// <summary>
241        /// Writes a double field value, including tag, to the stream.
242        /// </summary>
243        public void WriteDouble(int fieldNumber, string fieldName, double value)
244        {
245            WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
246            WriteDoubleNoTag(value);
247        }
248
249        /// <summary>
250        /// Writes a float field value, including tag, to the stream.
251        /// </summary>
252        public void WriteFloat(int fieldNumber, string fieldName, float value)
253        {
254            WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
255            WriteFloatNoTag(value);
256        }
257
258        /// <summary>
259        /// Writes a uint64 field value, including tag, to the stream.
260        /// </summary>
261        [CLSCompliant(false)]
262        public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
263        {
264            WriteTag(fieldNumber, WireFormat.WireType.Varint);
265            WriteRawVarint64(value);
266        }
267
268        /// <summary>
269        /// Writes an int64 field value, including tag, to the stream.
270        /// </summary>
271        public void WriteInt64(int fieldNumber, string fieldName, long value)
272        {
273            WriteTag(fieldNumber, WireFormat.WireType.Varint);
274            WriteRawVarint64((ulong) value);
275        }
276
277        /// <summary>
278        /// Writes an int32 field value, including tag, to the stream.
279        /// </summary>
280        public void WriteInt32(int fieldNumber, string fieldName, int value)
281        {
282            WriteTag(fieldNumber, WireFormat.WireType.Varint);
283            if (value >= 0)
284            {
285                WriteRawVarint32((uint) value);
286            }
287            else
288            {
289                // Must sign-extend.
290                WriteRawVarint64((ulong) value);
291            }
292        }
293
294        /// <summary>
295        /// Writes a fixed64 field value, including tag, to the stream.
296        /// </summary>
297        [CLSCompliant(false)]
298        public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
299        {
300            WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
301            WriteRawLittleEndian64(value);
302        }
303
304        /// <summary>
305        /// Writes a fixed32 field value, including tag, to the stream.
306        /// </summary>
307        [CLSCompliant(false)]
308        public void WriteFixed32(int fieldNumber, string fieldName, uint value)
309        {
310            WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
311            WriteRawLittleEndian32(value);
312        }
313
314        /// <summary>
315        /// Writes a bool field value, including tag, to the stream.
316        /// </summary>
317        public void WriteBool(int fieldNumber, string fieldName, bool value)
318        {
319            WriteTag(fieldNumber, WireFormat.WireType.Varint);
320            WriteRawByte(value ? (byte) 1 : (byte) 0);
321        }
322
323        /// <summary>
324        /// Writes a string field value, including tag, to the stream.
325        /// </summary>
326        public void WriteString(int fieldNumber, string fieldName, string value)
327        {
328            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
329            // Optimise the case where we have enough space to write
330            // the string directly to the buffer, which should be common.
331            int length = Encoding.UTF8.GetByteCount(value);
332            WriteRawVarint32((uint) length);
333            if (limit - position >= length)
334            {
335                Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
336                position += length;
337            }
338            else
339            {
340                byte[] bytes = Encoding.UTF8.GetBytes(value);
341                WriteRawBytes(bytes);
342            }
343        }
344
345        /// <summary>
346        /// Writes a group field value, including tag, to the stream.
347        /// </summary>
348        public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
349        {
350            WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
351            value.WriteTo(this);
352            WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
353        }
354
355        public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
356        {
357            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
358            WriteRawVarint32((uint) value.SerializedSize);
359            value.WriteTo(this);
360        }
361
362        public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
363        {
364            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
365            WriteRawVarint32((uint) value.Length);
366            value.WriteRawBytesTo(this);
367        }
368
369        [CLSCompliant(false)]
370        public void WriteUInt32(int fieldNumber, string fieldName, uint value)
371        {
372            WriteTag(fieldNumber, WireFormat.WireType.Varint);
373            WriteRawVarint32(value);
374        }
375
376        public void WriteEnum(int fieldNumber, string fieldName, int value, object rawValue)
377        {
378            WriteTag(fieldNumber, WireFormat.WireType.Varint);
379            WriteInt32NoTag(value);
380        }
381
382        public void WriteSFixed32(int fieldNumber, string fieldName, int value)
383        {
384            WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
385            WriteRawLittleEndian32((uint) value);
386        }
387
388        public void WriteSFixed64(int fieldNumber, string fieldName, long value)
389        {
390            WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
391            WriteRawLittleEndian64((ulong) value);
392        }
393
394        public void WriteSInt32(int fieldNumber, string fieldName, int value)
395        {
396            WriteTag(fieldNumber, WireFormat.WireType.Varint);
397            WriteRawVarint32(EncodeZigZag32(value));
398        }
399
400        public void WriteSInt64(int fieldNumber, string fieldName, long value)
401        {
402            WriteTag(fieldNumber, WireFormat.WireType.Varint);
403            WriteRawVarint64(EncodeZigZag64(value));
404        }
405
406        public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
407        {
408            WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
409            WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
410            WriteMessage(WireFormat.MessageSetField.Message, "message", value);
411            WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
412        }
413
414        public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
415        {
416            WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
417            WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
418            WriteBytes(WireFormat.MessageSetField.Message, "message", value);
419            WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
420        }
421
422        #endregion
423
424        #region Writing of values without tags
425
426        public void WriteFieldNoTag(FieldType fieldType, object value)
427        {
428            switch (fieldType)
429            {
430                case FieldType.String:
431                    WriteStringNoTag((string) value);
432                    break;
433                case FieldType.Message:
434                    WriteMessageNoTag((IMessageLite) value);
435                    break;
436                case FieldType.Group:
437                    WriteGroupNoTag((IMessageLite) value);
438                    break;
439                case FieldType.Bytes:
440                    WriteBytesNoTag((ByteString) value);
441                    break;
442                case FieldType.Bool:
443                    WriteBoolNoTag((bool) value);
444                    break;
445                case FieldType.Enum:
446                    if (value is Enum)
447                    {
448                        WriteEnumNoTag((int) value);
449                    }
450                    else
451                    {
452                        WriteEnumNoTag(((IEnumLite) value).Number);
453                    }
454                    break;
455                case FieldType.Int32:
456                    WriteInt32NoTag((int) value);
457                    break;
458                case FieldType.Int64:
459                    WriteInt64NoTag((long) value);
460                    break;
461                case FieldType.UInt32:
462                    WriteUInt32NoTag((uint) value);
463                    break;
464                case FieldType.UInt64:
465                    WriteUInt64NoTag((ulong) value);
466                    break;
467                case FieldType.SInt32:
468                    WriteSInt32NoTag((int) value);
469                    break;
470                case FieldType.SInt64:
471                    WriteSInt64NoTag((long) value);
472                    break;
473                case FieldType.Fixed32:
474                    WriteFixed32NoTag((uint) value);
475                    break;
476                case FieldType.Fixed64:
477                    WriteFixed64NoTag((ulong) value);
478                    break;
479                case FieldType.SFixed32:
480                    WriteSFixed32NoTag((int) value);
481                    break;
482                case FieldType.SFixed64:
483                    WriteSFixed64NoTag((long) value);
484                    break;
485                case FieldType.Double:
486                    WriteDoubleNoTag((double) value);
487                    break;
488                case FieldType.Float:
489                    WriteFloatNoTag((float) value);
490                    break;
491            }
492        }
493
494        /// <summary>
495        /// Writes a double field value, including tag, to the stream.
496        /// </summary>
497        public void WriteDoubleNoTag(double value)
498        {
499#if SILVERLIGHT || COMPACT_FRAMEWORK_35
500            byte[] rawBytes = BitConverter.GetBytes(value);
501            if (!BitConverter.IsLittleEndian)
502                ByteArray.Reverse(rawBytes);
503           
504            if (limit - position >= 8)
505            {
506                buffer[position++] = rawBytes[0];
507                buffer[position++] = rawBytes[1];
508                buffer[position++] = rawBytes[2];
509                buffer[position++] = rawBytes[3];
510                buffer[position++] = rawBytes[4];
511                buffer[position++] = rawBytes[5];
512                buffer[position++] = rawBytes[6];
513                buffer[position++] = rawBytes[7];
514            }
515            else
516                WriteRawBytes(rawBytes, 0, 8);
517#else
518            WriteRawLittleEndian64((ulong) BitConverter.DoubleToInt64Bits(value));
519#endif
520        }
521
522        /// <summary>
523        /// Writes a float field value, without a tag, to the stream.
524        /// </summary>
525        public void WriteFloatNoTag(float value)
526        {
527            byte[] rawBytes = BitConverter.GetBytes(value);
528            if (!BitConverter.IsLittleEndian)
529            {
530                ByteArray.Reverse(rawBytes);
531            }
532
533            if (limit - position >= 4)
534            {
535                buffer[position++] = rawBytes[0];
536                buffer[position++] = rawBytes[1];
537                buffer[position++] = rawBytes[2];
538                buffer[position++] = rawBytes[3];
539            }
540            else
541            {
542                WriteRawBytes(rawBytes, 0, 4);
543            }
544        }
545
546        /// <summary>
547        /// Writes a uint64 field value, without a tag, to the stream.
548        /// </summary>
549        [CLSCompliant(false)]
550        public void WriteUInt64NoTag(ulong value)
551        {
552            WriteRawVarint64(value);
553        }
554
555        /// <summary>
556        /// Writes an int64 field value, without a tag, to the stream.
557        /// </summary>
558        public void WriteInt64NoTag(long value)
559        {
560            WriteRawVarint64((ulong) value);
561        }
562
563        /// <summary>
564        /// Writes an int32 field value, without a tag, to the stream.
565        /// </summary>
566        public void WriteInt32NoTag(int value)
567        {
568            if (value >= 0)
569            {
570                WriteRawVarint32((uint) value);
571            }
572            else
573            {
574                // Must sign-extend.
575                WriteRawVarint64((ulong) value);
576            }
577        }
578
579        /// <summary>
580        /// Writes a fixed64 field value, without a tag, to the stream.
581        /// </summary>
582        [CLSCompliant(false)]
583        public void WriteFixed64NoTag(ulong value)
584        {
585            WriteRawLittleEndian64(value);
586        }
587
588        /// <summary>
589        /// Writes a fixed32 field value, without a tag, to the stream.
590        /// </summary>
591        [CLSCompliant(false)]
592        public void WriteFixed32NoTag(uint value)
593        {
594            WriteRawLittleEndian32(value);
595        }
596
597        /// <summary>
598        /// Writes a bool field value, without a tag, to the stream.
599        /// </summary>
600        public void WriteBoolNoTag(bool value)
601        {
602            WriteRawByte(value ? (byte) 1 : (byte) 0);
603        }
604
605        /// <summary>
606        /// Writes a string field value, without a tag, to the stream.
607        /// </summary>
608        public void WriteStringNoTag(string value)
609        {
610            // Optimise the case where we have enough space to write
611            // the string directly to the buffer, which should be common.
612            int length = Encoding.UTF8.GetByteCount(value);
613            WriteRawVarint32((uint) length);
614            if (limit - position >= length)
615            {
616                Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
617                position += length;
618            }
619            else
620            {
621                byte[] bytes = Encoding.UTF8.GetBytes(value);
622                WriteRawBytes(bytes);
623            }
624        }
625
626        /// <summary>
627        /// Writes a group field value, without a tag, to the stream.
628        /// </summary>
629        public void WriteGroupNoTag(IMessageLite value)
630        {
631            value.WriteTo(this);
632        }
633
634        public void WriteMessageNoTag(IMessageLite value)
635        {
636            WriteRawVarint32((uint) value.SerializedSize);
637            value.WriteTo(this);
638        }
639
640        public void WriteBytesNoTag(ByteString value)
641        {
642            WriteRawVarint32((uint) value.Length);
643            value.WriteRawBytesTo(this);
644        }
645
646        [CLSCompliant(false)]
647        public void WriteUInt32NoTag(uint value)
648        {
649            WriteRawVarint32(value);
650        }
651
652        public void WriteEnumNoTag(int value)
653        {
654            WriteInt32NoTag(value);
655        }
656
657        public void WriteSFixed32NoTag(int value)
658        {
659            WriteRawLittleEndian32((uint) value);
660        }
661
662        public void WriteSFixed64NoTag(long value)
663        {
664            WriteRawLittleEndian64((ulong) value);
665        }
666
667        public void WriteSInt32NoTag(int value)
668        {
669            WriteRawVarint32(EncodeZigZag32(value));
670        }
671
672        public void WriteSInt64NoTag(long value)
673        {
674            WriteRawVarint64(EncodeZigZag64(value));
675        }
676
677        #endregion
678
679        #region Write array members
680
681        public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
682        {
683            foreach (object element in list)
684            {
685                WriteField(fieldType, fieldNumber, fieldName, element);
686            }
687        }
688
689        public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
690            where T : IMessageLite
691        {
692            foreach (IMessageLite value in list)
693            {
694                WriteGroup(fieldNumber, fieldName, value);
695            }
696        }
697
698        public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
699            where T : IMessageLite
700        {
701            foreach (IMessageLite value in list)
702            {
703                WriteMessage(fieldNumber, fieldName, value);
704            }
705        }
706
707        public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
708        {
709            foreach (var value in list)
710            {
711                WriteString(fieldNumber, fieldName, value);
712            }
713        }
714
715        public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
716        {
717            foreach (var value in list)
718            {
719                WriteBytes(fieldNumber, fieldName, value);
720            }
721        }
722
723        public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
724        {
725            foreach (var value in list)
726            {
727                WriteBool(fieldNumber, fieldName, value);
728            }
729        }
730
731        public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
732        {
733            foreach (var value in list)
734            {
735                WriteInt32(fieldNumber, fieldName, value);
736            }
737        }
738
739        public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
740        {
741            foreach (var value in list)
742            {
743                WriteSInt32(fieldNumber, fieldName, value);
744            }
745        }
746
747        public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
748        {
749            foreach (var value in list)
750            {
751                WriteUInt32(fieldNumber, fieldName, value);
752            }
753        }
754
755        public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
756        {
757            foreach (var value in list)
758            {
759                WriteFixed32(fieldNumber, fieldName, value);
760            }
761        }
762
763        public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
764        {
765            foreach (var value in list)
766            {
767                WriteSFixed32(fieldNumber, fieldName, value);
768            }
769        }
770
771        public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
772        {
773            foreach (var value in list)
774            {
775                WriteInt64(fieldNumber, fieldName, value);
776            }
777        }
778
779        public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
780        {
781            foreach (var value in list)
782            {
783                WriteSInt64(fieldNumber, fieldName, value);
784            }
785        }
786
787        public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
788        {
789            foreach (var value in list)
790            {
791                WriteUInt64(fieldNumber, fieldName, value);
792            }
793        }
794
795        public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
796        {
797            foreach (var value in list)
798            {
799                WriteFixed64(fieldNumber, fieldName, value);
800            }
801        }
802
803        public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
804        {
805            foreach (var value in list)
806            {
807                WriteSFixed64(fieldNumber, fieldName, value);
808            }
809        }
810
811        public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
812        {
813            foreach (var value in list)
814            {
815                WriteDouble(fieldNumber, fieldName, value);
816            }
817        }
818
819        public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
820        {
821            foreach (var value in list)
822            {
823                WriteFloat(fieldNumber, fieldName, value);
824            }
825        }
826
827        [CLSCompliant(false)]
828        public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
829            where T : struct, IComparable, IFormattable, IConvertible
830        {
831            if (list is ICastArray)
832            {
833                foreach (int value in ((ICastArray) list).CastArray<int>())
834                {
835                    WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
836                }
837            }
838            else
839            {
840                foreach (object value in list)
841                {
842                    WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
843                }
844            }
845        }
846
847        #endregion
848
849        #region Write packed array members
850
851        public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, IEnumerable list)
852        {
853            int calculatedSize = 0;
854            foreach (object element in list)
855            {
856                calculatedSize += ComputeFieldSizeNoTag(fieldType, element);
857            }
858
859            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
860            WriteRawVarint32((uint) calculatedSize);
861
862            foreach (object element in list)
863            {
864                WriteFieldNoTag(fieldType, element);
865            }
866        }
867
868        public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
869            where T : IMessageLite
870        {
871            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
872            WriteRawVarint32((uint) calculatedSize);
873            foreach (IMessageLite value in list)
874            {
875                WriteGroupNoTag(value);
876            }
877        }
878
879        public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize,
880                                               IEnumerable<T> list)
881            where T : IMessageLite
882        {
883            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
884            WriteRawVarint32((uint) calculatedSize);
885            foreach (IMessageLite value in list)
886            {
887                WriteMessageNoTag(value);
888            }
889        }
890
891        public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize,
892                                           IEnumerable<string> list)
893        {
894            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
895            WriteRawVarint32((uint) calculatedSize);
896            foreach (var value in list)
897            {
898                WriteStringNoTag(value);
899            }
900        }
901
902        public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize,
903                                          IEnumerable<ByteString> list)
904        {
905            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
906            WriteRawVarint32((uint) calculatedSize);
907            foreach (var value in list)
908            {
909                WriteBytesNoTag(value);
910            }
911        }
912
913        public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
914        {
915            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
916            WriteRawVarint32((uint) calculatedSize);
917            foreach (var value in list)
918            {
919                WriteBoolNoTag(value);
920            }
921        }
922
923        public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
924        {
925            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
926            WriteRawVarint32((uint) calculatedSize);
927            foreach (var value in list)
928            {
929                WriteInt32NoTag(value);
930            }
931        }
932
933        public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
934        {
935            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
936            WriteRawVarint32((uint) calculatedSize);
937            foreach (var value in list)
938            {
939                WriteSInt32NoTag(value);
940            }
941        }
942
943        public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
944        {
945            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
946            WriteRawVarint32((uint) calculatedSize);
947            foreach (var value in list)
948            {
949                WriteUInt32NoTag(value);
950            }
951        }
952
953        public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
954                                            IEnumerable<uint> list)
955        {
956            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
957            WriteRawVarint32((uint) calculatedSize);
958            foreach (var value in list)
959            {
960                WriteFixed32NoTag(value);
961            }
962        }
963
964        public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize,
965                                             IEnumerable<int> list)
966        {
967            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
968            WriteRawVarint32((uint) calculatedSize);
969            foreach (var value in list)
970            {
971                WriteSFixed32NoTag(value);
972            }
973        }
974
975        public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
976        {
977            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
978            WriteRawVarint32((uint) calculatedSize);
979            foreach (var value in list)
980            {
981                WriteInt64NoTag(value);
982            }
983        }
984
985        public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
986        {
987            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
988            WriteRawVarint32((uint) calculatedSize);
989            foreach (var value in list)
990            {
991                WriteSInt64NoTag(value);
992            }
993        }
994
995        public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize,
996                                           IEnumerable<ulong> list)
997        {
998            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
999            WriteRawVarint32((uint) calculatedSize);
1000            foreach (var value in list)
1001            {
1002                WriteUInt64NoTag(value);
1003            }
1004        }
1005
1006        public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1007                                            IEnumerable<ulong> list)
1008        {
1009            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
1010            WriteRawVarint32((uint) calculatedSize);
1011            foreach (var value in list)
1012            {
1013                WriteFixed64NoTag(value);
1014            }
1015        }
1016
1017        public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize,
1018                                             IEnumerable<long> list)
1019        {
1020            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
1021            WriteRawVarint32((uint) calculatedSize);
1022            foreach (var value in list)
1023            {
1024                WriteSFixed64NoTag(value);
1025            }
1026        }
1027
1028        public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize,
1029                                           IEnumerable<double> list)
1030        {
1031            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
1032            WriteRawVarint32((uint) calculatedSize);
1033            foreach (var value in list)
1034            {
1035                WriteDoubleNoTag(value);
1036            }
1037        }
1038
1039        public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
1040        {
1041            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
1042            WriteRawVarint32((uint) calculatedSize);
1043            foreach (var value in list)
1044            {
1045                WriteFloatNoTag(value);
1046            }
1047        }
1048
1049        [CLSCompliant(false)]
1050        public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
1051            where T : struct, IComparable, IFormattable, IConvertible
1052        {
1053            WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
1054            WriteRawVarint32((uint) calculatedSize);
1055            if (list is ICastArray)
1056            {
1057                foreach (int value in ((ICastArray) list).CastArray<int>())
1058                {
1059                    WriteEnumNoTag(value);
1060                }
1061            }
1062            else
1063            {
1064                foreach (object value in list)
1065                {
1066                    WriteEnumNoTag((int) value);
1067                }
1068            }
1069        }
1070
1071        #endregion
1072
1073        #region Underlying writing primitives
1074
1075        /// <summary>
1076        /// Encodes and writes a tag.
1077        /// </summary>
1078        [CLSCompliant(false)]
1079        public void WriteTag(int fieldNumber, WireFormat.WireType type)
1080        {
1081            WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
1082        }
1083
1084        /// <summary>
1085        /// Writes a 32 bit value as a varint. The fast route is taken when
1086        /// there's enough buffer space left to whizz through without checking
1087        /// for each byte; otherwise, we resort to calling WriteRawByte each time.
1088        /// </summary>
1089        [CLSCompliant(false)]
1090        public void WriteRawVarint32(uint value)
1091        {
1092            while (value > 127 && position < limit)
1093            {
1094                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
1095                value >>= 7;
1096            }
1097            while (value > 127)
1098            {
1099                WriteRawByte((byte) ((value & 0x7F) | 0x80));
1100                value >>= 7;
1101            }
1102            if (position < limit)
1103            {
1104                buffer[position++] = (byte) value;
1105            }
1106            else
1107            {
1108                WriteRawByte((byte) value);
1109            }
1110        }
1111
1112        [CLSCompliant(false)]
1113        public void WriteRawVarint64(ulong value)
1114        {
1115            while (value > 127 && position < limit)
1116            {
1117                buffer[position++] = (byte) ((value & 0x7F) | 0x80);
1118                value >>= 7;
1119            }
1120            while (value > 127)
1121            {
1122                WriteRawByte((byte) ((value & 0x7F) | 0x80));
1123                value >>= 7;
1124            }
1125            if (position < limit)
1126            {
1127                buffer[position++] = (byte) value;
1128            }
1129            else
1130            {
1131                WriteRawByte((byte) value);
1132            }
1133        }
1134
1135        [CLSCompliant(false)]
1136        public void WriteRawLittleEndian32(uint value)
1137        {
1138            if (position + 4 > limit)
1139            {
1140                WriteRawByte((byte) value);
1141                WriteRawByte((byte) (value >> 8));
1142                WriteRawByte((byte) (value >> 16));
1143                WriteRawByte((byte) (value >> 24));
1144            }
1145            else
1146            {
1147                buffer[position++] = ((byte) value);
1148                buffer[position++] = ((byte) (value >> 8));
1149                buffer[position++] = ((byte) (value >> 16));
1150                buffer[position++] = ((byte) (value >> 24));
1151            }
1152        }
1153
1154        [CLSCompliant(false)]
1155        public void WriteRawLittleEndian64(ulong value)
1156        {
1157            if (position + 8 > limit)
1158            {
1159                WriteRawByte((byte) value);
1160                WriteRawByte((byte) (value >> 8));
1161                WriteRawByte((byte) (value >> 16));
1162                WriteRawByte((byte) (value >> 24));
1163                WriteRawByte((byte) (value >> 32));
1164                WriteRawByte((byte) (value >> 40));
1165                WriteRawByte((byte) (value >> 48));
1166                WriteRawByte((byte) (value >> 56));
1167            }
1168            else
1169            {
1170                buffer[position++] = ((byte) value);
1171                buffer[position++] = ((byte) (value >> 8));
1172                buffer[position++] = ((byte) (value >> 16));
1173                buffer[position++] = ((byte) (value >> 24));
1174                buffer[position++] = ((byte) (value >> 32));
1175                buffer[position++] = ((byte) (value >> 40));
1176                buffer[position++] = ((byte) (value >> 48));
1177                buffer[position++] = ((byte) (value >> 56));
1178            }
1179        }
1180
1181        public void WriteRawByte(byte value)
1182        {
1183            if (position == limit)
1184            {
1185                RefreshBuffer();
1186            }
1187
1188            buffer[position++] = value;
1189        }
1190
1191        [CLSCompliant(false)]
1192        public void WriteRawByte(uint value)
1193        {
1194            WriteRawByte((byte) value);
1195        }
1196
1197        /// <summary>
1198        /// Writes out an array of bytes.
1199        /// </summary>
1200        public void WriteRawBytes(byte[] value)
1201        {
1202            WriteRawBytes(value, 0, value.Length);
1203        }
1204
1205        /// <summary>
1206        /// Writes out part of an array of bytes.
1207        /// </summary>
1208        public void WriteRawBytes(byte[] value, int offset, int length)
1209        {
1210            if (limit - position >= length)
1211            {
1212                ByteArray.Copy(value, offset, buffer, position, length);
1213                // We have room in the current buffer.
1214                position += length;
1215            }
1216            else
1217            {
1218                // Write extends past current buffer.  Fill the rest of this buffer and
1219                // flush.
1220                int bytesWritten = limit - position;
1221                ByteArray.Copy(value, offset, buffer, position, bytesWritten);
1222                offset += bytesWritten;
1223                length -= bytesWritten;
1224                position = limit;
1225                RefreshBuffer();
1226
1227                // Now deal with the rest.
1228                // Since we have an output stream, this is our buffer
1229                // and buffer offset == 0
1230                if (length <= limit)
1231                {
1232                    // Fits in new buffer.
1233                    ByteArray.Copy(value, offset, buffer, 0, length);
1234                    position = length;
1235                }
1236                else
1237                {
1238                    // Write is very big.  Let's do it all at once.
1239                    output.Write(value, offset, length);
1240                }
1241            }
1242        }
1243
1244        #endregion
1245
1246        /// <summary>
1247        /// Encode a 32-bit value with ZigZag encoding.
1248        /// </summary>
1249        /// <remarks>
1250        /// ZigZag encodes signed integers into values that can be efficiently
1251        /// encoded with varint.  (Otherwise, negative values must be
1252        /// sign-extended to 64 bits to be varint encoded, thus always taking
1253        /// 10 bytes on the wire.)
1254        /// </remarks>
1255        [CLSCompliant(false)]
1256        public static uint EncodeZigZag32(int n)
1257        {
1258            // Note:  the right-shift must be arithmetic
1259            return (uint) ((n << 1) ^ (n >> 31));
1260        }
1261
1262        /// <summary>
1263        /// Encode a 64-bit value with ZigZag encoding.
1264        /// </summary>
1265        /// <remarks>
1266        /// ZigZag encodes signed integers into values that can be efficiently
1267        /// encoded with varint.  (Otherwise, negative values must be
1268        /// sign-extended to 64 bits to be varint encoded, thus always taking
1269        /// 10 bytes on the wire.)
1270        /// </remarks>
1271        [CLSCompliant(false)]
1272        public static ulong EncodeZigZag64(long n)
1273        {
1274            return (ulong) ((n << 1) ^ (n >> 63));
1275        }
1276
1277        private void RefreshBuffer()
1278        {
1279            if (output == null)
1280            {
1281                // We're writing to a single buffer.
1282                throw new OutOfSpaceException();
1283            }
1284
1285            // Since we have an output stream, this is our buffer
1286            // and buffer offset == 0
1287            output.Write(buffer, 0, position);
1288            position = 0;
1289        }
1290
1291        /// <summary>
1292        /// Indicates that a CodedOutputStream wrapping a flat byte array
1293        /// ran out of space.
1294        /// </summary>
1295        public sealed class OutOfSpaceException : IOException
1296        {
1297            internal OutOfSpaceException()
1298                : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1299            {
1300            }
1301        }
1302
1303        public void Flush()
1304        {
1305            if (output != null)
1306            {
1307                RefreshBuffer();
1308            }
1309        }
1310
1311        /// <summary>
1312        /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1313        /// that is exactly big enough to hold a message, then write to it with
1314        /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1315        /// the message was actually as big as expected, which can help bugs.
1316        /// </summary>
1317        public void CheckNoSpaceLeft()
1318        {
1319            if (SpaceLeft != 0)
1320            {
1321                throw new InvalidOperationException("Did not write as much data as expected.");
1322            }
1323        }
1324
1325        /// <summary>
1326        /// If writing to a flat array, returns the space left in the array. Otherwise,
1327        /// throws an InvalidOperationException.
1328        /// </summary>
1329        public int SpaceLeft
1330        {
1331            get
1332            {
1333                if (output == null)
1334                {
1335                    return limit - position;
1336                }
1337                else
1338                {
1339                    throw new InvalidOperationException(
1340                        "SpaceLeft can only be called on CodedOutputStreams that are " +
1341                        "writing to a flat array.");
1342                }
1343            }
1344        }
1345    }
1346}
Note: See TracBrowser for help on using the repository browser.