context: #region License
  // Copyright (c) 2007 James Newton-King
  //
  // Permission is hereby granted, free of charge, to any person
  // obtaining a copy of this software and associated documentation
  // files (the "Software"), to deal in the Software without
  // restriction, including without limitation the rights to use,
  // copy, modify, merge, publish, distribute, sublicense, and/or sell
  // copies of the Software, and to permit persons to whom the
  // Software is furnished to do so, subject to the following
  // conditions:
  //
  // The above copyright notice and this permission notice shall be
  // included in all copies or substantial portions of the Software.
  //
  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  // OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  // OTHER DEALINGS IN THE SOFTWARE.
  #endregion
  
  using System;
  using System.Collections.Generic;
  using System.Text;
  using System.IO;
  using System.Xml;
  using Newtonsoft.Json.Utilities;
  using Newtonsoft.Json.Linq;
  using System.Globalization;
  
  namespace Newtonsoft.Json
  {
    /// <summary>
    /// Specifies the state of the <see cref="JsonWriter"/>.
    /// </summary>
    public enum WriteState
    {
      /// <summary>
      /// An exception has been thrown, which has left the <see cref="JsonWriter"/> in an invalid state.
      /// You may call the <see cref="JsonWriter.Close"/> method to put the <see cref="JsonWriter"/> in the <c>Closed</c> state.
      /// Any other <see cref="JsonWriter"/> method calls results in an <see cref="InvalidOperationException"/> being thrown. 
      /// </summary>
      Error,
      /// <summary>
      /// The <see cref="JsonWriter.Close"/> method has been called. 
      /// </summary>
      Closed,
      /// <summary>
      /// An object is being written. 
      /// </summary>
      Object,
      /// <summary>
      /// A array is being written.
      /// </summary>
      Array,
      /// <summary>
      /// A constructor is being written.
      /// </summary>
      Constructor,
      /// <summary>
      /// A property is being written.
      /// </summary>
      Property,
      /// <summary>
      /// A write method has not been called.
      /// </summary>
      Start
    }
  
    /// <summary>
    /// Specifies formatting options for the <see cref="JsonTextWriter"/>.
    /// </summary>
    public enum Formatting
    {
      /// <summary>
      /// No special formatting is applied. This is the default.
      /// </summary>
      None,
      /// <summary>
      /// Causes child objects to be indented according to the <see cref="JsonTextWriter.Indentation"/> and <see cref="JsonTextWriter.IndentChar"/> settings.
      /// </summary>
      Indented
    }
  
    /// <summary>
    /// Represents a writer that provides a fast, non-cached, forward-only way of generating Json data.
    /// </summary>
    public abstract class JsonWriter : IDisposable
    {
      private enum State
      {
        Start,
        Property,
        ObjectStart,
        Object,
        ArrayStart,
        Array,
        ConstructorStart,
        Constructor,
        Bytes,
        Closed,
        Error
      }
  
      // array that gives a new state based on the current state an the token being written
      private static readonly State[][] stateArray = new[] {
  //                      Start                   PropertyName            ObjectStart         Object            ArrayStart              Array                   ConstructorStart        Constructor             Closed          Error
  //                        
  /* None             */new[]{ State.Error,            State.Error,            State.Error,        State.Error,      State.Error,            State.Error,            State.Error,            State.Error,            State.Error,    State.Error },
  /* StartObject      */new[]{ State.ObjectStart,      State.ObjectStart,      State.Error,        State.Error,      State.ObjectStart,      State.ObjectStart,      State.ObjectStart,      State.ObjectStart,      State.Error,    State.Error },
  /* StartArray       */new[]{ State.ArrayStart,       State.ArrayStart,       State.Error,        State.Error,      State.ArrayStart,       State.ArrayStart,       State.ArrayStart,       State.ArrayStart,       State.Error,    State.Error },
  /* StartConstructor */new[]{ State.ConstructorStart, State.ConstructorStart, State.Error,        State.Error,      State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.ConstructorStart, State.Error,    State.Error },
  /* StartProperty    */new[]{ State.Property,         State.Error,            State.Property,     State.Property,   State.Error,            State.Error,            State.Error,            State.Error,            State.Error,    State.Error },
  /* Comment          */new[]{ State.Start,            State.Property,         State.ObjectStart,  State.Object,     State.ArrayStart,       State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error },
  /* Raw              */new[]{ State.Start,            State.Property,         State.ObjectStart,  State.Object,     State.ArrayStart,       State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error },
  /* Value            */new[]{ State.Start,            State.Object,           State.Error,        State.Error,      State.Array,            State.Array,            State.Constructor,      State.Constructor,      State.Error,    State.Error },
  		};
  
      private int _top;
  
      private readonly List<JTokenType> _stack;
      private State _currentState;
      private Formatting _formatting;
  
      /// <summary>
      /// Gets the top.
      /// </summary>
      /// <value>The top.</value>
      protected internal int Top
      {
        get { return _top; }
      }
  
      /// <summary>
      /// Gets the state of the writer.
      /// </summary>
      public WriteState WriteState
      {
        get
        {
          switch (_currentState)
          {
            case State.Error:
              return WriteState.Error;
            case State.Closed:
              return WriteState.Closed;
            case State.Object:
            case State.ObjectStart:
              return WriteState.Object;
            case State.Array:
            case State.ArrayStart:
              return WriteState.Array;
            case State.Constructor:
            case State.ConstructorStart:
              return WriteState.Constructor;
            case State.Property:
              return WriteState.Property;
            case State.Start:
              return WriteState.Start;
            default:
              throw new JsonWriterException("Invalid state: " + _currentState);
          }
        }
      }
  
      /// <summary>
      /// Indicates how the output is formatted.
      /// </summary>
      public Formatting Formatting
      {
        get { return _formatting; }
        set { _formatting = value; }
      }
  
      /// <summary>
      /// Creates an instance of the <c>JsonWriter</c> class. 
      /// </summary>
      public JsonWriter()
      {
        _stack = new List<JTokenType>(8);
        _stack.Add(JTokenType.None);
        _currentState = State.Start;
        _formatting = Formatting.None;
      }
  
      private void Push(JTokenType value)
      {
        _top++;
        if (_stack.Count <= _top)
          _stack.Add(value);
        else
          _stack[_top] = value;
      }
  
      private JTokenType Pop()
      {
        JTokenType value = Peek();
        _top--;
  
        return value;
      }
  
      private JTokenType Peek()
      {
        return _stack[_top];
      }
  
      /// <summary>
      /// Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream.
      /// </summary>
      public abstract void Flush();
  
      /// <summary>
      /// Closes this stream and the underlying stream.
      /// </summary>
      public virtual void Close()
      {
        AutoCompleteAll();
      }
  
      /// <summary>
      /// Writes the beginning of a Json object.
      /// </summary>
      public virtual void WriteStartObject()
      {
        AutoComplete(JsonToken.StartObject);
        Push(JTokenType.Object);
      }
  
      /// <summary>
      /// Writes the end of a Json object.
      /// </summary>
      public void WriteEndObject()
      {
        AutoCompleteClose(JsonToken.EndObject);
      }
  
      /// <summary>
      /// Writes the beginning of a Json array.
      /// </summary>
      public virtual void WriteStartArray()
      {
        AutoComplete(JsonToken.StartArray);
        Push(JTokenType.Array);
      }
  
      /// <summary>
      /// Writes the end of an array.
      /// </summary>
      public void WriteEndArray()
      {
        AutoCompleteClose(JsonToken.EndArray);
      }
  
      /// <summary>
      /// Writes the start of a constructor with the given name.
      /// </summary>
      /// <param name="name">The name of the constructor.</param>
      public virtual void WriteStartConstructor(string name)
      {
        AutoComplete(JsonToken.StartConstructor);
        Push(JTokenType.Constructor);
      }
  
      /// <summary>
      /// Writes the end constructor.
      /// </summary>
      public void WriteEndConstructor()
      {
        AutoCompleteClose(JsonToken.EndConstructor);
      }
  
      /// <summary>
      /// Writes the property name of a name/value pair on a Json object.
      /// </summary>
      /// <param name="name">The name of the property.</param>
      public virtual void WritePropertyName(string name)
      {
        AutoComplete(JsonToken.PropertyName);
      }
  
      /// <summary>
      /// Writes the end of the current Json object or array.
      /// </summary>
      public void WriteEnd()
      {
        WriteEnd(Peek());
      }
  
      /// <summary>
      /// Writes the current <see cref="JsonReader"/> token.
      /// </summary>
      /// <param name="reader">The <see cref="JsonReader"/> to read the token from.</param>
      public void WriteToken(JsonReader reader)
      {
        ValidationUtils.ArgumentNotNull(reader, "reader");
  
        int initialDepth;
  
        if (reader.TokenType == JsonToken.None)
          initialDepth = -1;
  
gt:       else if (!IsStartToken(reader.TokenType))