XmlJsonWriter.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

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

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

namespace System.Runtime.Serialization.Json 
{
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization; 
    using System.IO;
    using System.Runtime; 
    using System.Runtime.Serialization;
    using System.Security;
    using System.ServiceModel;
    using System.Text; 
    using System.Xml;
 
    class XmlJsonWriter : XmlDictionaryWriter, IXmlJsonWriterInitializer 
    {
        const char BACK_SLASH = '\\'; 
        const char FORWARD_SLASH = '/';

        const char HIGH_SURROGATE_START = (char) 0xd800;
        const char LOW_SURROGATE_END = (char) 0xdfff; 
        const char MAX_CHAR = (char) 0xfffe;
        const char WHITESPACE = ' '; 
        const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 
        const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/";
 
        [Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        [SecurityCritical]
        static BinHexEncoding binHexEncoding; 

        string attributeText; 
        JsonDataType dataType; 
        int depth;
        bool endElementBuffer; 
        bool isWritingDataTypeAttribute;
        bool isWritingServerTypeAttribute;
        bool isWritingXmlnsAttribute;
        bool isWritingXmlnsAttributeDefaultNs; 
        NameState nameState;
        JsonNodeType nodeType; 
        JsonNodeWriter nodeWriter; 
        JsonNodeType[] scopes;
        string serverTypeValue; 
        // Do not use this field's value anywhere other than the WriteState property.
        // It's OK to set this field's value anywhere and then change the WriteState property appropriately.
        // If it's necessary to check the WriteState outside WriteState, use the WriteState property.
        WriteState writeState; 
        bool wroteServerTypeAttribute;
 
        public XmlJsonWriter() 
        {
            InitializeWriter(); 
        }

        enum JsonDataType
        { 
            None,
            Null, 
            Boolean, 
            Number,
            String, 
            Object,
            Array
        };
 
        [Flags]
        enum NameState 
        { 
            None = 0,
            IsWritingNameWithMapping = 1, 
            IsWritingNameAttribute = 2,
            WrittenNameWithMapping = 4,
        }
 
        public override XmlWriterSettings Settings
        { 
            // The XmlWriterSettings object used to create this writer instance. 
            // If this writer was not created using the Create method, this property
            // returns a null reference. 
            get { return null; }
        }

        public override WriteState WriteState 
        {
            get 
            { 
                if (writeState == WriteState.Closed)
                { 
                    return WriteState.Closed;
                }
                if (HasOpenAttribute)
                { 
                    return WriteState.Attribute;
                } 
                switch (nodeType) 
                {
                    case JsonNodeType.None: 
                        return WriteState.Start;
                    case JsonNodeType.Element:
                        return WriteState.Element;
                    case JsonNodeType.QuotedText: 
                    case JsonNodeType.StandaloneText:
                    case JsonNodeType.EndElement: 
                        return WriteState.Content; 
                    default:
                        return WriteState.Error; 
                }
            }
        }
 
        public override string XmlLang
        { 
            get { return null; } 
        }
 
        public override XmlSpace XmlSpace
        {
            get { return XmlSpace.None; }
        } 

        static BinHexEncoding BinHexEncoding 
        { 
            [Fx.Tag.SecurityNote(Critical = "Fetches the critical binHexEncoding field.",
                Safe = "Get-only properties only need to be protected for write; initialized in getter if null.")] 
            [SecuritySafeCritical]
            get
            {
                if (binHexEncoding == null) 
                {
                    binHexEncoding = new BinHexEncoding(); 
                } 
                return binHexEncoding;
            } 
        }

        bool HasOpenAttribute
        { 
            get
            { 
                return (isWritingDataTypeAttribute || isWritingServerTypeAttribute || IsWritingNameAttribute || isWritingXmlnsAttribute); 
            }
        } 

        bool IsClosed
        {
            get { return (WriteState == WriteState.Closed); } 
        }
 
        bool IsWritingCollection 
        {
            get { return (depth > 0) && (scopes[depth] == JsonNodeType.Collection); } 
        }

        bool IsWritingNameAttribute
        { 
            get { return (nameState & NameState.IsWritingNameAttribute) == NameState.IsWritingNameAttribute; }
        } 
 
        bool IsWritingNameWithMapping
        { 
            get { return (nameState & NameState.IsWritingNameWithMapping) == NameState.IsWritingNameWithMapping; }
        }

        bool WrittenNameWithMapping 
        {
            get { return (nameState & NameState.WrittenNameWithMapping) == NameState.WrittenNameWithMapping; } 
        } 

        public override void Close() 
        {
            if (!IsClosed)
            {
                try 
                {
                    WriteEndDocument(); 
                } 
                finally
                { 
                    try
                    {
                        nodeWriter.Flush();
                        nodeWriter.Close(); 
                    }
                    finally 
                    { 
                        writeState = WriteState.Closed;
                        if (depth != 0) 
                        {
                            depth = 0;
                        }
                    } 
                }
            } 
        } 

        public override void Flush() 
        {
            if (IsClosed)
            {
                ThrowClosed(); 
            }
            nodeWriter.Flush(); 
        } 

        public override string LookupPrefix(string ns) 
        {
            if (ns == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns"); 
            }
            if (ns == Globals.XmlnsNamespace) 
            { 
                return Globals.XmlnsPrefix;
            } 
            if (ns == xmlNamespace)
            {
                return JsonGlobals.xmlPrefix;
            } 
            if (ns == string.Empty)
            { 
                return string.Empty; 
            }
            return null; 
        }

        public void SetOutput(Stream stream, Encoding encoding, bool ownsStream)
        { 
            if (stream == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream"); 
            }
            if (encoding == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding");
            }
            if (encoding.WebName != Encoding.UTF8.WebName) 
            {
                stream = new JsonEncodingStreamWrapper(stream, encoding, false); 
            } 
            else
            { 
                encoding = null;
            }
            if (nodeWriter == null)
            { 
                nodeWriter = new JsonNodeWriter();
            } 
 
            nodeWriter.SetOutput(stream, ownsStream, encoding);
            InitializeWriter(); 
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, bool[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, Int16[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, Int32[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, Int64[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, float[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, double[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, DateTime[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, Guid[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, int[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, long[] array, int offset, int count) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, short[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteBase64(byte[] buffer, int index, int count) 
        {
            if (buffer == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does.
            if (index < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            } 

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            } 
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            }

            StartText(); 
            nodeWriter.WriteBase64Text(buffer, 0, buffer, index, count);
        } 
 
        public override void WriteBinHex(byte[] buffer, int index, int count)
        { 
            if (buffer == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does. 
            if (index < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative)));
            }

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
            if (count > buffer.Length - index) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            } 
 
            StartText();
            WriteEscapedJsonString(BinHexEncoding.GetString(buffer, index, count)); 
        }

        public override void WriteCData(string text)
        { 
            WriteString(text);
        } 
 
        public override void WriteCharEntity(char ch)
        { 
            WriteString(ch.ToString());
        }

        public override void WriteChars(char[] buffer, int index, int count) 
        {
            if (buffer == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does.
            if (index < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            } 

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            } 
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            }

            WriteString(new string(buffer, index, count)); 
        }
 
        public override void WriteComment(string text) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteComment"))); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2#sysid", Justification = "This method is derived from the base")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1#pubid", Justification = "This method is derived from the base")] 
        public override void WriteDocType(string name, string pubid, string sysid, string subset)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteDocType"))); 
        }
 
        public override void WriteEndAttribute()
        {
            if (IsClosed)
            { 
                ThrowClosed();
            } 
            if (!HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonNoMatchingStartAttribute)));
            }

            Fx.Assert(!(isWritingDataTypeAttribute && isWritingServerTypeAttribute), 
                "Can not write type attribute and __type attribute at the same time.");
 
            if (isWritingDataTypeAttribute) 
            {
                switch (attributeText) 
                {
                    case JsonGlobals.numberString:
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.numberString); 
                            dataType = JsonDataType.Number;
                            break; 
                        } 
                    case JsonGlobals.stringString:
                        { 
                            ThrowIfServerTypeWritten(JsonGlobals.stringString);
                            dataType = JsonDataType.String;
                            break;
                        } 
                    case JsonGlobals.arrayString:
                        { 
                            ThrowIfServerTypeWritten(JsonGlobals.arrayString); 
                            dataType = JsonDataType.Array;
                            break; 
                        }
                    case JsonGlobals.objectString:
                        {
                            dataType = JsonDataType.Object; 
                            break;
                        } 
                    case JsonGlobals.nullString: 
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.nullString); 
                            dataType = JsonDataType.Null;
                            break;
                        }
                    case JsonGlobals.booleanString: 
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.booleanString); 
                            dataType = JsonDataType.Boolean; 
                            break;
                        } 
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new XmlException(SR.GetString(SR.JsonUnexpectedAttributeValue, attributeText)));
                } 

                attributeText = null; 
                isWritingDataTypeAttribute = false; 

                if (!IsWritingNameWithMapping || WrittenNameWithMapping) 
                {
                    WriteDataTypeServerType();
                }
            } 
            else if (isWritingServerTypeAttribute)
            { 
                serverTypeValue = attributeText; 
                attributeText = null;
                isWritingServerTypeAttribute = false; 

                // we are writing __type after type="object" (enforced by WSE)
                if ((!IsWritingNameWithMapping || WrittenNameWithMapping) && dataType == JsonDataType.Object)
                { 
                    WriteServerTypeAttribute();
                } 
            } 
            else if (IsWritingNameAttribute)
            { 
                WriteJsonElementName(attributeText);
                attributeText = null;
                nameState = NameState.IsWritingNameWithMapping | NameState.WrittenNameWithMapping;
                WriteDataTypeServerType(); 
            }
            else if (isWritingXmlnsAttribute) 
            { 
                if (!string.IsNullOrEmpty(attributeText) && isWritingXmlnsAttributeDefaultNs)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, attributeText));
                }

                attributeText = null; 
                isWritingXmlnsAttribute = false;
                isWritingXmlnsAttributeDefaultNs = false; 
            } 
        }
 
        public override void WriteEndDocument()
        {
            if (IsClosed)
            { 
                ThrowClosed();
            } 
            if (nodeType != JsonNodeType.None) 
            {
                while (depth > 0) 
                {
                    WriteEndElement();
                }
            } 
        }
 
        public override void WriteEndElement() 
        {
            if (IsClosed) 
            {
                ThrowClosed();
            }
 
            if (depth == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonEndElementNoOpenNodes)));
            } 
            if (HasOpenAttribute)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteEndElement"))); 
            }
 
            endElementBuffer = false; 

            JsonNodeType token = ExitScope(); 
            if (token == JsonNodeType.Collection)
            {
                nodeWriter.WriteText(JsonGlobals.EndCollectionChar);
                token = ExitScope(); 
            }
            else if (nodeType == JsonNodeType.QuotedText) 
            { 
                // For writing "
                WriteJsonQuote(); 
            }
            else if (nodeType == JsonNodeType.Element)
            {
                if ((dataType == JsonDataType.None) && (serverTypeValue != null)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonMustSpecifyDataType, 
                        JsonGlobals.typeString, JsonGlobals.objectString, JsonGlobals.serverTypeString)));
                } 

                if (IsWritingNameWithMapping && !WrittenNameWithMapping)
                {
                    // Ending  without writing item attribute 
                    // Not providing a better error message because localization deadline has passed.
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonMustSpecifyDataType, 
                        JsonGlobals.itemString, string.Empty, JsonGlobals.itemString)));
                } 

                // the element is empty, it does not have any content,
                if ((dataType == JsonDataType.None) ||
                    (dataType == JsonDataType.String)) 
                {
                    nodeWriter.WriteText(JsonGlobals.QuoteChar); 
                    nodeWriter.WriteText(JsonGlobals.QuoteChar); 
                }
            } 
            else
            {
                // Assert on only StandaloneText and EndElement because preceding if
                //    conditions take care of checking for QuotedText and Element. 
                Fx.Assert((nodeType == JsonNodeType.StandaloneText) || (nodeType == JsonNodeType.EndElement),
                    "nodeType has invalid value " + nodeType + ". Expected it to be QuotedText, Element, StandaloneText, or EndElement."); 
            } 
            if (depth != 0)
            { 
                if (token == JsonNodeType.Element)
                {
                    endElementBuffer = true;
                } 
                else if (token == JsonNodeType.Object)
                { 
                    nodeWriter.WriteText(JsonGlobals.EndObjectChar); 
                    if ((depth > 0) && scopes[depth] == JsonNodeType.Element)
                    { 
                        ExitScope();
                        endElementBuffer = true;
                    }
                } 
            }
 
            dataType = JsonDataType.None; 
            nodeType = JsonNodeType.EndElement;
            nameState = NameState.None; 
            wroteServerTypeAttribute = false;
        }

        public override void WriteEntityRef(string name) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteEntityRef"))); 
        } 

        public override void WriteFullEndElement() 
        {
            WriteEndElement();
        }
 
        public override void WriteProcessingInstruction(string name, string text)
        { 
            if (IsClosed) 
            {
                ThrowClosed(); 
            }

            if (!name.Equals("xml", StringComparison.OrdinalIgnoreCase))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.JsonXmlProcessingInstructionNotSupported), "name"));
            } 
 
            if (WriteState != WriteState.Start)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonXmlInvalidDeclaration)));
            }
        }
 
        public override void WriteQualifiedName(string localName, string ns)
        { 
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName"); 
            }
            if (localName.Length == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", 
                    SR.GetString(SR.JsonInvalidLocalNameEmpty));
            } 
            if (ns == null) 
            {
                ns = string.Empty; 
            }

            base.WriteQualifiedName(localName, ns);
        } 

        public override void WriteRaw(string data) 
        { 
            WriteString(data);
        } 

        public override void WriteRaw(char[] buffer, int index, int count)
        {
            if (buffer == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); 
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does. 
            if (index < 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
 
            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            }
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", 
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            } 

            WriteString(new string(buffer, index, count));
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] // [....], ToLowerInvariant is just used in Json error message
        public override void WriteStartAttribute(string prefix, string localName, string ns) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }
            if (!string.IsNullOrEmpty(prefix))
            { 
                if (IsWritingNameWithMapping && prefix == JsonGlobals.xmlnsPrefix)
                { 
                    if (ns != null && ns != xmlnsNamespace) 
                    {
                        throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlPrefixBoundToNamespace, "xmlns", xmlnsNamespace, ns), "ns")); 
                    }
                }
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("prefix", SR.GetString(SR.JsonPrefixMustBeNullOrEmpty, prefix));
                } 
            } 
            else
            { 
                if (IsWritingNameWithMapping && ns == xmlnsNamespace && localName != JsonGlobals.xmlnsPrefix)
                {
                    prefix = JsonGlobals.xmlnsPrefix;
                } 
            }
            if (!string.IsNullOrEmpty(ns)) 
            { 
                if (IsWritingNameWithMapping && ns == xmlnsNamespace)
                { 
                    prefix = JsonGlobals.xmlnsPrefix;
                }
                else if (string.IsNullOrEmpty(prefix) && localName == JsonGlobals.xmlnsPrefix && ns == xmlnsNamespace)
                { 
                    prefix = JsonGlobals.xmlnsPrefix;
                    isWritingXmlnsAttributeDefaultNs = true; 
                } 
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, ns));
                }
            }
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName"); 
            } 
            if (localName.Length == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", SR.GetString(SR.JsonInvalidLocalNameEmpty));
            }
            if ((nodeType != JsonNodeType.Element) && !wroteServerTypeAttribute)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonAttributeMustHaveElement)));
            } 
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteStartAttribute")));
            }
            if (prefix == JsonGlobals.xmlnsPrefix)
            { 
                isWritingXmlnsAttribute = true;
            } 
            else if (localName == JsonGlobals.typeString) 
            {
                if (dataType != JsonDataType.None) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.typeString)));
                } 

                isWritingDataTypeAttribute = true; 
            } 
            else if (localName == JsonGlobals.serverTypeString)
            { 
                if (serverTypeValue != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.serverTypeString))); 
                }
 
                if ((dataType != JsonDataType.None) && (dataType != JsonDataType.Object)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonServerTypeSpecifiedForInvalidDataType,
                        JsonGlobals.serverTypeString, JsonGlobals.typeString, dataType.ToString().ToLowerInvariant(), JsonGlobals.objectString)));
                }
 
                isWritingServerTypeAttribute = true;
            } 
            else if (localName == JsonGlobals.itemString) 
            {
                if (WrittenNameWithMapping) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.itemString)));
                } 

                if (!IsWritingNameWithMapping) 
                { 
                    // Don't write attribute with local name "item" if  element is not open.
                    // Not providing a better error message because localization deadline has passed. 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEndElementNoOpenNodes)));
                }
 
                nameState |= NameState.IsWritingNameAttribute;
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", SR.GetString(SR.JsonUnexpectedAttributeLocalName, localName)); 
            }
        }

        public override void WriteStartDocument(bool standalone) 
        {
            // In XML, writes the XML declaration with the version "1.0" and the standalone attribute. 
            WriteStartDocument(); 
        }
 
        public override void WriteStartDocument()
        {
            // In XML, writes the XML declaration with the version "1.0".
            if (IsClosed) 
            {
                ThrowClosed(); 
            } 
            if (WriteState != WriteState.Start)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(
                    SR.GetString(SR.JsonInvalidWriteState, "WriteStartDocument", WriteState.ToString())));
            } 
        }
 
        public override void WriteStartElement(string prefix, string localName, string ns) 
        {
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName");
            }
            if (localName.Length == 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", 
                    SR.GetString(SR.JsonInvalidLocalNameEmpty)); 
            }
            if (!string.IsNullOrEmpty(prefix)) 
            {
                if (string.IsNullOrEmpty(ns) || !TrySetWritingNameWithMapping(localName, ns))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("prefix", SR.GetString(SR.JsonPrefixMustBeNullOrEmpty, prefix)); 
                }
            } 
            if (!string.IsNullOrEmpty(ns)) 
            {
                if (!TrySetWritingNameWithMapping(localName, ns)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, ns));
                }
            } 
            if (IsClosed)
            { 
                ThrowClosed(); 
            }
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteStartElement")));
            } 
            if ((nodeType != JsonNodeType.None) && depth == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMultipleRootElementsNotAllowedOnWriter)));
            } 

            switch (nodeType)
            {
                case JsonNodeType.None: 
                    {
                        if (!localName.Equals(JsonGlobals.rootString)) 
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new XmlException(SR.GetString(SR.JsonInvalidRootElementName, localName, JsonGlobals.rootString))); 
                        }
                        EnterScope(JsonNodeType.Element);
                        break;
                    } 
                case JsonNodeType.Element:
                    { 
                        if ((dataType != JsonDataType.Array) && (dataType != JsonDataType.Object)) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                new XmlException(SR.GetString(SR.JsonNodeTypeArrayOrObjectNotSpecified)));
                        }
                        if (!IsWritingCollection)
                        { 
                            if (nameState != NameState.IsWritingNameWithMapping)
                            { 
                                WriteJsonElementName(localName); 
                            }
                        } 
                        else if (!localName.Equals(JsonGlobals.itemString))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new XmlException(SR.GetString(SR.JsonInvalidItemNameForArrayElement, localName, JsonGlobals.itemString))); 
                        }
                        EnterScope(JsonNodeType.Element); 
                        break; 
                    }
                case JsonNodeType.EndElement: 
                    {
                        if (endElementBuffer)
                        {
                            nodeWriter.WriteText(JsonGlobals.MemberSeparatorChar); 
                        }
                        if (!IsWritingCollection) 
                        { 
                            if (nameState != NameState.IsWritingNameWithMapping)
                            { 
                                WriteJsonElementName(localName);
                            }
                        }
                        else if (!localName.Equals(JsonGlobals.itemString)) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                new XmlException(SR.GetString(SR.JsonInvalidItemNameForArrayElement, localName, JsonGlobals.itemString))); 
                        }
                        EnterScope(JsonNodeType.Element); 
                        break;
                    }
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonInvalidStartElementCall)));
            } 
 
            isWritingDataTypeAttribute = false;
            isWritingServerTypeAttribute = false; 
            isWritingXmlnsAttribute = false;
            wroteServerTypeAttribute = false;
            serverTypeValue = null;
            dataType = JsonDataType.None; 
            nodeType = JsonNodeType.Element;
        } 
 
        public override void WriteString(string text)
        { 
            if (HasOpenAttribute && (text != null))
            {
                attributeText += text;
            } 
            else
            { 
                if (text == null) 
                {
                    text = string.Empty; 
                }

                // do work only when not indenting whitespaces
                if (!((this.dataType == JsonDataType.Array || this.dataType == JsonDataType.Object || this.nodeType == JsonNodeType.EndElement) && XmlConverter.IsWhitespace(text))) 
                {
                    StartText(); 
                    WriteEscapedJsonString(text); 
                }
            } 
        }

        public override void WriteSurrogateCharEntity(char lowChar, char highChar)
        { 
            WriteString(string.Concat(highChar, lowChar));
        } 
 
        public override void WriteValue(bool value)
        { 
            StartText();
            nodeWriter.WriteBoolText(value);
        }
 
        public override void WriteValue(decimal value)
        { 
            StartText(); 
            nodeWriter.WriteDecimalText(value);
        } 

        public override void WriteValue(double value)
        {
            StartText(); 
            nodeWriter.WriteDoubleText(value);
        } 
 
        public override void WriteValue(float value)
        { 
            StartText();
            nodeWriter.WriteFloatText(value);
        }
 
        public override void WriteValue(int value)
        { 
            StartText(); 
            nodeWriter.WriteInt32Text(value);
        } 

        public override void WriteValue(long value)
        {
            StartText(); 
            nodeWriter.WriteInt64Text(value);
        } 
 
        public override void WriteValue(Guid value)
        { 
            StartText();
            nodeWriter.WriteGuidText(value);
        }
 
        public override void WriteValue(DateTime value)
        { 
            StartText(); 
            nodeWriter.WriteDateTimeText(value);
        } 

        public override void WriteValue(string value)
        {
            WriteString(value); 
        }
 
        public override void WriteValue(TimeSpan value) 
        {
            StartText(); 
            nodeWriter.WriteTimeSpanText(value);
        }

        public override void WriteValue(UniqueId value) 
        {
            if (value == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
            } 

            StartText();
            nodeWriter.WriteUniqueIdText(value);
        } 

        public override void WriteValue(object value) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }

            if (value == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); 
            } 

            if (value is Array) 
            {
                WriteValue((Array) value);
            }
            else if (value is IStreamProvider) 
            {
                WriteValue((IStreamProvider) value); 
            } 
            else
            { 
                WritePrimitiveValue(value);
            }
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Whitespace", Justification = "This method is derived from the base")]
        public override void WriteWhitespace(string ws) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }
            if (ws == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ws");
            } 
 
            for (int i = 0; i < ws.Length; ++i)
            { 
                char c = ws[i];
                if (c != ' ' &&
                    c != '\t' &&
                    c != '\n' && 
                    c != '\r')
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ws", 
                        SR.GetString(SR.JsonOnlyWhitespace, c.ToString(), "WriteWhitespace"));
                } 
            }

            WriteString(ws);
        } 

        public override void WriteXmlAttribute(string localName, string value) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlAttribute")));
        } 

        public override void WriteXmlAttribute(XmlDictionaryString localName, XmlDictionaryString value)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlAttribute"))); 
        }
 
        public override void WriteXmlnsAttribute(string prefix, string namespaceUri) 
        {
            if (!IsWritingNameWithMapping) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlnsAttribute")));
            }
        } 

        public override void WriteXmlnsAttribute(string prefix, XmlDictionaryString namespaceUri) 
        { 
            if (!IsWritingNameWithMapping)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlnsAttribute")));
            }
        }
 
        internal static bool CharacterNeedsEscaping(char ch)
        { 
            return (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar || ch < WHITESPACE || ch == BACK_SLASH 
                || (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR)));
        } 


        static void ThrowClosed()
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                new InvalidOperationException(SR.GetString(SR.JsonWriterClosed))); 
        } 

        void CheckText(JsonNodeType nextNodeType) 
        {
            if (IsClosed)
            {
                ThrowClosed(); 
            }
            if (depth == 0) 
            { 
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException( 
                    System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlIllegalOutsideRoot)));
            }

            if ((nextNodeType == JsonNodeType.StandaloneText) && 
                (nodeType == JsonNodeType.QuotedText))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(
                    SR.GetString(SR.JsonCannotWriteStandaloneTextAfterQuotedText))); 
            }
        }

        void EnterScope(JsonNodeType currentNodeType) 
        {
            depth++; 
            if (scopes == null) 
            {
                scopes = new JsonNodeType[4]; 
            }
            else if (scopes.Length == depth)
            {
                JsonNodeType[] newScopes = new JsonNodeType[depth * 2]; 
                Array.Copy(scopes, newScopes, depth);
                scopes = newScopes; 
            } 
            scopes[depth] = currentNodeType;
        } 

        JsonNodeType ExitScope()
        {
            JsonNodeType nodeTypeToReturn = scopes[depth]; 
            scopes[depth] = JsonNodeType.None;
            depth--; 
            return nodeTypeToReturn; 
        }
 
        void InitializeWriter()
        {
            nodeType = JsonNodeType.None;
            dataType = JsonDataType.None; 
            isWritingDataTypeAttribute = false;
            wroteServerTypeAttribute = false; 
            isWritingServerTypeAttribute = false; 
            serverTypeValue = null;
            attributeText = null; 

            if (depth != 0)
            {
                depth = 0; 
            }
            if ((scopes != null) && (scopes.Length > JsonGlobals.maxScopeSize)) 
            { 
                scopes = null;
            } 

            // Can't let writeState be at Closed if reinitializing.
            writeState = WriteState.Start;
            endElementBuffer = false; 
        }
 
        void StartText() 
        {
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.JsonMustUseWriteStringForWritingAttributeValues)));
            }
 
            if ((dataType == JsonDataType.None) && (serverTypeValue != null))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMustSpecifyDataType,
                    JsonGlobals.typeString, JsonGlobals.objectString, JsonGlobals.serverTypeString))); 
            }

            if (IsWritingNameWithMapping && !WrittenNameWithMapping)
            { 
                // Don't write out any text content unless the local name has been written.
                // Not providing a better error message because localization deadline has passed. 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMustSpecifyDataType,
                    JsonGlobals.itemString, string.Empty, JsonGlobals.itemString))); 
            }

            if ((dataType == JsonDataType.String) ||
                (dataType == JsonDataType.None)) 
            {
                CheckText(JsonNodeType.QuotedText); 
                if (nodeType != JsonNodeType.QuotedText) 
                {
                    WriteJsonQuote(); 
                }
                nodeType = JsonNodeType.QuotedText;
            }
            else if ((dataType == JsonDataType.Number) || 
                (dataType == JsonDataType.Boolean))
            { 
                CheckText(JsonNodeType.StandaloneText); 
                nodeType = JsonNodeType.StandaloneText;
            } 
            else
            {
                ThrowInvalidAttributeContent();
            } 
        }
 
        void ThrowIfServerTypeWritten(string dataTypeSpecified) 
        {
            if (serverTypeValue != null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonInvalidDataTypeSpecifiedForServerType,
                    JsonGlobals.typeString, dataTypeSpecified, JsonGlobals.serverTypeString, JsonGlobals.objectString))); 
            }
        } 
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] // [....], ToLowerInvariant is just used in Json error message
        void ThrowInvalidAttributeContent() 
        {
            if (HasOpenAttribute)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidMethodBetweenStartEndAttribute)));
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonCannotWriteTextAfterNonTextAttribute,
                    dataType.ToString().ToLowerInvariant())));
            }
        } 

        bool TrySetWritingNameWithMapping(string localName, string ns) 
        { 
            if (localName.Equals(JsonGlobals.itemString) && ns.Equals(JsonGlobals.itemString))
            { 
                nameState = NameState.IsWritingNameWithMapping;
                return true;
            }
            return false; 
        }
 
        void WriteDataTypeServerType() 
        {
            if (dataType != JsonDataType.None) 
            {
                switch (dataType)
                {
                    case JsonDataType.Array: 
                        {
                            EnterScope(JsonNodeType.Collection); 
                            nodeWriter.WriteText(JsonGlobals.CollectionChar); 
                            break;
                        } 
                    case JsonDataType.Object:
                        {
                            EnterScope(JsonNodeType.Object);
                            nodeWriter.WriteText(JsonGlobals.ObjectChar); 
                            break;
                        } 
                    case JsonDataType.Null: 
                        {
                            nodeWriter.WriteText(JsonGlobals.nullString); 
                            break;
                        }
                    default:
                        break; 
                }
 
                if (serverTypeValue != null) 
                {
                    // dataType must be object because we throw in all other case. 
                    WriteServerTypeAttribute();
                }
            }
        } 

        [SecuritySafeCritical] 
        unsafe void WriteEscapedJsonString(string str) 
        {
            fixed (char *chars = str) 
            {
                int i = 0;
                int j;
                for (j = 0; j < str.Length; j++) 
                {
                    char ch = chars[j]; 
                    if (ch <= FORWARD_SLASH) 
                    {
                        if (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar) 
                        {
                            nodeWriter.WriteChars(chars + i, j - i);
                            nodeWriter.WriteText(BACK_SLASH);
                            nodeWriter.WriteText(ch); 
                            i = j + 1;
                        } 
                        else if (ch < WHITESPACE) 
                        {
                            nodeWriter.WriteChars(chars + i, j - i); 
                            nodeWriter.WriteText(BACK_SLASH);
                            nodeWriter.WriteText('u');
                            nodeWriter.WriteText(string.Format(CultureInfo.InvariantCulture, "{0:x4}", (int) ch));
                            i = j + 1; 
                        }
                    } 
                    else if (ch == BACK_SLASH) 
                    {
                        nodeWriter.WriteChars(chars + i, j - i); 
                        nodeWriter.WriteText(BACK_SLASH);
                        nodeWriter.WriteText(ch);
                        i = j + 1;
                    } 
                    else if (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR))
                    { 
                        nodeWriter.WriteChars(chars + i, j - i); 
                        nodeWriter.WriteText(BACK_SLASH);
                        nodeWriter.WriteText('u'); 
                        nodeWriter.WriteText(string.Format(CultureInfo.InvariantCulture, "{0:x4}", (int) ch));
                        i = j + 1;
                    }
                } 
                if (i < j)
                { 
                    nodeWriter.WriteChars(chars + i, j - i); 
                }
            } 
        }

        void WriteJsonElementName(string localName)
        { 
            WriteJsonQuote();
            WriteEscapedJsonString(localName); 
            WriteJsonQuote(); 
            nodeWriter.WriteText(JsonGlobals.NameValueSeparatorChar);
        } 

        void WriteJsonQuote()
        {
            nodeWriter.WriteText(JsonGlobals.QuoteChar); 
        }
 
        void WritePrimitiveValue(object value) 
        {
            if (IsClosed) 
            {
                ThrowClosed();
            }
 
            if (value == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); 
            }
 
            if (value is ulong)
            {
                WriteValue((ulong) value);
            } 
            else if (value is string)
            { 
                WriteValue((string) value); 
            }
            else if (value is int) 
            {
                WriteValue((int) value);
            }
            else if (value is long) 
            {
                WriteValue((long) value); 
            } 
            else if (value is bool)
            { 
                WriteValue((bool) value);
            }
            else if (value is double)
            { 
                WriteValue((double) value);
            } 
            else if (value is DateTime) 
            {
                WriteValue((DateTime) value); 
            }
            else if (value is float)
            {
                WriteValue((float) value); 
            }
            else if (value is decimal) 
            { 
                WriteValue((decimal) value);
            } 
            else if (value is XmlDictionaryString)
            {
                WriteValue((XmlDictionaryString) value);
            } 
            else if (value is UniqueId)
            { 
                WriteValue((UniqueId) value); 
            }
            else if (value is Guid) 
            {
                WriteValue((Guid) value);
            }
            else if (value is TimeSpan) 
            {
                WriteValue((TimeSpan) value); 
            } 
            else if (value.GetType().IsArray)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.JsonNestedArraysNotSupported), "value"));
            }
            else
            { 
                base.WriteValue(value);
            } 
        } 

        void WriteServerTypeAttribute() 
        {
            string value = serverTypeValue;
            JsonDataType oldDataType = dataType;
            NameState oldNameState = nameState; 
            WriteStartElement(JsonGlobals.serverTypeString);
            WriteValue(value); 
            WriteEndElement(); 
            dataType = oldDataType;
            nameState = oldNameState; 
            wroteServerTypeAttribute = true;
        }

        void WriteValue(ulong value) 
        {
            StartText(); 
            nodeWriter.WriteUInt64Text(value); 
        }
 
        void WriteValue(Array array)
        {
            // This method is called only if WriteValue(object) is called with an array
            // The contract for XmlWriter.WriteValue(object) requires that this object array be written out as a string. 
            // E.g. WriteValue(new int[] { 1, 2, 3}) should be equivalent to WriteString("1 2 3").
            JsonDataType oldDataType = dataType; 
            // Set attribute mode to String because WritePrimitiveValue might write numerical text. 
            //  Calls to methods that write numbers can't be mixed with calls that write quoted text unless the attribute mode is explictly string.
            dataType = JsonDataType.String; 
            StartText();
            for (int i = 0; i < array.Length; i++)
            {
                if (i != 0) 
                {
                    nodeWriter.WriteText(JsonGlobals.WhitespaceChar); 
                } 
                WritePrimitiveValue(array.GetValue(i));
            } 
            dataType = oldDataType;
        }

        class JsonNodeWriter : XmlUTF8NodeWriter 
        {
            [SecurityCritical] 
            internal unsafe void WriteChars(char *chars, int charCount) 
            {
                base.UnsafeWriteUTF8Chars(chars, charCount); 
            }
        }
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.Runtime.Serialization.Json 
{
    using System.Diagnostics.CodeAnalysis; 
    using System.Globalization; 
    using System.IO;
    using System.Runtime; 
    using System.Runtime.Serialization;
    using System.Security;
    using System.ServiceModel;
    using System.Text; 
    using System.Xml;
 
    class XmlJsonWriter : XmlDictionaryWriter, IXmlJsonWriterInitializer 
    {
        const char BACK_SLASH = '\\'; 
        const char FORWARD_SLASH = '/';

        const char HIGH_SURROGATE_START = (char) 0xd800;
        const char LOW_SURROGATE_END = (char) 0xdfff; 
        const char MAX_CHAR = (char) 0xfffe;
        const char WHITESPACE = ' '; 
        const string xmlNamespace = "http://www.w3.org/XML/1998/namespace"; 
        const string xmlnsNamespace = "http://www.w3.org/2000/xmlns/";
 
        [Fx.Tag.SecurityNote(Critical = "Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        [SecurityCritical]
        static BinHexEncoding binHexEncoding; 

        string attributeText; 
        JsonDataType dataType; 
        int depth;
        bool endElementBuffer; 
        bool isWritingDataTypeAttribute;
        bool isWritingServerTypeAttribute;
        bool isWritingXmlnsAttribute;
        bool isWritingXmlnsAttributeDefaultNs; 
        NameState nameState;
        JsonNodeType nodeType; 
        JsonNodeWriter nodeWriter; 
        JsonNodeType[] scopes;
        string serverTypeValue; 
        // Do not use this field's value anywhere other than the WriteState property.
        // It's OK to set this field's value anywhere and then change the WriteState property appropriately.
        // If it's necessary to check the WriteState outside WriteState, use the WriteState property.
        WriteState writeState; 
        bool wroteServerTypeAttribute;
 
        public XmlJsonWriter() 
        {
            InitializeWriter(); 
        }

        enum JsonDataType
        { 
            None,
            Null, 
            Boolean, 
            Number,
            String, 
            Object,
            Array
        };
 
        [Flags]
        enum NameState 
        { 
            None = 0,
            IsWritingNameWithMapping = 1, 
            IsWritingNameAttribute = 2,
            WrittenNameWithMapping = 4,
        }
 
        public override XmlWriterSettings Settings
        { 
            // The XmlWriterSettings object used to create this writer instance. 
            // If this writer was not created using the Create method, this property
            // returns a null reference. 
            get { return null; }
        }

        public override WriteState WriteState 
        {
            get 
            { 
                if (writeState == WriteState.Closed)
                { 
                    return WriteState.Closed;
                }
                if (HasOpenAttribute)
                { 
                    return WriteState.Attribute;
                } 
                switch (nodeType) 
                {
                    case JsonNodeType.None: 
                        return WriteState.Start;
                    case JsonNodeType.Element:
                        return WriteState.Element;
                    case JsonNodeType.QuotedText: 
                    case JsonNodeType.StandaloneText:
                    case JsonNodeType.EndElement: 
                        return WriteState.Content; 
                    default:
                        return WriteState.Error; 
                }
            }
        }
 
        public override string XmlLang
        { 
            get { return null; } 
        }
 
        public override XmlSpace XmlSpace
        {
            get { return XmlSpace.None; }
        } 

        static BinHexEncoding BinHexEncoding 
        { 
            [Fx.Tag.SecurityNote(Critical = "Fetches the critical binHexEncoding field.",
                Safe = "Get-only properties only need to be protected for write; initialized in getter if null.")] 
            [SecuritySafeCritical]
            get
            {
                if (binHexEncoding == null) 
                {
                    binHexEncoding = new BinHexEncoding(); 
                } 
                return binHexEncoding;
            } 
        }

        bool HasOpenAttribute
        { 
            get
            { 
                return (isWritingDataTypeAttribute || isWritingServerTypeAttribute || IsWritingNameAttribute || isWritingXmlnsAttribute); 
            }
        } 

        bool IsClosed
        {
            get { return (WriteState == WriteState.Closed); } 
        }
 
        bool IsWritingCollection 
        {
            get { return (depth > 0) && (scopes[depth] == JsonNodeType.Collection); } 
        }

        bool IsWritingNameAttribute
        { 
            get { return (nameState & NameState.IsWritingNameAttribute) == NameState.IsWritingNameAttribute; }
        } 
 
        bool IsWritingNameWithMapping
        { 
            get { return (nameState & NameState.IsWritingNameWithMapping) == NameState.IsWritingNameWithMapping; }
        }

        bool WrittenNameWithMapping 
        {
            get { return (nameState & NameState.WrittenNameWithMapping) == NameState.WrittenNameWithMapping; } 
        } 

        public override void Close() 
        {
            if (!IsClosed)
            {
                try 
                {
                    WriteEndDocument(); 
                } 
                finally
                { 
                    try
                    {
                        nodeWriter.Flush();
                        nodeWriter.Close(); 
                    }
                    finally 
                    { 
                        writeState = WriteState.Closed;
                        if (depth != 0) 
                        {
                            depth = 0;
                        }
                    } 
                }
            } 
        } 

        public override void Flush() 
        {
            if (IsClosed)
            {
                ThrowClosed(); 
            }
            nodeWriter.Flush(); 
        } 

        public override string LookupPrefix(string ns) 
        {
            if (ns == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ns"); 
            }
            if (ns == Globals.XmlnsNamespace) 
            { 
                return Globals.XmlnsPrefix;
            } 
            if (ns == xmlNamespace)
            {
                return JsonGlobals.xmlPrefix;
            } 
            if (ns == string.Empty)
            { 
                return string.Empty; 
            }
            return null; 
        }

        public void SetOutput(Stream stream, Encoding encoding, bool ownsStream)
        { 
            if (stream == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("stream"); 
            }
            if (encoding == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding");
            }
            if (encoding.WebName != Encoding.UTF8.WebName) 
            {
                stream = new JsonEncodingStreamWrapper(stream, encoding, false); 
            } 
            else
            { 
                encoding = null;
            }
            if (nodeWriter == null)
            { 
                nodeWriter = new JsonNodeWriter();
            } 
 
            nodeWriter.SetOutput(stream, ownsStream, encoding);
            InitializeWriter(); 
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, bool[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, Int16[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, Int32[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, Int64[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, float[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, double[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, string localName, string namespaceUri, DateTime[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, string localName, string namespaceUri, Guid[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }

        public override void WriteArray(string prefix, string localName, string namespaceUri, TimeSpan[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, int[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, long[] array, int offset, int count) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, short[] array, int offset, int count)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported))); 
        }

        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        } 
 
        public override void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonWriteArrayNotSupported)));
        }

        public override void WriteBase64(byte[] buffer, int index, int count) 
        {
            if (buffer == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does.
            if (index < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            } 

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            } 
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            }

            StartText(); 
            nodeWriter.WriteBase64Text(buffer, 0, buffer, index, count);
        } 
 
        public override void WriteBinHex(byte[] buffer, int index, int count)
        { 
            if (buffer == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does. 
            if (index < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative)));
            }

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
            if (count > buffer.Length - index) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            } 
 
            StartText();
            WriteEscapedJsonString(BinHexEncoding.GetString(buffer, index, count)); 
        }

        public override void WriteCData(string text)
        { 
            WriteString(text);
        } 
 
        public override void WriteCharEntity(char ch)
        { 
            WriteString(ch.ToString());
        }

        public override void WriteChars(char[] buffer, int index, int count) 
        {
            if (buffer == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer");
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does.
            if (index < 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            } 

            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            } 
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count",
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            }

            WriteString(new string(buffer, index, count)); 
        }
 
        public override void WriteComment(string text) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteComment"))); 
        }

        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "2#sysid", Justification = "This method is derived from the base")]
        [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "1#pubid", Justification = "This method is derived from the base")] 
        public override void WriteDocType(string name, string pubid, string sysid, string subset)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteDocType"))); 
        }
 
        public override void WriteEndAttribute()
        {
            if (IsClosed)
            { 
                ThrowClosed();
            } 
            if (!HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonNoMatchingStartAttribute)));
            }

            Fx.Assert(!(isWritingDataTypeAttribute && isWritingServerTypeAttribute), 
                "Can not write type attribute and __type attribute at the same time.");
 
            if (isWritingDataTypeAttribute) 
            {
                switch (attributeText) 
                {
                    case JsonGlobals.numberString:
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.numberString); 
                            dataType = JsonDataType.Number;
                            break; 
                        } 
                    case JsonGlobals.stringString:
                        { 
                            ThrowIfServerTypeWritten(JsonGlobals.stringString);
                            dataType = JsonDataType.String;
                            break;
                        } 
                    case JsonGlobals.arrayString:
                        { 
                            ThrowIfServerTypeWritten(JsonGlobals.arrayString); 
                            dataType = JsonDataType.Array;
                            break; 
                        }
                    case JsonGlobals.objectString:
                        {
                            dataType = JsonDataType.Object; 
                            break;
                        } 
                    case JsonGlobals.nullString: 
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.nullString); 
                            dataType = JsonDataType.Null;
                            break;
                        }
                    case JsonGlobals.booleanString: 
                        {
                            ThrowIfServerTypeWritten(JsonGlobals.booleanString); 
                            dataType = JsonDataType.Boolean; 
                            break;
                        } 
                    default:
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                            new XmlException(SR.GetString(SR.JsonUnexpectedAttributeValue, attributeText)));
                } 

                attributeText = null; 
                isWritingDataTypeAttribute = false; 

                if (!IsWritingNameWithMapping || WrittenNameWithMapping) 
                {
                    WriteDataTypeServerType();
                }
            } 
            else if (isWritingServerTypeAttribute)
            { 
                serverTypeValue = attributeText; 
                attributeText = null;
                isWritingServerTypeAttribute = false; 

                // we are writing __type after type="object" (enforced by WSE)
                if ((!IsWritingNameWithMapping || WrittenNameWithMapping) && dataType == JsonDataType.Object)
                { 
                    WriteServerTypeAttribute();
                } 
            } 
            else if (IsWritingNameAttribute)
            { 
                WriteJsonElementName(attributeText);
                attributeText = null;
                nameState = NameState.IsWritingNameWithMapping | NameState.WrittenNameWithMapping;
                WriteDataTypeServerType(); 
            }
            else if (isWritingXmlnsAttribute) 
            { 
                if (!string.IsNullOrEmpty(attributeText) && isWritingXmlnsAttributeDefaultNs)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, attributeText));
                }

                attributeText = null; 
                isWritingXmlnsAttribute = false;
                isWritingXmlnsAttributeDefaultNs = false; 
            } 
        }
 
        public override void WriteEndDocument()
        {
            if (IsClosed)
            { 
                ThrowClosed();
            } 
            if (nodeType != JsonNodeType.None) 
            {
                while (depth > 0) 
                {
                    WriteEndElement();
                }
            } 
        }
 
        public override void WriteEndElement() 
        {
            if (IsClosed) 
            {
                ThrowClosed();
            }
 
            if (depth == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonEndElementNoOpenNodes)));
            } 
            if (HasOpenAttribute)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteEndElement"))); 
            }
 
            endElementBuffer = false; 

            JsonNodeType token = ExitScope(); 
            if (token == JsonNodeType.Collection)
            {
                nodeWriter.WriteText(JsonGlobals.EndCollectionChar);
                token = ExitScope(); 
            }
            else if (nodeType == JsonNodeType.QuotedText) 
            { 
                // For writing "
                WriteJsonQuote(); 
            }
            else if (nodeType == JsonNodeType.Element)
            {
                if ((dataType == JsonDataType.None) && (serverTypeValue != null)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonMustSpecifyDataType, 
                        JsonGlobals.typeString, JsonGlobals.objectString, JsonGlobals.serverTypeString)));
                } 

                if (IsWritingNameWithMapping && !WrittenNameWithMapping)
                {
                    // Ending  without writing item attribute 
                    // Not providing a better error message because localization deadline has passed.
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonMustSpecifyDataType, 
                        JsonGlobals.itemString, string.Empty, JsonGlobals.itemString)));
                } 

                // the element is empty, it does not have any content,
                if ((dataType == JsonDataType.None) ||
                    (dataType == JsonDataType.String)) 
                {
                    nodeWriter.WriteText(JsonGlobals.QuoteChar); 
                    nodeWriter.WriteText(JsonGlobals.QuoteChar); 
                }
            } 
            else
            {
                // Assert on only StandaloneText and EndElement because preceding if
                //    conditions take care of checking for QuotedText and Element. 
                Fx.Assert((nodeType == JsonNodeType.StandaloneText) || (nodeType == JsonNodeType.EndElement),
                    "nodeType has invalid value " + nodeType + ". Expected it to be QuotedText, Element, StandaloneText, or EndElement."); 
            } 
            if (depth != 0)
            { 
                if (token == JsonNodeType.Element)
                {
                    endElementBuffer = true;
                } 
                else if (token == JsonNodeType.Object)
                { 
                    nodeWriter.WriteText(JsonGlobals.EndObjectChar); 
                    if ((depth > 0) && scopes[depth] == JsonNodeType.Element)
                    { 
                        ExitScope();
                        endElementBuffer = true;
                    }
                } 
            }
 
            dataType = JsonDataType.None; 
            nodeType = JsonNodeType.EndElement;
            nameState = NameState.None; 
            wroteServerTypeAttribute = false;
        }

        public override void WriteEntityRef(string name) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteEntityRef"))); 
        } 

        public override void WriteFullEndElement() 
        {
            WriteEndElement();
        }
 
        public override void WriteProcessingInstruction(string name, string text)
        { 
            if (IsClosed) 
            {
                ThrowClosed(); 
            }

            if (!name.Equals("xml", StringComparison.OrdinalIgnoreCase))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.JsonXmlProcessingInstructionNotSupported), "name"));
            } 
 
            if (WriteState != WriteState.Start)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonXmlInvalidDeclaration)));
            }
        }
 
        public override void WriteQualifiedName(string localName, string ns)
        { 
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName"); 
            }
            if (localName.Length == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", 
                    SR.GetString(SR.JsonInvalidLocalNameEmpty));
            } 
            if (ns == null) 
            {
                ns = string.Empty; 
            }

            base.WriteQualifiedName(localName, ns);
        } 

        public override void WriteRaw(string data) 
        { 
            WriteString(data);
        } 

        public override void WriteRaw(char[] buffer, int index, int count)
        {
            if (buffer == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("buffer"); 
            } 

            // Not checking upper bound because it will be caught by "count".  This is what XmlTextWriter does. 
            if (index < 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("index", SR.GetString(SR.ValueMustBeNonNegative))); 
            }
 
            if (count < 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative)));
            }
            if (count > buffer.Length - index)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("count", 
                    SR.GetString(SR.JsonSizeExceedsRemainingBufferSpace, 
                    buffer.Length - index)));
            } 

            WriteString(new string(buffer, index, count));
        }
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] // [....], ToLowerInvariant is just used in Json error message
        public override void WriteStartAttribute(string prefix, string localName, string ns) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }
            if (!string.IsNullOrEmpty(prefix))
            { 
                if (IsWritingNameWithMapping && prefix == JsonGlobals.xmlnsPrefix)
                { 
                    if (ns != null && ns != xmlnsNamespace) 
                    {
                        throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlPrefixBoundToNamespace, "xmlns", xmlnsNamespace, ns), "ns")); 
                    }
                }
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("prefix", SR.GetString(SR.JsonPrefixMustBeNullOrEmpty, prefix));
                } 
            } 
            else
            { 
                if (IsWritingNameWithMapping && ns == xmlnsNamespace && localName != JsonGlobals.xmlnsPrefix)
                {
                    prefix = JsonGlobals.xmlnsPrefix;
                } 
            }
            if (!string.IsNullOrEmpty(ns)) 
            { 
                if (IsWritingNameWithMapping && ns == xmlnsNamespace)
                { 
                    prefix = JsonGlobals.xmlnsPrefix;
                }
                else if (string.IsNullOrEmpty(prefix) && localName == JsonGlobals.xmlnsPrefix && ns == xmlnsNamespace)
                { 
                    prefix = JsonGlobals.xmlnsPrefix;
                    isWritingXmlnsAttributeDefaultNs = true; 
                } 
                else
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, ns));
                }
            }
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName"); 
            } 
            if (localName.Length == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", SR.GetString(SR.JsonInvalidLocalNameEmpty));
            }
            if ((nodeType != JsonNodeType.Element) && !wroteServerTypeAttribute)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonAttributeMustHaveElement)));
            } 
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteStartAttribute")));
            }
            if (prefix == JsonGlobals.xmlnsPrefix)
            { 
                isWritingXmlnsAttribute = true;
            } 
            else if (localName == JsonGlobals.typeString) 
            {
                if (dataType != JsonDataType.None) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.typeString)));
                } 

                isWritingDataTypeAttribute = true; 
            } 
            else if (localName == JsonGlobals.serverTypeString)
            { 
                if (serverTypeValue != null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.serverTypeString))); 
                }
 
                if ((dataType != JsonDataType.None) && (dataType != JsonDataType.Object)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonServerTypeSpecifiedForInvalidDataType,
                        JsonGlobals.serverTypeString, JsonGlobals.typeString, dataType.ToString().ToLowerInvariant(), JsonGlobals.objectString)));
                }
 
                isWritingServerTypeAttribute = true;
            } 
            else if (localName == JsonGlobals.itemString) 
            {
                if (WrittenNameWithMapping) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonAttributeAlreadyWritten, JsonGlobals.itemString)));
                } 

                if (!IsWritingNameWithMapping) 
                { 
                    // Don't write attribute with local name "item" if  element is not open.
                    // Not providing a better error message because localization deadline has passed. 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEndElementNoOpenNodes)));
                }
 
                nameState |= NameState.IsWritingNameAttribute;
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", SR.GetString(SR.JsonUnexpectedAttributeLocalName, localName)); 
            }
        }

        public override void WriteStartDocument(bool standalone) 
        {
            // In XML, writes the XML declaration with the version "1.0" and the standalone attribute. 
            WriteStartDocument(); 
        }
 
        public override void WriteStartDocument()
        {
            // In XML, writes the XML declaration with the version "1.0".
            if (IsClosed) 
            {
                ThrowClosed(); 
            } 
            if (WriteState != WriteState.Start)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(
                    SR.GetString(SR.JsonInvalidWriteState, "WriteStartDocument", WriteState.ToString())));
            } 
        }
 
        public override void WriteStartElement(string prefix, string localName, string ns) 
        {
            if (localName == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("localName");
            }
            if (localName.Length == 0) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("localName", 
                    SR.GetString(SR.JsonInvalidLocalNameEmpty)); 
            }
            if (!string.IsNullOrEmpty(prefix)) 
            {
                if (string.IsNullOrEmpty(ns) || !TrySetWritingNameWithMapping(localName, ns))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("prefix", SR.GetString(SR.JsonPrefixMustBeNullOrEmpty, prefix)); 
                }
            } 
            if (!string.IsNullOrEmpty(ns)) 
            {
                if (!TrySetWritingNameWithMapping(localName, ns)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ns", SR.GetString(SR.JsonNamespaceMustBeEmpty, ns));
                }
            } 
            if (IsClosed)
            { 
                ThrowClosed(); 
            }
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonOpenAttributeMustBeClosedFirst, "WriteStartElement")));
            } 
            if ((nodeType != JsonNodeType.None) && depth == 0)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMultipleRootElementsNotAllowedOnWriter)));
            } 

            switch (nodeType)
            {
                case JsonNodeType.None: 
                    {
                        if (!localName.Equals(JsonGlobals.rootString)) 
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new XmlException(SR.GetString(SR.JsonInvalidRootElementName, localName, JsonGlobals.rootString))); 
                        }
                        EnterScope(JsonNodeType.Element);
                        break;
                    } 
                case JsonNodeType.Element:
                    { 
                        if ((dataType != JsonDataType.Array) && (dataType != JsonDataType.Object)) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                new XmlException(SR.GetString(SR.JsonNodeTypeArrayOrObjectNotSpecified)));
                        }
                        if (!IsWritingCollection)
                        { 
                            if (nameState != NameState.IsWritingNameWithMapping)
                            { 
                                WriteJsonElementName(localName); 
                            }
                        } 
                        else if (!localName.Equals(JsonGlobals.itemString))
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                                new XmlException(SR.GetString(SR.JsonInvalidItemNameForArrayElement, localName, JsonGlobals.itemString))); 
                        }
                        EnterScope(JsonNodeType.Element); 
                        break; 
                    }
                case JsonNodeType.EndElement: 
                    {
                        if (endElementBuffer)
                        {
                            nodeWriter.WriteText(JsonGlobals.MemberSeparatorChar); 
                        }
                        if (!IsWritingCollection) 
                        { 
                            if (nameState != NameState.IsWritingNameWithMapping)
                            { 
                                WriteJsonElementName(localName);
                            }
                        }
                        else if (!localName.Equals(JsonGlobals.itemString)) 
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                                new XmlException(SR.GetString(SR.JsonInvalidItemNameForArrayElement, localName, JsonGlobals.itemString))); 
                        }
                        EnterScope(JsonNodeType.Element); 
                        break;
                    }
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonInvalidStartElementCall)));
            } 
 
            isWritingDataTypeAttribute = false;
            isWritingServerTypeAttribute = false; 
            isWritingXmlnsAttribute = false;
            wroteServerTypeAttribute = false;
            serverTypeValue = null;
            dataType = JsonDataType.None; 
            nodeType = JsonNodeType.Element;
        } 
 
        public override void WriteString(string text)
        { 
            if (HasOpenAttribute && (text != null))
            {
                attributeText += text;
            } 
            else
            { 
                if (text == null) 
                {
                    text = string.Empty; 
                }

                // do work only when not indenting whitespaces
                if (!((this.dataType == JsonDataType.Array || this.dataType == JsonDataType.Object || this.nodeType == JsonNodeType.EndElement) && XmlConverter.IsWhitespace(text))) 
                {
                    StartText(); 
                    WriteEscapedJsonString(text); 
                }
            } 
        }

        public override void WriteSurrogateCharEntity(char lowChar, char highChar)
        { 
            WriteString(string.Concat(highChar, lowChar));
        } 
 
        public override void WriteValue(bool value)
        { 
            StartText();
            nodeWriter.WriteBoolText(value);
        }
 
        public override void WriteValue(decimal value)
        { 
            StartText(); 
            nodeWriter.WriteDecimalText(value);
        } 

        public override void WriteValue(double value)
        {
            StartText(); 
            nodeWriter.WriteDoubleText(value);
        } 
 
        public override void WriteValue(float value)
        { 
            StartText();
            nodeWriter.WriteFloatText(value);
        }
 
        public override void WriteValue(int value)
        { 
            StartText(); 
            nodeWriter.WriteInt32Text(value);
        } 

        public override void WriteValue(long value)
        {
            StartText(); 
            nodeWriter.WriteInt64Text(value);
        } 
 
        public override void WriteValue(Guid value)
        { 
            StartText();
            nodeWriter.WriteGuidText(value);
        }
 
        public override void WriteValue(DateTime value)
        { 
            StartText(); 
            nodeWriter.WriteDateTimeText(value);
        } 

        public override void WriteValue(string value)
        {
            WriteString(value); 
        }
 
        public override void WriteValue(TimeSpan value) 
        {
            StartText(); 
            nodeWriter.WriteTimeSpanText(value);
        }

        public override void WriteValue(UniqueId value) 
        {
            if (value == null) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
            } 

            StartText();
            nodeWriter.WriteUniqueIdText(value);
        } 

        public override void WriteValue(object value) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }

            if (value == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); 
            } 

            if (value is Array) 
            {
                WriteValue((Array) value);
            }
            else if (value is IStreamProvider) 
            {
                WriteValue((IStreamProvider) value); 
            } 
            else
            { 
                WritePrimitiveValue(value);
            }
        }
 
        [SuppressMessage("Microsoft.Naming", "CA1702:CompoundWordsShouldBeCasedCorrectly", MessageId = "Whitespace", Justification = "This method is derived from the base")]
        public override void WriteWhitespace(string ws) 
        { 
            if (IsClosed)
            { 
                ThrowClosed();
            }
            if (ws == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ws");
            } 
 
            for (int i = 0; i < ws.Length; ++i)
            { 
                char c = ws[i];
                if (c != ' ' &&
                    c != '\t' &&
                    c != '\n' && 
                    c != '\r')
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("ws", 
                        SR.GetString(SR.JsonOnlyWhitespace, c.ToString(), "WriteWhitespace"));
                } 
            }

            WriteString(ws);
        } 

        public override void WriteXmlAttribute(string localName, string value) 
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlAttribute")));
        } 

        public override void WriteXmlAttribute(XmlDictionaryString localName, XmlDictionaryString value)
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlAttribute"))); 
        }
 
        public override void WriteXmlnsAttribute(string prefix, string namespaceUri) 
        {
            if (!IsWritingNameWithMapping) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlnsAttribute")));
            }
        } 

        public override void WriteXmlnsAttribute(string prefix, XmlDictionaryString namespaceUri) 
        { 
            if (!IsWritingNameWithMapping)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString(SR.JsonMethodNotSupported, "WriteXmlnsAttribute")));
            }
        }
 
        internal static bool CharacterNeedsEscaping(char ch)
        { 
            return (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar || ch < WHITESPACE || ch == BACK_SLASH 
                || (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR)));
        } 


        static void ThrowClosed()
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                new InvalidOperationException(SR.GetString(SR.JsonWriterClosed))); 
        } 

        void CheckText(JsonNodeType nextNodeType) 
        {
            if (IsClosed)
            {
                ThrowClosed(); 
            }
            if (depth == 0) 
            { 
                throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new InvalidOperationException( 
                    System.Runtime.Serialization.SR.GetString(System.Runtime.Serialization.SR.XmlIllegalOutsideRoot)));
            }

            if ((nextNodeType == JsonNodeType.StandaloneText) && 
                (nodeType == JsonNodeType.QuotedText))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(
                    SR.GetString(SR.JsonCannotWriteStandaloneTextAfterQuotedText))); 
            }
        }

        void EnterScope(JsonNodeType currentNodeType) 
        {
            depth++; 
            if (scopes == null) 
            {
                scopes = new JsonNodeType[4]; 
            }
            else if (scopes.Length == depth)
            {
                JsonNodeType[] newScopes = new JsonNodeType[depth * 2]; 
                Array.Copy(scopes, newScopes, depth);
                scopes = newScopes; 
            } 
            scopes[depth] = currentNodeType;
        } 

        JsonNodeType ExitScope()
        {
            JsonNodeType nodeTypeToReturn = scopes[depth]; 
            scopes[depth] = JsonNodeType.None;
            depth--; 
            return nodeTypeToReturn; 
        }
 
        void InitializeWriter()
        {
            nodeType = JsonNodeType.None;
            dataType = JsonDataType.None; 
            isWritingDataTypeAttribute = false;
            wroteServerTypeAttribute = false; 
            isWritingServerTypeAttribute = false; 
            serverTypeValue = null;
            attributeText = null; 

            if (depth != 0)
            {
                depth = 0; 
            }
            if ((scopes != null) && (scopes.Length > JsonGlobals.maxScopeSize)) 
            { 
                scopes = null;
            } 

            // Can't let writeState be at Closed if reinitializing.
            writeState = WriteState.Start;
            endElementBuffer = false; 
        }
 
        void StartText() 
        {
            if (HasOpenAttribute) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.JsonMustUseWriteStringForWritingAttributeValues)));
            }
 
            if ((dataType == JsonDataType.None) && (serverTypeValue != null))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMustSpecifyDataType,
                    JsonGlobals.typeString, JsonGlobals.objectString, JsonGlobals.serverTypeString))); 
            }

            if (IsWritingNameWithMapping && !WrittenNameWithMapping)
            { 
                // Don't write out any text content unless the local name has been written.
                // Not providing a better error message because localization deadline has passed. 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonMustSpecifyDataType,
                    JsonGlobals.itemString, string.Empty, JsonGlobals.itemString))); 
            }

            if ((dataType == JsonDataType.String) ||
                (dataType == JsonDataType.None)) 
            {
                CheckText(JsonNodeType.QuotedText); 
                if (nodeType != JsonNodeType.QuotedText) 
                {
                    WriteJsonQuote(); 
                }
                nodeType = JsonNodeType.QuotedText;
            }
            else if ((dataType == JsonDataType.Number) || 
                (dataType == JsonDataType.Boolean))
            { 
                CheckText(JsonNodeType.StandaloneText); 
                nodeType = JsonNodeType.StandaloneText;
            } 
            else
            {
                ThrowInvalidAttributeContent();
            } 
        }
 
        void ThrowIfServerTypeWritten(string dataTypeSpecified) 
        {
            if (serverTypeValue != null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonInvalidDataTypeSpecifiedForServerType,
                    JsonGlobals.typeString, dataTypeSpecified, JsonGlobals.serverTypeString, JsonGlobals.objectString))); 
            }
        } 
 
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase")] // [....], ToLowerInvariant is just used in Json error message
        void ThrowInvalidAttributeContent() 
        {
            if (HasOpenAttribute)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidMethodBetweenStartEndAttribute)));
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonCannotWriteTextAfterNonTextAttribute,
                    dataType.ToString().ToLowerInvariant())));
            }
        } 

        bool TrySetWritingNameWithMapping(string localName, string ns) 
        { 
            if (localName.Equals(JsonGlobals.itemString) && ns.Equals(JsonGlobals.itemString))
            { 
                nameState = NameState.IsWritingNameWithMapping;
                return true;
            }
            return false; 
        }
 
        void WriteDataTypeServerType() 
        {
            if (dataType != JsonDataType.None) 
            {
                switch (dataType)
                {
                    case JsonDataType.Array: 
                        {
                            EnterScope(JsonNodeType.Collection); 
                            nodeWriter.WriteText(JsonGlobals.CollectionChar); 
                            break;
                        } 
                    case JsonDataType.Object:
                        {
                            EnterScope(JsonNodeType.Object);
                            nodeWriter.WriteText(JsonGlobals.ObjectChar); 
                            break;
                        } 
                    case JsonDataType.Null: 
                        {
                            nodeWriter.WriteText(JsonGlobals.nullString); 
                            break;
                        }
                    default:
                        break; 
                }
 
                if (serverTypeValue != null) 
                {
                    // dataType must be object because we throw in all other case. 
                    WriteServerTypeAttribute();
                }
            }
        } 

        [SecuritySafeCritical] 
        unsafe void WriteEscapedJsonString(string str) 
        {
            fixed (char *chars = str) 
            {
                int i = 0;
                int j;
                for (j = 0; j < str.Length; j++) 
                {
                    char ch = chars[j]; 
                    if (ch <= FORWARD_SLASH) 
                    {
                        if (ch == FORWARD_SLASH || ch == JsonGlobals.QuoteChar) 
                        {
                            nodeWriter.WriteChars(chars + i, j - i);
                            nodeWriter.WriteText(BACK_SLASH);
                            nodeWriter.WriteText(ch); 
                            i = j + 1;
                        } 
                        else if (ch < WHITESPACE) 
                        {
                            nodeWriter.WriteChars(chars + i, j - i); 
                            nodeWriter.WriteText(BACK_SLASH);
                            nodeWriter.WriteText('u');
                            nodeWriter.WriteText(string.Format(CultureInfo.InvariantCulture, "{0:x4}", (int) ch));
                            i = j + 1; 
                        }
                    } 
                    else if (ch == BACK_SLASH) 
                    {
                        nodeWriter.WriteChars(chars + i, j - i); 
                        nodeWriter.WriteText(BACK_SLASH);
                        nodeWriter.WriteText(ch);
                        i = j + 1;
                    } 
                    else if (ch >= HIGH_SURROGATE_START && (ch <= LOW_SURROGATE_END || ch >= MAX_CHAR))
                    { 
                        nodeWriter.WriteChars(chars + i, j - i); 
                        nodeWriter.WriteText(BACK_SLASH);
                        nodeWriter.WriteText('u'); 
                        nodeWriter.WriteText(string.Format(CultureInfo.InvariantCulture, "{0:x4}", (int) ch));
                        i = j + 1;
                    }
                } 
                if (i < j)
                { 
                    nodeWriter.WriteChars(chars + i, j - i); 
                }
            } 
        }

        void WriteJsonElementName(string localName)
        { 
            WriteJsonQuote();
            WriteEscapedJsonString(localName); 
            WriteJsonQuote(); 
            nodeWriter.WriteText(JsonGlobals.NameValueSeparatorChar);
        } 

        void WriteJsonQuote()
        {
            nodeWriter.WriteText(JsonGlobals.QuoteChar); 
        }
 
        void WritePrimitiveValue(object value) 
        {
            if (IsClosed) 
            {
                ThrowClosed();
            }
 
            if (value == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); 
            }
 
            if (value is ulong)
            {
                WriteValue((ulong) value);
            } 
            else if (value is string)
            { 
                WriteValue((string) value); 
            }
            else if (value is int) 
            {
                WriteValue((int) value);
            }
            else if (value is long) 
            {
                WriteValue((long) value); 
            } 
            else if (value is bool)
            { 
                WriteValue((bool) value);
            }
            else if (value is double)
            { 
                WriteValue((double) value);
            } 
            else if (value is DateTime) 
            {
                WriteValue((DateTime) value); 
            }
            else if (value is float)
            {
                WriteValue((float) value); 
            }
            else if (value is decimal) 
            { 
                WriteValue((decimal) value);
            } 
            else if (value is XmlDictionaryString)
            {
                WriteValue((XmlDictionaryString) value);
            } 
            else if (value is UniqueId)
            { 
                WriteValue((UniqueId) value); 
            }
            else if (value is Guid) 
            {
                WriteValue((Guid) value);
            }
            else if (value is TimeSpan) 
            {
                WriteValue((TimeSpan) value); 
            } 
            else if (value.GetType().IsArray)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.JsonNestedArraysNotSupported), "value"));
            }
            else
            { 
                base.WriteValue(value);
            } 
        } 

        void WriteServerTypeAttribute() 
        {
            string value = serverTypeValue;
            JsonDataType oldDataType = dataType;
            NameState oldNameState = nameState; 
            WriteStartElement(JsonGlobals.serverTypeString);
            WriteValue(value); 
            WriteEndElement(); 
            dataType = oldDataType;
            nameState = oldNameState; 
            wroteServerTypeAttribute = true;
        }

        void WriteValue(ulong value) 
        {
            StartText(); 
            nodeWriter.WriteUInt64Text(value); 
        }
 
        void WriteValue(Array array)
        {
            // This method is called only if WriteValue(object) is called with an array
            // The contract for XmlWriter.WriteValue(object) requires that this object array be written out as a string. 
            // E.g. WriteValue(new int[] { 1, 2, 3}) should be equivalent to WriteString("1 2 3").
            JsonDataType oldDataType = dataType; 
            // Set attribute mode to String because WritePrimitiveValue might write numerical text. 
            //  Calls to methods that write numbers can't be mixed with calls that write quoted text unless the attribute mode is explictly string.
            dataType = JsonDataType.String; 
            StartText();
            for (int i = 0; i < array.Length; i++)
            {
                if (i != 0) 
                {
                    nodeWriter.WriteText(JsonGlobals.WhitespaceChar); 
                } 
                WritePrimitiveValue(array.GetValue(i));
            } 
            dataType = oldDataType;
        }

        class JsonNodeWriter : XmlUTF8NodeWriter 
        {
            [SecurityCritical] 
            internal unsafe void WriteChars(char *chars, int charCount) 
            {
                base.UnsafeWriteUTF8Chars(chars, charCount); 
            }
        }
    }
} 

// 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