blob: 25fc0eaa6742cabb23fffda83c7e1393382d9fec [file] [log] [blame]
csharptest71f662c2011-05-20 15:15:34 -05001#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;
csharptestc671a4b2011-06-08 11:51:24 -050038using System.Collections.Generic;
csharptest90922db2011-06-03 11:57:47 -050039using System.Globalization;
csharptest71f662c2011-05-20 15:15:34 -050040using System.IO;
csharptest2772dfe2011-06-08 15:50:58 -050041using System.Runtime.InteropServices;
csharptest71f662c2011-05-20 15:15:34 -050042using System.Text;
csharptestced18e12011-06-09 19:47:56 -050043using Google.ProtocolBuffers.Collections;
csharptest71f662c2011-05-20 15:15:34 -050044using Google.ProtocolBuffers.Descriptors;
45
46namespace Google.ProtocolBuffers
47{
48 /// <summary>
49 /// Encodes and writes protocol message fields.
50 /// </summary>
51 /// <remarks>
52 /// This class contains two kinds of methods: methods that write specific
53 /// protocol message constructs and field types (e.g. WriteTag and
54 /// WriteInt32) and methods that write low-level values (e.g.
55 /// WriteRawVarint32 and WriteRawBytes). If you are writing encoded protocol
56 /// messages, you should use the former methods, but if you are writing some
57 /// other format of your own design, use the latter. The names of the former
58 /// methods are taken from the protocol buffer type names, not .NET types.
59 /// (Hence WriteFloat instead of WriteSingle, and WriteBool instead of WriteBoolean.)
60 /// </remarks>
csharptestcc8d2aa2011-06-03 12:15:42 -050061 public sealed partial class CodedOutputStream : ICodedOutputStream
csharptest71f662c2011-05-20 15:15:34 -050062 {
63 /// <summary>
64 /// The buffer size used by CreateInstance(Stream).
65 /// </summary>
66 public static readonly int DefaultBufferSize = 4096;
67
68 private readonly byte[] buffer;
69 private readonly int limit;
70 private int position;
71 private readonly Stream output;
72
73 #region Construction
74
75 private CodedOutputStream(byte[] buffer, int offset, int length)
76 {
77 this.output = null;
78 this.buffer = buffer;
79 this.position = offset;
80 this.limit = offset + length;
81 }
82
83 private CodedOutputStream(Stream output, byte[] buffer)
84 {
85 this.output = output;
86 this.buffer = buffer;
87 this.position = 0;
88 this.limit = buffer.Length;
89 }
90
91 /// <summary>
92 /// Creates a new CodedOutputStream which write to the given stream.
93 /// </summary>
94 public static CodedOutputStream CreateInstance(Stream output)
95 {
96 return CreateInstance(output, DefaultBufferSize);
97 }
98
99 /// <summary>
100 /// Creates a new CodedOutputStream which write to the given stream and uses
101 /// the specified buffer size.
102 /// </summary>
103 public static CodedOutputStream CreateInstance(Stream output, int bufferSize)
104 {
105 return new CodedOutputStream(output, new byte[bufferSize]);
106 }
107
108 /// <summary>
109 /// Creates a new CodedOutputStream that writes directly to the given
110 /// byte array. If more bytes are written than fit in the array,
111 /// OutOfSpaceException will be thrown.
112 /// </summary>
113 public static CodedOutputStream CreateInstance(byte[] flatArray)
114 {
115 return CreateInstance(flatArray, 0, flatArray.Length);
116 }
117
118 /// <summary>
119 /// Creates a new CodedOutputStream that writes directly to the given
120 /// byte array slice. If more bytes are written than fit in the array,
121 /// OutOfSpaceException will be thrown.
122 /// </summary>
123 public static CodedOutputStream CreateInstance(byte[] flatArray, int offset, int length)
124 {
125 return new CodedOutputStream(flatArray, offset, length);
126 }
127
128 #endregion
129
csharptest2b868842011-06-10 14:41:47 -0500130 #region Writing of unknown fields
131
132 [Obsolete]
133 public void WriteUnknownGroup(int fieldNumber, IMessageLite value)
134 {
135 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
136 value.WriteTo(this);
137 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
138 }
139
140 public void WriteUnknownBytes(int fieldNumber, ByteString value)
141 {
142 WriteBytes(fieldNumber, null /*not used*/, value);
143 }
144
145 [CLSCompliant(false)]
146 public void WriteUnknownField(int fieldNumber, WireFormat.WireType wireType, ulong value)
147 {
148 if(wireType == WireFormat.WireType.Varint)
149 WriteUInt64(fieldNumber, null /*not used*/, value);
150 else if (wireType == WireFormat.WireType.Fixed32)
151 WriteFixed32(fieldNumber, null /*not used*/, (uint)value);
152 else if (wireType == WireFormat.WireType.Fixed64)
153 WriteFixed64(fieldNumber, null /*not used*/, value);
154 else
155 throw InvalidProtocolBufferException.InvalidWireType();
156 }
157
158 #endregion
159
csharptestb00ea132011-06-10 01:09:57 -0500160 #region Writing of tags and fields
161
162 public void WriteField(FieldType fieldType, int fieldNumber, string fieldName, object value)
163 {
164 switch (fieldType)
165 {
166 case FieldType.String:
167 WriteString(fieldNumber, fieldName, (string)value);
168 break;
169 case FieldType.Message:
170 WriteMessage(fieldNumber, fieldName, (IMessageLite)value);
171 break;
172 case FieldType.Group:
173 WriteGroup(fieldNumber, fieldName, (IMessageLite)value);
174 break;
175 case FieldType.Bytes:
176 WriteBytes(fieldNumber, fieldName, (ByteString)value);
177 break;
178 case FieldType.Bool:
179 WriteBool(fieldNumber, fieldName, (bool)value);
180 break;
181 case FieldType.Enum:
182 if (value is System.Enum)
183 WriteEnum(fieldNumber, fieldName, (int)value, null/*not used*/);
184 else
185 WriteEnum(fieldNumber, fieldName, ((IEnumLite)value).Number, null/*not used*/);
186 break;
187 case FieldType.Int32:
188 WriteInt32(fieldNumber, fieldName, (int)value);
189 break;
190 case FieldType.Int64:
191 WriteInt64(fieldNumber, fieldName, (long)value);
192 break;
193 case FieldType.UInt32:
194 WriteUInt32(fieldNumber, fieldName, (uint)value);
195 break;
196 case FieldType.UInt64:
197 WriteUInt64(fieldNumber, fieldName, (ulong)value);
198 break;
199 case FieldType.SInt32:
200 WriteSInt32(fieldNumber, fieldName, (int)value);
201 break;
202 case FieldType.SInt64:
203 WriteSInt64(fieldNumber, fieldName, (long)value);
204 break;
205 case FieldType.Fixed32:
206 WriteFixed32(fieldNumber, fieldName, (uint)value);
207 break;
208 case FieldType.Fixed64:
209 WriteFixed64(fieldNumber, fieldName, (ulong)value);
210 break;
211 case FieldType.SFixed32:
212 WriteSFixed32(fieldNumber, fieldName, (int)value);
213 break;
214 case FieldType.SFixed64:
215 WriteSFixed64(fieldNumber, fieldName, (long)value);
216 break;
217 case FieldType.Double:
218 WriteDouble(fieldNumber, fieldName, (double)value);
219 break;
220 case FieldType.Float:
221 WriteFloat(fieldNumber, fieldName, (float)value);
222 break;
223 }
224 }
csharptest71f662c2011-05-20 15:15:34 -0500225
226 /// <summary>
227 /// Writes a double field value, including tag, to the stream.
228 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500229 public void WriteDouble(int fieldNumber, string fieldName, double value)
csharptest71f662c2011-05-20 15:15:34 -0500230 {
231 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
232 WriteDoubleNoTag(value);
233 }
234
235 /// <summary>
236 /// Writes a float field value, including tag, to the stream.
237 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500238 public void WriteFloat(int fieldNumber, string fieldName, float value)
csharptest71f662c2011-05-20 15:15:34 -0500239 {
240 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
241 WriteFloatNoTag(value);
242 }
243
244 /// <summary>
245 /// Writes a uint64 field value, including tag, to the stream.
246 /// </summary>
247 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500248 public void WriteUInt64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500249 {
250 WriteTag(fieldNumber, WireFormat.WireType.Varint);
251 WriteRawVarint64(value);
252 }
253
254 /// <summary>
255 /// Writes an int64 field value, including tag, to the stream.
256 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500257 public void WriteInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500258 {
259 WriteTag(fieldNumber, WireFormat.WireType.Varint);
260 WriteRawVarint64((ulong) value);
261 }
262
263 /// <summary>
264 /// Writes an int32 field value, including tag, to the stream.
265 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500266 public void WriteInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500267 {
268 WriteTag(fieldNumber, WireFormat.WireType.Varint);
269 if (value >= 0)
270 {
271 WriteRawVarint32((uint) value);
272 }
273 else
274 {
275 // Must sign-extend.
276 WriteRawVarint64((ulong) value);
277 }
278 }
279
280 /// <summary>
281 /// Writes a fixed64 field value, including tag, to the stream.
282 /// </summary>
283 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500284 public void WriteFixed64(int fieldNumber, string fieldName, ulong value)
csharptest71f662c2011-05-20 15:15:34 -0500285 {
286 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
287 WriteRawLittleEndian64(value);
288 }
289
290 /// <summary>
291 /// Writes a fixed32 field value, including tag, to the stream.
292 /// </summary>
293 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500294 public void WriteFixed32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500295 {
296 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
297 WriteRawLittleEndian32(value);
298 }
299
300 /// <summary>
301 /// Writes a bool field value, including tag, to the stream.
302 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500303 public void WriteBool(int fieldNumber, string fieldName, bool value)
csharptest71f662c2011-05-20 15:15:34 -0500304 {
305 WriteTag(fieldNumber, WireFormat.WireType.Varint);
306 WriteRawByte(value ? (byte) 1 : (byte) 0);
307 }
308
309 /// <summary>
310 /// Writes a string field value, including tag, to the stream.
311 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500312 public void WriteString(int fieldNumber, string fieldName, string value)
csharptest71f662c2011-05-20 15:15:34 -0500313 {
314 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
315 // Optimise the case where we have enough space to write
316 // the string directly to the buffer, which should be common.
317 int length = Encoding.UTF8.GetByteCount(value);
318 WriteRawVarint32((uint) length);
319 if (limit - position >= length)
320 {
321 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
322 position += length;
323 }
324 else
325 {
326 byte[] bytes = Encoding.UTF8.GetBytes(value);
327 WriteRawBytes(bytes);
328 }
329 }
330
331 /// <summary>
332 /// Writes a group field value, including tag, to the stream.
333 /// </summary>
csharptest90922db2011-06-03 11:57:47 -0500334 public void WriteGroup(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500335 {
336 WriteTag(fieldNumber, WireFormat.WireType.StartGroup);
337 value.WriteTo(this);
338 WriteTag(fieldNumber, WireFormat.WireType.EndGroup);
339 }
340
csharptest90922db2011-06-03 11:57:47 -0500341 public void WriteMessage(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500342 {
343 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
344 WriteRawVarint32((uint) value.SerializedSize);
345 value.WriteTo(this);
346 }
347
csharptest90922db2011-06-03 11:57:47 -0500348 public void WriteBytes(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500349 {
csharptest71f662c2011-05-20 15:15:34 -0500350 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
csharptest45a93fa2011-06-02 10:52:37 -0500351 WriteRawVarint32((uint)value.Length);
352 value.WriteTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500353 }
354
355 [CLSCompliant(false)]
csharptest90922db2011-06-03 11:57:47 -0500356 public void WriteUInt32(int fieldNumber, string fieldName, uint value)
csharptest71f662c2011-05-20 15:15:34 -0500357 {
358 WriteTag(fieldNumber, WireFormat.WireType.Varint);
359 WriteRawVarint32(value);
360 }
361
csharptestced18e12011-06-09 19:47:56 -0500362 public void WriteEnum(int fieldNumber, string fieldName, int value, object textValue)
csharptest71f662c2011-05-20 15:15:34 -0500363 {
364 WriteTag(fieldNumber, WireFormat.WireType.Varint);
365 WriteRawVarint32((uint) value);
366 }
367
csharptest90922db2011-06-03 11:57:47 -0500368 public void WriteSFixed32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500369 {
370 WriteTag(fieldNumber, WireFormat.WireType.Fixed32);
371 WriteRawLittleEndian32((uint) value);
372 }
373
csharptest90922db2011-06-03 11:57:47 -0500374 public void WriteSFixed64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500375 {
376 WriteTag(fieldNumber, WireFormat.WireType.Fixed64);
377 WriteRawLittleEndian64((ulong) value);
378 }
379
csharptest90922db2011-06-03 11:57:47 -0500380 public void WriteSInt32(int fieldNumber, string fieldName, int value)
csharptest71f662c2011-05-20 15:15:34 -0500381 {
382 WriteTag(fieldNumber, WireFormat.WireType.Varint);
383 WriteRawVarint32(EncodeZigZag32(value));
384 }
385
csharptest90922db2011-06-03 11:57:47 -0500386 public void WriteSInt64(int fieldNumber, string fieldName, long value)
csharptest71f662c2011-05-20 15:15:34 -0500387 {
388 WriteTag(fieldNumber, WireFormat.WireType.Varint);
389 WriteRawVarint64(EncodeZigZag64(value));
390 }
391
csharptest90922db2011-06-03 11:57:47 -0500392 public void WriteMessageSetExtension(int fieldNumber, string fieldName, IMessageLite value)
csharptest71f662c2011-05-20 15:15:34 -0500393 {
394 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500395 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
396 WriteMessage(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500397 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
398 }
399
csharptestffafdaa2011-06-03 12:58:14 -0500400 public void WriteMessageSetExtension(int fieldNumber, string fieldName, ByteString value)
csharptest71f662c2011-05-20 15:15:34 -0500401 {
402 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.StartGroup);
csharptest90922db2011-06-03 11:57:47 -0500403 WriteUInt32(WireFormat.MessageSetField.TypeID, "type_id", (uint) fieldNumber);
404 WriteBytes(WireFormat.MessageSetField.Message, "message", value);
csharptest71f662c2011-05-20 15:15:34 -0500405 WriteTag(WireFormat.MessageSetField.Item, WireFormat.WireType.EndGroup);
406 }
csharptest90922db2011-06-03 11:57:47 -0500407
csharptestb00ea132011-06-10 01:09:57 -0500408 #endregion
csharptestc671a4b2011-06-08 11:51:24 -0500409
csharptestb00ea132011-06-10 01:09:57 -0500410 #region Writing of values without tags
csharptest71f662c2011-05-20 15:15:34 -0500411
412 public void WriteFieldNoTag(FieldType fieldType, object value)
413 {
414 switch (fieldType)
415 {
csharptestc671a4b2011-06-08 11:51:24 -0500416 case FieldType.String:
417 WriteStringNoTag((string)value);
csharptest71f662c2011-05-20 15:15:34 -0500418 break;
csharptestc671a4b2011-06-08 11:51:24 -0500419 case FieldType.Message:
420 WriteMessageNoTag((IMessageLite)value);
csharptest71f662c2011-05-20 15:15:34 -0500421 break;
csharptestc671a4b2011-06-08 11:51:24 -0500422 case FieldType.Group:
423 WriteGroupNoTag((IMessageLite)value);
csharptest71f662c2011-05-20 15:15:34 -0500424 break;
csharptestc671a4b2011-06-08 11:51:24 -0500425 case FieldType.Bytes:
426 WriteBytesNoTag((ByteString)value);
427 break;
428 case FieldType.Bool:
429 WriteBoolNoTag((bool)value);
430 break;
431 case FieldType.Enum:
432 if (value is System.Enum)
csharptestced18e12011-06-09 19:47:56 -0500433 WriteEnumNoTag((int)value);
csharptestc671a4b2011-06-08 11:51:24 -0500434 else
435 WriteEnumNoTag(((IEnumLite)value).Number);
csharptest71f662c2011-05-20 15:15:34 -0500436 break;
437 case FieldType.Int32:
csharptestb00ea132011-06-10 01:09:57 -0500438 WriteInt32NoTag((int)value);
csharptest71f662c2011-05-20 15:15:34 -0500439 break;
csharptestc671a4b2011-06-08 11:51:24 -0500440 case FieldType.Int64:
csharptestb00ea132011-06-10 01:09:57 -0500441 WriteInt64NoTag((long)value);
csharptest71f662c2011-05-20 15:15:34 -0500442 break;
443 case FieldType.UInt32:
csharptestb00ea132011-06-10 01:09:57 -0500444 WriteUInt32NoTag((uint)value);
csharptest71f662c2011-05-20 15:15:34 -0500445 break;
csharptestc671a4b2011-06-08 11:51:24 -0500446 case FieldType.UInt64:
csharptestb00ea132011-06-10 01:09:57 -0500447 WriteUInt64NoTag((ulong)value);
csharptest71f662c2011-05-20 15:15:34 -0500448 break;
449 case FieldType.SInt32:
csharptestb00ea132011-06-10 01:09:57 -0500450 WriteSInt32NoTag((int)value);
csharptest71f662c2011-05-20 15:15:34 -0500451 break;
452 case FieldType.SInt64:
csharptestb00ea132011-06-10 01:09:57 -0500453 WriteSInt64NoTag((long)value);
csharptest71f662c2011-05-20 15:15:34 -0500454 break;
csharptestc671a4b2011-06-08 11:51:24 -0500455 case FieldType.Fixed32:
csharptestb00ea132011-06-10 01:09:57 -0500456 WriteFixed32NoTag((uint)value);
csharptestc671a4b2011-06-08 11:51:24 -0500457 break;
458 case FieldType.Fixed64:
csharptestb00ea132011-06-10 01:09:57 -0500459 WriteFixed64NoTag((ulong)value);
csharptestc671a4b2011-06-08 11:51:24 -0500460 break;
461 case FieldType.SFixed32:
csharptestb00ea132011-06-10 01:09:57 -0500462 WriteSFixed32NoTag((int)value);
csharptestc671a4b2011-06-08 11:51:24 -0500463 break;
464 case FieldType.SFixed64:
csharptestb00ea132011-06-10 01:09:57 -0500465 WriteSFixed64NoTag((long)value);
csharptestc671a4b2011-06-08 11:51:24 -0500466 break;
467 case FieldType.Double:
468 WriteDoubleNoTag((double)value);
469 break;
470 case FieldType.Float:
471 WriteFloatNoTag((float)value);
csharptest71f662c2011-05-20 15:15:34 -0500472 break;
473 }
474 }
475
csharptest71f662c2011-05-20 15:15:34 -0500476 /// <summary>
477 /// Writes a double field value, including tag, to the stream.
478 /// </summary>
479 public void WriteDoubleNoTag(double value)
480 {
csharptest71f662c2011-05-20 15:15:34 -0500481#if SILVERLIGHT2 || COMPACT_FRAMEWORK_35
csharptest8a2d0f42011-06-02 17:02:41 -0500482 byte[] rawBytes = BitConverter.GetBytes(value);
483 if (!BitConverter.IsLittleEndian)
csharptestaef072a2011-06-08 18:00:43 -0500484 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500485
486 if (limit - position >= 8)
487 {
488 buffer[position++] = rawBytes[0];
489 buffer[position++] = rawBytes[1];
490 buffer[position++] = rawBytes[2];
491 buffer[position++] = rawBytes[3];
492 buffer[position++] = rawBytes[4];
493 buffer[position++] = rawBytes[5];
494 buffer[position++] = rawBytes[6];
495 buffer[position++] = rawBytes[7];
496 }
497 else
498 WriteRawBytes(rawBytes, 0, 8);
csharptest71f662c2011-05-20 15:15:34 -0500499#else
csharptest8a2d0f42011-06-02 17:02:41 -0500500 WriteRawLittleEndian64((ulong)BitConverter.DoubleToInt64Bits(value));
csharptest71f662c2011-05-20 15:15:34 -0500501#endif
502 }
503
504 /// <summary>
505 /// Writes a float field value, without a tag, to the stream.
506 /// </summary>
507 public void WriteFloatNoTag(float value)
508 {
csharptest71f662c2011-05-20 15:15:34 -0500509 byte[] rawBytes = BitConverter.GetBytes(value);
csharptestaef072a2011-06-08 18:00:43 -0500510 if (!BitConverter.IsLittleEndian)
511 ByteArray.Reverse(rawBytes);
csharptest2772dfe2011-06-08 15:50:58 -0500512
513 if (limit - position >= 4)
514 {
515 buffer[position++] = rawBytes[0];
516 buffer[position++] = rawBytes[1];
517 buffer[position++] = rawBytes[2];
518 buffer[position++] = rawBytes[3];
519 }
520 else
521 WriteRawBytes(rawBytes, 0, 4);
csharptest71f662c2011-05-20 15:15:34 -0500522 }
523
524 /// <summary>
525 /// Writes a uint64 field value, without a tag, to the stream.
526 /// </summary>
527 [CLSCompliant(false)]
528 public void WriteUInt64NoTag(ulong value)
529 {
530 WriteRawVarint64(value);
531 }
532
533 /// <summary>
534 /// Writes an int64 field value, without a tag, to the stream.
535 /// </summary>
536 public void WriteInt64NoTag(long value)
537 {
csharptestb00ea132011-06-10 01:09:57 -0500538 WriteRawVarint64((ulong)value);
csharptest71f662c2011-05-20 15:15:34 -0500539 }
540
541 /// <summary>
542 /// Writes an int32 field value, without a tag, to the stream.
543 /// </summary>
544 public void WriteInt32NoTag(int value)
545 {
546 if (value >= 0)
547 {
csharptestb00ea132011-06-10 01:09:57 -0500548 WriteRawVarint32((uint)value);
csharptest71f662c2011-05-20 15:15:34 -0500549 }
550 else
551 {
552 // Must sign-extend.
csharptestb00ea132011-06-10 01:09:57 -0500553 WriteRawVarint64((ulong)value);
csharptest71f662c2011-05-20 15:15:34 -0500554 }
555 }
556
557 /// <summary>
558 /// Writes a fixed64 field value, without a tag, to the stream.
559 /// </summary>
560 [CLSCompliant(false)]
561 public void WriteFixed64NoTag(ulong value)
562 {
563 WriteRawLittleEndian64(value);
564 }
565
566 /// <summary>
567 /// Writes a fixed32 field value, without a tag, to the stream.
568 /// </summary>
569 [CLSCompliant(false)]
570 public void WriteFixed32NoTag(uint value)
571 {
572 WriteRawLittleEndian32(value);
573 }
574
575 /// <summary>
576 /// Writes a bool field value, without a tag, to the stream.
577 /// </summary>
578 public void WriteBoolNoTag(bool value)
579 {
csharptestb00ea132011-06-10 01:09:57 -0500580 WriteRawByte(value ? (byte)1 : (byte)0);
csharptest71f662c2011-05-20 15:15:34 -0500581 }
582
583 /// <summary>
584 /// Writes a string field value, without a tag, to the stream.
585 /// </summary>
586 public void WriteStringNoTag(string value)
587 {
588 // Optimise the case where we have enough space to write
589 // the string directly to the buffer, which should be common.
590 int length = Encoding.UTF8.GetByteCount(value);
csharptestb00ea132011-06-10 01:09:57 -0500591 WriteRawVarint32((uint)length);
csharptest71f662c2011-05-20 15:15:34 -0500592 if (limit - position >= length)
593 {
594 Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, position);
595 position += length;
596 }
597 else
598 {
599 byte[] bytes = Encoding.UTF8.GetBytes(value);
600 WriteRawBytes(bytes);
601 }
602 }
603
604 /// <summary>
605 /// Writes a group field value, without a tag, to the stream.
606 /// </summary>
607 public void WriteGroupNoTag(IMessageLite value)
608 {
609 value.WriteTo(this);
610 }
611
612 public void WriteMessageNoTag(IMessageLite value)
613 {
csharptestb00ea132011-06-10 01:09:57 -0500614 WriteRawVarint32((uint)value.SerializedSize);
csharptest71f662c2011-05-20 15:15:34 -0500615 value.WriteTo(this);
616 }
617
618 public void WriteBytesNoTag(ByteString value)
619 {
csharptest45a93fa2011-06-02 10:52:37 -0500620 WriteRawVarint32((uint)value.Length);
621 value.WriteTo(this);
csharptest71f662c2011-05-20 15:15:34 -0500622 }
623
624 [CLSCompliant(false)]
625 public void WriteUInt32NoTag(uint value)
626 {
627 WriteRawVarint32(value);
628 }
629
630 public void WriteEnumNoTag(int value)
631 {
csharptestb00ea132011-06-10 01:09:57 -0500632 WriteRawVarint32((uint)value);
csharptest71f662c2011-05-20 15:15:34 -0500633 }
634
635 public void WriteSFixed32NoTag(int value)
636 {
csharptestb00ea132011-06-10 01:09:57 -0500637 WriteRawLittleEndian32((uint)value);
csharptest71f662c2011-05-20 15:15:34 -0500638 }
639
640 public void WriteSFixed64NoTag(long value)
641 {
csharptestb00ea132011-06-10 01:09:57 -0500642 WriteRawLittleEndian64((ulong)value);
csharptest71f662c2011-05-20 15:15:34 -0500643 }
644
645 public void WriteSInt32NoTag(int value)
646 {
647 WriteRawVarint32(EncodeZigZag32(value));
648 }
649
650 public void WriteSInt64NoTag(long value)
651 {
652 WriteRawVarint64(EncodeZigZag64(value));
653 }
654
655 #endregion
656
csharptestb00ea132011-06-10 01:09:57 -0500657 #region Write array members
658
659 public void WriteArray(FieldType fieldType, int fieldNumber, string fieldName, System.Collections.IEnumerable list)
660 {
661 foreach (object element in list)
662 WriteField(fieldType, fieldNumber, fieldName, element);
663 }
664
665 public void WriteGroupArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
666 where T : IMessageLite
667 {
668 foreach (IMessageLite value in list)
669 WriteGroup(fieldNumber, fieldName, value);
670 }
671
672 public void WriteMessageArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
673 where T : IMessageLite
674 {
675 foreach (IMessageLite value in list)
676 WriteMessage(fieldNumber, fieldName, value);
677 }
678
679 public void WriteStringArray(int fieldNumber, string fieldName, IEnumerable<string> list)
680 {
681 foreach (var value in list)
682 WriteString(fieldNumber, fieldName, value);
683 }
684
685 public void WriteBytesArray(int fieldNumber, string fieldName, IEnumerable<ByteString> list)
686 {
687 foreach (var value in list)
688 WriteBytes(fieldNumber, fieldName, value);
689 }
690
691 public void WriteBoolArray(int fieldNumber, string fieldName, IEnumerable<bool> list)
692 {
693 foreach (var value in list)
694 WriteBool(fieldNumber, fieldName, value);
695 }
696
697 public void WriteInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
698 {
699 foreach (var value in list)
700 WriteInt32(fieldNumber, fieldName, value);
701 }
702
703 public void WriteSInt32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
704 {
705 foreach (var value in list)
706 WriteSInt32(fieldNumber, fieldName, value);
707 }
708
709 public void WriteUInt32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
710 {
711 foreach (var value in list)
712 WriteUInt32(fieldNumber, fieldName, value);
713 }
714
715 public void WriteFixed32Array(int fieldNumber, string fieldName, IEnumerable<uint> list)
716 {
717 foreach (var value in list)
718 WriteFixed32(fieldNumber, fieldName, value);
719 }
720
721 public void WriteSFixed32Array(int fieldNumber, string fieldName, IEnumerable<int> list)
722 {
723 foreach (var value in list)
724 WriteSFixed32(fieldNumber, fieldName, value);
725 }
726
727 public void WriteInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
728 {
729 foreach (var value in list)
730 WriteInt64(fieldNumber, fieldName, value);
731 }
732
733 public void WriteSInt64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
734 {
735 foreach (var value in list)
736 WriteSInt64(fieldNumber, fieldName, value);
737 }
738
739 public void WriteUInt64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
740 {
741 foreach (var value in list)
742 WriteUInt64(fieldNumber, fieldName, value);
743 }
744
745 public void WriteFixed64Array(int fieldNumber, string fieldName, IEnumerable<ulong> list)
746 {
747 foreach (var value in list)
748 WriteFixed64(fieldNumber, fieldName, value);
749 }
750
751 public void WriteSFixed64Array(int fieldNumber, string fieldName, IEnumerable<long> list)
752 {
753 foreach (var value in list)
754 WriteSFixed64(fieldNumber, fieldName, value);
755 }
756
757 public void WriteDoubleArray(int fieldNumber, string fieldName, IEnumerable<double> list)
758 {
759 foreach (var value in list)
760 WriteDouble(fieldNumber, fieldName, value);
761 }
762
763 public void WriteFloatArray(int fieldNumber, string fieldName, IEnumerable<float> list)
764 {
765 foreach (var value in list)
766 WriteFloat(fieldNumber, fieldName, value);
767 }
768
769 [CLSCompliant(false)]
770 public void WriteEnumArray<T>(int fieldNumber, string fieldName, IEnumerable<T> list)
771 where T : struct, IComparable, IFormattable, IConvertible
772 {
773 if (list is ICastArray)
774 {
775 foreach (int value in ((ICastArray)list).CastArray<int>())
776 WriteEnum(fieldNumber, fieldName, value, null /*unused*/);
777 }
778 else
779 {
780 foreach (object value in list)
781 WriteEnum(fieldNumber, fieldName, (int) value, null /*unused*/);
782 }
783 }
784
785 #endregion
786
787 #region Write packed array members
788
789 public void WritePackedArray(FieldType fieldType, int fieldNumber, string fieldName, System.Collections.IEnumerable list)
790 {
791 int calculatedSize = 0;
792 foreach (object element in list)
793 calculatedSize += CodedOutputStream.ComputeFieldSizeNoTag(fieldType, element);
794
795 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
796 WriteRawVarint32((uint)calculatedSize);
797
798 foreach (object element in list)
799 WriteFieldNoTag(fieldType, element);
800 }
801
802 public void WritePackedGroupArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
803 where T : IMessageLite
804 {
805 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
806 WriteRawVarint32((uint)calculatedSize);
807 foreach (IMessageLite value in list)
808 WriteGroupNoTag(value);
809 }
810
811 public void WritePackedMessageArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
812 where T : IMessageLite
813 {
814 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
815 WriteRawVarint32((uint)calculatedSize);
816 foreach (IMessageLite value in list)
817 WriteMessageNoTag(value);
818 }
819
820 public void WritePackedStringArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<string> list)
821 {
822 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
823 WriteRawVarint32((uint)calculatedSize);
824 foreach (var value in list)
825 WriteStringNoTag(value);
826 }
827
828 public void WritePackedBytesArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<ByteString> list)
829 {
830 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
831 WriteRawVarint32((uint)calculatedSize);
832 foreach (var value in list)
833 WriteBytesNoTag(value);
834 }
835
836 public void WritePackedBoolArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<bool> list)
837 {
838 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
839 WriteRawVarint32((uint)calculatedSize);
840 foreach (var value in list)
841 WriteBoolNoTag(value);
842 }
843
844 public void WritePackedInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
845 {
846 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
847 WriteRawVarint32((uint)calculatedSize);
848 foreach (var value in list)
849 WriteInt32NoTag(value);
850 }
851
852 public void WritePackedSInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
853 {
854 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
855 WriteRawVarint32((uint)calculatedSize);
856 foreach (var value in list)
857 WriteSInt32NoTag(value);
858 }
859
860 public void WritePackedUInt32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
861 {
862 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
863 WriteRawVarint32((uint)calculatedSize);
864 foreach (var value in list)
865 WriteUInt32NoTag(value);
866 }
867
868 public void WritePackedFixed32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<uint> list)
869 {
870 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
871 WriteRawVarint32((uint)calculatedSize);
872 foreach (var value in list)
873 WriteFixed32NoTag(value);
874 }
875
876 public void WritePackedSFixed32Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<int> list)
877 {
878 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
879 WriteRawVarint32((uint)calculatedSize);
880 foreach (var value in list)
881 WriteSFixed32NoTag(value);
882 }
883
884 public void WritePackedInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
885 {
886 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
887 WriteRawVarint32((uint)calculatedSize);
888 foreach (var value in list)
889 WriteInt64NoTag(value);
890 }
891
892 public void WritePackedSInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
893 {
894 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
895 WriteRawVarint32((uint)calculatedSize);
896 foreach (var value in list)
897 WriteSInt64NoTag(value);
898 }
899
900 public void WritePackedUInt64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<ulong> list)
901 {
902 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
903 WriteRawVarint32((uint)calculatedSize);
904 foreach (var value in list)
905 WriteUInt64NoTag(value);
906 }
907
908 public void WritePackedFixed64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<ulong> list)
909 {
910 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
911 WriteRawVarint32((uint)calculatedSize);
912 foreach (var value in list)
913 WriteFixed64NoTag(value);
914 }
915
916 public void WritePackedSFixed64Array(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<long> list)
917 {
918 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
919 WriteRawVarint32((uint)calculatedSize);
920 foreach (var value in list)
921 WriteSFixed64NoTag(value);
922 }
923
924 public void WritePackedDoubleArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<double> list)
925 {
926 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
927 WriteRawVarint32((uint)calculatedSize);
928 foreach (var value in list)
929 WriteDoubleNoTag(value);
930 }
931
932 public void WritePackedFloatArray(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<float> list)
933 {
934 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
935 WriteRawVarint32((uint)calculatedSize);
936 foreach (var value in list)
937 WriteFloatNoTag(value);
938 }
939
940 [CLSCompliant(false)]
941 public void WritePackedEnumArray<T>(int fieldNumber, string fieldName, int calculatedSize, IEnumerable<T> list)
942 where T : struct, IComparable, IFormattable, IConvertible
943 {
944 WriteTag(fieldNumber, WireFormat.WireType.LengthDelimited);
945 WriteRawVarint32((uint)calculatedSize);
946 if (list is ICastArray)
947 {
948 foreach (int value in ((ICastArray)list).CastArray<int>())
949 WriteEnumNoTag(value);
950 }
951 else
952 {
953 foreach (object value in list)
954 WriteEnumNoTag((int)value);
955 }
956 }
957
958 #endregion
959
csharptest71f662c2011-05-20 15:15:34 -0500960 #region Underlying writing primitives
961
962 /// <summary>
963 /// Encodes and writes a tag.
964 /// </summary>
965 [CLSCompliant(false)]
966 public void WriteTag(int fieldNumber, WireFormat.WireType type)
967 {
968 WriteRawVarint32(WireFormat.MakeTag(fieldNumber, type));
969 }
970
csharptestc671a4b2011-06-08 11:51:24 -0500971#if false
csharptest71f662c2011-05-20 15:15:34 -0500972 private void SlowWriteRawVarint32(uint value)
973 {
974 while (true)
975 {
976 if ((value & ~0x7F) == 0)
977 {
978 WriteRawByte(value);
979 return;
980 }
981 else
982 {
983 WriteRawByte((value & 0x7F) | 0x80);
984 value >>= 7;
985 }
986 }
987 }
csharptestc671a4b2011-06-08 11:51:24 -0500988#endif
csharptest71f662c2011-05-20 15:15:34 -0500989 /// <summary>
990 /// Writes a 32 bit value as a varint. The fast route is taken when
991 /// there's enough buffer space left to whizz through without checking
992 /// for each byte; otherwise, we resort to calling WriteRawByte each time.
993 /// </summary>
994 [CLSCompliant(false)]
995 public void WriteRawVarint32(uint value)
996 {
csharptestc671a4b2011-06-08 11:51:24 -0500997#if true
998 while (value > 127 && position < limit)
999 {
1000 buffer[position++] = (byte)((value & 0x7F) | 0x80);
1001 value >>= 7;
1002 }
1003 while (value > 127)
1004 {
1005 WriteRawByte((byte)((value & 0x7F) | 0x80));
1006 value >>= 7;
1007 }
1008 if(position < limit)
1009 buffer[position++] = (byte)value;
1010 else
1011 WriteRawByte((byte)value);
1012#else
csharptest71f662c2011-05-20 15:15:34 -05001013 if (position + 5 > limit)
1014 {
1015 SlowWriteRawVarint32(value);
1016 return;
1017 }
1018
1019 while (true)
1020 {
1021 if ((value & ~0x7F) == 0)
1022 {
1023 buffer[position++] = (byte) value;
1024 return;
1025 }
1026 else
1027 {
1028 buffer[position++] = (byte) ((value & 0x7F) | 0x80);
1029 value >>= 7;
1030 }
1031 }
csharptestc671a4b2011-06-08 11:51:24 -05001032#endif
csharptest71f662c2011-05-20 15:15:34 -05001033 }
1034
1035 [CLSCompliant(false)]
1036 public void WriteRawVarint64(ulong value)
1037 {
csharptestc671a4b2011-06-08 11:51:24 -05001038#if true
1039 while (value > 127 && position < limit)
1040 {
1041 buffer[position++] = (byte)((value & 0x7F) | 0x80);
1042 value >>= 7;
1043 }
1044 while (value > 127)
1045 {
1046 WriteRawByte((byte)((value & 0x7F) | 0x80));
1047 value >>= 7;
1048 }
1049 if(position < limit)
1050 buffer[position++] = (byte)value;
1051 else
1052 WriteRawByte((byte)value);
1053#else
csharptest71f662c2011-05-20 15:15:34 -05001054 while (true)
1055 {
1056 if ((value & ~0x7FUL) == 0)
1057 {
1058 WriteRawByte((uint) value);
1059 return;
1060 }
1061 else
1062 {
1063 WriteRawByte(((uint) value & 0x7F) | 0x80);
1064 value >>= 7;
1065 }
1066 }
csharptestc671a4b2011-06-08 11:51:24 -05001067#endif
csharptest71f662c2011-05-20 15:15:34 -05001068 }
1069
1070 [CLSCompliant(false)]
1071 public void WriteRawLittleEndian32(uint value)
1072 {
csharptestc671a4b2011-06-08 11:51:24 -05001073 if (position + 4 > limit)
1074 {
1075 WriteRawByte((byte) value);
1076 WriteRawByte((byte) (value >> 8));
1077 WriteRawByte((byte) (value >> 16));
1078 WriteRawByte((byte) (value >> 24));
1079 }
1080 else
1081 {
1082 buffer[position++] = ((byte)value);
1083 buffer[position++] = ((byte)(value >> 8));
1084 buffer[position++] = ((byte)(value >> 16));
1085 buffer[position++] = ((byte)(value >> 24));
1086 }
csharptest71f662c2011-05-20 15:15:34 -05001087 }
1088
1089 [CLSCompliant(false)]
1090 public void WriteRawLittleEndian64(ulong value)
1091 {
csharptestc671a4b2011-06-08 11:51:24 -05001092 if (position + 8 > limit)
1093 {
1094 WriteRawByte((byte) value);
1095 WriteRawByte((byte) (value >> 8));
1096 WriteRawByte((byte) (value >> 16));
1097 WriteRawByte((byte) (value >> 24));
1098 WriteRawByte((byte) (value >> 32));
1099 WriteRawByte((byte) (value >> 40));
1100 WriteRawByte((byte) (value >> 48));
1101 WriteRawByte((byte) (value >> 56));
1102 }
1103 else
1104 {
1105 buffer[position++] = ((byte)value);
1106 buffer[position++] = ((byte)(value >> 8));
1107 buffer[position++] = ((byte)(value >> 16));
1108 buffer[position++] = ((byte)(value >> 24));
1109 buffer[position++] = ((byte)(value >> 32));
1110 buffer[position++] = ((byte)(value >> 40));
1111 buffer[position++] = ((byte)(value >> 48));
1112 buffer[position++] = ((byte)(value >> 56));
1113 }
csharptest71f662c2011-05-20 15:15:34 -05001114 }
1115
1116 public void WriteRawByte(byte value)
1117 {
1118 if (position == limit)
1119 {
1120 RefreshBuffer();
1121 }
1122
1123 buffer[position++] = value;
1124 }
1125
1126 [CLSCompliant(false)]
1127 public void WriteRawByte(uint value)
1128 {
1129 WriteRawByte((byte) value);
1130 }
1131
1132 /// <summary>
1133 /// Writes out an array of bytes.
1134 /// </summary>
1135 public void WriteRawBytes(byte[] value)
1136 {
1137 WriteRawBytes(value, 0, value.Length);
1138 }
1139
1140 /// <summary>
1141 /// Writes out part of an array of bytes.
1142 /// </summary>
1143 public void WriteRawBytes(byte[] value, int offset, int length)
1144 {
1145 if (limit - position >= length)
1146 {
csharptestaef072a2011-06-08 18:00:43 -05001147 ByteArray.Copy(value, offset, buffer, position, length);
csharptest71f662c2011-05-20 15:15:34 -05001148 // We have room in the current buffer.
1149 position += length;
1150 }
1151 else
1152 {
1153 // Write extends past current buffer. Fill the rest of this buffer and
1154 // flush.
1155 int bytesWritten = limit - position;
csharptestaef072a2011-06-08 18:00:43 -05001156 ByteArray.Copy(value, offset, buffer, position, bytesWritten);
csharptest71f662c2011-05-20 15:15:34 -05001157 offset += bytesWritten;
1158 length -= bytesWritten;
1159 position = limit;
1160 RefreshBuffer();
1161
1162 // Now deal with the rest.
1163 // Since we have an output stream, this is our buffer
1164 // and buffer offset == 0
1165 if (length <= limit)
1166 {
1167 // Fits in new buffer.
csharptestaef072a2011-06-08 18:00:43 -05001168 ByteArray.Copy(value, offset, buffer, 0, length);
csharptest71f662c2011-05-20 15:15:34 -05001169 position = length;
1170 }
1171 else
1172 {
1173 // Write is very big. Let's do it all at once.
1174 output.Write(value, offset, length);
1175 }
1176 }
1177 }
1178
1179 #endregion
csharptest71f662c2011-05-20 15:15:34 -05001180 /// <summary>
1181 /// Encode a 32-bit value with ZigZag encoding.
1182 /// </summary>
1183 /// <remarks>
1184 /// ZigZag encodes signed integers into values that can be efficiently
1185 /// encoded with varint. (Otherwise, negative values must be
1186 /// sign-extended to 64 bits to be varint encoded, thus always taking
1187 /// 10 bytes on the wire.)
1188 /// </remarks>
1189 [CLSCompliant(false)]
1190 public static uint EncodeZigZag32(int n)
1191 {
1192 // Note: the right-shift must be arithmetic
1193 return (uint) ((n << 1) ^ (n >> 31));
1194 }
1195
1196 /// <summary>
1197 /// Encode a 64-bit value with ZigZag encoding.
1198 /// </summary>
1199 /// <remarks>
1200 /// ZigZag encodes signed integers into values that can be efficiently
1201 /// encoded with varint. (Otherwise, negative values must be
1202 /// sign-extended to 64 bits to be varint encoded, thus always taking
1203 /// 10 bytes on the wire.)
1204 /// </remarks>
1205 [CLSCompliant(false)]
1206 public static ulong EncodeZigZag64(long n)
1207 {
1208 return (ulong) ((n << 1) ^ (n >> 63));
1209 }
1210
1211 private void RefreshBuffer()
1212 {
1213 if (output == null)
1214 {
1215 // We're writing to a single buffer.
1216 throw new OutOfSpaceException();
1217 }
1218
1219 // Since we have an output stream, this is our buffer
1220 // and buffer offset == 0
1221 output.Write(buffer, 0, position);
1222 position = 0;
1223 }
1224
1225 /// <summary>
1226 /// Indicates that a CodedOutputStream wrapping a flat byte array
1227 /// ran out of space.
1228 /// </summary>
1229 public sealed class OutOfSpaceException : IOException
1230 {
1231 internal OutOfSpaceException()
1232 : base("CodedOutputStream was writing to a flat byte array and ran out of space.")
1233 {
1234 }
1235 }
1236
1237 public void Flush()
1238 {
1239 if (output != null)
1240 {
1241 RefreshBuffer();
1242 }
1243 }
1244
1245 /// <summary>
1246 /// Verifies that SpaceLeft returns zero. It's common to create a byte array
1247 /// that is exactly big enough to hold a message, then write to it with
1248 /// a CodedOutputStream. Calling CheckNoSpaceLeft after writing verifies that
1249 /// the message was actually as big as expected, which can help bugs.
1250 /// </summary>
1251 public void CheckNoSpaceLeft()
1252 {
1253 if (SpaceLeft != 0)
1254 {
1255 throw new InvalidOperationException("Did not write as much data as expected.");
1256 }
1257 }
1258
1259 /// <summary>
1260 /// If writing to a flat array, returns the space left in the array. Otherwise,
1261 /// throws an InvalidOperationException.
1262 /// </summary>
1263 public int SpaceLeft
1264 {
1265 get
1266 {
1267 if (output == null)
1268 {
1269 return limit - position;
1270 }
1271 else
1272 {
1273 throw new InvalidOperationException(
1274 "SpaceLeft can only be called on CodedOutputStreams that are " +
1275 "writing to a flat array.");
1276 }
1277 }
1278 }
1279 }
1280}