/// <summary> /// Gets a token sequence from the reader /// </summary> /// <param name="reader"></param> /// <returns></returns> protected IEnumerable <Token <ModelTokenType> > GetTokens(BinaryReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } this.Reader = reader; using (reader) { List <Token <ModelTokenType> > tokens = new List <Token <ModelTokenType> >(); BsonTokenizer.ReadDocument(tokens, reader, false); this.Reader = BsonTokenizer.NullBinaryReader; return(tokens); }; }
private static void ReadDocument(List <Token <ModelTokenType> > tokens, BinaryReader reader, bool isArray) { if (reader.PeekChar() < 0) { return; } long start = reader.BaseStream.Position; int size = reader.ReadInt32(); tokens.Add(isArray ? ModelGrammar.TokenArrayBeginUnnamed : ModelGrammar.TokenObjectBeginUnnamed); while (reader.BaseStream.Position - start < size - 1) { BsonTokenizer.ReadElement(tokens, reader, isArray); } if (reader.ReadByte() != 0x00) { throw new DeserializationException(BsonWriter.ErrorUnterminated, start); } tokens.Add(isArray ? ModelGrammar.TokenArrayEnd : ModelGrammar.TokenObjectEnd); }
private static void ReadElement(List <Token <ModelTokenType> > tokens, BinaryReader reader, bool isArrayItem) { BsonElementType elemType = (BsonElementType)reader.ReadByte(); string ename = BsonTokenizer.ReadCString(reader); if (!isArrayItem) { tokens.Add(ModelGrammar.TokenProperty(ename)); } switch (elemType) { case BsonElementType.Double: { double value = reader.ReadDouble(); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.String: { string value = BsonTokenizer.ReadString(reader); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.JavaScriptCode: { BsonJavaScriptCode value = (BsonJavaScriptCode)BsonTokenizer.ReadString(reader); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.Symbol: { BsonSymbol value = (BsonSymbol)BsonTokenizer.ReadString(reader); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.Document: { BsonTokenizer.ReadDocument(tokens, reader, false); break; } case BsonElementType.Array: { BsonTokenizer.ReadDocument(tokens, reader, true); break; } case BsonElementType.Binary: { BsonTokenizer.ReadBinary(tokens, reader); break; } case BsonElementType.ObjectID: { byte[] value = reader.ReadBytes(BsonWriter.SizeOfObjectID); tokens.Add(ModelGrammar.TokenPrimitive(new BsonObjectID(value))); break; } case BsonElementType.Boolean: { bool value = reader.ReadByte() != BsonWriter.FalseByte; tokens.Add(value ? ModelGrammar.TokenTrue : ModelGrammar.TokenFalse); break; } case BsonElementType.DateTimeUtc: { DateTime value = BsonWriter.UnixEpoch.AddMilliseconds(reader.ReadInt64()); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.RegExp: { string pattern = BsonTokenizer.ReadCString(reader); string optionsStr = BsonTokenizer.ReadCString(reader); RegexOptions options = RegexOptions.ECMAScript; for (int i = optionsStr.Length - 1; i >= 0; i--) { char ch = optionsStr[i]; switch (ch) { case 'g': { // TODO: ensure correct encoding of ^$ //options |= RegexOptions.Multiline; break; } case 'i': { options |= RegexOptions.IgnoreCase; break; } case 'm': { options |= RegexOptions.Multiline; break; } } } Regex regex = new Regex(pattern, options); tokens.Add(ModelGrammar.TokenPrimitive(regex)); break; } case BsonElementType.DBPointer: { string value1 = BsonTokenizer.ReadString(reader); byte[] value2 = reader.ReadBytes(BsonWriter.SizeOfObjectID); BsonDBPointer pointer = new BsonDBPointer { Namespace = value1, ObjectID = new BsonObjectID(value2) }; tokens.Add(ModelGrammar.TokenPrimitive(pointer)); break; } case BsonElementType.CodeWithScope: { int size = reader.ReadInt32(); string value = BsonTokenizer.ReadString(reader); tokens.Add(ModelGrammar.TokenPrimitive(value)); BsonTokenizer.ReadDocument(tokens, reader, false); break; } case BsonElementType.Int32: { int value = reader.ReadInt32(); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.TimeStamp: { long value = reader.ReadInt64(); // TODO: convert to TimeSpan? tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.Int64: { long value = reader.ReadInt64(); tokens.Add(ModelGrammar.TokenPrimitive(value)); break; } case BsonElementType.Undefined: case BsonElementType.Null: case BsonElementType.MinKey: case BsonElementType.MaxKey: { // no data value break; } default: { throw new DeserializationException( String.Format(BsonTokenizer.ErrorUnexpectedElementType, elemType), reader.BaseStream.Position); } } }