PageRenderTime 60ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ProtocolBuffers/CodedInputStream.cs

https://code.google.com/p/protobuf-csharp-port/
C# | 1841 lines | 1368 code | 132 blank | 341 comment | 185 complexity | 733cdc7607b4a5f7db78bf9c676404d2 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. #region Copyright notice and license
  2. // Protocol Buffers - Google's data interchange format
  3. // Copyright 2008 Google Inc. All rights reserved.
  4. // http://github.com/jskeet/dotnet-protobufs/
  5. // Original C++/Java/Python code:
  6. // http://code.google.com/p/protobuf/
  7. //
  8. // Redistribution and use in source and binary forms, with or without
  9. // modification, are permitted provided that the following conditions are
  10. // met:
  11. //
  12. // * Redistributions of source code must retain the above copyright
  13. // notice, this list of conditions and the following disclaimer.
  14. // * Redistributions in binary form must reproduce the above
  15. // copyright notice, this list of conditions and the following disclaimer
  16. // in the documentation and/or other materials provided with the
  17. // distribution.
  18. // * Neither the name of Google Inc. nor the names of its
  19. // contributors may be used to endorse or promote products derived from
  20. // this software without specific prior written permission.
  21. //
  22. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  26. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  27. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  28. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  29. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  30. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  32. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. #endregion
  34. using System;
  35. using System.Collections.Generic;
  36. using System.IO;
  37. using System.Text;
  38. using Google.ProtocolBuffers.Descriptors;
  39. namespace Google.ProtocolBuffers
  40. {
  41. /// <summary>
  42. /// Readings and decodes protocol message fields.
  43. /// </summary>
  44. /// <remarks>
  45. /// This class contains two kinds of methods: methods that read specific
  46. /// protocol message constructs and field types (e.g. ReadTag and
  47. /// ReadInt32) and methods that read low-level values (e.g.
  48. /// ReadRawVarint32 and ReadRawBytes). If you are reading encoded protocol
  49. /// messages, you should use the former methods, but if you are reading some
  50. /// other format of your own design, use the latter. The names of the former
  51. /// methods are taken from the protocol buffer type names, not .NET types.
  52. /// (Hence ReadFloat instead of ReadSingle, and ReadBool instead of ReadBoolean.)
  53. ///
  54. /// TODO(jonskeet): Consider whether recursion and size limits shouldn't be readonly,
  55. /// set at construction time.
  56. /// </remarks>
  57. public sealed class CodedInputStream : ICodedInputStream
  58. {
  59. private readonly byte[] buffer;
  60. private int bufferSize;
  61. private int bufferSizeAfterLimit = 0;
  62. private int bufferPos = 0;
  63. private readonly Stream input;
  64. private uint lastTag = 0;
  65. private uint nextTag = 0;
  66. private bool hasNextTag = false;
  67. internal const int DefaultRecursionLimit = 64;
  68. internal const int DefaultSizeLimit = 64 << 20; // 64MB
  69. public const int BufferSize = 4096;
  70. /// <summary>
  71. /// The total number of bytes read before the current buffer. The
  72. /// total bytes read up to the current position can be computed as
  73. /// totalBytesRetired + bufferPos.
  74. /// </summary>
  75. private int totalBytesRetired = 0;
  76. /// <summary>
  77. /// The absolute position of the end of the current message.
  78. /// </summary>
  79. private int currentLimit = int.MaxValue;
  80. /// <summary>
  81. /// <see cref="SetRecursionLimit"/>
  82. /// </summary>
  83. private int recursionDepth = 0;
  84. private int recursionLimit = DefaultRecursionLimit;
  85. /// <summary>
  86. /// <see cref="SetSizeLimit"/>
  87. /// </summary>
  88. private int sizeLimit = DefaultSizeLimit;
  89. #region Construction
  90. /// <summary>
  91. /// Creates a new CodedInputStream reading data from the given
  92. /// stream.
  93. /// </summary>
  94. public static CodedInputStream CreateInstance(Stream input)
  95. {
  96. return new CodedInputStream(input);
  97. }
  98. /// <summary>
  99. /// Creates a new CodedInputStream reading data from the given
  100. /// byte array.
  101. /// </summary>
  102. public static CodedInputStream CreateInstance(byte[] buf)
  103. {
  104. return new CodedInputStream(buf, 0, buf.Length);
  105. }
  106. /// <summary>
  107. /// Creates a new CodedInputStream that reads from the given
  108. /// byte array slice.
  109. /// </summary>
  110. public static CodedInputStream CreateInstance(byte[] buf, int offset, int length)
  111. {
  112. return new CodedInputStream(buf, offset, length);
  113. }
  114. private CodedInputStream(byte[] buffer, int offset, int length)
  115. {
  116. this.buffer = buffer;
  117. this.bufferPos = offset;
  118. this.bufferSize = offset + length;
  119. this.input = null;
  120. }
  121. private CodedInputStream(Stream input)
  122. {
  123. this.buffer = new byte[BufferSize];
  124. this.bufferSize = 0;
  125. this.input = input;
  126. }
  127. #endregion
  128. void ICodedInputStream.ReadMessageStart() { }
  129. void ICodedInputStream.ReadMessageEnd() { }
  130. #region Validation
  131. /// <summary>
  132. /// Verifies that the last call to ReadTag() returned the given tag value.
  133. /// This is used to verify that a nested group ended with the correct
  134. /// end tag.
  135. /// </summary>
  136. /// <exception cref="InvalidProtocolBufferException">The last
  137. /// tag read was not the one specified</exception>
  138. [CLSCompliant(false)]
  139. public void CheckLastTagWas(uint value)
  140. {
  141. if (lastTag != value)
  142. {
  143. throw InvalidProtocolBufferException.InvalidEndTag();
  144. }
  145. }
  146. #endregion
  147. #region Reading of tags etc
  148. /// <summary>
  149. /// Attempt to peek at the next field tag.
  150. /// </summary>
  151. [CLSCompliant(false)]
  152. public bool PeekNextTag(out uint fieldTag, out string fieldName)
  153. {
  154. if (hasNextTag)
  155. {
  156. fieldName = null;
  157. fieldTag = nextTag;
  158. return true;
  159. }
  160. uint savedLast = lastTag;
  161. hasNextTag = ReadTag(out nextTag, out fieldName);
  162. lastTag = savedLast;
  163. fieldTag = nextTag;
  164. return hasNextTag;
  165. }
  166. /// <summary>
  167. /// Attempt to read a field tag, returning false if we have reached the end
  168. /// of the input data.
  169. /// </summary>
  170. /// <param name="fieldTag">The 'tag' of the field (id * 8 + wire-format)</param>
  171. /// <param name="fieldName">Not Supported - For protobuffer streams, this parameter is always null</param>
  172. /// <returns>true if the next fieldTag was read</returns>
  173. [CLSCompliant(false)]
  174. public bool ReadTag(out uint fieldTag, out string fieldName)
  175. {
  176. fieldName = null;
  177. if (hasNextTag)
  178. {
  179. fieldTag = nextTag;
  180. lastTag = fieldTag;
  181. hasNextTag = false;
  182. return true;
  183. }
  184. if (IsAtEnd)
  185. {
  186. fieldTag = 0;
  187. lastTag = fieldTag;
  188. return false;
  189. }
  190. fieldTag = ReadRawVarint32();
  191. lastTag = fieldTag;
  192. if (lastTag == 0)
  193. {
  194. // If we actually read zero, that's not a valid tag.
  195. throw InvalidProtocolBufferException.InvalidTag();
  196. }
  197. return true;
  198. }
  199. /// <summary>
  200. /// Read a double field from the stream.
  201. /// </summary>
  202. public bool ReadDouble(ref double value)
  203. {
  204. #if SILVERLIGHT || COMPACT_FRAMEWORK_35
  205. if (BitConverter.IsLittleEndian && 8 <= bufferSize - bufferPos)
  206. {
  207. value = BitConverter.ToDouble(buffer, bufferPos);
  208. bufferPos += 8;
  209. }
  210. else
  211. {
  212. byte[] rawBytes = ReadRawBytes(8);
  213. if (!BitConverter.IsLittleEndian)
  214. ByteArray.Reverse(rawBytes);
  215. value = BitConverter.ToDouble(rawBytes, 0);
  216. }
  217. #else
  218. value = BitConverter.Int64BitsToDouble((long) ReadRawLittleEndian64());
  219. #endif
  220. return true;
  221. }
  222. /// <summary>
  223. /// Read a float field from the stream.
  224. /// </summary>
  225. public bool ReadFloat(ref float value)
  226. {
  227. if (BitConverter.IsLittleEndian && 4 <= bufferSize - bufferPos)
  228. {
  229. value = BitConverter.ToSingle(buffer, bufferPos);
  230. bufferPos += 4;
  231. }
  232. else
  233. {
  234. byte[] rawBytes = ReadRawBytes(4);
  235. if (!BitConverter.IsLittleEndian)
  236. {
  237. ByteArray.Reverse(rawBytes);
  238. }
  239. value = BitConverter.ToSingle(rawBytes, 0);
  240. }
  241. return true;
  242. }
  243. /// <summary>
  244. /// Read a uint64 field from the stream.
  245. /// </summary>
  246. [CLSCompliant(false)]
  247. public bool ReadUInt64(ref ulong value)
  248. {
  249. value = ReadRawVarint64();
  250. return true;
  251. }
  252. /// <summary>
  253. /// Read an int64 field from the stream.
  254. /// </summary>
  255. public bool ReadInt64(ref long value)
  256. {
  257. value = (long) ReadRawVarint64();
  258. return true;
  259. }
  260. /// <summary>
  261. /// Read an int32 field from the stream.
  262. /// </summary>
  263. public bool ReadInt32(ref int value)
  264. {
  265. value = (int) ReadRawVarint32();
  266. return true;
  267. }
  268. /// <summary>
  269. /// Read a fixed64 field from the stream.
  270. /// </summary>
  271. [CLSCompliant(false)]
  272. public bool ReadFixed64(ref ulong value)
  273. {
  274. value = ReadRawLittleEndian64();
  275. return true;
  276. }
  277. /// <summary>
  278. /// Read a fixed32 field from the stream.
  279. /// </summary>
  280. [CLSCompliant(false)]
  281. public bool ReadFixed32(ref uint value)
  282. {
  283. value = ReadRawLittleEndian32();
  284. return true;
  285. }
  286. /// <summary>
  287. /// Read a bool field from the stream.
  288. /// </summary>
  289. public bool ReadBool(ref bool value)
  290. {
  291. value = ReadRawVarint32() != 0;
  292. return true;
  293. }
  294. /// <summary>
  295. /// Reads a string field from the stream.
  296. /// </summary>
  297. public bool ReadString(ref string value)
  298. {
  299. int size = (int) ReadRawVarint32();
  300. // No need to read any data for an empty string.
  301. if (size == 0)
  302. {
  303. value = "";
  304. return true;
  305. }
  306. if (size <= bufferSize - bufferPos)
  307. {
  308. // Fast path: We already have the bytes in a contiguous buffer, so
  309. // just copy directly from it.
  310. String result = Encoding.UTF8.GetString(buffer, bufferPos, size);
  311. bufferPos += size;
  312. value = result;
  313. return true;
  314. }
  315. // Slow path: Build a byte array first then copy it.
  316. value = Encoding.UTF8.GetString(ReadRawBytes(size), 0, size);
  317. return true;
  318. }
  319. /// <summary>
  320. /// Reads a group field value from the stream.
  321. /// </summary>
  322. public void ReadGroup(int fieldNumber, IBuilderLite builder,
  323. ExtensionRegistry extensionRegistry)
  324. {
  325. if (recursionDepth >= recursionLimit)
  326. {
  327. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  328. }
  329. ++recursionDepth;
  330. builder.WeakMergeFrom(this, extensionRegistry);
  331. CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
  332. --recursionDepth;
  333. }
  334. /// <summary>
  335. /// Reads a group field value from the stream and merges it into the given
  336. /// UnknownFieldSet.
  337. /// </summary>
  338. [Obsolete]
  339. public void ReadUnknownGroup(int fieldNumber, IBuilderLite builder)
  340. {
  341. if (recursionDepth >= recursionLimit)
  342. {
  343. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  344. }
  345. ++recursionDepth;
  346. builder.WeakMergeFrom(this);
  347. CheckLastTagWas(WireFormat.MakeTag(fieldNumber, WireFormat.WireType.EndGroup));
  348. --recursionDepth;
  349. }
  350. /// <summary>
  351. /// Reads an embedded message field value from the stream.
  352. /// </summary>
  353. public void ReadMessage(IBuilderLite builder, ExtensionRegistry extensionRegistry)
  354. {
  355. int length = (int) ReadRawVarint32();
  356. if (recursionDepth >= recursionLimit)
  357. {
  358. throw InvalidProtocolBufferException.RecursionLimitExceeded();
  359. }
  360. int oldLimit = PushLimit(length);
  361. ++recursionDepth;
  362. builder.WeakMergeFrom(this, extensionRegistry);
  363. CheckLastTagWas(0);
  364. --recursionDepth;
  365. PopLimit(oldLimit);
  366. }
  367. /// <summary>
  368. /// Reads a bytes field value from the stream.
  369. /// </summary>
  370. public bool ReadBytes(ref ByteString value)
  371. {
  372. int size = (int) ReadRawVarint32();
  373. if (size < bufferSize - bufferPos && size > 0)
  374. {
  375. // Fast path: We already have the bytes in a contiguous buffer, so
  376. // just copy directly from it.
  377. ByteString result = ByteString.CopyFrom(buffer, bufferPos, size);
  378. bufferPos += size;
  379. value = result;
  380. return true;
  381. }
  382. else
  383. {
  384. // Slow path: Build a byte array and attach it to a new ByteString.
  385. value = ByteString.AttachBytes(ReadRawBytes(size));
  386. return true;
  387. }
  388. }
  389. /// <summary>
  390. /// Reads a uint32 field value from the stream.
  391. /// </summary>
  392. [CLSCompliant(false)]
  393. public bool ReadUInt32(ref uint value)
  394. {
  395. value = ReadRawVarint32();
  396. return true;
  397. }
  398. /// <summary>
  399. /// Reads an enum field value from the stream. The caller is responsible
  400. /// for converting the numeric value to an actual enum.
  401. /// </summary>
  402. public bool ReadEnum(ref IEnumLite value, out object unknown, IEnumLiteMap mapping)
  403. {
  404. int rawValue = (int) ReadRawVarint32();
  405. value = mapping.FindValueByNumber(rawValue);
  406. if (value != null)
  407. {
  408. unknown = null;
  409. return true;
  410. }
  411. unknown = rawValue;
  412. return false;
  413. }
  414. /// <summary>
  415. /// Reads an enum field value from the stream. If the enum is valid for type T,
  416. /// then the ref value is set and it returns true. Otherwise the unkown output
  417. /// value is set and this method returns false.
  418. /// </summary>
  419. [CLSCompliant(false)]
  420. public bool ReadEnum<T>(ref T value, out object unknown)
  421. where T : struct, IComparable, IFormattable, IConvertible
  422. {
  423. int number = (int) ReadRawVarint32();
  424. if (Enum.IsDefined(typeof (T), number))
  425. {
  426. unknown = null;
  427. value = (T) (object) number;
  428. return true;
  429. }
  430. unknown = number;
  431. return false;
  432. }
  433. /// <summary>
  434. /// Reads an sfixed32 field value from the stream.
  435. /// </summary>
  436. public bool ReadSFixed32(ref int value)
  437. {
  438. value = (int) ReadRawLittleEndian32();
  439. return true;
  440. }
  441. /// <summary>
  442. /// Reads an sfixed64 field value from the stream.
  443. /// </summary>
  444. public bool ReadSFixed64(ref long value)
  445. {
  446. value = (long) ReadRawLittleEndian64();
  447. return true;
  448. }
  449. /// <summary>
  450. /// Reads an sint32 field value from the stream.
  451. /// </summary>
  452. public bool ReadSInt32(ref int value)
  453. {
  454. value = DecodeZigZag32(ReadRawVarint32());
  455. return true;
  456. }
  457. /// <summary>
  458. /// Reads an sint64 field value from the stream.
  459. /// </summary>
  460. public bool ReadSInt64(ref long value)
  461. {
  462. value = DecodeZigZag64(ReadRawVarint64());
  463. return true;
  464. }
  465. private bool BeginArray(uint fieldTag, out bool isPacked, out int oldLimit)
  466. {
  467. isPacked = WireFormat.GetTagWireType(fieldTag) == WireFormat.WireType.LengthDelimited;
  468. if (isPacked)
  469. {
  470. int length = (int) (ReadRawVarint32() & int.MaxValue);
  471. if (length > 0)
  472. {
  473. oldLimit = PushLimit(length);
  474. return true;
  475. }
  476. oldLimit = -1;
  477. return false; //packed but empty
  478. }
  479. oldLimit = -1;
  480. return true;
  481. }
  482. /// <summary>
  483. /// Returns true if the next tag is also part of the same unpacked array.
  484. /// </summary>
  485. private bool ContinueArray(uint currentTag)
  486. {
  487. string ignore;
  488. uint next;
  489. if (PeekNextTag(out next, out ignore))
  490. {
  491. if (next == currentTag)
  492. {
  493. hasNextTag = false;
  494. return true;
  495. }
  496. }
  497. return false;
  498. }
  499. /// <summary>
  500. /// Returns true if the next tag is also part of the same array, which may or may not be packed.
  501. /// </summary>
  502. private bool ContinueArray(uint currentTag, bool packed, int oldLimit)
  503. {
  504. if (packed)
  505. {
  506. if (ReachedLimit)
  507. {
  508. PopLimit(oldLimit);
  509. return false;
  510. }
  511. return true;
  512. }
  513. string ignore;
  514. uint next;
  515. if (PeekNextTag(out next, out ignore))
  516. {
  517. if (next == currentTag)
  518. {
  519. hasNextTag = false;
  520. return true;
  521. }
  522. }
  523. return false;
  524. }
  525. [CLSCompliant(false)]
  526. public void ReadPrimitiveArray(FieldType fieldType, uint fieldTag, string fieldName, ICollection<object> list)
  527. {
  528. WireFormat.WireType normal = WireFormat.GetWireType(fieldType);
  529. WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
  530. // 2.3 allows packed form even if the field is not declared packed.
  531. if (normal != wformat && wformat == WireFormat.WireType.LengthDelimited)
  532. {
  533. int length = (int) (ReadRawVarint32() & int.MaxValue);
  534. int limit = PushLimit(length);
  535. while (!ReachedLimit)
  536. {
  537. Object value = null;
  538. if (ReadPrimitiveField(fieldType, ref value))
  539. {
  540. list.Add(value);
  541. }
  542. }
  543. PopLimit(limit);
  544. }
  545. else
  546. {
  547. Object value = null;
  548. do
  549. {
  550. if (ReadPrimitiveField(fieldType, ref value))
  551. {
  552. list.Add(value);
  553. }
  554. } while (ContinueArray(fieldTag));
  555. }
  556. }
  557. [CLSCompliant(false)]
  558. public void ReadStringArray(uint fieldTag, string fieldName, ICollection<string> list)
  559. {
  560. string tmp = null;
  561. do
  562. {
  563. ReadString(ref tmp);
  564. list.Add(tmp);
  565. } while (ContinueArray(fieldTag));
  566. }
  567. [CLSCompliant(false)]
  568. public void ReadBytesArray(uint fieldTag, string fieldName, ICollection<ByteString> list)
  569. {
  570. ByteString tmp = null;
  571. do
  572. {
  573. ReadBytes(ref tmp);
  574. list.Add(tmp);
  575. } while (ContinueArray(fieldTag));
  576. }
  577. [CLSCompliant(false)]
  578. public void ReadBoolArray(uint fieldTag, string fieldName, ICollection<bool> list)
  579. {
  580. bool isPacked;
  581. int holdLimit;
  582. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  583. {
  584. bool tmp = false;
  585. do
  586. {
  587. ReadBool(ref tmp);
  588. list.Add(tmp);
  589. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  590. }
  591. }
  592. [CLSCompliant(false)]
  593. public void ReadInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
  594. {
  595. bool isPacked;
  596. int holdLimit;
  597. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  598. {
  599. int tmp = 0;
  600. do
  601. {
  602. ReadInt32(ref tmp);
  603. list.Add(tmp);
  604. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  605. }
  606. }
  607. [CLSCompliant(false)]
  608. public void ReadSInt32Array(uint fieldTag, string fieldName, ICollection<int> list)
  609. {
  610. bool isPacked;
  611. int holdLimit;
  612. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  613. {
  614. int tmp = 0;
  615. do
  616. {
  617. ReadSInt32(ref tmp);
  618. list.Add(tmp);
  619. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  620. }
  621. }
  622. [CLSCompliant(false)]
  623. public void ReadUInt32Array(uint fieldTag, string fieldName, ICollection<uint> list)
  624. {
  625. bool isPacked;
  626. int holdLimit;
  627. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  628. {
  629. uint tmp = 0;
  630. do
  631. {
  632. ReadUInt32(ref tmp);
  633. list.Add(tmp);
  634. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  635. }
  636. }
  637. [CLSCompliant(false)]
  638. public void ReadFixed32Array(uint fieldTag, string fieldName, ICollection<uint> list)
  639. {
  640. bool isPacked;
  641. int holdLimit;
  642. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  643. {
  644. uint tmp = 0;
  645. do
  646. {
  647. ReadFixed32(ref tmp);
  648. list.Add(tmp);
  649. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  650. }
  651. }
  652. [CLSCompliant(false)]
  653. public void ReadSFixed32Array(uint fieldTag, string fieldName, ICollection<int> list)
  654. {
  655. bool isPacked;
  656. int holdLimit;
  657. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  658. {
  659. int tmp = 0;
  660. do
  661. {
  662. ReadSFixed32(ref tmp);
  663. list.Add(tmp);
  664. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  665. }
  666. }
  667. [CLSCompliant(false)]
  668. public void ReadInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
  669. {
  670. bool isPacked;
  671. int holdLimit;
  672. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  673. {
  674. long tmp = 0;
  675. do
  676. {
  677. ReadInt64(ref tmp);
  678. list.Add(tmp);
  679. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  680. }
  681. }
  682. [CLSCompliant(false)]
  683. public void ReadSInt64Array(uint fieldTag, string fieldName, ICollection<long> list)
  684. {
  685. bool isPacked;
  686. int holdLimit;
  687. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  688. {
  689. long tmp = 0;
  690. do
  691. {
  692. ReadSInt64(ref tmp);
  693. list.Add(tmp);
  694. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  695. }
  696. }
  697. [CLSCompliant(false)]
  698. public void ReadUInt64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
  699. {
  700. bool isPacked;
  701. int holdLimit;
  702. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  703. {
  704. ulong tmp = 0;
  705. do
  706. {
  707. ReadUInt64(ref tmp);
  708. list.Add(tmp);
  709. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  710. }
  711. }
  712. [CLSCompliant(false)]
  713. public void ReadFixed64Array(uint fieldTag, string fieldName, ICollection<ulong> list)
  714. {
  715. bool isPacked;
  716. int holdLimit;
  717. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  718. {
  719. ulong tmp = 0;
  720. do
  721. {
  722. ReadFixed64(ref tmp);
  723. list.Add(tmp);
  724. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  725. }
  726. }
  727. [CLSCompliant(false)]
  728. public void ReadSFixed64Array(uint fieldTag, string fieldName, ICollection<long> list)
  729. {
  730. bool isPacked;
  731. int holdLimit;
  732. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  733. {
  734. long tmp = 0;
  735. do
  736. {
  737. ReadSFixed64(ref tmp);
  738. list.Add(tmp);
  739. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  740. }
  741. }
  742. [CLSCompliant(false)]
  743. public void ReadDoubleArray(uint fieldTag, string fieldName, ICollection<double> list)
  744. {
  745. bool isPacked;
  746. int holdLimit;
  747. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  748. {
  749. double tmp = 0;
  750. do
  751. {
  752. ReadDouble(ref tmp);
  753. list.Add(tmp);
  754. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  755. }
  756. }
  757. [CLSCompliant(false)]
  758. public void ReadFloatArray(uint fieldTag, string fieldName, ICollection<float> list)
  759. {
  760. bool isPacked;
  761. int holdLimit;
  762. if (BeginArray(fieldTag, out isPacked, out holdLimit))
  763. {
  764. float tmp = 0;
  765. do
  766. {
  767. ReadFloat(ref tmp);
  768. list.Add(tmp);
  769. } while (ContinueArray(fieldTag, isPacked, holdLimit));
  770. }
  771. }
  772. [CLSCompliant(false)]
  773. public void ReadEnumArray(uint fieldTag, string fieldName, ICollection<IEnumLite> list,
  774. out ICollection<object> unknown, IEnumLiteMap mapping)
  775. {
  776. unknown = null;
  777. object unkval;
  778. IEnumLite value = null;
  779. WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
  780. // 2.3 allows packed form even if the field is not declared packed.
  781. if (wformat == WireFormat.WireType.LengthDelimited)
  782. {
  783. int length = (int) (ReadRawVarint32() & int.MaxValue);
  784. int limit = PushLimit(length);
  785. while (!ReachedLimit)
  786. {
  787. if (ReadEnum(ref value, out unkval, mapping))
  788. {
  789. list.Add(value);
  790. }
  791. else
  792. {
  793. if (unknown == null)
  794. {
  795. unknown = new List<object>();
  796. }
  797. unknown.Add(unkval);
  798. }
  799. }
  800. PopLimit(limit);
  801. }
  802. else
  803. {
  804. do
  805. {
  806. if (ReadEnum(ref value, out unkval, mapping))
  807. {
  808. list.Add(value);
  809. }
  810. else
  811. {
  812. if (unknown == null)
  813. {
  814. unknown = new List<object>();
  815. }
  816. unknown.Add(unkval);
  817. }
  818. } while (ContinueArray(fieldTag));
  819. }
  820. }
  821. [CLSCompliant(false)]
  822. public void ReadEnumArray<T>(uint fieldTag, string fieldName, ICollection<T> list,
  823. out ICollection<object> unknown)
  824. where T : struct, IComparable, IFormattable, IConvertible
  825. {
  826. unknown = null;
  827. object unkval;
  828. T value = default(T);
  829. WireFormat.WireType wformat = WireFormat.GetTagWireType(fieldTag);
  830. // 2.3 allows packed form even if the field is not declared packed.
  831. if (wformat == WireFormat.WireType.LengthDelimited)
  832. {
  833. int length = (int) (ReadRawVarint32() & int.MaxValue);
  834. int limit = PushLimit(length);
  835. while (!ReachedLimit)
  836. {
  837. if (ReadEnum<T>(ref value, out unkval))
  838. {
  839. list.Add(value);
  840. }
  841. else
  842. {
  843. if (unknown == null)
  844. {
  845. unknown = new List<object>();
  846. }
  847. unknown.Add(unkval);
  848. }
  849. }
  850. PopLimit(limit);
  851. }
  852. else
  853. {
  854. do
  855. {
  856. if (ReadEnum(ref value, out unkval))
  857. {
  858. list.Add(value);
  859. }
  860. else
  861. {
  862. if (unknown == null)
  863. {
  864. unknown = new List<object>();
  865. }
  866. unknown.Add(unkval);
  867. }
  868. } while (ContinueArray(fieldTag));
  869. }
  870. }
  871. [CLSCompliant(false)]
  872. public void ReadMessageArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
  873. ExtensionRegistry registry) where T : IMessageLite
  874. {
  875. do
  876. {
  877. IBuilderLite builder = messageType.WeakCreateBuilderForType();
  878. ReadMessage(builder, registry);
  879. list.Add((T) builder.WeakBuildPartial());
  880. } while (ContinueArray(fieldTag));
  881. }
  882. [CLSCompliant(false)]
  883. public void ReadGroupArray<T>(uint fieldTag, string fieldName, ICollection<T> list, T messageType,
  884. ExtensionRegistry registry) where T : IMessageLite
  885. {
  886. do
  887. {
  888. IBuilderLite builder = messageType.WeakCreateBuilderForType();
  889. ReadGroup(WireFormat.GetTagFieldNumber(fieldTag), builder, registry);
  890. list.Add((T) builder.WeakBuildPartial());
  891. } while (ContinueArray(fieldTag));
  892. }
  893. /// <summary>
  894. /// Reads a field of any primitive type. Enums, groups and embedded
  895. /// messages are not handled by this method.
  896. /// </summary>
  897. public bool ReadPrimitiveField(FieldType fieldType, ref object value)
  898. {
  899. switch (fieldType)
  900. {
  901. case FieldType.Double:
  902. {
  903. double tmp = 0;
  904. if (ReadDouble(ref tmp))
  905. {
  906. value = tmp;
  907. return true;
  908. }
  909. return false;
  910. }
  911. case FieldType.Float:
  912. {
  913. float tmp = 0;
  914. if (ReadFloat(ref tmp))
  915. {
  916. value = tmp;
  917. return true;
  918. }
  919. return false;
  920. }
  921. case FieldType.Int64:
  922. {
  923. long tmp = 0;
  924. if (ReadInt64(ref tmp))
  925. {
  926. value = tmp;
  927. return true;
  928. }
  929. return false;
  930. }
  931. case FieldType.UInt64:
  932. {
  933. ulong tmp = 0;
  934. if (ReadUInt64(ref tmp))
  935. {
  936. value = tmp;
  937. return true;
  938. }
  939. return false;
  940. }
  941. case FieldType.Int32:
  942. {
  943. int tmp = 0;
  944. if (ReadInt32(ref tmp))
  945. {
  946. value = tmp;
  947. return true;
  948. }
  949. return false;
  950. }
  951. case FieldType.Fixed64:
  952. {
  953. ulong tmp = 0;
  954. if (ReadFixed64(ref tmp))
  955. {
  956. value = tmp;
  957. return true;
  958. }
  959. return false;
  960. }
  961. case FieldType.Fixed32:
  962. {
  963. uint tmp = 0;
  964. if (ReadFixed32(ref tmp))
  965. {
  966. value = tmp;
  967. return true;
  968. }
  969. return false;
  970. }
  971. case FieldType.Bool:
  972. {
  973. bool tmp = false;
  974. if (ReadBool(ref tmp))
  975. {
  976. value = tmp;
  977. return true;
  978. }
  979. return false;
  980. }
  981. case FieldType.String:
  982. {
  983. string tmp = null;
  984. if (ReadString(ref tmp))
  985. {
  986. value = tmp;
  987. return true;
  988. }
  989. return false;
  990. }
  991. case FieldType.Bytes:
  992. {
  993. ByteString tmp = null;
  994. if (ReadBytes(ref tmp))
  995. {
  996. value = tmp;
  997. return true;
  998. }
  999. return false;
  1000. }
  1001. case FieldType.UInt32:
  1002. {
  1003. uint tmp = 0;
  1004. if (ReadUInt32(ref tmp))
  1005. {
  1006. value = tmp;
  1007. return true;
  1008. }
  1009. return false;
  1010. }
  1011. case FieldType.SFixed32:
  1012. {
  1013. int tmp = 0;
  1014. if (ReadSFixed32(ref tmp))
  1015. {
  1016. value = tmp;
  1017. return true;
  1018. }
  1019. return false;
  1020. }
  1021. case FieldType.SFixed64:
  1022. {
  1023. long tmp = 0;
  1024. if (ReadSFixed64(ref tmp))
  1025. {
  1026. value = tmp;
  1027. return true;
  1028. }
  1029. return false;
  1030. }
  1031. case FieldType.SInt32:
  1032. {
  1033. int tmp = 0;
  1034. if (ReadSInt32(ref tmp))
  1035. {
  1036. value = tmp;
  1037. return true;
  1038. }
  1039. return false;
  1040. }
  1041. case FieldType.SInt64:
  1042. {
  1043. long tmp = 0;
  1044. if (ReadSInt64(ref tmp))
  1045. {
  1046. value = tmp;
  1047. return true;
  1048. }
  1049. return false;
  1050. }
  1051. case FieldType.Group:
  1052. throw new ArgumentException("ReadPrimitiveField() cannot handle nested groups.");
  1053. case FieldType.Message:
  1054. throw new ArgumentException("ReadPrimitiveField() cannot handle embedded messages.");
  1055. // We don't handle enums because we don't know what to do if the
  1056. // value is not recognized.
  1057. case FieldType.Enum:
  1058. throw new ArgumentException("ReadPrimitiveField() cannot handle enums.");
  1059. default:
  1060. throw new ArgumentOutOfRangeException("Invalid field type " + fieldType);
  1061. }
  1062. }
  1063. #endregion
  1064. #region Underlying reading primitives
  1065. /// <summary>
  1066. /// Same code as ReadRawVarint32, but read each byte individually, checking for
  1067. /// buffer overflow.
  1068. /// </summary>
  1069. private uint SlowReadRawVarint32()
  1070. {
  1071. int tmp = ReadRawByte();
  1072. if (tmp < 128)
  1073. {
  1074. return (uint) tmp;
  1075. }
  1076. int result = tmp & 0x7f;
  1077. if ((tmp = ReadRawByte()) < 128)
  1078. {
  1079. result |= tmp << 7;
  1080. }
  1081. else
  1082. {
  1083. result |= (tmp & 0x7f) << 7;
  1084. if ((tmp = ReadRawByte()) < 128)
  1085. {
  1086. result |= tmp << 14;
  1087. }
  1088. else
  1089. {
  1090. result |= (tmp & 0x7f) << 14;
  1091. if ((tmp = ReadRawByte()) < 128)
  1092. {
  1093. result |= tmp << 21;
  1094. }
  1095. else
  1096. {
  1097. result |= (tmp & 0x7f) << 21;
  1098. result |= (tmp = ReadRawByte()) << 28;
  1099. if (tmp >= 128)
  1100. {
  1101. // Discard upper 32 bits.
  1102. for (int i = 0; i < 5; i++)
  1103. {
  1104. if (ReadRawByte() < 128)
  1105. {
  1106. return (uint) result;
  1107. }
  1108. }
  1109. throw InvalidProtocolBufferException.MalformedVarint();
  1110. }
  1111. }
  1112. }
  1113. }
  1114. return (uint) result;
  1115. }
  1116. /// <summary>
  1117. /// Read a raw Varint from the stream. If larger than 32 bits, discard the upper bits.
  1118. /// This method is optimised for the case where we've got lots of data in the buffer.
  1119. /// That means we can check the size just once, then just read directly from the buffer
  1120. /// without constant rechecking of the buffer length.
  1121. /// </summary>
  1122. [CLSCompliant(false)]
  1123. public uint ReadRawVarint32()
  1124. {
  1125. if (bufferPos + 5 > bufferSize)
  1126. {
  1127. return SlowReadRawVarint32();
  1128. }
  1129. int tmp = buffer[bufferPos++];
  1130. if (tmp < 128)
  1131. {
  1132. return (uint) tmp;
  1133. }
  1134. int result = tmp & 0x7f;
  1135. if ((tmp = buffer[bufferPos++]) < 128)
  1136. {
  1137. result |= tmp << 7;
  1138. }
  1139. else
  1140. {
  1141. result |= (tmp & 0x7f) << 7;
  1142. if ((tmp = buffer[bufferPos++]) < 128)
  1143. {
  1144. result |= tmp << 14;
  1145. }
  1146. else
  1147. {
  1148. result |= (tmp & 0x7f) << 14;
  1149. if ((tmp = buffer[bufferPos++]) < 128)
  1150. {
  1151. result |= tmp << 21;
  1152. }
  1153. else
  1154. {
  1155. result |= (tmp & 0x7f) << 21;
  1156. result |= (tmp = buffer[bufferPos++]) << 28;
  1157. if (tmp >= 128)
  1158. {
  1159. // Discard upper 32 bits.
  1160. // Note that this has to use ReadRawByte() as we only ensure we've
  1161. // got at least 5 bytes at the start of the method. This lets us
  1162. // use the fast path in more cases, and we rarely hit this section of code.
  1163. for (int i = 0; i < 5; i++)
  1164. {
  1165. if (ReadRawByte() < 128)
  1166. {
  1167. return (uint) result;
  1168. }
  1169. }
  1170. throw InvalidProtocolBufferException.MalformedVarint();
  1171. }
  1172. }
  1173. }
  1174. }
  1175. return (uint) result;
  1176. }
  1177. /// <summary>
  1178. /// Reads a varint from the input one byte at a time, so that it does not
  1179. /// read any bytes after the end of the varint. If you simply wrapped the
  1180. /// stream in a CodedInputStream and used ReadRawVarint32(Stream)}
  1181. /// then you would probably end up reading past the end of the varint since
  1182. /// CodedInputStream buffers its input.
  1183. /// </summary>
  1184. /// <param name="input"></param>
  1185. /// <returns></returns>
  1186. [CLSCompliant(false)]
  1187. public static uint ReadRawVarint32(Stream input)
  1188. {
  1189. int result = 0;
  1190. int offset = 0;
  1191. for (; offset < 32; offset += 7)
  1192. {
  1193. int b = input.ReadByte();
  1194. if (b == -1)
  1195. {
  1196. throw InvalidProtocolBufferException.TruncatedMessage();
  1197. }
  1198. result |= (b & 0x7f) << offset;
  1199. if ((b & 0x80) == 0)
  1200. {
  1201. return (uint) result;
  1202. }
  1203. }
  1204. // Keep reading up to 64 bits.
  1205. for (; offset < 64; offset += 7)
  1206. {
  1207. int b = input.ReadByte();
  1208. if (b == -1)
  1209. {
  1210. throw InvalidProtocolBufferException.TruncatedMessage();
  1211. }
  1212. if ((b & 0x80) == 0)
  1213. {
  1214. return (uint) result;
  1215. }
  1216. }
  1217. throw InvalidProtocolBufferException.MalformedVarint();
  1218. }
  1219. /// <summary>
  1220. /// Read a raw varint from the stream.
  1221. /// </summary>
  1222. [CLSCompliant(false)]
  1223. public ulong ReadRawVarint64()
  1224. {
  1225. int shift = 0;
  1226. ulong result = 0;
  1227. while (shift < 64)
  1228. {
  1229. byte b = ReadRawByte();
  1230. result |= (ulong) (b & 0x7F) << shift;
  1231. if ((b & 0x80) == 0)
  1232. {
  1233. return result;
  1234. }
  1235. shift += 7;
  1236. }
  1237. throw InvalidProtocolBufferException.MalformedVarint();
  1238. }
  1239. /// <summary>
  1240. /// Read a 32-bit little-endian integer from the stream.
  1241. /// </summary>
  1242. [CLSCompliant(false)]
  1243. public uint ReadRawLittleEndian32()
  1244. {
  1245. uint b1 = ReadRawByte();
  1246. uint b2 = ReadRawByte();
  1247. uint b3 = ReadRawByte();
  1248. uint b4 = ReadRawByte();
  1249. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24);
  1250. }
  1251. /// <summary>
  1252. /// Read a 64-bit little-endian integer from the stream.
  1253. /// </summary>
  1254. [CLSCompliant(false)]
  1255. public ulong ReadRawLittleEndian64()
  1256. {
  1257. ulong b1 = ReadRawByte();
  1258. ulong b2 = ReadRawByte();
  1259. ulong b3 = ReadRawByte();
  1260. ulong b4 = ReadRawByte();
  1261. ulong b5 = ReadRawByte();
  1262. ulong b6 = ReadRawByte();
  1263. ulong b7 = ReadRawByte();
  1264. ulong b8 = ReadRawByte();
  1265. return b1 | (b2 << 8) | (b3 << 16) | (b4 << 24)
  1266. | (b5 << 32) | (b6 << 40) | (b7 << 48) | (b8 << 56);
  1267. }
  1268. #endregion
  1269. /// <summary>
  1270. /// Decode a 32-bit value with ZigZag encoding.
  1271. /// </summary>
  1272. /// <remarks>
  1273. /// ZigZag encodes signed integers into values that can be efficiently
  1274. /// encoded with varint. (Otherwise, negative values must be
  1275. /// sign-extended to 64 bits to be varint encoded, thus always taking
  1276. /// 10 bytes on the wire.)
  1277. /// </remarks>
  1278. [CLSCompliant(false)]
  1279. public static int DecodeZigZag32(uint n)
  1280. {
  1281. return (int) (n >> 1) ^ -(int) (n & 1);
  1282. }
  1283. /// <summary>
  1284. /// Decode a 32-bit value with ZigZag encoding.
  1285. /// </summary>
  1286. /// <remarks>
  1287. /// ZigZag encodes signed integers into values that can be efficiently
  1288. /// encoded with varint. (Otherwise, negative values must be
  1289. /// sign-extended to 64 bits to be varint encoded, thus always taking
  1290. /// 10 bytes on the wire.)
  1291. /// </remarks>
  1292. [CLSCompliant(false)]
  1293. public static long DecodeZigZag64(ulong n)
  1294. {
  1295. return (long) (n >> 1) ^ -(long) (n & 1);
  1296. }
  1297. /// <summary>
  1298. /// Set the maximum message recursion depth.
  1299. /// </summary>
  1300. /// <remarks>
  1301. /// In order to prevent malicious
  1302. /// messages from causing stack overflows, CodedInputStream limits
  1303. /// how deeply messages may be nested. The default limit is 64.
  1304. /// </remarks>
  1305. public int SetRecursionLimit(int limit)
  1306. {
  1307. if (limit < 0)
  1308. {
  1309. throw new ArgumentOutOfRangeException("Recursion limit cannot be negative: " + limit);
  1310. }
  1311. int oldLimit = recursionLimit;
  1312. recursionLimit = limit;
  1313. return oldLimit;
  1314. }
  1315. /// <summary>
  1316. /// Set the maximum message size.
  1317. /// </summary>
  1318. /// <remarks>
  1319. /// In order to prevent malicious messages from exhausting memory or
  1320. /// causing integer overflows, CodedInputStream limits how large a message may be.
  1321. /// The default limit is 64MB. You should set this limit as small
  1322. /// as you can without harming your app's functionality. Note that
  1323. /// size limits only apply when reading from an InputStream, not
  1324. /// when constructed around a raw byte array (nor with ByteString.NewCodedInput).
  1325. /// If you want to read several messages from a single CodedInputStream, you
  1326. /// can call ResetSizeCounter() after each message to avoid hitting the
  1327. /// size limit.
  1328. /// </remarks>
  1329. public int SetSizeLimit(int

Large files files are truncated, but you can click here to view the full file