BsonBinaryReader.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /* Copyright 2010-2014 MongoDB Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. using System;
  16. using System.IO;
  17. namespace MongoDB.Bson.IO
  18. {
  19. /// <summary>
  20. /// Represents a BSON reader for a binary BSON byte array.
  21. /// </summary>
  22. public class BsonBinaryReader : BsonReader
  23. {
  24. // private fields
  25. private BsonBuffer _buffer; // if reading from a stream Create will have loaded the buffer
  26. private bool _disposeBuffer;
  27. private BsonBinaryReaderSettings _binaryReaderSettings; // same value as in base class just declared as derived class
  28. private BsonBinaryReaderContext _context;
  29. // constructors
  30. /// <summary>
  31. /// Initializes a new instance of the BsonBinaryReader class.
  32. /// </summary>
  33. /// <param name="buffer">A BsonBuffer.</param>
  34. /// <param name="settings">A BsonBinaryReaderSettings.</param>
  35. public BsonBinaryReader(BsonBuffer buffer, BsonBinaryReaderSettings settings)
  36. : this(buffer ?? new BsonBuffer(), buffer == null, settings)
  37. {
  38. }
  39. /// <summary>
  40. /// Initializes a new instance of the BsonBinaryReader class.
  41. /// </summary>
  42. /// <param name="buffer">A BsonBuffer.</param>
  43. /// <param name="disposeBuffer">if set to <c>true</c> this BsonBinaryReader will own the buffer and when Dispose is called the buffer will be Disposed also.</param>
  44. /// <param name="settings">A BsonBinaryReaderSettings.</param>
  45. /// <exception cref="System.ArgumentNullException">
  46. /// buffer
  47. /// or
  48. /// settings
  49. /// </exception>
  50. public BsonBinaryReader(BsonBuffer buffer, bool disposeBuffer, BsonBinaryReaderSettings settings)
  51. : base(settings)
  52. {
  53. if (buffer == null)
  54. {
  55. throw new ArgumentNullException("buffer");
  56. }
  57. _buffer = buffer;
  58. _disposeBuffer = disposeBuffer;
  59. _binaryReaderSettings = settings; // already frozen by base class
  60. _context = new BsonBinaryReaderContext(null, ContextType.TopLevel, 0, 0);
  61. }
  62. // public properties
  63. /// <summary>
  64. /// Gets the reader's buffer.
  65. /// </summary>
  66. public BsonBuffer Buffer
  67. {
  68. get { return _buffer; }
  69. }
  70. // public methods
  71. /// <summary>
  72. /// Closes the reader.
  73. /// </summary>
  74. public override void Close()
  75. {
  76. // Close can be called on Disposed objects
  77. if (State != BsonReaderState.Closed)
  78. {
  79. State = BsonReaderState.Closed;
  80. }
  81. }
  82. /// <summary>
  83. /// Gets a bookmark to the reader's current position and state.
  84. /// </summary>
  85. /// <returns>A bookmark.</returns>
  86. public override BsonReaderBookmark GetBookmark()
  87. {
  88. return new BsonBinaryReaderBookmark(State, CurrentBsonType, CurrentName, _context, _buffer.Position);
  89. }
  90. /// <summary>
  91. /// Reads BSON binary data from the reader.
  92. /// </summary>
  93. /// <returns>A BsonBinaryData.</returns>
  94. #pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
  95. public override BsonBinaryData ReadBinaryData()
  96. {
  97. if (Disposed) { ThrowObjectDisposedException(); }
  98. VerifyBsonType("ReadBinaryData", BsonType.Binary);
  99. int size = ReadSize();
  100. var subType = (BsonBinarySubType)_buffer.ReadByte();
  101. if (subType == BsonBinarySubType.OldBinary)
  102. {
  103. // sub type OldBinary has two sizes (for historical reasons)
  104. int size2 = ReadSize();
  105. if (size2 != size - 4)
  106. {
  107. throw new Exception("Binary sub type OldBinary has inconsistent sizes");
  108. }
  109. size = size2;
  110. if (_binaryReaderSettings.FixOldBinarySubTypeOnInput)
  111. {
  112. subType = BsonBinarySubType.Binary; // replace obsolete OldBinary with new Binary sub type
  113. }
  114. }
  115. var bytes = _buffer.ReadBytes(size);
  116. var guidRepresentation = GuidRepresentation.Unspecified;
  117. if (subType == BsonBinarySubType.UuidLegacy || subType == BsonBinarySubType.UuidStandard)
  118. {
  119. if (_binaryReaderSettings.GuidRepresentation != GuidRepresentation.Unspecified)
  120. {
  121. var expectedSubType = (_binaryReaderSettings.GuidRepresentation == GuidRepresentation.Standard) ? BsonBinarySubType.UuidStandard : BsonBinarySubType.UuidLegacy;
  122. if (subType != expectedSubType)
  123. {
  124. var message = string.Format(
  125. "The GuidRepresentation for the reader is {0}, which requires the binary sub type to be {1}, not {2}.",
  126. _binaryReaderSettings.GuidRepresentation, expectedSubType, subType);
  127. throw new Exception(message);
  128. }
  129. }
  130. guidRepresentation = (subType == BsonBinarySubType.UuidStandard) ? GuidRepresentation.Standard : _binaryReaderSettings.GuidRepresentation;
  131. }
  132. State = GetNextState();
  133. return new BsonBinaryData(bytes, subType, guidRepresentation);
  134. }
  135. #pragma warning restore 618
  136. /// <summary>
  137. /// Reads a BSON boolean from the reader.
  138. /// </summary>
  139. /// <returns>A Boolean.</returns>
  140. public override bool ReadBoolean()
  141. {
  142. if (Disposed) { ThrowObjectDisposedException(); }
  143. VerifyBsonType("ReadBoolean", BsonType.Boolean);
  144. State = GetNextState();
  145. return _buffer.ReadBoolean();
  146. }
  147. /// <summary>
  148. /// Reads a BsonType from the reader.
  149. /// </summary>
  150. /// <typeparam name="TValue">The type of the BsonTrie values.</typeparam>
  151. /// <param name="bsonTrie">An optional trie to search for a value that matches the next element name.</param>
  152. /// <param name="found">Set to true if a matching value was found in the trie.</param>
  153. /// <param name="value">Set to the matching value found in the trie or null if no matching value was found.</param>
  154. /// <returns>A BsonType.</returns>
  155. public override BsonType ReadBsonType<TValue>(BsonTrie<TValue> bsonTrie, out bool found, out TValue value)
  156. {
  157. if (Disposed) { ThrowObjectDisposedException(); }
  158. found = false;
  159. value = default(TValue);
  160. if (State == BsonReaderState.Initial || State == BsonReaderState.Done || State == BsonReaderState.ScopeDocument)
  161. {
  162. // there is an implied type of Document for the top level and for scope documents
  163. CurrentBsonType = BsonType.Document;
  164. State = BsonReaderState.Value;
  165. return CurrentBsonType;
  166. }
  167. if (State != BsonReaderState.Type)
  168. {
  169. ThrowInvalidState("ReadBsonType", BsonReaderState.Type);
  170. }
  171. CurrentBsonType = _buffer.ReadBsonType();
  172. if (CurrentBsonType == BsonType.EndOfDocument)
  173. {
  174. switch (_context.ContextType)
  175. {
  176. case ContextType.Array:
  177. State = BsonReaderState.EndOfArray;
  178. return BsonType.EndOfDocument;
  179. case ContextType.Document:
  180. case ContextType.ScopeDocument:
  181. State = BsonReaderState.EndOfDocument;
  182. return BsonType.EndOfDocument;
  183. default:
  184. var message = string.Format("BsonType EndOfDocument is not valid when ContextType is {0}.", _context.ContextType);
  185. throw new Exception(message);
  186. }
  187. }
  188. else
  189. {
  190. switch (_context.ContextType)
  191. {
  192. case ContextType.Array:
  193. _buffer.SkipCString(); // ignore array element names
  194. State = BsonReaderState.Value;
  195. break;
  196. case ContextType.Document:
  197. case ContextType.ScopeDocument:
  198. CurrentName = _buffer.ReadName(bsonTrie, out found, out value);
  199. State = BsonReaderState.Name;
  200. break;
  201. default:
  202. throw new BsonInternalException("Unexpected ContextType.");
  203. }
  204. return CurrentBsonType;
  205. }
  206. }
  207. /// <summary>
  208. /// Reads BSON binary data from the reader.
  209. /// </summary>
  210. /// <returns>A byte array.</returns>
  211. #pragma warning disable 618 // about obsolete BsonBinarySubType.OldBinary
  212. public override byte[] ReadBytes()
  213. {
  214. if (Disposed) { ThrowObjectDisposedException(); }
  215. VerifyBsonType("ReadBytes", BsonType.Binary);
  216. int size = ReadSize();
  217. var subType = (BsonBinarySubType)_buffer.ReadByte();
  218. if (subType != BsonBinarySubType.Binary && subType != BsonBinarySubType.OldBinary)
  219. {
  220. var message = string.Format("ReadBytes requires the binary sub type to be Binary, not {2}.", subType);
  221. throw new Exception(message);
  222. }
  223. State = GetNextState();
  224. return _buffer.ReadBytes(size);
  225. }
  226. #pragma warning restore 618
  227. /// <summary>
  228. /// Reads a BSON DateTime from the reader.
  229. /// </summary>
  230. /// <returns>The number of milliseconds since the Unix epoch.</returns>
  231. public override long ReadDateTime()
  232. {
  233. if (Disposed) { ThrowObjectDisposedException(); }
  234. VerifyBsonType("ReadDateTime", BsonType.DateTime);
  235. State = GetNextState();
  236. var value = _buffer.ReadInt64();
  237. if (value == BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch + 1)
  238. {
  239. if (_binaryReaderSettings.FixOldDateTimeMaxValueOnInput)
  240. {
  241. value = BsonConstants.DateTimeMaxValueMillisecondsSinceEpoch;
  242. }
  243. }
  244. return value;
  245. }
  246. /// <summary>
  247. /// Reads a BSON Double from the reader.
  248. /// </summary>
  249. /// <returns>A Double.</returns>
  250. public override double ReadDouble()
  251. {
  252. if (Disposed) { ThrowObjectDisposedException(); }
  253. VerifyBsonType("ReadDouble", BsonType.Double);
  254. State = GetNextState();
  255. return _buffer.ReadDouble();
  256. }
  257. /// <summary>
  258. /// Reads the end of a BSON array from the reader.
  259. /// </summary>
  260. public override void ReadEndArray()
  261. {
  262. if (Disposed) { ThrowObjectDisposedException(); }
  263. if (_context.ContextType != ContextType.Array)
  264. {
  265. ThrowInvalidContextType("ReadEndArray", _context.ContextType, ContextType.Array);
  266. }
  267. if (State == BsonReaderState.Type)
  268. {
  269. ReadBsonType(); // will set state to EndOfArray if at end of array
  270. }
  271. if (State != BsonReaderState.EndOfArray)
  272. {
  273. ThrowInvalidState("ReadEndArray", BsonReaderState.EndOfArray);
  274. }
  275. _context = _context.PopContext(_buffer.Position);
  276. switch (_context.ContextType)
  277. {
  278. case ContextType.Array: State = BsonReaderState.Type; break;
  279. case ContextType.Document: State = BsonReaderState.Type; break;
  280. case ContextType.TopLevel: State = BsonReaderState.Done; break;
  281. default: throw new BsonInternalException("Unexpected ContextType.");
  282. }
  283. }
  284. /// <summary>
  285. /// Reads the end of a BSON document from the reader.
  286. /// </summary>
  287. public override void ReadEndDocument()
  288. {
  289. if (Disposed) { ThrowObjectDisposedException(); }
  290. if (_context.ContextType != ContextType.Document && _context.ContextType != ContextType.ScopeDocument)
  291. {
  292. ThrowInvalidContextType("ReadEndDocument", _context.ContextType, ContextType.Document, ContextType.ScopeDocument);
  293. }
  294. if (State == BsonReaderState.Type)
  295. {
  296. ReadBsonType(); // will set state to EndOfDocument if at end of document
  297. }
  298. if (State != BsonReaderState.EndOfDocument)
  299. {
  300. ThrowInvalidState("ReadEndDocument", BsonReaderState.EndOfDocument);
  301. }
  302. _context = _context.PopContext(_buffer.Position);
  303. if (_context.ContextType == ContextType.JavaScriptWithScope)
  304. {
  305. _context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
  306. }
  307. switch (_context.ContextType)
  308. {
  309. case ContextType.Array: State = BsonReaderState.Type; break;
  310. case ContextType.Document: State = BsonReaderState.Type; break;
  311. case ContextType.TopLevel: State = BsonReaderState.Done; break;
  312. default: throw new BsonInternalException("Unexpected ContextType.");
  313. }
  314. }
  315. /// <summary>
  316. /// Reads a BSON Int32 from the reader.
  317. /// </summary>
  318. /// <returns>An Int32.</returns>
  319. public override int ReadInt32()
  320. {
  321. if (Disposed) { ThrowObjectDisposedException(); }
  322. VerifyBsonType("ReadInt32", BsonType.Int32);
  323. State = GetNextState();
  324. return _buffer.ReadInt32();
  325. }
  326. /// <summary>
  327. /// Reads a BSON Int64 from the reader.
  328. /// </summary>
  329. /// <returns>An Int64.</returns>
  330. public override long ReadInt64()
  331. {
  332. if (Disposed) { ThrowObjectDisposedException(); }
  333. VerifyBsonType("ReadInt64", BsonType.Int64);
  334. State = GetNextState();
  335. return _buffer.ReadInt64();
  336. }
  337. /// <summary>
  338. /// Reads a BSON JavaScript from the reader.
  339. /// </summary>
  340. /// <returns>A string.</returns>
  341. public override string ReadJavaScript()
  342. {
  343. if (Disposed) { ThrowObjectDisposedException(); }
  344. VerifyBsonType("ReadJavaScript", BsonType.JavaScript);
  345. State = GetNextState();
  346. return _buffer.ReadString(_binaryReaderSettings.Encoding);
  347. }
  348. /// <summary>
  349. /// Reads a BSON JavaScript with scope from the reader (call ReadStartDocument next to read the scope).
  350. /// </summary>
  351. /// <returns>A string.</returns>
  352. public override string ReadJavaScriptWithScope()
  353. {
  354. if (Disposed) { ThrowObjectDisposedException(); }
  355. VerifyBsonType("ReadJavaScriptWithScope", BsonType.JavaScriptWithScope);
  356. var startPosition = _buffer.Position; // position of size field
  357. var size = ReadSize();
  358. _context = new BsonBinaryReaderContext(_context, ContextType.JavaScriptWithScope, startPosition, size);
  359. var code = _buffer.ReadString(_binaryReaderSettings.Encoding);
  360. State = BsonReaderState.ScopeDocument;
  361. return code;
  362. }
  363. /// <summary>
  364. /// Reads a BSON MaxKey from the reader.
  365. /// </summary>
  366. public override void ReadMaxKey()
  367. {
  368. if (Disposed) { ThrowObjectDisposedException(); }
  369. VerifyBsonType("ReadMaxKey", BsonType.MaxKey);
  370. State = GetNextState();
  371. }
  372. /// <summary>
  373. /// Reads a BSON MinKey from the reader.
  374. /// </summary>
  375. public override void ReadMinKey()
  376. {
  377. if (Disposed) { ThrowObjectDisposedException(); }
  378. VerifyBsonType("ReadMinKey", BsonType.MinKey);
  379. State = GetNextState();
  380. }
  381. /// <summary>
  382. /// Reads a BSON null from the reader.
  383. /// </summary>
  384. public override void ReadNull()
  385. {
  386. if (Disposed) { ThrowObjectDisposedException(); }
  387. VerifyBsonType("ReadNull", BsonType.Null);
  388. State = GetNextState();
  389. }
  390. /// <summary>
  391. /// Reads a BSON ObjectId from the reader.
  392. /// </summary>
  393. /// <returns>An ObjectId.</returns>
  394. public override ObjectId ReadObjectId()
  395. {
  396. if (Disposed) { ThrowObjectDisposedException(); }
  397. VerifyBsonType("ReadObjectId", BsonType.ObjectId);
  398. State = GetNextState();
  399. return _buffer.ReadObjectId();
  400. }
  401. /// <summary>
  402. /// Reads a raw BSON array.
  403. /// </summary>
  404. /// <returns>
  405. /// The raw BSON array.
  406. /// </returns>
  407. public override IByteBuffer ReadRawBsonArray()
  408. {
  409. if (Disposed) { ThrowObjectDisposedException(); }
  410. VerifyBsonType("ReadRawBsonArray", BsonType.Array);
  411. var position = _buffer.Position;
  412. var length = _buffer.ReadInt32();
  413. var slice = _buffer.ByteBuffer.GetSlice(position, length);
  414. _buffer.Position = position + length;
  415. switch (_context.ContextType)
  416. {
  417. case ContextType.Array: State = BsonReaderState.Type; break;
  418. case ContextType.Document: State = BsonReaderState.Type; break;
  419. case ContextType.TopLevel: State = BsonReaderState.Done; break;
  420. default: throw new BsonInternalException("Unexpected ContextType.");
  421. }
  422. return slice;
  423. }
  424. /// <summary>
  425. /// Reads a raw BSON document.
  426. /// </summary>
  427. /// <returns>
  428. /// The raw BSON document.
  429. /// </returns>
  430. public override IByteBuffer ReadRawBsonDocument()
  431. {
  432. if (Disposed) { ThrowObjectDisposedException(); }
  433. VerifyBsonType("ReadRawBsonDocument", BsonType.Document);
  434. var position = _buffer.Position;
  435. var length = _buffer.ReadInt32();
  436. var slice = _buffer.ByteBuffer.GetSlice(position, length);
  437. _buffer.Position = position + length;
  438. if (_context.ContextType == ContextType.JavaScriptWithScope)
  439. {
  440. _context = _context.PopContext(_buffer.Position); // JavaScriptWithScope
  441. }
  442. switch (_context.ContextType)
  443. {
  444. case ContextType.Array: State = BsonReaderState.Type; break;
  445. case ContextType.Document: State = BsonReaderState.Type; break;
  446. case ContextType.TopLevel: State = BsonReaderState.Done; break;
  447. default: throw new BsonInternalException("Unexpected ContextType.");
  448. }
  449. return slice;
  450. }
  451. /// <summary>
  452. /// Reads a BSON regular expression from the reader.
  453. /// </summary>
  454. /// <returns>A BsonRegularExpression.</returns>
  455. public override BsonRegularExpression ReadRegularExpression()
  456. {
  457. if (Disposed) { ThrowObjectDisposedException(); }
  458. VerifyBsonType("ReadRegularExpression", BsonType.RegularExpression);
  459. State = GetNextState();
  460. var pattern = _buffer.ReadCString(_binaryReaderSettings.Encoding);
  461. var options = _buffer.ReadCString(_binaryReaderSettings.Encoding);
  462. return new BsonRegularExpression(pattern, options);
  463. }
  464. /// <summary>
  465. /// Reads the start of a BSON array.
  466. /// </summary>
  467. public override void ReadStartArray()
  468. {
  469. if (Disposed) { ThrowObjectDisposedException(); }
  470. VerifyBsonType("ReadStartArray", BsonType.Array);
  471. var startPosition = _buffer.Position; // position of size field
  472. var size = ReadSize();
  473. _context = new BsonBinaryReaderContext(_context, ContextType.Array, startPosition, size);
  474. State = BsonReaderState.Type;
  475. }
  476. /// <summary>
  477. /// Reads the start of a BSON document.
  478. /// </summary>
  479. public override void ReadStartDocument()
  480. {
  481. if (Disposed) { ThrowObjectDisposedException(); }
  482. VerifyBsonType("ReadStartDocument", BsonType.Document);
  483. var contextType = (State == BsonReaderState.ScopeDocument) ? ContextType.ScopeDocument : ContextType.Document;
  484. var startPosition = _buffer.Position; // position of size field
  485. var size = ReadSize();
  486. _context = new BsonBinaryReaderContext(_context, contextType, startPosition, size);
  487. State = BsonReaderState.Type;
  488. }
  489. /// <summary>
  490. /// Reads a BSON string from the reader.
  491. /// </summary>
  492. /// <returns>A String.</returns>
  493. public override string ReadString()
  494. {
  495. if (Disposed) { ThrowObjectDisposedException(); }
  496. VerifyBsonType("ReadString", BsonType.String);
  497. State = GetNextState();
  498. return _buffer.ReadString(_binaryReaderSettings.Encoding);
  499. }
  500. /// <summary>
  501. /// Reads a BSON symbol from the reader.
  502. /// </summary>
  503. /// <returns>A string.</returns>
  504. public override string ReadSymbol()
  505. {
  506. if (Disposed) { ThrowObjectDisposedException(); }
  507. VerifyBsonType("ReadSymbol", BsonType.Symbol);
  508. State = GetNextState();
  509. return _buffer.ReadString(_binaryReaderSettings.Encoding);
  510. }
  511. /// <summary>
  512. /// Reads a BSON timestamp from the reader.
  513. /// </summary>
  514. /// <returns>The combined timestamp/increment.</returns>
  515. public override long ReadTimestamp()
  516. {
  517. if (Disposed) { ThrowObjectDisposedException(); }
  518. VerifyBsonType("ReadTimestamp", BsonType.Timestamp);
  519. State = GetNextState();
  520. return _buffer.ReadInt64();
  521. }
  522. /// <summary>
  523. /// Reads a BSON undefined from the reader.
  524. /// </summary>
  525. public override void ReadUndefined()
  526. {
  527. if (Disposed) { ThrowObjectDisposedException(); }
  528. VerifyBsonType("ReadUndefined", BsonType.Undefined);
  529. State = GetNextState();
  530. }
  531. /// <summary>
  532. /// Returns the reader to previously bookmarked position and state.
  533. /// </summary>
  534. /// <param name="bookmark">The bookmark.</param>
  535. public override void ReturnToBookmark(BsonReaderBookmark bookmark)
  536. {
  537. var binaryReaderBookmark = (BsonBinaryReaderBookmark)bookmark;
  538. State = binaryReaderBookmark.State;
  539. CurrentBsonType = binaryReaderBookmark.CurrentBsonType;
  540. CurrentName = binaryReaderBookmark.CurrentName;
  541. _context = binaryReaderBookmark.CloneContext();
  542. _buffer.Position = binaryReaderBookmark.Position;
  543. }
  544. /// <summary>
  545. /// Skips the name (reader must be positioned on a name).
  546. /// </summary>
  547. public override void SkipName()
  548. {
  549. if (Disposed) { ThrowObjectDisposedException(); }
  550. if (State != BsonReaderState.Name)
  551. {
  552. ThrowInvalidState("SkipName", BsonReaderState.Name);
  553. }
  554. State = BsonReaderState.Value;
  555. }
  556. /// <summary>
  557. /// Skips the value (reader must be positioned on a value).
  558. /// </summary>
  559. public override void SkipValue()
  560. {
  561. if (Disposed) { ThrowObjectDisposedException(); }
  562. if (State != BsonReaderState.Value)
  563. {
  564. ThrowInvalidState("SkipValue", BsonReaderState.Value);
  565. }
  566. int skip;
  567. switch (CurrentBsonType)
  568. {
  569. case BsonType.Array: skip = ReadSize() - 4; break;
  570. case BsonType.Binary: skip = ReadSize() + 1; break;
  571. case BsonType.Boolean: skip = 1; break;
  572. case BsonType.DateTime: skip = 8; break;
  573. case BsonType.Document: skip = ReadSize() - 4; break;
  574. case BsonType.Double: skip = 8; break;
  575. case BsonType.Int32: skip = 4; break;
  576. case BsonType.Int64: skip = 8; break;
  577. case BsonType.JavaScript: skip = ReadSize(); break;
  578. case BsonType.JavaScriptWithScope: skip = ReadSize() - 4; break;
  579. case BsonType.MaxKey: skip = 0; break;
  580. case BsonType.MinKey: skip = 0; break;
  581. case BsonType.Null: skip = 0; break;
  582. case BsonType.ObjectId: skip = 12; break;
  583. case BsonType.RegularExpression: _buffer.SkipCString(); _buffer.SkipCString(); skip = 0; break;
  584. case BsonType.String: skip = ReadSize(); break;
  585. case BsonType.Symbol: skip = ReadSize(); break;
  586. case BsonType.Timestamp: skip = 8; break;
  587. case BsonType.Undefined: skip = 0; break;
  588. default: throw new BsonInternalException("Unexpected BsonType.");
  589. }
  590. _buffer.Skip(skip);
  591. State = BsonReaderState.Type;
  592. }
  593. // protected methods
  594. /// <summary>
  595. /// Disposes of any resources used by the reader.
  596. /// </summary>
  597. /// <param name="disposing">True if called from Dispose.</param>
  598. protected override void Dispose(bool disposing)
  599. {
  600. if (disposing)
  601. {
  602. try
  603. {
  604. Close();
  605. if (_buffer != null)
  606. {
  607. if (_disposeBuffer)
  608. {
  609. _buffer.Dispose();
  610. }
  611. _buffer = null;
  612. }
  613. }
  614. catch { } // ignore exceptions
  615. }
  616. base.Dispose(disposing);
  617. }
  618. // private methods
  619. private BsonReaderState GetNextState()
  620. {
  621. switch (_context.ContextType)
  622. {
  623. case ContextType.Array:
  624. case ContextType.Document:
  625. case ContextType.ScopeDocument:
  626. return BsonReaderState.Type;
  627. case ContextType.TopLevel:
  628. return BsonReaderState.Done;
  629. default:
  630. throw new BsonInternalException("Unexpected ContextType.");
  631. }
  632. }
  633. private int ReadSize()
  634. {
  635. int size = _buffer.ReadInt32();
  636. if (size < 0)
  637. {
  638. var message = string.Format("Size {0} is not valid because it is negative.", size);
  639. throw new Exception(message);
  640. }
  641. if (size > _binaryReaderSettings.MaxDocumentSize)
  642. {
  643. var message = string.Format("Size {0} is not valid because it is larger than MaxDocumentSize {1}.", size, _binaryReaderSettings.MaxDocumentSize);
  644. throw new Exception(message);
  645. }
  646. return size;
  647. }
  648. }
  649. }