XmlJsonReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Serialization / System / Runtime / Serialization / Json / XmlJsonReader.cs / 1305376 / XmlJsonReader.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.Runtime.Serialization.Json 
{
    using System.Globalization; 
    using System.IO; 
    using System.ServiceModel;
    using System.Text; 
    using System.Runtime.Serialization;
    using System.Collections.Generic;
    using System.Xml;
 
    class XmlJsonReader : XmlBaseReader, IXmlJsonReaderInitializer
    { 
        const int MaxTextChunk = 2048; 

        static byte[] charType = new byte[256] 
            {
                CharType.None, //   0 (.)
                CharType.None, //   1 (.)
                CharType.None, //   2 (.) 
                CharType.None, //   3 (.)
                CharType.None, //   4 (.) 
                CharType.None, //   5 (.) 
                CharType.None, //   6 (.)
                CharType.None, //   7 (.) 
                CharType.None, //   8 (.)
                CharType.None, //   9 (.)
                CharType.None, //   A (.)
                CharType.None, //   B (.) 
                CharType.None, //   C (.)
                CharType.None, //   D (.) 
                CharType.None, //   E (.) 
                CharType.None, //   F (.)
                CharType.None, //  10 (.) 
                CharType.None, //  11 (.)
                CharType.None, //  12 (.)
                CharType.None, //  13 (.)
                CharType.None, //  14 (.) 
                CharType.None, //  15 (.)
                CharType.None, //  16 (.) 
                CharType.None, //  17 (.) 
                CharType.None, //  18 (.)
                CharType.None, //  19 (.) 
                CharType.None, //  1A (.)
                CharType.None, //  1B (.)
                CharType.None, //  1C (.)
                CharType.None, //  1D (.) 
                CharType.None, //  1E (.)
                CharType.None, //  1F (.) 
                CharType.None, //  20 ( ) 
                CharType.None, //  21 (!)
                CharType.None, //  22 (") 
                CharType.None, //  23 (#)
                CharType.None, //  24 ($)
                CharType.None, //  25 (%)
                CharType.None, //  26 (&) 
                CharType.None, //  27 (')
                CharType.None, //  28 (() 
                CharType.None, //  29 ()) 
                CharType.None, //  2A (*)
                CharType.None, //  2B (+) 
                CharType.None, //  2C (,)
                CharType.None | CharType.Name, //  2D (-)
                CharType.None | CharType.Name, //  2E (.)
                CharType.None, //  2F (/) 
                CharType.None | CharType.Name, //  30 (0)
                CharType.None | CharType.Name, //  31 (1) 
                CharType.None | CharType.Name, //  32 (2) 
                CharType.None | CharType.Name, //  33 (3)
                CharType.None | CharType.Name, //  34 (4) 
                CharType.None | CharType.Name, //  35 (5)
                CharType.None | CharType.Name, //  36 (6)
                CharType.None | CharType.Name, //  37 (7)
                CharType.None | CharType.Name, //  38 (8) 
                CharType.None | CharType.Name, //  39 (9)
                CharType.None, //  3A (:) 
                CharType.None, //  3B (;) 
                CharType.None, //  3C (<)
                CharType.None, //  3D (=) 
                CharType.None, //  3E (>)
                CharType.None, //  3F (?)
                CharType.None, //  40 (@)
                CharType.None | CharType.FirstName | CharType.Name, //  41 (A) 
                CharType.None | CharType.FirstName | CharType.Name, //  42 (B)
                CharType.None | CharType.FirstName | CharType.Name, //  43 (C) 
                CharType.None | CharType.FirstName | CharType.Name, //  44 (D) 
                CharType.None | CharType.FirstName | CharType.Name, //  45 (E)
                CharType.None | CharType.FirstName | CharType.Name, //  46 (F) 
                CharType.None | CharType.FirstName | CharType.Name, //  47 (G)
                CharType.None | CharType.FirstName | CharType.Name, //  48 (H)
                CharType.None | CharType.FirstName | CharType.Name, //  49 (I)
                CharType.None | CharType.FirstName | CharType.Name, //  4A (J) 
                CharType.None | CharType.FirstName | CharType.Name, //  4B (K)
                CharType.None | CharType.FirstName | CharType.Name, //  4C (L) 
                CharType.None | CharType.FirstName | CharType.Name, //  4D (M) 
                CharType.None | CharType.FirstName | CharType.Name, //  4E (N)
                CharType.None | CharType.FirstName | CharType.Name, //  4F (O) 
                CharType.None | CharType.FirstName | CharType.Name, //  50 (P)
                CharType.None | CharType.FirstName | CharType.Name, //  51 (Q)
                CharType.None | CharType.FirstName | CharType.Name, //  52 (R)
                CharType.None | CharType.FirstName | CharType.Name, //  53 (S) 
                CharType.None | CharType.FirstName | CharType.Name, //  54 (T)
                CharType.None | CharType.FirstName | CharType.Name, //  55 (U) 
                CharType.None | CharType.FirstName | CharType.Name, //  56 (V) 
                CharType.None | CharType.FirstName | CharType.Name, //  57 (W)
                CharType.None | CharType.FirstName | CharType.Name, //  58 (X) 
                CharType.None | CharType.FirstName | CharType.Name, //  59 (Y)
                CharType.None | CharType.FirstName | CharType.Name, //  5A (Z)
                CharType.None, //  5B ([)
                CharType.None, //  5C (\) 
                CharType.None, //  5D (])
                CharType.None, //  5E (^) 
                CharType.None | CharType.FirstName | CharType.Name, //  5F (_) 
                CharType.None, //  60 (`)
                CharType.None | CharType.FirstName | CharType.Name, //  61 (a) 
                CharType.None | CharType.FirstName | CharType.Name, //  62 (b)
                CharType.None | CharType.FirstName | CharType.Name, //  63 (c)
                CharType.None | CharType.FirstName | CharType.Name, //  64 (d)
                CharType.None | CharType.FirstName | CharType.Name, //  65 (e) 
                CharType.None | CharType.FirstName | CharType.Name, //  66 (f)
                CharType.None | CharType.FirstName | CharType.Name, //  67 (g) 
                CharType.None | CharType.FirstName | CharType.Name, //  68 (h) 
                CharType.None | CharType.FirstName | CharType.Name, //  69 (i)
                CharType.None | CharType.FirstName | CharType.Name, //  6A (j) 
                CharType.None | CharType.FirstName | CharType.Name, //  6B (k)
                CharType.None | CharType.FirstName | CharType.Name, //  6C (l)
                CharType.None | CharType.FirstName | CharType.Name, //  6D (m)
                CharType.None | CharType.FirstName | CharType.Name, //  6E (n) 
                CharType.None | CharType.FirstName | CharType.Name, //  6F (o)
                CharType.None | CharType.FirstName | CharType.Name, //  70 (p) 
                CharType.None | CharType.FirstName | CharType.Name, //  71 (q) 
                CharType.None | CharType.FirstName | CharType.Name, //  72 (r)
                CharType.None | CharType.FirstName | CharType.Name, //  73 (s) 
                CharType.None | CharType.FirstName | CharType.Name, //  74 (t)
                CharType.None | CharType.FirstName | CharType.Name, //  75 (u)
                CharType.None | CharType.FirstName | CharType.Name, //  76 (v)
                CharType.None | CharType.FirstName | CharType.Name, //  77 (w) 
                CharType.None | CharType.FirstName | CharType.Name, //  78 (x)
                CharType.None | CharType.FirstName | CharType.Name, //  79 (y) 
                CharType.None | CharType.FirstName | CharType.Name, //  7A (z) 
                CharType.None, //  7B ({)
                CharType.None, //  7C (|) 
                CharType.None, //  7D (})
                CharType.None, //  7E (~)
                CharType.None, //  7F (.)
                CharType.None | CharType.FirstName | CharType.Name, //  80 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  81 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  82 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  83 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  84 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  85 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  86 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  87 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  88 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  89 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  8A (.)
                CharType.None | CharType.FirstName | CharType.Name, //  8B (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  8C (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  8D (.)
                CharType.None | CharType.FirstName | CharType.Name, //  8E (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  8F (.)
                CharType.None | CharType.FirstName | CharType.Name, //  90 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  91 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  92 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  93 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  94 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  95 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  96 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  97 (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  98 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  99 (.)
                CharType.None | CharType.FirstName | CharType.Name, //  9A (.)
                CharType.None | CharType.FirstName | CharType.Name, //  9B (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  9C (.)
                CharType.None | CharType.FirstName | CharType.Name, //  9D (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  9E (.) 
                CharType.None | CharType.FirstName | CharType.Name, //  9F (.)
                CharType.None | CharType.FirstName | CharType.Name, //  A0 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  A1 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  A2 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  A3 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  A4 () 
                CharType.None | CharType.FirstName | CharType.Name, //  A5 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  A6 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  A7 () 
                CharType.None | CharType.FirstName | CharType.Name, //  A8 (")
                CharType.None | CharType.FirstName | CharType.Name, //  A9 (c) 
                CharType.None | CharType.FirstName | CharType.Name, //  AA (�)
                CharType.None | CharType.FirstName | CharType.Name, //  AB (�)
                CharType.None | CharType.FirstName | CharType.Name, //  AC (�)
                CharType.None | CharType.FirstName | CharType.Name, //  AD (-) 
                CharType.None | CharType.FirstName | CharType.Name, //  AE (r)
                CharType.None | CharType.FirstName | CharType.Name, //  AF (_) 
                CharType.None | CharType.FirstName | CharType.Name, //  B0 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  B1 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  B2 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  B3 (3)
                CharType.None | CharType.FirstName | CharType.Name, //  B4 (')
                CharType.None | CharType.FirstName | CharType.Name, //  B5 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  B6 () 
                CharType.None | CharType.FirstName | CharType.Name, //  B7 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  B8 (,) 
                CharType.None | CharType.FirstName | CharType.Name, //  B9 (1) 
                CharType.None | CharType.FirstName | CharType.Name, //  BA (�)
                CharType.None | CharType.FirstName | CharType.Name, //  BB (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  BC (�)
                CharType.None | CharType.FirstName | CharType.Name, //  BD (�)
                CharType.None | CharType.FirstName | CharType.Name, //  BE (_)
                CharType.None | CharType.FirstName | CharType.Name, //  BF (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  C0 (A)
                CharType.None | CharType.FirstName | CharType.Name, //  C1 (A) 
                CharType.None | CharType.FirstName | CharType.Name, //  C2 (A) 
                CharType.None | CharType.FirstName | CharType.Name, //  C3 (A)
                CharType.None | CharType.FirstName | CharType.Name, //  C4 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  C5 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  C6 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  C7 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  C8 (E) 
                CharType.None | CharType.FirstName | CharType.Name, //  C9 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  CA (E) 
                CharType.None | CharType.FirstName | CharType.Name, //  CB (E) 
                CharType.None | CharType.FirstName | CharType.Name, //  CC (I)
                CharType.None | CharType.FirstName | CharType.Name, //  CD (I) 
                CharType.None | CharType.FirstName | CharType.Name, //  CE (I)
                CharType.None | CharType.FirstName | CharType.Name, //  CF (I)
                CharType.None | CharType.FirstName | CharType.Name, //  D0 (D)
                CharType.None | CharType.FirstName | CharType.Name, //  D1 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  D2 (O)
                CharType.None | CharType.FirstName | CharType.Name, //  D3 (O) 
                CharType.None | CharType.FirstName | CharType.Name, //  D4 (O) 
                CharType.None | CharType.FirstName | CharType.Name, //  D5 (O)
                CharType.None | CharType.FirstName | CharType.Name, //  D6 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  D7 (x)
                CharType.None | CharType.FirstName | CharType.Name, //  D8 (O)
                CharType.None | CharType.FirstName | CharType.Name, //  D9 (U)
                CharType.None | CharType.FirstName | CharType.Name, //  DA (U) 
                CharType.None | CharType.FirstName | CharType.Name, //  DB (U)
                CharType.None | CharType.FirstName | CharType.Name, //  DC (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  DD (Y) 
                CharType.None | CharType.FirstName | CharType.Name, //  DE (_)
                CharType.None | CharType.FirstName | CharType.Name, //  DF (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  E0 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  E1 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  E2 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  E3 (a) 
                CharType.None | CharType.FirstName | CharType.Name, //  E4 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  E5 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  E6 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  E7 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  E8 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  E9 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  EA (�)
                CharType.None | CharType.FirstName | CharType.Name, //  EB (�)
                CharType.None | CharType.FirstName | CharType.Name, //  EC (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  ED (�)
                CharType.None | CharType.FirstName | CharType.Name, //  EE (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  EF (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  F0 (d)
                CharType.None | CharType.FirstName | CharType.Name, //  F1 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  F2 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  F3 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  F4 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  F5 (o) 
                CharType.None | CharType.FirstName | CharType.Name, //  F6 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  F7 (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  F8 (o) 
                CharType.None | CharType.FirstName | CharType.Name, //  F9 (�)
                CharType.None | CharType.FirstName | CharType.Name, //  FA (�) 
                CharType.None | CharType.FirstName | CharType.Name, //  FB (�)
                CharType.None | CharType.FirstName | CharType.Name, //  FC (�)
                CharType.None | CharType.FirstName | CharType.Name, //  FD (y)
                CharType.None | CharType.FirstName | CharType.Name, //  FE (_) 
                CharType.None | CharType.FirstName | CharType.Name, //  FF (�)
            }; 
        bool buffered; 
        byte[] charactersToSkipOnNextRead;
        JsonComplexTextMode complexTextMode = JsonComplexTextMode.None; 
        bool expectingFirstElementInNonPrimitiveChild;
        int maxBytesPerRead;
        OnXmlDictionaryReaderClose onReaderClose;
        bool readServerTypeElement = false; 
        int scopeDepth = 0;
        JsonNodeType[] scopes; 
 
        enum JsonComplexTextMode
        { 
            QuotedText,
            NumericalText,
            None
        }; 

        public override bool CanCanonicalize 
        { 
            get
            { 
                return false;
            }
        }
 
        public override string Value
        { 
            get 
            {
                if (IsAttributeValue && !this.IsLocalName(JsonGlobals.typeString)) 
                {
                    return UnescapeJsonString(base.Value);
                }
                return base.Value; 
            }
        } 
 
        bool IsAttributeValue
        { 
            get
            {
                return (this.Node.NodeType == XmlNodeType.Attribute || this.Node is XmlAttributeTextNode);
            } 
        }
 
        bool IsReadingCollection 
        {
            get 
            {
                return ((scopeDepth > 0) && (scopes[scopeDepth] == JsonNodeType.Collection));
            }
        } 

        bool IsReadingComplexText 
        { 
            get
            { 
                return ((!this.Node.IsAtomicValue) &&
                    (this.Node.NodeType == XmlNodeType.Text));

            } 
        }
 
        public override void Close() 
        {
            base.Close(); 
            OnXmlDictionaryReaderClose onClose = this.onReaderClose;
            this.onReaderClose = null;
            ResetState();
            if (onClose != null) 
            {
                try 
                { 
                    onClose(this);
                } 
                catch (Exception e)
                {
                    if (Fx.IsFatal(e))
                    { 
                        throw;
                    } 
 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
                } 
            }
        }

        public override void EndCanonicalization() 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); 
        } 

        public override string GetAttribute(int index) 
        {
            return UnescapeJsonString(base.GetAttribute(index));
        }
 
        public override string GetAttribute(string localName, string namespaceUri)
        { 
            if (localName != JsonGlobals.typeString) 
            {
                return UnescapeJsonString(base.GetAttribute(localName, namespaceUri)); 
            }
            return base.GetAttribute(localName, namespaceUri);
        }
        public override string GetAttribute(string name) 
        {
            if (name != JsonGlobals.typeString) 
            { 
                return UnescapeJsonString(base.GetAttribute(name));
            } 
            return base.GetAttribute(name);
        }

        public override string GetAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri) 
        {
            if (XmlDictionaryString.GetString(localName) != JsonGlobals.typeString) 
            { 
                return UnescapeJsonString(base.GetAttribute(localName, namespaceUri));
            } 
            return base.GetAttribute(localName, namespaceUri);
        }

        public override bool Read() 
        {
            if (this.Node.CanMoveToElement) 
            { 
                // If we're positioned on an attribute or attribute text on an empty element, we need to move back
                // to the element in order to get the correct setting of ExitScope 
                MoveToElement();
            }

            if (this.Node.ReadState == ReadState.Closed) 
            {
                return false; 
            } 
            if (this.Node.ExitScope)
            { 
                ExitScope();
            }
            if (!buffered)
            { 
                BufferReader.SetWindow(ElementNode.BufferOffset, this.maxBytesPerRead);
            } 
 
            byte ch;
 
            // Skip whitespace before checking EOF
            // Complex text check necessary because whitespace could be part of really long
            //    quoted text that's read using multiple Read() calls.
            // This also ensures that we deal with the whitespace-only input case properly by not 
            //    floating a root element at all.
            if (!IsReadingComplexText) 
            { 
                SkipWhitespaceInBufferReader();
 
                if (TryGetByte(out ch))
                {
                    if (charactersToSkipOnNextRead[0] == ch || charactersToSkipOnNextRead[1] == ch)
                    { 
                        BufferReader.SkipByte();
                        charactersToSkipOnNextRead[0] = 0; 
                        charactersToSkipOnNextRead[1] = 0; 
                    }
                } 

                SkipWhitespaceInBufferReader();

                if (TryGetByte(out ch)) 
                {
                    if (ch == JsonGlobals.EndCollectionByte && IsReadingCollection) 
                    { 
                        BufferReader.SkipByte();
                        SkipWhitespaceInBufferReader(); 
                        ExitJsonScope();
                    }
                }
 
                if (BufferReader.EndOfFile)
                { 
                    if (scopeDepth > 0) 
                    {
                        MoveToEndElement(); 
                        return true;
                    }
                    else
                    { 
                        MoveToEndOfFile();
                        return false; 
                    } 
                }
            } 

            ch = BufferReader.GetByte();

            if (scopeDepth == 0) 
            {
                ReadNonExistentElementName(StringHandleConstStringType.Root); 
            } 
            else if (IsReadingComplexText)
            { 
                switch (complexTextMode)
                {
                    case JsonComplexTextMode.NumericalText:
                        ReadNumericalText(); 
                        break;
                    case JsonComplexTextMode.QuotedText: 
                        if (ch == (byte) '\\') 
                        {
                            ReadEscapedCharacter(true); //  moveToText 
                        }
                        else
                        {
                            ReadQuotedText(true); //  moveToText 
                        }
                        break; 
                    case JsonComplexTextMode.None: 
                        XmlExceptionHelper.ThrowXmlException(this,
                            new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char) ch))); 
                        break;
                }
            }
            else if (IsReadingCollection) 
            {
                ReadNonExistentElementName(StringHandleConstStringType.Item); 
            } 
            else if (ch == JsonGlobals.EndCollectionByte)
            { 
                BufferReader.SkipByte();
                MoveToEndElement();
                ExitJsonScope();
            } 
            else if (ch == JsonGlobals.ObjectByte)
            { 
                BufferReader.SkipByte(); 
                SkipWhitespaceInBufferReader();
                ch = (byte) BufferReader.GetByte(); 
                if (ch == JsonGlobals.EndObjectByte)
                {
                    BufferReader.SkipByte();
                    SkipWhitespaceInBufferReader(); 
                    if (TryGetByte(out ch))
                    { 
                        if (ch == JsonGlobals.MemberSeparatorByte) 
                        {
                            BufferReader.SkipByte(); 
                        }
                    }
                    else
                    { 
                        charactersToSkipOnNextRead[0] = JsonGlobals.MemberSeparatorByte;
                    } 
                    MoveToEndElement(); 
                }
                else 
                {
                    EnterJsonScope(JsonNodeType.Object);
                    ParseStartElement();
                } 
            }
            else if (ch == JsonGlobals.EndObjectByte) 
            { 
                BufferReader.SkipByte();
                if (expectingFirstElementInNonPrimitiveChild) 
                {
                    SkipWhitespaceInBufferReader();
                    ch = BufferReader.GetByte();
                    if ((ch == JsonGlobals.MemberSeparatorByte) || 
                        (ch == JsonGlobals.EndObjectByte))
                    { 
                        BufferReader.SkipByte(); 
                    }
                    else 
                    {
                        XmlExceptionHelper.ThrowXmlException(this,
                            new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter,
                            (char) ch))); 
                    }
                    expectingFirstElementInNonPrimitiveChild = false; 
                } 
                MoveToEndElement();
            } 
            else if (ch == JsonGlobals.MemberSeparatorByte)
            {
                BufferReader.SkipByte();
                MoveToEndElement(); 
            }
            else if (ch == JsonGlobals.QuoteByte) 
            { 
                if (readServerTypeElement)
                { 
                    readServerTypeElement = false;
                    EnterJsonScope(JsonNodeType.Object);
                    ParseStartElement();
                } 
                else if (this.Node.NodeType == XmlNodeType.Element)
                { 
                    if (expectingFirstElementInNonPrimitiveChild) 
                    {
                        EnterJsonScope(JsonNodeType.Object); 
                        ParseStartElement();
                    }
                    else
                    { 
                        BufferReader.SkipByte();
                        ReadQuotedText(true); //  moveToText 
                    } 
                }
                else if (this.Node.NodeType == XmlNodeType.EndElement) 
                {
                    EnterJsonScope(JsonNodeType.Element);
                    ParseStartElement();
                } 
                else
                { 
                    XmlExceptionHelper.ThrowXmlException(this, 
                        new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter,
                        JsonGlobals.QuoteChar))); 
                }
            }
            else if (ch == (byte) 'f')
            { 
                int offset;
                byte[] buffer = BufferReader.GetBuffer(5, out offset); 
                if (buffer[offset + 1] != (byte) 'a' || 
                    buffer[offset + 2] != (byte) 'l' ||
                    buffer[offset + 3] != (byte) 's' || 
                    buffer[offset + 4] != (byte) 'e')
                {
                    XmlExceptionHelper.ThrowTokenExpected(this, "false", Encoding.UTF8.GetString(buffer, offset, 5));
                } 
                BufferReader.Advance(5);
 
                if (TryGetByte(out ch)) 
                {
                    if (!IsWhitespace(ch) && ch != JsonGlobals.MemberSeparatorByte && ch != JsonGlobals.EndObjectChar && ch != JsonGlobals.EndCollectionByte) 
                    {
                        XmlExceptionHelper.ThrowTokenExpected(this, "false", Encoding.UTF8.GetString(buffer, offset, 4) + (char) ch);
                    }
                } 
                MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, 5);
            } 
            else if (ch == (byte) 't') 
            {
                int offset; 
                byte[] buffer = BufferReader.GetBuffer(4, out offset);
                if (buffer[offset + 1] != (byte) 'r' ||
                    buffer[offset + 2] != (byte) 'u' ||
                    buffer[offset + 3] != (byte) 'e') 
                {
                    XmlExceptionHelper.ThrowTokenExpected(this, "true", Encoding.UTF8.GetString(buffer, offset, 4)); 
                } 
                BufferReader.Advance(4);
 
                if (TryGetByte(out ch))
                {
                    if (!IsWhitespace(ch) && ch != JsonGlobals.MemberSeparatorByte && ch != JsonGlobals.EndObjectChar && ch != JsonGlobals.EndCollectionByte)
                    { 
                        XmlExceptionHelper.ThrowTokenExpected(this, "true", Encoding.UTF8.GetString(buffer, offset, 4) + (char) ch);
                    } 
                } 
                MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, 4);
            } 
            else if (ch == (byte) 'n')
            {
                int offset;
                byte[] buffer = BufferReader.GetBuffer(4, out offset); 
                if (buffer[offset + 1] != (byte) 'u' ||
                    buffer[offset + 2] != (byte) 'l' || 
                    buffer[offset + 3] != (byte) 'l') 
                {
                    XmlExceptionHelper.ThrowTokenExpected(this, "null", Encoding.UTF8.GetString(buffer, offset, 4)); 
                }
                BufferReader.Advance(4);
                SkipWhitespaceInBufferReader();
 
                if (TryGetByte(out ch))
                { 
                    if (ch == JsonGlobals.MemberSeparatorByte || ch == JsonGlobals.EndObjectChar) 
                    {
                        BufferReader.SkipByte(); 
                    }
                    else if (ch != JsonGlobals.EndCollectionByte)
                    {
                        XmlExceptionHelper.ThrowTokenExpected(this, "null", Encoding.UTF8.GetString(buffer, offset, 4) + (char) ch); 
                    }
                } 
                else 
                {
                    charactersToSkipOnNextRead[0] = JsonGlobals.MemberSeparatorByte; 
                    charactersToSkipOnNextRead[1] = JsonGlobals.EndObjectByte;
                }
                MoveToEndElement();
            } 
            else if ((ch == (byte) '-') ||
                (((byte) '0' <= ch) && (ch <= (byte) '9')) || 
                (ch == (byte) 'I') || 
                (ch == (byte) 'N'))
            { 
                ReadNumericalText();
            }
            else
            { 
                XmlExceptionHelper.ThrowXmlException(this,
                    new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char) ch))); 
            } 

            return true; 
        }

        public override decimal ReadContentAsDecimal()
        { 
            string value = ReadContentAsString();
            try 
            { 
                return decimal.Parse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo);
            } 
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
            } 
            catch (FormatException exception)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception)); 
            }
            catch (OverflowException exception) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "decimal", exception));
            }
        } 

        public override int ReadContentAsInt() 
        { 
            return ParseInt(ReadContentAsString(), NumberStyles.Float);
        } 

        public override long ReadContentAsLong()
        {
            string value = ReadContentAsString(); 
            try
            { 
                return long.Parse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo); 
            }
            catch (ArgumentException exception) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
            }
            catch (FormatException exception) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception)); 
            } 
            catch (OverflowException exception)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int64", exception));
            }
        }
 
        public override int ReadValueAsBase64(byte[] buffer, int offset, int count)
        { 
            if (IsAttributeValue) 
            {
                if (buffer == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
                }
                if (offset < 0) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative))); 
                } 
                if (offset > buffer.Length)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.OffsetExceedsBufferSize, buffer.Length)));
                }
                if (count < 0)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
                } 
                if (count > buffer.Length - offset) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.SizeExceedsRemainingBufferSpace, buffer.Length - offset))); 
                }

                return 0;
            } 

            return base.ReadValueAsBase64(buffer, offset, count); 
        } 

        public override int ReadValueChunk(char[] chars, int offset, int count) 
        {
            if (IsAttributeValue)
            {
                if (chars == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("chars")); 
                } 
                if (offset < 0)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative)));
                }
                if (offset > chars.Length)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.OffsetExceedsBufferSize, chars.Length)));
                } 
                if (count < 0) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.ValueMustBeNonNegative))); 
                }
                if (count > chars.Length - offset)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.SizeExceedsRemainingBufferSpace, chars.Length - offset))); 
                }
                int actual; 
 
                string value = UnescapeJsonString(this.Node.ValueAsString);
                actual = Math.Min(count, value.Length); 
                if (actual > 0)
                {
                    value.CopyTo(0, chars, offset, actual);
                    if (this.Node.QNameType == QNameType.Xmlns) 
                    {
                        this.Node.Namespace.Uri.SetValue(0, 0); 
                    } 
                    else
                    { 
                        this.Node.Value.SetValue(ValueHandleType.UTF8, 0, 0);
                    }
                }
                return actual; 
            }
 
            return base.ReadValueChunk(chars, offset, count); 
        }
 
        public void SetInput(byte[] buffer, int offset, int count, Encoding encoding, XmlDictionaryReaderQuotas quotas,
            OnXmlDictionaryReaderClose onClose)
        {
            if (buffer == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); 
            } 
            if (offset < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
            }
            if (offset > buffer.Length) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("offset", 
                    SR.GetString(SR.JsonOffsetExceedsBufferSize, buffer.Length)));
            } 
            if (count < 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
            if (count > buffer.Length - offset) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", 
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace,
                    buffer.Length - offset)));
            }
            MoveToInitial(quotas, onClose); 

            ArraySegment seg = JsonEncodingStreamWrapper.ProcessBuffer(buffer, offset, count, encoding); 
            BufferReader.SetBuffer(seg.Array, seg.Offset, seg.Count, null, null); 
            this.buffered = true;
            ResetState(); 
        }

        public void SetInput(Stream stream, Encoding encoding, XmlDictionaryReaderQuotas quotas,
            OnXmlDictionaryReaderClose onClose) 
        {
            if (stream == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream");
            } 
            MoveToInitial(quotas, onClose);

            stream = new JsonEncodingStreamWrapper(stream, encoding, true);
 
            BufferReader.SetBuffer(stream, null, null);
            this.buffered = false; 
            ResetState(); 
        }
 
        public override void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
        } 

        internal static void CheckArray(Array array, int offset, int count) 
        { 
            if (array == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("array"));
            }
            if (offset < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative)));
            } 
            if (offset > array.Length) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, array.Length))); 
            }
            if (count < 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
            if (count > array.Length - offset) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, array.Length - offset)));
            } 
        }

        protected override XmlSigningNodeWriter CreateSigningNodeWriter()
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "CreateSigningNodeWriter")));
        } 
 
        static int BreakText(byte[] buffer, int offset, int length)
        { 
            // See if we might be breaking a utf8 sequence
            if (length > 0 && (buffer[offset + length - 1] & 0x80) == 0x80)
            {
                // Find the lead char of the utf8 sequence (0x11xxxxxx) 
                int originalLength = length;
                do 
                { 
                    length--;
                } while (length > 0 && (buffer[offset + length] & 0xC0) != 0xC0); 
                // Couldn't find the lead char
                if (length == 0)
                {
                    return originalLength; // Invalid utf8 sequence - can't break 
                }
                // Count how many bytes follow the lead char 
                byte b = (byte)(buffer[offset + length] << 2); 
                int byteCount = 2;
                while ((b & 0x80) == 0x80) 
                {
                    b = (byte)(b << 1);
                    byteCount++;
                    // There shouldn't be more than 3 bytes following the lead char 
                    if (byteCount > 4)
                    { 
                        return originalLength; // Invalid utf8 sequence - can't break 
                    }
                } 
                if (length + byteCount == originalLength)
                {
                    return originalLength; // sequence fits exactly
                } 
                if (length == 0)
                { 
                    return originalLength; // Quota too small to read a char 
                }
            } 
            return length;
        }

        static int ComputeNumericalTextLength(byte[] buffer, int offset, int offsetMax) 
        {
            int beginOffset = offset; 
            while (offset < offsetMax) 
            {
                byte ch = buffer[offset]; 
                if (ch == JsonGlobals.MemberSeparatorByte || ch == JsonGlobals.EndObjectByte || ch == JsonGlobals.EndCollectionByte
                    || IsWhitespace(ch))
                {
                    break; 
                }
                offset++; 
            } 
            return offset - beginOffset;
        } 

        static int ComputeQuotedTextLengthUntilEndQuote(byte[] buffer, int offset, int offsetMax, out bool escaped)
        {
            // Assumes that for quoted text "someText", the first " has been consumed. 
            // For original text "someText", buffer passed in is someText".
            // This method returns return 8 for someText" (s, o, m, e, T, e, x, t). 
            int beginOffset = offset; 
            escaped = false;
 
            while (offset < offsetMax)
            {
                byte ch = buffer[offset];
                if (ch < 0x20) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new FormatException(SR.GetString(SR.InvalidCharacterEncountered, (char) ch))); 
                } 
                else if (ch == (byte) '\\' || ch == 0xEF)
                { 
                    escaped = true;
                    break;
                }
                else if (ch == JsonGlobals.QuoteByte) 
                {
                    break; 
                } 

                offset++; 
            }

            return offset - beginOffset;
        } 

 
        // From JSON spec: 
        // ws = *(
        //    %x20 /              ; Space 
        //    %x09 /              ; Horizontal tab
        //    %x0A /              ; Line feed or New line
        //    %x0D                ; Carriage return
        // ) 
        static bool IsWhitespace(byte ch)
        { 
            return ((ch == 0x20) || (ch == 0x09) || (ch == 0x0A) || (ch == 0x0D)); 
        }
 
        static char ParseChar(string value, NumberStyles style)
        {
            int intValue = ParseInt(value, style);
            try 
            {
                return Convert.ToChar(intValue); 
            } 
            catch (OverflowException exception)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "char", exception));
            }
        }
 
        static int ParseInt(string value, NumberStyles style)
        { 
            try 
            {
                return int.Parse(value, style, NumberFormatInfo.InvariantInfo); 
            }
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception)); 
            }
            catch (FormatException exception) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
            } 
            catch (OverflowException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value, "Int32", exception));
            } 
        }
 
        void BufferElement() 
        {
            int elementOffset = BufferReader.Offset; 
            const int byteCount = 128;
            bool done = false;
            byte quoteChar = 0;
            while (!done) 
            {
                int offset; 
                int offsetMax; 
                byte[] buffer = BufferReader.GetBuffer(byteCount, out offset, out offsetMax);
                if (offset + byteCount != offsetMax) 
                {
                    break;
                }
                for (int i = offset; i < offsetMax && !done; i++) 
                {
                    byte b = buffer[i]; 
                    if (b == '\\') 
                    {
                        i++; 
                        if (i >= offsetMax)
                        {
                            break;
                        } 
                    }
                    else if (quoteChar == 0) 
                    { 
                        if (b == (byte) '\'' || b == JsonGlobals.QuoteByte)
                        { 
                            quoteChar = b;
                        }
                        if (b == JsonGlobals.NameValueSeparatorByte)
                        { 
                            done = true;
                        } 
                    } 
                    else
                    { 
                        if (b == quoteChar)
                        {
                            quoteChar = 0;
                        } 
                    }
                } 
                BufferReader.Advance(byteCount); 
            }
            BufferReader.Offset = elementOffset; 
        }

        void EnterJsonScope(JsonNodeType currentNodeType)
        { 
            scopeDepth++;
            if (scopes == null) 
            { 
                scopes = new JsonNodeType[4];
            } 
            else if (scopes.Length == scopeDepth)
            {
                JsonNodeType[] newScopes = new JsonNodeType[scopeDepth * 2];
                Array.Copy(scopes, newScopes, scopeDepth); 
                scopes = newScopes;
            } 
            scopes[scopeDepth] = currentNodeType; 
        }
 
        JsonNodeType ExitJsonScope()
        {
            JsonNodeType nodeTypeToReturn = scopes[scopeDepth];
            scopes[scopeDepth] = JsonNodeType.None; 
            scopeDepth--;
            return nodeTypeToReturn; 
        } 

        new void MoveToEndElement() 
        {
            ExitJsonScope();
            base.MoveToEndElement();
        } 

        void MoveToInitial(XmlDictionaryReaderQuotas quotas, OnXmlDictionaryReaderClose onClose) 
        { 
            MoveToInitial(quotas);
            this.maxBytesPerRead = quotas.MaxBytesPerRead; 
            this.onReaderClose = onClose;
        }

        void ParseAndSetLocalName() 
        {
            XmlElementNode elementNode = EnterScope(); 
            elementNode.NameOffset = BufferReader.Offset; 

            do 
            {
                if (BufferReader.GetByte() == '\\')
                {
                    ReadEscapedCharacter(false); //  moveToText 
                }
                else 
                { 
                    ReadQuotedText(false); //  moveToText
                } 
            } while (complexTextMode == JsonComplexTextMode.QuotedText);

            int actualOffset = BufferReader.Offset - 1; //  -1 to ignore " at end of local name
            elementNode.LocalName.SetValue(elementNode.NameOffset, actualOffset - elementNode.NameOffset); 
            elementNode.NameLength = actualOffset - elementNode.NameOffset;
            elementNode.Namespace.Uri.SetValue(elementNode.NameOffset, 0); 
            elementNode.Prefix.SetValue(PrefixHandleType.Empty); 
            elementNode.IsEmptyElement = false;
            elementNode.ExitScope = false; 
            elementNode.BufferOffset = actualOffset;

            int currentCharacter = (int) BufferReader.GetByte(elementNode.NameOffset);
            if ((charType[currentCharacter] & CharType.FirstName) == 0) 
            {
                SetJsonNameWithMapping(elementNode); 
            } 
            else
            { 
                for (int i = 0, offset = elementNode.NameOffset; i < elementNode.NameLength; i++, offset++)
                {
                    currentCharacter = (int) BufferReader.GetByte(offset);
                    if ((charType[currentCharacter] & CharType.Name) == 0 || currentCharacter >= 0x80) 
                    {
                        SetJsonNameWithMapping(elementNode); 
                        break; 
                    }
                } 
            }
        }

        void ParseStartElement() 
        {
            if (!buffered) 
            { 
                BufferElement();
            } 

            expectingFirstElementInNonPrimitiveChild = false;

            byte ch = BufferReader.GetByte(); 
            if (ch == JsonGlobals.QuoteByte)
            { 
                BufferReader.SkipByte(); 

                ParseAndSetLocalName(); 

                SkipWhitespaceInBufferReader();
                SkipExpectedByteInBufferReader(JsonGlobals.NameValueSeparatorByte);
                SkipWhitespaceInBufferReader(); 

 
                if (BufferReader.GetByte() == JsonGlobals.ObjectByte) 
                {
                    BufferReader.SkipByte(); 
                    expectingFirstElementInNonPrimitiveChild = true;
                }
                ReadAttributes();
            } 
            else
            { 
                // " and } are the only two valid characters that may follow a { 
                XmlExceptionHelper.ThrowTokenExpected(this, "\"", (char) ch);
            } 
        }

        void ReadAttributes()
        { 
            XmlAttributeNode attribute = AddAttribute();
            attribute.LocalName.SetConstantValue(StringHandleConstStringType.Type); 
            attribute.Namespace.Uri.SetValue(0, 0); 
            attribute.Prefix.SetValue(PrefixHandleType.Empty);
 
            SkipWhitespaceInBufferReader();
            byte nextByte = BufferReader.GetByte();
            switch (nextByte)
            { 
                case JsonGlobals.QuoteByte:
                    if (!expectingFirstElementInNonPrimitiveChild) 
                    { 
                        attribute.Value.SetConstantValue(ValueHandleConstStringType.String);
                    } 
                    else
                    {
                        attribute.Value.SetConstantValue(ValueHandleConstStringType.Object);
                        ReadServerTypeAttribute(true); 
                    }
                    break; 
                case (byte) 'n': 
                    attribute.Value.SetConstantValue(ValueHandleConstStringType.Null);
                    break; 
                case (byte) 't':
                case (byte) 'f':
                    attribute.Value.SetConstantValue(ValueHandleConstStringType.Boolean);
                    break; 
                case JsonGlobals.ObjectByte:
                    attribute.Value.SetConstantValue(ValueHandleConstStringType.Object); 
                    ReadServerTypeAttribute(false); 
                    break;
                case JsonGlobals.EndObjectByte: 
                    if (expectingFirstElementInNonPrimitiveChild)
                    {
                        attribute.Value.SetConstantValue(ValueHandleConstStringType.Object);
                    } 
                    else
                    { 
                        XmlExceptionHelper.ThrowXmlException(this, 
                            new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char) nextByte)));
                    } 
                    break;
                case JsonGlobals.CollectionByte:
                    attribute.Value.SetConstantValue(ValueHandleConstStringType.Array);
                    BufferReader.SkipByte(); 
                    EnterJsonScope(JsonNodeType.Collection);
                    break; 
                default: 
                    if (nextByte == '-' ||
                        (nextByte <= '9' && nextByte >= '0') || 
                        nextByte == 'N' ||
                        nextByte == 'I')
                    {
                        attribute.Value.SetConstantValue(ValueHandleConstStringType.Number); 
                    }
                    else 
                    { 
                        XmlExceptionHelper.ThrowXmlException(this,
                            new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char) nextByte))); 
                    }
                    break;
            }
        } 

        void ReadEscapedCharacter(bool moveToText) 
        { 
            BufferReader.SkipByte();
            char ch = (char) BufferReader.GetByte(); 
            if (ch == 'u')
            {
                BufferReader.SkipByte();
                int offset; 
                byte[] buffer = BufferReader.GetBuffer(5, out offset);
                string bufferAsString = Encoding.UTF8.GetString(buffer, offset, 4); 
                BufferReader.Advance(4); 
                int charValue = ParseChar(bufferAsString, NumberStyles.HexNumber);
                if (Char.IsHighSurrogate((char) charValue)) 
                {
                    byte nextByte = BufferReader.GetByte();
                    if (nextByte == (byte) '\\')
                    { 
                        BufferReader.SkipByte();
                        SkipExpectedByteInBufferReader((byte) 'u'); 
                        buffer = BufferReader.GetBuffer(5, out offset); 
                        bufferAsString = Encoding.UTF8.GetString(buffer, offset, 4);
                        BufferReader.Advance(4); 
                        char lowChar = ParseChar(bufferAsString, NumberStyles.HexNumber);
                        if (!Char.IsLowSurrogate(lowChar))
                        {
                            XmlExceptionHelper.ThrowXmlException(this, 
                                new XmlException(System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlInvalidLowSurrogate, bufferAsString)));
                        } 
                        charValue = new SurrogateChar(lowChar, (char) charValue).Char; 
                    }
                } 

                if (buffer[offset + 4] == JsonGlobals.QuoteByte)
                {
                    BufferReader.SkipByte(); 
                    if (moveToText)
                    { 
                        MoveToAtomicText().Value.SetCharValue(charValue); 
                    }
                    complexTextMode = JsonComplexTextMode.None; 
                }
                else
                {
                    if (moveToText) 
                    {
                        MoveToComplexText().Value.SetCharValue(charValue); 
                    } 
                    complexTextMode = JsonComplexTextMode.QuotedText;
                } 
            }
            else
            {
                switch (ch) 
                {
                    case 'b': 
                        ch = '\b'; 
                        break;
                    case 'f': 
                        ch = '\f';
                        break;
                    case 'n':
                        ch = '\n'; 
                        break;
                    case 'r': 
                        ch = '\r'; 
                        break;
                    case 't': 
                        ch = '\t';
                        break;
                    case '\"':
                    case '\\': 
                    case '/':
                        // Do nothing. These are the actual unescaped values. 
                        break; 
                    default:
                        XmlExceptionHelper.ThrowXmlException(this, 
                            new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, (char) ch)));
                        break;
                }
                BufferReader.SkipByte(); 
                if (BufferReader.GetByte() == JsonGlobals.QuoteByte)
                { 
                    BufferReader.SkipByte(); 
                    if (moveToText)
                    { 
                        MoveToAtomicText().Value.SetCharValue(ch);
                    }
                    complexTextMode = JsonComplexTextMode.None;
                } 
                else
                { 
                    if (moveToText) 
                    {
                        MoveToComplexText().Value.SetCharValue(ch); 
                    }
                    complexTextMode = JsonComplexTextMode.QuotedText;
                }
            } 
        }
 
        void ReadNonExistentElementName(StringHandleConstStringType elementName) 
        {
            EnterJsonScope(JsonNodeType.Object); 
            XmlElementNode elementNode = EnterScope();
            elementNode.LocalName.SetConstantValue(elementName);
            elementNode.Namespace.Uri.SetValue(elementNode.NameOffset, 0);
            elementNode.Prefix.SetValue(PrefixHandleType.Empty); 
            elementNode.BufferOffset = BufferReader.Offset;
            elementNode.IsEmptyElement = false; 
            elementNode.ExitScope = false; 
            ReadAttributes();
        } 

        int ReadNonFFFE()
        {
            int off; 
            byte[] buff = BufferReader.GetBuffer(3, out off);
            if (buff[off + 1] == 0xBF && (buff[off + 2] == 0xBE || buff[off + 2] == 0xBF)) 
            { 
                XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.JsonInvalidFFFE)));
            } 
            return 3;
        }

        void ReadNumericalText() 
        {
            byte[] buffer; 
            int offset; 
            int offsetMax;
            int length; 

            if (buffered)
            {
                buffer = BufferReader.GetBuffer(out offset, out offsetMax); 
                length = ComputeNumericalTextLength(buffer, offset, offsetMax);
            } 
            else 
            {
                buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax); 
                length = ComputeNumericalTextLength(buffer, offset, offsetMax);
                length = BreakText(buffer, offset, length);
            }
            BufferReader.Advance(length); 

            if (offset <= offsetMax - length) 
            { 
                MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, length);
                complexTextMode = JsonComplexTextMode.None; 
            }
            else
            {
                MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, length); 
                complexTextMode = JsonComplexTextMode.NumericalText;
            } 
        } 

        void ReadQuotedText(bool moveToText) 
        {
            byte[] buffer;
            int offset;
            int offsetMax; 
            int length;
            bool escaped; 
 
            if (buffered)
            { 
                buffer = BufferReader.GetBuffer(out offset, out offsetMax);
                length = ComputeQuotedTextLengthUntilEndQuote(buffer, offset, offsetMax, out escaped);
            }
            else 
            {
                buffer = BufferReader.GetBuffer(MaxTextChunk, out offset, out offsetMax); 
                length = ComputeQuotedTextLengthUntilEndQuote(buffer, offset, offsetMax, out escaped); 
                length = BreakText(buffer, offset, length);
            } 

            if (escaped && BufferReader.GetByte() == 0xEF)
            {
                offset = BufferReader.Offset; 
                length = ReadNonFFFE();
            } 
 
            BufferReader.Advance(length);
 

            if (!escaped && (offset < offsetMax - length))
            {
                if (moveToText) 
                {
                    MoveToAtomicText().Value.SetValue(ValueHandleType.UTF8, offset, length); 
                } 
                SkipExpectedByteInBufferReader(JsonGlobals.QuoteByte);
                complexTextMode = JsonComplexTextMode.None; 
            }
            else
            {
                if ((length == 0) && escaped) 
                {
                    ReadEscapedCharacter(moveToText); 
                } 
                else
                { 
                    if (moveToText)
                    {
                        MoveToComplexText().Value.SetValue(ValueHandleType.UTF8, offset, length);
                    } 
                    complexTextMode = JsonComplexTextMode.QuotedText;
                } 
            } 
        }
 
        void ReadServerTypeAttribute(bool consumedObjectChar)
        {
            int offset;
            int offsetMax; 
            int correction = consumedObjectChar ? -1 : 0;
            byte[] buffer = BufferReader.GetBuffer(9 + correction, out offset, out offsetMax); 
            if (offset + 9 + correction <= offsetMax) 
            {
                if (buffer[offset + correction + 1] == (byte) '\"' && 
                    buffer[offset + correction + 2] == (byte) '_' &&
                    buffer[offset + correction + 3] == (byte) '_' &&
                    buffer[offset + correction + 4] == (byte) 't' &&
                    buffer[offset + correction + 5] == (byte) 'y' && 
                    buffer[offset + correction + 6] == (byte) 'p' &&
                    buffer[offset + correction + 7] == (byte) 'e' && 
                    buffer[offset + correction + 8] == (byte) '\"') 
                {
                    XmlAttributeNode attribute = AddAttribute(); 

                    attribute.LocalName.SetValue(offset + 2 + correction, 6);
                    attribute.Namespace.Uri.SetValue(0, 0);
                    attribute.Prefix.SetValue(PrefixHandleType.Empty); 
                    BufferReader.Advance(9 + correction);
 
                    if (!buffered) 
                    {
                        BufferElement(); 
                    }

                    SkipWhitespaceInBufferReader();
                    SkipExpectedByteInBufferReader(JsonGlobals.NameValueSeparatorByte); 
                    SkipWhitespaceInBufferReader();
                    SkipExpectedByteInBufferReader(JsonGlobals.QuoteByte); 
 
                    buffer = BufferReader.GetBuffer(out offset, out offsetMax);
 
                    do
                    {
                        if (BufferReader.GetByte() == '\\')
                        { 
                            ReadEscapedCharacter(false); //  moveToText
                        } 
                        else 
                        {
                            ReadQuotedText(false); //  moveToText 
                        }
                    } while (complexTextMode == JsonComplexTextMode.QuotedText);

                    attribute.Value.SetValue(ValueHandleType.UTF8, offset, BufferReader.Offset - 1 - offset); 

                    SkipWhitespaceInBufferReader(); 
 
                    if (BufferReader.GetByte() == JsonGlobals.MemberSeparatorByte)
                    { 
                        BufferReader.SkipByte();
                        readServerTypeElement = true;
                    }
                    else if (BufferReader.GetByte() == JsonGlobals.EndObjectByte) 
                    {
                        BufferReader.SkipByte(); 
                        readServerTypeElement = false; 
                        expectingFirstElementInNonPrimitiveChild = false;
                    } 
                    else
                    {
                        readServerTypeElement = true;
                    } 

                } 
            } 
        }
 
        void ResetState()
        {
            complexTextMode = JsonComplexTextMode.None;
            expectingFirstElementInNonPrimitiveChild = false; 
            charactersToSkipOnNextRead = new byte[2];
            scopeDepth = 0; 
            if ((scopes != null) && (scopes.Length > JsonGlobals.maxScopeSize)) 
            {
                scopes = null; 
            }
        }

        void SetJsonNameWithMapping(XmlElementNode elementNode) 
        {
            Namespace ns = AddNamespace(); 
            ns.Prefix.SetValue(PrefixHandleType.A); 
            ns.Uri.SetConstantValue(StringHandleConstStringType.Item);
            AddXmlnsAttribute(ns); 

            XmlAttributeNode attribute = AddAttribute();
            attribute.LocalName.SetConstantValue(StringHandleConstStringType.Item);
            attribute.Namespace.Uri.SetValue(0, 0); 
            attribute.Prefix.SetValue(PrefixHandleType.Empty);
            attribute.Value.SetValue(ValueHandleType.UTF8, elementNode.NameOffset, elementNode.NameLength); 
 
            elementNode.NameLength = 0;
            elementNode.Prefix.SetValue(PrefixHandleType.A); 
            elementNode.LocalName.SetConstantValue(StringHandleConstStringType.Item);
            elementNode.Namespace = ns;
        }
 
        void SkipExpectedByteInBufferReader(byte characterToSkip)
        { 
            if (BufferReader.GetByte() != characterToSkip) 
            {
                XmlExceptionHelper.ThrowTokenExpected(this, ((char) characterToSkip).ToString(), (char) BufferReader.GetByte()); 
            }
            BufferReader.SkipByte();
        }
 
        void SkipWhitespaceInBufferReader()
        { 
            byte ch; 
            while (TryGetByte(out ch) && IsWhitespace(ch))
            { 
                BufferReader.SkipByte();
            }
        }
 
        bool TryGetByte(out byte ch)
        { 
            int offset, offsetMax; 
            byte[] buffer = BufferReader.GetBuffer(1, out offset, out offsetMax);
 
            if (offset < offsetMax)
            {
                ch = buffer[offset];
                return true; 
            }
            else 
            { 
                ch = (byte) '\0';
                return false; 
            }
        }

        string UnescapeJsonString(string val) 
        {
            if (val == null) 
            { 
                return null;
            } 

            StringBuilder sb = null;
            int startIndex = 0, count = 0;
            for (int i = 0; i < val.Length; i++) 
            {
                if (val[i] == '\\') 
                { 
                    i++;
                    if (sb == null) 
                    {
                        sb = new StringBuilder();
                    }
                    sb.Append(val, startIndex, count); 
                    Fx.Assert(i < val.Length, "Found that an '\' was the last character in a string. ReadServerTypeAttriute validates that the escape sequence is valid when it calls ReadQuotedText and ReadEscapedCharacter");
                    if (i >= val.Length) 
                    { 
                        XmlExceptionHelper.ThrowXmlException(this, new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, val[i])));
                    } 
                    switch (val[i])
                    {
                        case '"':
                        case '\'': 
                        case '/':
                        case '\\': 
                            sb.Append(val[i]); 
                            break;
                        case 'b': 
                            sb.Append('\b');
                            break;
                        case 'f':
                            sb.Append('\f'); 
                            break;
                        case 'n': 
                            sb.Append('\n'); 
                            break;
                        case 'r': 
                            sb.Append('\r');
                            break;
                        case 't':
                            sb.Append('\t'); 
                            break;
                        case 'u': 
                            if ((i + 3) >= val.Length) 
                            {
                                XmlExceptionHelper.ThrowXmlException(this, 
                                    new XmlException(SR.GetString(SR.JsonEncounteredUnexpectedCharacter, val[i])));
                            }
                            sb.Append(ParseChar(val.Substring(i + 1, 4), NumberStyles.HexNumber));
                            i += 4; 
                            break;
                    } 
                    startIndex = i + 1; 
                    count = 0;
                } 
                else
                {
                    count++;
                } 
            }
            if (sb == null) 
            { 
                return val;
            } 
            if (count > 0)
            {
                sb.Append(val, startIndex, count);
            } 

            return sb.ToString(); 
        } 

        static class CharType 
        {
            public const byte FirstName = 0x01;
            public const byte Name = 0x02;
            public const byte None = 0x00; 
        }
    } 
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK