예제 #1
0
            /// <summary>
            /// Emits a code_w_s value
            /// </summary>
            /// <param name="writer"></param>
            /// <param name="tokens"></param>
            /// <returns>number of bytes written</returns>
            private int WriteCodeWithScope(BinaryWriter writer, BsonCodeWithScope value)
            {
                long start = writer.BaseStream.Position;
                int  total = BsonWriter.SizeOfInt32;               // code_w_s length field

                // leave room for length
                writer.Seek(BsonWriter.SizeOfInt32, SeekOrigin.Current);

                // write code
                total += BsonFormatter.WriteString(writer, (string)value.Code, false);

                //TODO: this is currently broken.

                // write scope
                total += this.WriteDocument(writer, value.Scope);

                // seek back to write out code_w_s length
                long end = writer.BaseStream.Position;

                writer.Seek((int)(start - end), SeekOrigin.Current);
                writer.Write(total);

                // seek back to end
                writer.Seek((int)(end - start - BsonWriter.SizeOfInt32), SeekOrigin.Current);

                return(total);
            }
예제 #2
0
            /// <summary>
            /// Emits a single element to the binary stream
            /// </summary>
            /// <param name="writer"></param>
            /// <param name="tokens"></param>
            /// <param name="ename"></param>
            /// <returns>number of bytes written</returns>
            private int WriteElement(BinaryWriter writer, IStream <Token <ModelTokenType> > tokens, string ename)
            {
                Token <ModelTokenType> token = tokens.Peek();

                if (tokens.IsCompleted || token == null)
                {
                    throw new TokenException <ModelTokenType>(token, BsonWriter.ErrorUnterminated);
                }

                BsonElementType elemType;

                switch (token.TokenType)
                {
                case ModelTokenType.ArrayBegin:
                {
                    elemType = BsonElementType.Array;
                    break;
                }

                case ModelTokenType.ObjectBegin:
                {
                    elemType = BsonElementType.Document;
                    break;
                }

                case ModelTokenType.Primitive:
                {
                    elemType = BsonFormatter.GetElementType(token.Value);
                    break;
                }

                default:
                {
                    // the rest are invalid states
                    throw new TokenException <ModelTokenType>(token,
                                                              String.Format(BsonWriter.ErrorUnexpectedToken, token.TokenType));
                }
                }

                // write element type
                writer.Write((byte)elemType);
                int total = BsonWriter.SizeOfByte;                 // for element type

                // write EName
                total += BsonFormatter.WriteString(writer, ename, true);

                IBsonFormattable formattable = token.Value as IBsonFormattable;

                if (formattable != null)
                {
                    total += formattable.Format(this, writer);
                }
                else
                {
                    switch (elemType)
                    {
                    case BsonElementType.Double:
                    {
                        // consume token value
                        tokens.Pop();

                        // write double data
                        writer.Write((double)token.Value);
                        total += BsonWriter.SizeOfDouble;
                        break;
                    }

                    case BsonElementType.String:
                    case BsonElementType.JavaScriptCode:
                    case BsonElementType.Symbol:
                    {
                        // consume token value
                        tokens.Pop();

                        // write as string data
                        total += BsonFormatter.WriteString(writer, token.ValueAsString(), false);
                        break;
                    }

                    case BsonElementType.Document:
                    case BsonElementType.Array:
                    {
                        // delegate property to sub-document
                        total += this.WriteDocument(writer, tokens);
                        break;
                    }

                    case BsonElementType.Binary:
                    {
                        // consume token value
                        tokens.Pop();

                        total += BsonFormatter.WriteBinary(writer, token);
                        break;
                    }

                    case BsonElementType.ObjectID:
                    {
                        // consume token value
                        tokens.Pop();

                        // write ObjectID data
                        writer.Write((byte[])token.Value);
                        total += BsonWriter.SizeOfObjectID;
                        break;
                    }

                    case BsonElementType.Boolean:
                    {
                        // consume token value
                        tokens.Pop();

                        // write bool data
                        bool value = true.Equals(token.Value);
                        writer.Write(value ? BsonWriter.TrueByte : BsonWriter.FalseByte);
                        total += BsonWriter.SizeOfByte;
                        break;
                    }

                    case BsonElementType.DateTimeUtc:
                    {
                        // consume token value
                        tokens.Pop();

                        DateTime value = (DateTime)token.Value;
                        if (value.Kind == DateTimeKind.Local)
                        {
                            // convert server-local to UTC
                            value = value.ToUniversalTime();
                        }

                        // find the duration since Jan 1, 1970
                        TimeSpan duration = value.Subtract(BsonWriter.UnixEpoch);

                        // get the total milliseconds
                        long ticks = (long)duration.TotalMilliseconds;

                        // write long data
                        writer.Write((long)ticks);
                        total += BsonWriter.SizeOfInt64;
                        break;
                    }

                    case BsonElementType.RegExp:
                    {
                        // consume token value
                        tokens.Pop();

                        Regex regex = token.Value as Regex;
                        if (regex == null)
                        {
                            goto default;
                        }

                        // default implementation is to simply return the pattern string
                        string pattern = regex.ToString();

                        // write cstring data
                        total += BsonFormatter.WriteString(writer, pattern, true);

                        bool isGlobal = false;                                 // nothing to switch on

                        string options = isGlobal ? "g" : "";
                        switch (regex.Options & (RegexOptions.IgnoreCase | RegexOptions.Multiline))
                        {
                        case RegexOptions.IgnoreCase:
                        {
                            options += "i";
                            break;
                        }

                        case RegexOptions.Multiline:
                        {
                            options += "m";
                            break;
                        }

                        case RegexOptions.IgnoreCase | RegexOptions.Multiline:
                        {
                            options += "im";
                            break;
                        }
                        }

                        // write cstring data
                        total += BsonFormatter.WriteString(writer, options, true);
                        break;
                    }

                    case BsonElementType.DBPointer:
                    {
                        // consume token value
                        tokens.Pop();

                        BsonDBPointer pointer = token.Value as BsonDBPointer;
                        if (pointer == null)
                        {
                            goto default;
                        }

                        // write string data
                        total += BsonFormatter.WriteString(writer, pointer.Namespace, false);

                        // write bytes
                        writer.Write((byte[])pointer.ObjectID);
                        total += BsonWriter.SizeOfObjectID;
                        break;
                    }

                    case BsonElementType.CodeWithScope:
                    {
                        // consume token value
                        tokens.Pop();

                        BsonCodeWithScope codews = token.Value as BsonCodeWithScope;
                        if (codews == null)
                        {
                            goto default;
                        }

                        total += this.WriteCodeWithScope(writer, codews);
                        break;
                    }

                    case BsonElementType.Int32:
                    {
                        // consume token value
                        tokens.Pop();

                        // write int data
                        writer.Write((int)token.Value);
                        total += BsonWriter.SizeOfInt32;
                        break;
                    }

                    case BsonElementType.TimeStamp:
                    case BsonElementType.Int64:
                    {
                        // consume token value
                        tokens.Pop();

                        // TODO: determine how to convert TimeStamp

                        // write long data
                        writer.Write((long)token.Value);
                        total += BsonWriter.SizeOfInt64;
                        break;
                    }

                    case BsonElementType.Undefined:
                    case BsonElementType.Null:
                    case BsonElementType.MinKey:
                    case BsonElementType.MaxKey:
                    {
                        // consume token value
                        tokens.Pop();

                        // no data emitted for these
                        break;
                    }

                    default:
                    {
                        // the rest are invalid states
                        throw new TokenException <ModelTokenType>(token,
                                                                  String.Format(BsonWriter.ErrorUnexpectedToken, token.TokenType));
                    }
                    }
                }

                return(total);
            }