Ran codeformatter
authorStephen Toub <stoub@microsoft.com>
Thu, 7 Jul 2016 16:30:16 +0000 (12:30 -0400)
committerStephen Toub <stoub@microsoft.com>
Thu, 7 Jul 2016 18:03:03 +0000 (14:03 -0400)
Commit migrated from https://github.com/dotnet/corefx/commit/9af844cd6705b9dacbf08655d45a110d16355cb9

src/libraries/System.Json/src/System/Json/JavaScriptReader.cs
src/libraries/System.Json/src/System/Json/JsonArray.cs
src/libraries/System.Json/src/System/Json/JsonObject.cs
src/libraries/System.Json/src/System/Json/JsonPrimitive.cs
src/libraries/System.Json/src/System/Json/JsonType.cs
src/libraries/System.Json/src/System/Json/JsonValue.cs
src/libraries/System.Json/tests/JsonValueTests.cs

index d2a18bd..bf3dad6 100644 (file)
@@ -10,315 +10,342 @@ using System.Text;
 
 namespace System.Runtime.Serialization.Json
 {
-       internal class JavaScriptReader
-       {
-               private readonly TextReader _r;
-               private int _line = 1, _column = 0;
+    internal class JavaScriptReader
+    {
+        private readonly TextReader _r;
+        private int _line = 1, _column = 0;
 
-               public JavaScriptReader (TextReader reader, bool raiseOnNumberError)
-               {
-                       if (reader == null)
-                               throw new ArgumentNullException (nameof(reader));
-                       this._r = reader;
-               }
+        public JavaScriptReader(TextReader reader, bool raiseOnNumberError)
+        {
+            if (reader == null)
+                throw new ArgumentNullException(nameof(reader));
+            _r = reader;
+        }
 
-               public object Read ()
-               {
-                       object v = ReadCore ();
-                       SkipSpaces ();
-                       if (ReadChar () >= 0)
-                               throw JsonError (string.Format ("extra characters in JSON input"));
-                       return v;
-               }
+        public object Read()
+        {
+            object v = ReadCore();
+            SkipSpaces();
+            if (ReadChar() >= 0)
+                throw JsonError(string.Format("extra characters in JSON input"));
+            return v;
+        }
 
-               object ReadCore ()
-               {
-                       SkipSpaces ();
-                       int c = PeekChar ();
-                       if (c < 0)
-                               throw JsonError ("Incomplete JSON input");
-                       switch (c) {
-                       case '[':
-                               ReadChar ();
-                               var list = new List<object> ();
-                               SkipSpaces ();
-                               if (PeekChar () == ']') {
-                                       ReadChar ();
-                                       return list;
-                               }
-                               while (true) {
-                                       list.Add (ReadCore ());
-                                       SkipSpaces ();
-                                       c = PeekChar ();
-                                       if (c != ',')
-                                               break;
-                                       ReadChar ();
-                                       continue;
-                               }
-                               if (ReadChar () != ']')
-                                       throw JsonError ("JSON array must end with ']'");
-                               return list.ToArray ();
-                       case '{':
-                               ReadChar ();
-                               var obj = new Dictionary<string,object> ();
-                               SkipSpaces ();
-                               if (PeekChar () == '}') {
-                                       ReadChar ();
-                                       return obj;
-                               }
-                               while (true) {
-                                       SkipSpaces ();
-                                       if (PeekChar () == '}') {
-                                               ReadChar ();
-                                               break;
-                                       }
-                                       string name = ReadStringLiteral ();
-                                       SkipSpaces ();
-                                       Expect (':');
-                                       SkipSpaces ();
-                                       obj [name] = ReadCore (); // it does not reject duplicate names.
-                                       SkipSpaces ();
-                                       c = ReadChar ();
-                                       if (c == ',')
-                                               continue;
-                                       if (c == '}')
-                                               break;
-                               }
-                               return obj.ToArray ();
-                       case 't':
-                               Expect ("true");
-                               return true;
-                       case 'f':
-                               Expect ("false");
-                               return false;
-                       case 'n':
-                               Expect ("null");
-                               // FIXME: what should we return?
-                               return (string) null;
-                       case '"':
-                               return ReadStringLiteral ();
-                       default:
-                               if ('0' <= c && c <= '9' || c == '-')
-                                       return ReadNumericLiteral ();
-                               else
-                                       throw JsonError (string.Format ("Unexpected character '{0}'", (char) c));
-                       }
-               }
+        private object ReadCore()
+        {
+            SkipSpaces();
+            int c = PeekChar();
+            if (c < 0)
+                throw JsonError("Incomplete JSON input");
+            switch (c)
+            {
+                case '[':
+                    ReadChar();
+                    var list = new List<object>();
+                    SkipSpaces();
+                    if (PeekChar() == ']')
+                    {
+                        ReadChar();
+                        return list;
+                    }
+                    while (true)
+                    {
+                        list.Add(ReadCore());
+                        SkipSpaces();
+                        c = PeekChar();
+                        if (c != ',')
+                            break;
+                        ReadChar();
+                        continue;
+                    }
+                    if (ReadChar() != ']')
+                        throw JsonError("JSON array must end with ']'");
+                    return list.ToArray();
+                case '{':
+                    ReadChar();
+                    var obj = new Dictionary<string, object>();
+                    SkipSpaces();
+                    if (PeekChar() == '}')
+                    {
+                        ReadChar();
+                        return obj;
+                    }
+                    while (true)
+                    {
+                        SkipSpaces();
+                        if (PeekChar() == '}')
+                        {
+                            ReadChar();
+                            break;
+                        }
+                        string name = ReadStringLiteral();
+                        SkipSpaces();
+                        Expect(':');
+                        SkipSpaces();
+                        obj[name] = ReadCore(); // it does not reject duplicate names.
+                        SkipSpaces();
+                        c = ReadChar();
+                        if (c == ',')
+                            continue;
+                        if (c == '}')
+                            break;
+                    }
+                    return obj.ToArray();
+                case 't':
+                    Expect("true");
+                    return true;
+                case 'f':
+                    Expect("false");
+                    return false;
+                case 'n':
+                    Expect("null");
+                    // FIXME: what should we return?
+                    return (string)null;
+                case '"':
+                    return ReadStringLiteral();
+                default:
+                    if ('0' <= c && c <= '9' || c == '-')
+                        return ReadNumericLiteral();
+                    else
+                        throw JsonError(string.Format("Unexpected character '{0}'", (char)c));
+            }
+        }
 
-               int peek;
-               bool has_peek;
-               bool prev_lf;
+        private int _peek;
+        private bool _has_peek;
+        private bool _prev_lf;
 
-               int PeekChar ()
-               {
-                       if (!has_peek) {
-                               peek = _r.Read ();
-                               has_peek = true;
-                       }
-                       return peek;
-               }
+        private int PeekChar()
+        {
+            if (!_has_peek)
+            {
+                _peek = _r.Read();
+                _has_peek = true;
+            }
+            return _peek;
+        }
 
-               int ReadChar ()
-               {
-                       int v = has_peek ? peek : _r.Read ();
+        private int ReadChar()
+        {
+            int v = _has_peek ? _peek : _r.Read();
 
-                       has_peek = false;
+            _has_peek = false;
 
-                       if (prev_lf) {
-                               _line++;
-                               _column = 0;
-                               prev_lf = false;
-                       }
+            if (_prev_lf)
+            {
+                _line++;
+                _column = 0;
+                _prev_lf = false;
+            }
 
-                       if (v == '\n')
-                               prev_lf = true;
-                       _column++;
+            if (v == '\n')
+                _prev_lf = true;
+            _column++;
 
-                       return v;
-               }
+            return v;
+        }
 
-               void SkipSpaces ()
-               {
-                       while (true) {
-                               switch (PeekChar ()) {
-                               case ' ': case '\t': case '\r': case '\n':
-                                       ReadChar ();
-                                       continue;
-                               default:
-                                       return;
-                               }
-                       }
-               }
+        private void SkipSpaces()
+        {
+            while (true)
+            {
+                switch (PeekChar())
+                {
+                    case ' ':
+                    case '\t':
+                    case '\r':
+                    case '\n':
+                        ReadChar();
+                        continue;
+                    default:
+                        return;
+                }
+            }
+        }
 
-               // It could return either int, long or decimal, depending on the parsed value.
-               object ReadNumericLiteral ()
-               {
-                       var sb = new StringBuilder ();
-                       
-                       if (PeekChar () == '-') {
-                               sb.Append ((char) ReadChar ());
-                       }
+        // It could return either int, long or decimal, depending on the parsed value.
+        private object ReadNumericLiteral()
+        {
+            var sb = new StringBuilder();
 
-                       int c;
-                       int x = 0;
-                       bool zeroStart = PeekChar () == '0';
-                       for (; ; x++) {
-                               c = PeekChar ();
-                               if (c < '0' || '9' < c)
-                                       break;
-                               sb.Append ((char) ReadChar ());
-                               if (zeroStart && x == 1)
-                                       throw JsonError ("leading zeros are not allowed");
-                       }
-                       if (x == 0) // Reached e.g. for "- "
-                               throw JsonError ("Invalid JSON numeric literal; no digit found");
+            if (PeekChar() == '-')
+            {
+                sb.Append((char)ReadChar());
+            }
 
-                       // fraction
-                       bool hasFrac = false;
-                       int fdigits = 0;
-                       if (PeekChar () == '.') {
-                               hasFrac = true;
-                               sb.Append ((char) ReadChar ());
-                               if (PeekChar () < 0)
-                                       throw JsonError ("Invalid JSON numeric literal; extra dot");
-                               while (true) {
-                                       c = PeekChar ();
-                                       if (c < '0' || '9' < c)
-                                               break;
-                                       sb.Append ((char) ReadChar ());
-                                       fdigits++;
-                               }
-                               if (fdigits == 0)
-                                       throw JsonError ("Invalid JSON numeric literal; extra dot");
-                       }
+            int c;
+            int x = 0;
+            bool zeroStart = PeekChar() == '0';
+            for (; ; x++)
+            {
+                c = PeekChar();
+                if (c < '0' || '9' < c)
+                    break;
+                sb.Append((char)ReadChar());
+                if (zeroStart && x == 1)
+                    throw JsonError("leading zeros are not allowed");
+            }
+            if (x == 0) // Reached e.g. for "- "
+                throw JsonError("Invalid JSON numeric literal; no digit found");
 
-                       c = PeekChar ();
-                       if (c != 'e' && c != 'E') {
-                               if (!hasFrac) {
-                                       int valueInt;
-                                       if (int.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueInt))
-                                               return valueInt;
-                                       
-                                       long valueLong;
-                                       if (long.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueLong))
-                                               return valueLong;
-                                       
-                                       ulong valueUlong;
-                                       if (ulong.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueUlong))
-                                               return valueUlong;
-                               }
-                               decimal valueDecimal;
-                               if (decimal.TryParse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture, out valueDecimal) && valueDecimal != 0)
-                                       return valueDecimal;
-                       } else {
-                               // exponent
-                               sb.Append ((char) ReadChar ());
-                               if (PeekChar () < 0)
-                                       throw new ArgumentException ("Invalid JSON numeric literal; incomplete exponent");
-                       
-                               c = PeekChar ();
-                               if (c == '-') {
-                                       sb.Append ((char) ReadChar ());
-                               }
-                               else if (c == '+')
-                                       sb.Append ((char) ReadChar ());
+            // fraction
+            bool hasFrac = false;
+            int fdigits = 0;
+            if (PeekChar() == '.')
+            {
+                hasFrac = true;
+                sb.Append((char)ReadChar());
+                if (PeekChar() < 0)
+                    throw JsonError("Invalid JSON numeric literal; extra dot");
+                while (true)
+                {
+                    c = PeekChar();
+                    if (c < '0' || '9' < c)
+                        break;
+                    sb.Append((char)ReadChar());
+                    fdigits++;
+                }
+                if (fdigits == 0)
+                    throw JsonError("Invalid JSON numeric literal; extra dot");
+            }
 
-                               if (PeekChar () < 0)
-                                       throw JsonError ("Invalid JSON numeric literal; incomplete exponent");
-                               while (true) {
-                                       c = PeekChar ();
-                                       if (c < '0' || '9' < c)
-                                               break;
-                                       sb.Append ((char) ReadChar ());
-                               }
-                       }
+            c = PeekChar();
+            if (c != 'e' && c != 'E')
+            {
+                if (!hasFrac)
+                {
+                    int valueInt;
+                    if (int.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueInt))
+                        return valueInt;
 
-                       return double.Parse (sb.ToString (), NumberStyles.Float, CultureInfo.InvariantCulture);
-               }
+                    long valueLong;
+                    if (long.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueLong))
+                        return valueLong;
 
-               private readonly StringBuilder _vb = new StringBuilder ();
+                    ulong valueUlong;
+                    if (ulong.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueUlong))
+                        return valueUlong;
+                }
+                decimal valueDecimal;
+                if (decimal.TryParse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture, out valueDecimal) && valueDecimal != 0)
+                    return valueDecimal;
+            }
+            else
+            {
+                // exponent
+                sb.Append((char)ReadChar());
+                if (PeekChar() < 0)
+                    throw new ArgumentException("Invalid JSON numeric literal; incomplete exponent");
 
-               private string ReadStringLiteral ()
-               {
-                       if (PeekChar () != '"')
-                               throw JsonError ("Invalid JSON string literal format");
+                c = PeekChar();
+                if (c == '-')
+                {
+                    sb.Append((char)ReadChar());
+                }
+                else if (c == '+')
+                    sb.Append((char)ReadChar());
 
-                       ReadChar ();
-                       _vb.Length = 0;
-                       while (true) {
-                               int c = ReadChar ();
-                               if (c < 0)
-                                       throw JsonError ("JSON string is not closed");
-                               if (c == '"')
-                                       return _vb.ToString ();
-                               else if (c != '\\') {
-                                       _vb.Append ((char) c);
-                                       continue;
-                               }
+                if (PeekChar() < 0)
+                    throw JsonError("Invalid JSON numeric literal; incomplete exponent");
+                while (true)
+                {
+                    c = PeekChar();
+                    if (c < '0' || '9' < c)
+                        break;
+                    sb.Append((char)ReadChar());
+                }
+            }
 
-                               // escaped expression
-                               c = ReadChar ();
-                               if (c < 0)
-                                       throw JsonError ("Invalid JSON string literal; incomplete escape sequence");
-                               switch (c) {
-                               case '"':
-                               case '\\':
-                               case '/':
-                                       _vb.Append ((char) c);
-                                       break;
-                               case 'b':
-                                       _vb.Append ('\x8');
-                                       break;
-                               case 'f':
-                                       _vb.Append ('\f');
-                                       break;
-                               case 'n':
-                                       _vb.Append ('\n');
-                                       break;
-                               case 'r':
-                                       _vb.Append ('\r');
-                                       break;
-                               case 't':
-                                       _vb.Append ('\t');
-                                       break;
-                               case 'u':
-                                       ushort cp = 0;
-                                       for (int i = 0; i < 4; i++) {
-                                               cp <<= 4;
-                                               if ((c = ReadChar ()) < 0)
-                                                       throw JsonError ("Incomplete unicode character escape literal");
-                                               if ('0' <= c && c <= '9')
-                                                       cp += (ushort) (c - '0');
-                                               if ('A' <= c && c <= 'F')
-                                                       cp += (ushort) (c - 'A' + 10);
-                                               if ('a' <= c && c <= 'f')
-                                                       cp += (ushort) (c - 'a' + 10);
-                                       }
-                                       _vb.Append ((char) cp);
-                                       break;
-                               default:
-                                       throw JsonError ("Invalid JSON string literal; unexpected escape character");
-                               }
-                       }
-               }
+            return double.Parse(sb.ToString(), NumberStyles.Float, CultureInfo.InvariantCulture);
+        }
 
-               private void Expect (char expected)
-               {
-                       int c;
-                       if ((c = ReadChar ()) != expected)
-                               throw JsonError (string.Format ("Expected '{0}', got '{1}'", expected, (char) c));
-               }
+        private readonly StringBuilder _vb = new StringBuilder();
 
-               private void Expect (string expected)
-               {
-                       for (int i = 0; i < expected.Length; i++)
-                               if (ReadChar () != expected [i])
-                                       throw JsonError (string.Format ("Expected '{0}', differed at {1}", expected, i));
-               }
+        private string ReadStringLiteral()
+        {
+            if (PeekChar() != '"')
+                throw JsonError("Invalid JSON string literal format");
 
-               private Exception JsonError (string msg)
-               {
-                       return new ArgumentException (string.Format ("{0}. At line {1}, column {2}", msg, _line, _column));
-               }
-       }
+            ReadChar();
+            _vb.Length = 0;
+            while (true)
+            {
+                int c = ReadChar();
+                if (c < 0)
+                    throw JsonError("JSON string is not closed");
+                if (c == '"')
+                    return _vb.ToString();
+                else if (c != '\\')
+                {
+                    _vb.Append((char)c);
+                    continue;
+                }
+
+                // escaped expression
+                c = ReadChar();
+                if (c < 0)
+                    throw JsonError("Invalid JSON string literal; incomplete escape sequence");
+                switch (c)
+                {
+                    case '"':
+                    case '\\':
+                    case '/':
+                        _vb.Append((char)c);
+                        break;
+                    case 'b':
+                        _vb.Append('\x8');
+                        break;
+                    case 'f':
+                        _vb.Append('\f');
+                        break;
+                    case 'n':
+                        _vb.Append('\n');
+                        break;
+                    case 'r':
+                        _vb.Append('\r');
+                        break;
+                    case 't':
+                        _vb.Append('\t');
+                        break;
+                    case 'u':
+                        ushort cp = 0;
+                        for (int i = 0; i < 4; i++)
+                        {
+                            cp <<= 4;
+                            if ((c = ReadChar()) < 0)
+                                throw JsonError("Incomplete unicode character escape literal");
+                            if ('0' <= c && c <= '9')
+                                cp += (ushort)(c - '0');
+                            if ('A' <= c && c <= 'F')
+                                cp += (ushort)(c - 'A' + 10);
+                            if ('a' <= c && c <= 'f')
+                                cp += (ushort)(c - 'a' + 10);
+                        }
+                        _vb.Append((char)cp);
+                        break;
+                    default:
+                        throw JsonError("Invalid JSON string literal; unexpected escape character");
+                }
+            }
+        }
+
+        private void Expect(char expected)
+        {
+            int c;
+            if ((c = ReadChar()) != expected)
+                throw JsonError(string.Format("Expected '{0}', got '{1}'", expected, (char)c));
+        }
+
+        private void Expect(string expected)
+        {
+            for (int i = 0; i < expected.Length; i++)
+                if (ReadChar() != expected[i])
+                    throw JsonError(string.Format("Expected '{0}', differed at {1}", expected, i));
+        }
+
+        private Exception JsonError(string msg)
+        {
+            return new ArgumentException(string.Format("{0}. At line {1}, column {2}", msg, _line, _column));
+        }
+    }
 }
index 8cd476b..e2b0439 100644 (file)
@@ -8,132 +8,139 @@ using System.IO;
 
 namespace System.Json
 {
-       public class JsonArray : JsonValue, IList<JsonValue>
-       {
-               private readonly List<JsonValue> _list;
-
-               public JsonArray (params JsonValue [] items)
-               {
-                       _list = new List<JsonValue> ();
-                       AddRange (items);
-               }
-
-               public JsonArray (IEnumerable<JsonValue> items)
-               {
-                       if (items == null)
-                               throw new ArgumentNullException (nameof(items));
-
-                       _list = new List<JsonValue> (items);
-               }
-
-               public override int Count {
-                       get { return _list.Count; }
-               }
-
-               public bool IsReadOnly {
-                       get { return false; }
-               }
-
-               public override sealed JsonValue this [int index] {
-                       get { return _list [index]; }
-                       set { _list [index] = value; }
-               }
-
-               public override JsonType JsonType {
-                       get { return JsonType.Array; }
-               }
-
-               public void Add (JsonValue item)
-               {
-                       if (item == null)
-                               throw new ArgumentNullException (nameof(item));
-
-                       _list.Add (item);
-               }
-
-               public void AddRange (IEnumerable<JsonValue> items)
-               {
+    public class JsonArray : JsonValue, IList<JsonValue>
+    {
+        private readonly List<JsonValue> _list;
+
+        public JsonArray(params JsonValue[] items)
+        {
+            _list = new List<JsonValue>();
+            AddRange(items);
+        }
+
+        public JsonArray(IEnumerable<JsonValue> items)
+        {
             if (items == null)
                 throw new ArgumentNullException(nameof(items));
 
-                       _list.AddRange (items);
-               }
-
-               public void AddRange (params JsonValue [] items)
-               {
-                       if (items == null)
-                               return;
-
-                       _list.AddRange (items);
-               }
-
-               public void Clear ()
-               {
-                       _list.Clear ();
-               }
-
-               public bool Contains (JsonValue item)
-               {
-                       return _list.Contains (item);
-               }
-
-               public void CopyTo (JsonValue [] array, int arrayIndex)
-               {
-                       _list.CopyTo (array, arrayIndex);
-               }
-
-               public int IndexOf (JsonValue item)
-               {
-                       return _list.IndexOf (item);
-               }
-
-               public void Insert (int index, JsonValue item)
-               {
-                       _list.Insert (index, item);
-               }
-
-               public bool Remove (JsonValue item)
-               {
-                       return _list.Remove (item);
-               }
-
-               public void RemoveAt (int index)
-               {
-                       _list.RemoveAt (index);
-               }
-
-               public override void Save (Stream stream)
-               {
+            _list = new List<JsonValue>(items);
+        }
+
+        public override int Count
+        {
+            get { return _list.Count; }
+        }
+
+        public bool IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public override sealed JsonValue this[int index]
+        {
+            get { return _list[index]; }
+            set { _list[index] = value; }
+        }
+
+        public override JsonType JsonType
+        {
+            get { return JsonType.Array; }
+        }
+
+        public void Add(JsonValue item)
+        {
+            if (item == null)
+                throw new ArgumentNullException(nameof(item));
+
+            _list.Add(item);
+        }
+
+        public void AddRange(IEnumerable<JsonValue> items)
+        {
+            if (items == null)
+                throw new ArgumentNullException(nameof(items));
+
+            _list.AddRange(items);
+        }
+
+        public void AddRange(params JsonValue[] items)
+        {
+            if (items == null)
+                return;
+
+            _list.AddRange(items);
+        }
+
+        public void Clear()
+        {
+            _list.Clear();
+        }
+
+        public bool Contains(JsonValue item)
+        {
+            return _list.Contains(item);
+        }
+
+        public void CopyTo(JsonValue[] array, int arrayIndex)
+        {
+            _list.CopyTo(array, arrayIndex);
+        }
+
+        public int IndexOf(JsonValue item)
+        {
+            return _list.IndexOf(item);
+        }
+
+        public void Insert(int index, JsonValue item)
+        {
+            _list.Insert(index, item);
+        }
+
+        public bool Remove(JsonValue item)
+        {
+            return _list.Remove(item);
+        }
+
+        public void RemoveAt(int index)
+        {
+            _list.RemoveAt(index);
+        }
+
+        public override void Save(Stream stream)
+        {
             if (stream == null)
                 throw new ArgumentNullException(nameof(stream));
-                       stream.WriteByte ((byte) '[');
-                       for (int i = 0; i < _list.Count; i++) {
-                               JsonValue v = _list [i];
-                               if (v != null)
-                                       v.Save (stream);
-                               else {
-                                       stream.WriteByte ((byte) 'n');
-                                       stream.WriteByte ((byte) 'u');
-                                       stream.WriteByte ((byte) 'l');
-                                       stream.WriteByte ((byte) 'l');
-                               }
-
-                               if (i < Count - 1) {
-                                       stream.WriteByte ((byte) ',');
-                                       stream.WriteByte ((byte) ' ');
-                               }
-                       }
-                       stream.WriteByte ((byte) ']');
-               }
-
-               IEnumerator<JsonValue> IEnumerable<JsonValue>.GetEnumerator ()
-               {
-                       return _list.GetEnumerator ();
-               }
-
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       return _list.GetEnumerator ();
-               }
-       }
+            stream.WriteByte((byte)'[');
+            for (int i = 0; i < _list.Count; i++)
+            {
+                JsonValue v = _list[i];
+                if (v != null)
+                    v.Save(stream);
+                else
+                {
+                    stream.WriteByte((byte)'n');
+                    stream.WriteByte((byte)'u');
+                    stream.WriteByte((byte)'l');
+                    stream.WriteByte((byte)'l');
+                }
+
+                if (i < Count - 1)
+                {
+                    stream.WriteByte((byte)',');
+                    stream.WriteByte((byte)' ');
+                }
+            }
+            stream.WriteByte((byte)']');
+        }
+
+        IEnumerator<JsonValue> IEnumerable<JsonValue>.GetEnumerator()
+        {
+            return _list.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return _list.GetEnumerator();
+        }
+    }
 }
index 010cd9c..71e4463 100644 (file)
@@ -13,151 +13,160 @@ using JsonPairEnumerable = System.Collections.Generic.IEnumerable<System.Collect
 namespace System.Json
 {
     public class JsonObject : JsonValue, IDictionary<string, JsonValue>, ICollection<JsonPair>
-       {
-               // Use SortedDictionary to make result of ToString() deterministic
-               SortedDictionary<string, JsonValue> map;
+    {
+        // Use SortedDictionary to make result of ToString() deterministic
+        private SortedDictionary<string, JsonValue> _map;
 
-               public JsonObject (params JsonPair [] items)
-               {
-                       map = new SortedDictionary<string, JsonValue> (StringComparer.Ordinal);
+        public JsonObject(params JsonPair[] items)
+        {
+            _map = new SortedDictionary<string, JsonValue>(StringComparer.Ordinal);
 
-                       if (items != null)
-                               AddRange (items);
-               }
+            if (items != null)
+                AddRange(items);
+        }
 
-               public JsonObject (JsonPairEnumerable items)
-               {
+        public JsonObject(JsonPairEnumerable items)
+        {
             if (items == null)
                 throw new ArgumentNullException(nameof(items));
 
-                       map = new SortedDictionary<string, JsonValue> (StringComparer.Ordinal);
-                       AddRange (items);
-               }
-
-               public override int Count {
-                       get { return map.Count; }
-               }
-
-               public IEnumerator<JsonPair> GetEnumerator ()
-               {
-                       return map.GetEnumerator ();
-               }
-
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       return map.GetEnumerator ();
-               }
-
-               public override sealed JsonValue this [string key] {
-                       get { return map [key]; }
-                       set { map [key] = value; }
-               }
-
-               public override JsonType JsonType {
-                       get { return JsonType.Object; }
-               }
-
-               public ICollection<string> Keys {
-                       get { return map.Keys; }
-               }
-
-               public ICollection<JsonValue> Values {
-                       get { return map.Values; }
-               }
-
-               public void Add (string key, JsonValue value)
-               {
-                       if (key == null)
-                               throw new ArgumentNullException ("key");
-
-                       map.Add (key, value);
-               }
-
-               public void Add (JsonPair pair)
-               {
-                       Add (pair.Key, pair.Value);
-               }
-
-               public void AddRange (JsonPairEnumerable items)
-               {
-                       if (items == null)
-                               throw new ArgumentNullException ("items");
-
-                       foreach (var pair in items)
-                               map.Add (pair.Key, pair.Value);
-               }
-
-               public void AddRange (params JsonPair [] items)
-               {
-                       AddRange ((JsonPairEnumerable) items);
-               }
-
-               public void Clear ()
-               {
-                       map.Clear ();
-               }
-
-               bool ICollection<JsonPair>.Contains (JsonPair item)
-               {
-                       return (map as ICollection<JsonPair>).Contains (item);
-               }
-
-               bool ICollection<JsonPair>.Remove (JsonPair item)
-               {
-                       return (map as ICollection<JsonPair>).Remove (item);
-               }
-
-               public override bool ContainsKey (string key)
-               {
-                       if (key == null)
-                               throw new ArgumentNullException ("key");
-
-                       return map.ContainsKey (key);
-               }
-
-               public void CopyTo (JsonPair [] array, int arrayIndex)
-               {
-                       (map as ICollection<JsonPair>).CopyTo (array, arrayIndex);
-               }
-
-               public bool Remove (string key)
-               {
-                       if (key == null)
-                               throw new ArgumentNullException ("key");
-
-                       return map.Remove (key);
-               }
-
-               bool ICollection<JsonPair>.IsReadOnly {
-                       get { return false; }
-               }
-
-               public override void Save (Stream stream)
-               {
-                       if (stream == null)
-                               throw new ArgumentNullException ("stream");
-                       stream.WriteByte ((byte) '{');
-                       foreach (JsonPair pair in map) {
-                               stream.WriteByte ((byte) '"');
-                               byte [] bytes = Encoding.UTF8.GetBytes (EscapeString (pair.Key));
-                               stream.Write (bytes, 0, bytes.Length);
-                               stream.WriteByte ((byte) '"');
-                               stream.WriteByte ((byte) ',');
-                               stream.WriteByte ((byte) ' ');
-                               if (pair.Value == null) {
-                                       stream.WriteByte ((byte) 'n');
-                                       stream.WriteByte ((byte) 'u');
-                                       stream.WriteByte ((byte) 'l');
-                                       stream.WriteByte ((byte) 'l');
-                               } else
-                                       pair.Value.Save (stream);
-                       }
-                       stream.WriteByte ((byte) '}');
-               }
-
-               public bool TryGetValue (string key, out JsonValue value)
-               {
-                       return map.TryGetValue (key, out value);
-               }
-       }
+            _map = new SortedDictionary<string, JsonValue>(StringComparer.Ordinal);
+            AddRange(items);
+        }
+
+        public override int Count
+        {
+            get { return _map.Count; }
+        }
+
+        public IEnumerator<JsonPair> GetEnumerator()
+        {
+            return _map.GetEnumerator();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            return _map.GetEnumerator();
+        }
+
+        public override sealed JsonValue this[string key]
+        {
+            get { return _map[key]; }
+            set { _map[key] = value; }
+        }
+
+        public override JsonType JsonType
+        {
+            get { return JsonType.Object; }
+        }
+
+        public ICollection<string> Keys
+        {
+            get { return _map.Keys; }
+        }
+
+        public ICollection<JsonValue> Values
+        {
+            get { return _map.Values; }
+        }
+
+        public void Add(string key, JsonValue value)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            _map.Add(key, value);
+        }
+
+        public void Add(JsonPair pair)
+        {
+            Add(pair.Key, pair.Value);
+        }
+
+        public void AddRange(JsonPairEnumerable items)
+        {
+            if (items == null)
+                throw new ArgumentNullException("items");
+
+            foreach (var pair in items)
+                _map.Add(pair.Key, pair.Value);
+        }
+
+        public void AddRange(params JsonPair[] items)
+        {
+            AddRange((JsonPairEnumerable)items);
+        }
+
+        public void Clear()
+        {
+            _map.Clear();
+        }
+
+        bool ICollection<JsonPair>.Contains(JsonPair item)
+        {
+            return (_map as ICollection<JsonPair>).Contains(item);
+        }
+
+        bool ICollection<JsonPair>.Remove(JsonPair item)
+        {
+            return (_map as ICollection<JsonPair>).Remove(item);
+        }
+
+        public override bool ContainsKey(string key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            return _map.ContainsKey(key);
+        }
+
+        public void CopyTo(JsonPair[] array, int arrayIndex)
+        {
+            (_map as ICollection<JsonPair>).CopyTo(array, arrayIndex);
+        }
+
+        public bool Remove(string key)
+        {
+            if (key == null)
+                throw new ArgumentNullException("key");
+
+            return _map.Remove(key);
+        }
+
+        bool ICollection<JsonPair>.IsReadOnly
+        {
+            get { return false; }
+        }
+
+        public override void Save(Stream stream)
+        {
+            if (stream == null)
+                throw new ArgumentNullException("stream");
+            stream.WriteByte((byte)'{');
+            foreach (JsonPair pair in _map)
+            {
+                stream.WriteByte((byte)'"');
+                byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(pair.Key));
+                stream.Write(bytes, 0, bytes.Length);
+                stream.WriteByte((byte)'"');
+                stream.WriteByte((byte)',');
+                stream.WriteByte((byte)' ');
+                if (pair.Value == null)
+                {
+                    stream.WriteByte((byte)'n');
+                    stream.WriteByte((byte)'u');
+                    stream.WriteByte((byte)'l');
+                    stream.WriteByte((byte)'l');
+                }
+                else
+                    pair.Value.Save(stream);
+            }
+            stream.WriteByte((byte)'}');
+        }
+
+        public bool TryGetValue(string key, out JsonValue value)
+        {
+            return _map.TryGetValue(key, out value);
+        }
+    }
 }
index 1bc2c0c..cd932a2 100644 (file)
@@ -10,110 +10,110 @@ namespace System.Json
 {
     public class JsonPrimitive : JsonValue
     {
-        object value;
+        private object _value;
 
         public JsonPrimitive(bool value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(byte value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(char value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(decimal value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(double value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(float value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(int value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(long value)
         {
-            this.value = value;
+            _value = value;
         }
 
         [CLSCompliant(false)]
         public JsonPrimitive(sbyte value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(short value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(string value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(DateTime value)
         {
-            this.value = value;
+            _value = value;
         }
 
         [CLSCompliant(false)]
         public JsonPrimitive(uint value)
         {
-            this.value = value;
+            _value = value;
         }
 
         [CLSCompliant(false)]
         public JsonPrimitive(ulong value)
         {
-            this.value = value;
+            _value = value;
         }
 
         [CLSCompliant(false)]
         public JsonPrimitive(ushort value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(DateTimeOffset value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(Guid value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(TimeSpan value)
         {
-            this.value = value;
+            _value = value;
         }
 
         public JsonPrimitive(Uri value)
         {
-            this.value = value;
+            _value = value;
         }
 
         internal object Value
         {
-            get { return value; }
+            get { return _value; }
         }
 
         public override JsonType JsonType
@@ -121,8 +121,8 @@ namespace System.Json
             get
             {
                 return
-                    value == null || value.GetType() == typeof(char) || value.GetType() == typeof(string) || value.GetType() == typeof(DateTime) || value.GetType() == typeof(object) ? JsonType.String : // DateTimeOffset || Guid || TimeSpan || Uri
-                    value.GetType() == typeof(bool) ? JsonType.Boolean :
+                    _value == null || _value.GetType() == typeof(char) || _value.GetType() == typeof(string) || _value.GetType() == typeof(DateTime) || _value.GetType() == typeof(object) ? JsonType.String : // DateTimeOffset || Guid || TimeSpan || Uri
+                    _value.GetType() == typeof(bool) ? JsonType.Boolean :
                     JsonType.Number;
             }
         }
@@ -135,14 +135,14 @@ namespace System.Json
             switch (JsonType)
             {
                 case JsonType.Boolean:
-                    if ((bool)value)
+                    if ((bool)_value)
                         stream.Write(s_trueBytes, 0, 4);
                     else
                         stream.Write(s_falseBytes, 0, 5);
                     break;
                 case JsonType.String:
                     stream.WriteByte((byte)'\"');
-                    byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(value.ToString()));
+                    byte[] bytes = Encoding.UTF8.GetBytes(EscapeString(_value.ToString()));
                     stream.Write(bytes, 0, bytes.Length);
                     stream.WriteByte((byte)'\"');
                     break;
@@ -158,18 +158,18 @@ namespace System.Json
             switch (JsonType)
             {
                 case JsonType.String:
-                    if (value is string || value == null)
-                        return (string)value;
-                    if (value is char)
-                        return value.ToString();
-                    throw new NotImplementedException("GetFormattedString from value type " + value.GetType());
+                    if (_value is string || _value == null)
+                        return (string)_value;
+                    if (_value is char)
+                        return _value.ToString();
+                    throw new NotImplementedException("GetFormattedString from value type " + _value.GetType());
                 case JsonType.Number:
                     string s;
-                    if (value is float || value is double)
+                    if (_value is float || _value is double)
                         // Use "round-trip" format
-                        s = ((IFormattable)value).ToString("R", NumberFormatInfo.InvariantInfo);
+                        s = ((IFormattable)_value).ToString("R", NumberFormatInfo.InvariantInfo);
                     else
-                        s = ((IFormattable)value).ToString("G", NumberFormatInfo.InvariantInfo);
+                        s = ((IFormattable)_value).ToString("G", NumberFormatInfo.InvariantInfo);
                     if (s == "NaN" || s == "Infinity" || s == "-Infinity")
                         return "\"" + s + "\"";
                     else
index ee8503e..b6922e0 100644 (file)
@@ -4,12 +4,12 @@
 
 namespace System.Json
 {
-       public enum JsonType
-       {
-               String,
-               Number,
-               Object,
-               Array,
-               Boolean,
-       }
+    public enum JsonType
+    {
+        String,
+        Number,
+        Object,
+        Array,
+        Boolean,
+    }
 }
index ed84a99..5ad9c88 100644 (file)
@@ -14,493 +14,503 @@ using JsonPair = System.Collections.Generic.KeyValuePair<string, System.Json.Jso
 namespace System.Json
 {
     public abstract class JsonValue : IEnumerable
-       {
-               public static JsonValue Load (Stream stream)
-               {
+    {
+        public static JsonValue Load(Stream stream)
+        {
             if (stream == null)
                 throw new ArgumentNullException(nameof(stream));
-                       return Load (new StreamReader (stream, true));
-               }
+            return Load(new StreamReader(stream, true));
+        }
 
-               public static JsonValue Load (TextReader textReader)
-               {
+        public static JsonValue Load(TextReader textReader)
+        {
             if (textReader == null)
                 throw new ArgumentNullException(nameof(textReader));
 
-                       var ret = new JavaScriptReader (textReader, true).Read ();
-
-                       return ToJsonValue (ret);
-               }
-
-               static IEnumerable<KeyValuePair<string,JsonValue>> ToJsonPairEnumerable (IEnumerable<KeyValuePair<string,object>> kvpc)
-               {
-                       foreach (var kvp in kvpc)
-                               yield return new KeyValuePair<string,JsonValue> (kvp.Key, ToJsonValue (kvp.Value));
-               }
-
-               static IEnumerable<JsonValue> ToJsonValueEnumerable (IEnumerable<object> arr)
-               {
-                       foreach (var obj in arr)
-                               yield return ToJsonValue (obj);
-               }
-
-               static JsonValue ToJsonValue (object ret)
-               {
-                       if (ret == null)
-                               return null;
-                       var kvpc = ret as IEnumerable<KeyValuePair<string,object>>;
-                       if (kvpc != null)
-                               return new JsonObject (ToJsonPairEnumerable (kvpc));
-                       var arr = ret as IEnumerable<object>;
-                       if (arr != null)
-                               return new JsonArray (ToJsonValueEnumerable (arr));
-
-                       if (ret is bool)
-                               return new JsonPrimitive ((bool) ret);
-                       if (ret is byte)
-                               return new JsonPrimitive ((byte) ret);
-                       if (ret is char)
-                               return new JsonPrimitive ((char) ret);
-                       if (ret is decimal)
-                               return new JsonPrimitive ((decimal) ret);
-                       if (ret is double)
-                               return new JsonPrimitive ((double) ret);
-                       if (ret is float)
-                               return new JsonPrimitive ((float) ret);
-                       if (ret is int)
-                               return new JsonPrimitive ((int) ret);
-                       if (ret is long)
-                               return new JsonPrimitive ((long) ret);
-                       if (ret is sbyte)
-                               return new JsonPrimitive ((sbyte) ret);
-                       if (ret is short)
-                               return new JsonPrimitive ((short) ret);
-                       if (ret is string)
-                               return new JsonPrimitive ((string) ret);
-                       if (ret is uint)
-                               return new JsonPrimitive ((uint) ret);
-                       if (ret is ulong)
-                               return new JsonPrimitive ((ulong) ret);
-                       if (ret is ushort)
-                               return new JsonPrimitive ((ushort) ret);
-                       if (ret is DateTime)
-                               return new JsonPrimitive ((DateTime) ret);
-                       if (ret is DateTimeOffset)
-                               return new JsonPrimitive ((DateTimeOffset) ret);
-                       if (ret is Guid)
-                               return new JsonPrimitive ((Guid) ret);
-                       if (ret is TimeSpan)
-                               return new JsonPrimitive ((TimeSpan) ret);
-                       if (ret is Uri)
-                               return new JsonPrimitive ((Uri) ret);
-                       throw new NotSupportedException (string.Format ("Unexpected parser return type: {0}", ret.GetType ()));
-               }
-
-               public static JsonValue Parse (string jsonString)
-               {
+            var ret = new JavaScriptReader(textReader, true).Read();
+
+            return ToJsonValue(ret);
+        }
+
+        private static IEnumerable<KeyValuePair<string, JsonValue>> ToJsonPairEnumerable(IEnumerable<KeyValuePair<string, object>> kvpc)
+        {
+            foreach (var kvp in kvpc)
+                yield return new KeyValuePair<string, JsonValue>(kvp.Key, ToJsonValue(kvp.Value));
+        }
+
+        private static IEnumerable<JsonValue> ToJsonValueEnumerable(IEnumerable<object> arr)
+        {
+            foreach (var obj in arr)
+                yield return ToJsonValue(obj);
+        }
+
+        private static JsonValue ToJsonValue(object ret)
+        {
+            if (ret == null)
+                return null;
+            var kvpc = ret as IEnumerable<KeyValuePair<string, object>>;
+            if (kvpc != null)
+                return new JsonObject(ToJsonPairEnumerable(kvpc));
+            var arr = ret as IEnumerable<object>;
+            if (arr != null)
+                return new JsonArray(ToJsonValueEnumerable(arr));
+
+            if (ret is bool)
+                return new JsonPrimitive((bool)ret);
+            if (ret is byte)
+                return new JsonPrimitive((byte)ret);
+            if (ret is char)
+                return new JsonPrimitive((char)ret);
+            if (ret is decimal)
+                return new JsonPrimitive((decimal)ret);
+            if (ret is double)
+                return new JsonPrimitive((double)ret);
+            if (ret is float)
+                return new JsonPrimitive((float)ret);
+            if (ret is int)
+                return new JsonPrimitive((int)ret);
+            if (ret is long)
+                return new JsonPrimitive((long)ret);
+            if (ret is sbyte)
+                return new JsonPrimitive((sbyte)ret);
+            if (ret is short)
+                return new JsonPrimitive((short)ret);
+            if (ret is string)
+                return new JsonPrimitive((string)ret);
+            if (ret is uint)
+                return new JsonPrimitive((uint)ret);
+            if (ret is ulong)
+                return new JsonPrimitive((ulong)ret);
+            if (ret is ushort)
+                return new JsonPrimitive((ushort)ret);
+            if (ret is DateTime)
+                return new JsonPrimitive((DateTime)ret);
+            if (ret is DateTimeOffset)
+                return new JsonPrimitive((DateTimeOffset)ret);
+            if (ret is Guid)
+                return new JsonPrimitive((Guid)ret);
+            if (ret is TimeSpan)
+                return new JsonPrimitive((TimeSpan)ret);
+            if (ret is Uri)
+                return new JsonPrimitive((Uri)ret);
+            throw new NotSupportedException(string.Format("Unexpected parser return type: {0}", ret.GetType()));
+        }
+
+        public static JsonValue Parse(string jsonString)
+        {
             if (jsonString == null)
                 throw new ArgumentNullException(nameof(jsonString));
-                       return Load (new StringReader (jsonString));
-               }
-
-               public virtual int Count {
-                       get { throw new InvalidOperationException (); }
-               }
-
-               public abstract JsonType JsonType { get; }
-
-               public virtual JsonValue this [int index] {
-                       get { throw new InvalidOperationException (); }
-                       set { throw new InvalidOperationException (); }
-               }
-
-               public virtual JsonValue this [string key] {
-                       get { throw new InvalidOperationException (); }
-                       set { throw new InvalidOperationException (); }
-               }
-
-               public virtual bool ContainsKey (string key)
-               {
-                       throw new InvalidOperationException ();
-               }
-
-               public virtual void Save (Stream stream)
-               {
-                       if (stream == null)
-                               throw new ArgumentNullException ("stream");
-                       Save (new StreamWriter (stream));
-               }
-
-               public virtual void Save (TextWriter textWriter)
-               {
-                       if (textWriter == null)
-                               throw new ArgumentNullException ("textWriter");
-                       SaveInternal (textWriter);
-               }
-               
-               void SaveInternal (TextWriter w)
-               {
-                       switch (JsonType) {
-                       case JsonType.Object:
-                               w.Write ('{');
-                               bool following = false;
-                               foreach (JsonPair pair in ((JsonObject) this)) {
-                                       if (following)
-                                               w.Write (", ");
-                                       w.Write ('\"');
-                                       w.Write (EscapeString (pair.Key));
-                                       w.Write ("\": ");
-                                       if (pair.Value == null)
-                                               w.Write ("null");
-                                       else
-                                               pair.Value.SaveInternal (w);
-                                       following = true;
-                               }
-                               w.Write ('}');
-                               break;
-                       case JsonType.Array:
-                               w.Write ('[');
-                               following = false;
-                               foreach (JsonValue v in ((JsonArray) this)) {
-                                       if (following)
-                                               w.Write (", ");
-                                       if (v != null) 
-                                               v.SaveInternal (w);
-                                       else
-                                               w.Write ("null");
-                                       following = true;
-                               }
-                               w.Write (']');
-                               break;
-                       case JsonType.Boolean:
-                               w.Write ((bool) this ? "true" : "false");
-                               break;
-                       case JsonType.String:
-                               w.Write ('"');
-                               w.Write (EscapeString (((JsonPrimitive) this).GetFormattedString ()));
-                               w.Write ('"');
-                               break;
-                       default:
-                               w.Write (((JsonPrimitive) this).GetFormattedString ());
-                               break;
-                       }
-               }
-
-               public override string ToString ()
-               {
-                       StringWriter sw = new StringWriter ();
-                       Save (sw);
-                       return sw.ToString ();
-               }
-
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       throw new InvalidOperationException ();
-               }
-
-               // Characters which have to be escaped:
-               // - Required by JSON Spec: Control characters, '"' and '\\'
-               // - Broken surrogates to make sure the JSON string is valid Unicode
-               //   (and can be encoded as UTF8)
-               // - JSON does not require U+2028 and U+2029 to be escaped, but
-               //   JavaScript does require this:
-               //   http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character/9168133#9168133
-               // - '/' also does not have to be escaped, but escaping it when
-               //   preceeded by a '<' avoids problems with JSON in HTML <script> tags
-               bool NeedEscape (string src, int i) {
-                       char c = src [i];
-                       return c < 32 || c == '"' || c == '\\'
-                               // Broken lead surrogate
-                               || (c >= '\uD800' && c <= '\uDBFF' &&
-                                       (i == src.Length - 1 || src [i + 1] < '\uDC00' || src [i + 1] > '\uDFFF'))
-                               // Broken tail surrogate
-                               || (c >= '\uDC00' && c <= '\uDFFF' &&
-                                       (i == 0 || src [i - 1] < '\uD800' || src [i - 1] > '\uDBFF'))
-                               // To produce valid JavaScript
-                               || c == '\u2028' || c == '\u2029'
-                               // Escape "</" for <script> tags
-                               || (c == '/' && i > 0 && src [i - 1] == '<');
-               }
-               
-               internal string EscapeString (string src)
-               {
-                       if (src == null)
-                               return null;
-
-                       for (int i = 0; i < src.Length; i++)
-                               if (NeedEscape (src, i)) {
-                                       var sb = new StringBuilder ();
-                                       if (i > 0)
-                                               sb.Append (src, 0, i);
-                                       return DoEscapeString (sb, src, i);
-                               }
-                       return src;
-               }
-
-               string DoEscapeString (StringBuilder sb, string src, int cur)
-               {
-                       int start = cur;
-                       for (int i = cur; i < src.Length; i++)
-                               if (NeedEscape (src, i)) {
-                                       sb.Append (src, start, i - start);
-                                       switch (src [i]) {
-                                       case '\b': sb.Append ("\\b"); break;
-                                       case '\f': sb.Append ("\\f"); break;
-                                       case '\n': sb.Append ("\\n"); break;
-                                       case '\r': sb.Append ("\\r"); break;
-                                       case '\t': sb.Append ("\\t"); break;
-                                       case '\"': sb.Append ("\\\""); break;
-                                       case '\\': sb.Append ("\\\\"); break;
-                                       case '/': sb.Append ("\\/"); break;
-                                       default:
-                                               sb.Append ("\\u");
-                                               sb.Append (((int) src [i]).ToString ("x04"));
-                                               break;
-                                       }
-                                       start = i + 1;
-                               }
-                       sb.Append (src, start, src.Length - start);
-                       return sb.ToString ();
-               }
-
-               // CLI -> JsonValue
-
-               public static implicit operator JsonValue (bool value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (byte value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (char value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (decimal value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (double value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (float value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (int value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (long value)
-               {
-                       return new JsonPrimitive (value);
-               }
+            return Load(new StringReader(jsonString));
+        }
+
+        public virtual int Count
+        {
+            get { throw new InvalidOperationException(); }
+        }
+
+        public abstract JsonType JsonType { get; }
+
+        public virtual JsonValue this[int index]
+        {
+            get { throw new InvalidOperationException(); }
+            set { throw new InvalidOperationException(); }
+        }
+
+        public virtual JsonValue this[string key]
+        {
+            get { throw new InvalidOperationException(); }
+            set { throw new InvalidOperationException(); }
+        }
+
+        public virtual bool ContainsKey(string key)
+        {
+            throw new InvalidOperationException();
+        }
+
+        public virtual void Save(Stream stream)
+        {
+            if (stream == null)
+                throw new ArgumentNullException("stream");
+            Save(new StreamWriter(stream));
+        }
+
+        public virtual void Save(TextWriter textWriter)
+        {
+            if (textWriter == null)
+                throw new ArgumentNullException("textWriter");
+            SaveInternal(textWriter);
+        }
+
+        private void SaveInternal(TextWriter w)
+        {
+            switch (JsonType)
+            {
+                case JsonType.Object:
+                    w.Write('{');
+                    bool following = false;
+                    foreach (JsonPair pair in ((JsonObject)this))
+                    {
+                        if (following)
+                            w.Write(", ");
+                        w.Write('\"');
+                        w.Write(EscapeString(pair.Key));
+                        w.Write("\": ");
+                        if (pair.Value == null)
+                            w.Write("null");
+                        else
+                            pair.Value.SaveInternal(w);
+                        following = true;
+                    }
+                    w.Write('}');
+                    break;
+                case JsonType.Array:
+                    w.Write('[');
+                    following = false;
+                    foreach (JsonValue v in ((JsonArray)this))
+                    {
+                        if (following)
+                            w.Write(", ");
+                        if (v != null)
+                            v.SaveInternal(w);
+                        else
+                            w.Write("null");
+                        following = true;
+                    }
+                    w.Write(']');
+                    break;
+                case JsonType.Boolean:
+                    w.Write((bool)this ? "true" : "false");
+                    break;
+                case JsonType.String:
+                    w.Write('"');
+                    w.Write(EscapeString(((JsonPrimitive)this).GetFormattedString()));
+                    w.Write('"');
+                    break;
+                default:
+                    w.Write(((JsonPrimitive)this).GetFormattedString());
+                    break;
+            }
+        }
+
+        public override string ToString()
+        {
+            StringWriter sw = new StringWriter();
+            Save(sw);
+            return sw.ToString();
+        }
+
+        IEnumerator IEnumerable.GetEnumerator()
+        {
+            throw new InvalidOperationException();
+        }
+
+        // Characters which have to be escaped:
+        // - Required by JSON Spec: Control characters, '"' and '\\'
+        // - Broken surrogates to make sure the JSON string is valid Unicode
+        //   (and can be encoded as UTF8)
+        // - JSON does not require U+2028 and U+2029 to be escaped, but
+        //   JavaScript does require this:
+        //   http://stackoverflow.com/questions/2965293/javascript-parse-error-on-u2028-unicode-character/9168133#9168133
+        // - '/' also does not have to be escaped, but escaping it when
+        //   preceeded by a '<' avoids problems with JSON in HTML <script> tags
+        private bool NeedEscape(string src, int i)
+        {
+            char c = src[i];
+            return c < 32 || c == '"' || c == '\\'
+                // Broken lead surrogate
+                || (c >= '\uD800' && c <= '\uDBFF' &&
+                    (i == src.Length - 1 || src[i + 1] < '\uDC00' || src[i + 1] > '\uDFFF'))
+                // Broken tail surrogate
+                || (c >= '\uDC00' && c <= '\uDFFF' &&
+                    (i == 0 || src[i - 1] < '\uD800' || src[i - 1] > '\uDBFF'))
+                // To produce valid JavaScript
+                || c == '\u2028' || c == '\u2029'
+                // Escape "</" for <script> tags
+                || (c == '/' && i > 0 && src[i - 1] == '<');
+        }
+
+        internal string EscapeString(string src)
+        {
+            if (src == null)
+                return null;
+
+            for (int i = 0; i < src.Length; i++)
+                if (NeedEscape(src, i))
+                {
+                    var sb = new StringBuilder();
+                    if (i > 0)
+                        sb.Append(src, 0, i);
+                    return DoEscapeString(sb, src, i);
+                }
+            return src;
+        }
+
+        private string DoEscapeString(StringBuilder sb, string src, int cur)
+        {
+            int start = cur;
+            for (int i = cur; i < src.Length; i++)
+                if (NeedEscape(src, i))
+                {
+                    sb.Append(src, start, i - start);
+                    switch (src[i])
+                    {
+                        case '\b': sb.Append("\\b"); break;
+                        case '\f': sb.Append("\\f"); break;
+                        case '\n': sb.Append("\\n"); break;
+                        case '\r': sb.Append("\\r"); break;
+                        case '\t': sb.Append("\\t"); break;
+                        case '\"': sb.Append("\\\""); break;
+                        case '\\': sb.Append("\\\\"); break;
+                        case '/': sb.Append("\\/"); break;
+                        default:
+                            sb.Append("\\u");
+                            sb.Append(((int)src[i]).ToString("x04"));
+                            break;
+                    }
+                    start = i + 1;
+                }
+            sb.Append(src, start, src.Length - start);
+            return sb.ToString();
+        }
+
+        // CLI -> JsonValue
+
+        public static implicit operator JsonValue(bool value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(byte value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(char value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(decimal value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(double value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(float value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(int value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(long value)
+        {
+            return new JsonPrimitive(value);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator JsonValue (sbyte value)
-               {
-                       return new JsonPrimitive (value);
-               }
+        public static implicit operator JsonValue(sbyte value)
+        {
+            return new JsonPrimitive(value);
+        }
 
-               public static implicit operator JsonValue (short value)
-               {
-                       return new JsonPrimitive (value);
-               }
+        public static implicit operator JsonValue(short value)
+        {
+            return new JsonPrimitive(value);
+        }
 
-               public static implicit operator JsonValue (string value)
-               {
-                       return new JsonPrimitive (value);
-               }
+        public static implicit operator JsonValue(string value)
+        {
+            return new JsonPrimitive(value);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator JsonValue (uint value)
+        public static implicit operator JsonValue(uint value)
         {
-                       return new JsonPrimitive (value);
-               }
+            return new JsonPrimitive(value);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator JsonValue (ulong value)
+        public static implicit operator JsonValue(ulong value)
         {
-                       return new JsonPrimitive (value);
-               }
+            return new JsonPrimitive(value);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator JsonValue (ushort value)
-        {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (DateTime value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (DateTimeOffset value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (Guid value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (TimeSpan value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               public static implicit operator JsonValue (Uri value)
-               {
-                       return new JsonPrimitive (value);
-               }
-
-               // JsonValue -> CLI
-
-               public static implicit operator bool (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToBoolean (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator byte (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator char (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToChar (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator decimal (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToDecimal (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator double (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToDouble (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator float (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToSingle (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator int (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator long (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToInt64 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
+        public static implicit operator JsonValue(ushort value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(DateTime value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(DateTimeOffset value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(Guid value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(TimeSpan value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        public static implicit operator JsonValue(Uri value)
+        {
+            return new JsonPrimitive(value);
+        }
+
+        // JsonValue -> CLI
+
+        public static implicit operator bool (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToBoolean(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator byte (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator char (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToChar(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator decimal (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToDecimal(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator double (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToDouble(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator float (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToSingle(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator int (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator long (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator sbyte (JsonValue value)
-        {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToSByte (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator short (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator string (JsonValue value)
-               {
-                       if (value == null)
-                               return null;
-                       return (string) ((JsonPrimitive) value).Value;
-               }
+        public static implicit operator sbyte (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToSByte(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator short (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator string (JsonValue value)
+        {
+            if (value == null)
+                return null;
+            return (string)((JsonPrimitive)value).Value;
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator uint (JsonValue value)
+        public static implicit operator uint (JsonValue value)
         {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToUInt32 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToUInt32(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator ulong (JsonValue value)
+        public static implicit operator ulong (JsonValue value)
         {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToUInt64(((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToUInt64(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
 
         [CLSCompliant(false)]
-               public static implicit operator ushort (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return Convert.ToUInt16 (((JsonPrimitive) value).Value, NumberFormatInfo.InvariantInfo);
-               }
-
-               public static implicit operator DateTime (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return (DateTime) ((JsonPrimitive) value).Value;
-               }
-
-               public static implicit operator DateTimeOffset (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return (DateTimeOffset) ((JsonPrimitive) value).Value;
-               }
-
-               public static implicit operator TimeSpan (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return (TimeSpan) ((JsonPrimitive) value).Value;
-               }
-
-               public static implicit operator Guid (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return (Guid) ((JsonPrimitive) value).Value;
-               }
-
-               public static implicit operator Uri (JsonValue value)
-               {
-                       if (value == null)
-                               throw new ArgumentNullException (nameof(value));
-                       return (Uri) ((JsonPrimitive) value).Value;
-               }
-       }
+        public static implicit operator ushort (JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return Convert.ToUInt16(((JsonPrimitive)value).Value, NumberFormatInfo.InvariantInfo);
+        }
+
+        public static implicit operator DateTime(JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return (DateTime)((JsonPrimitive)value).Value;
+        }
+
+        public static implicit operator DateTimeOffset(JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return (DateTimeOffset)((JsonPrimitive)value).Value;
+        }
+
+        public static implicit operator TimeSpan(JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return (TimeSpan)((JsonPrimitive)value).Value;
+        }
+
+        public static implicit operator Guid(JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return (Guid)((JsonPrimitive)value).Value;
+        }
+
+        public static implicit operator Uri(JsonValue value)
+        {
+            if (value == null)
+                throw new ArgumentNullException(nameof(value));
+            return (Uri)((JsonPrimitive)value).Value;
+        }
+    }
 }
index 63ac33f..20beeb9 100644 (file)
@@ -86,14 +86,14 @@ namespace System.Json.Tests
         }
 
         // Parse a json string and compare to the expected value
-        void CheckDouble(double expected, string json)
+        private void CheckDouble(double expected, string json)
         {
             double jvalue = (double)JsonValue.Parse(json);
             Assert.Equal(expected, jvalue);
         }
 
         // Convert a number to json and parse the string, then compare the result to the original value
-        void CheckDouble(double number)
+        private void CheckDouble(double number)
         {
             double jvalue = (double)JsonValue.Parse(new JsonPrimitive(number).ToString());
             Assert.Equal(number, jvalue); // should be exactly the same
@@ -217,7 +217,7 @@ namespace System.Json.Tests
         }
 
         // Convert a string to json and parse the string, then compare the result to the original value
-        void CheckString(string str)
+        private void CheckString(string str)
         {
             var json = new JsonPrimitive(str).ToString();
             // Check whether the string is valid Unicode (will throw for broken surrogate pairs)