| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478 | #region Header/** * JsonReader.cs *   Stream-like access to JSON text. * * The authors disclaim copyright to this source code. For more details, see * the COPYING file included with this distribution. **/#endregionusing System;using System.Collections.Generic;using System.Globalization;using System.IO;using System.Text;namespace LitJson{    public enum JsonToken    {        None,        ObjectStart,        PropertyName,        ObjectEnd,        ArrayStart,        ArrayEnd,        Int,        Long,        Double,        String,        Boolean,        Null    }    public class JsonReader    {        #region Fields        private static readonly IDictionary<int, IDictionary<int, int[]>> parse_table;        private Stack<int>    automaton_stack;        private int           current_input;        private int           current_symbol;        private bool          end_of_json;        private bool          end_of_input;        private Lexer         lexer;        private bool          parser_in_string;        private bool          parser_return;        private bool          read_started;        private TextReader    reader;        private bool          reader_is_owned;        private bool          skip_non_members;        private object        token_value;        private JsonToken     token;        #endregion        #region Public Properties        public bool AllowComments {            get { return lexer.AllowComments; }            set { lexer.AllowComments = value; }        }        public bool AllowSingleQuotedStrings {            get { return lexer.AllowSingleQuotedStrings; }            set { lexer.AllowSingleQuotedStrings = value; }        }        public bool SkipNonMembers {            get { return skip_non_members; }            set { skip_non_members = value; }        }        public bool EndOfInput {            get { return end_of_input; }        }        public bool EndOfJson {            get { return end_of_json; }        }        public JsonToken Token {            get { return token; }        }        public object Value {            get { return token_value; }        }        #endregion        #region Constructors        static JsonReader ()        {            parse_table = PopulateParseTable ();        }        public JsonReader (string json_text) :            this (new StringReader (json_text), true)        {        }        public JsonReader (TextReader reader) :            this (reader, false)        {        }        private JsonReader (TextReader reader, bool owned)        {            if (reader == null)                throw new ArgumentNullException ("reader");            parser_in_string = false;            parser_return    = false;            read_started = false;            automaton_stack = new Stack<int> ();            automaton_stack.Push ((int) ParserToken.End);            automaton_stack.Push ((int) ParserToken.Text);            lexer = new Lexer (reader);            end_of_input = false;            end_of_json  = false;            skip_non_members = true;            this.reader = reader;            reader_is_owned = owned;        }        #endregion        #region Static Methods        private static IDictionary<int, IDictionary<int, int[]>> PopulateParseTable ()        {            // See section A.2. of the manual for details            IDictionary<int, IDictionary<int, int[]>> parse_table = new Dictionary<int, IDictionary<int, int[]>> ();            TableAddRow (parse_table, ParserToken.Array);            TableAddCol (parse_table, ParserToken.Array, '[',                            '[',                            (int) ParserToken.ArrayPrime);            TableAddRow (parse_table, ParserToken.ArrayPrime);            TableAddCol (parse_table, ParserToken.ArrayPrime, '"',                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, '[',                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, ']',                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, '{',                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Number,                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.True,                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.False,                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddCol (parse_table, ParserToken.ArrayPrime, (int) ParserToken.Null,                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest,                            ']');            TableAddRow (parse_table, ParserToken.Object);            TableAddCol (parse_table, ParserToken.Object, '{',                            '{',                            (int) ParserToken.ObjectPrime);            TableAddRow (parse_table, ParserToken.ObjectPrime);            TableAddCol (parse_table, ParserToken.ObjectPrime, '"',                            (int) ParserToken.Pair,                            (int) ParserToken.PairRest,                            '}');            TableAddCol (parse_table, ParserToken.ObjectPrime, '}',                            '}');            TableAddRow (parse_table, ParserToken.Pair);            TableAddCol (parse_table, ParserToken.Pair, '"',                            (int) ParserToken.String,                            ':',                            (int) ParserToken.Value);            TableAddRow (parse_table, ParserToken.PairRest);            TableAddCol (parse_table, ParserToken.PairRest, ',',                            ',',                            (int) ParserToken.Pair,                            (int) ParserToken.PairRest);            TableAddCol (parse_table, ParserToken.PairRest, '}',                            (int) ParserToken.Epsilon);            TableAddRow (parse_table, ParserToken.String);            TableAddCol (parse_table, ParserToken.String, '"',                            '"',                            (int) ParserToken.CharSeq,                            '"');            TableAddRow (parse_table, ParserToken.Text);            TableAddCol (parse_table, ParserToken.Text, '[',                            (int) ParserToken.Array);            TableAddCol (parse_table, ParserToken.Text, '{',                            (int) ParserToken.Object);            TableAddRow (parse_table, ParserToken.Value);            TableAddCol (parse_table, ParserToken.Value, '"',                            (int) ParserToken.String);            TableAddCol (parse_table, ParserToken.Value, '[',                            (int) ParserToken.Array);            TableAddCol (parse_table, ParserToken.Value, '{',                            (int) ParserToken.Object);            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Number,                            (int) ParserToken.Number);            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.True,                            (int) ParserToken.True);            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.False,                            (int) ParserToken.False);            TableAddCol (parse_table, ParserToken.Value, (int) ParserToken.Null,                            (int) ParserToken.Null);            TableAddRow (parse_table, ParserToken.ValueRest);            TableAddCol (parse_table, ParserToken.ValueRest, ',',                            ',',                            (int) ParserToken.Value,                            (int) ParserToken.ValueRest);            TableAddCol (parse_table, ParserToken.ValueRest, ']',                            (int) ParserToken.Epsilon);            return parse_table;        }        private static void TableAddCol (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken row, int col,                                         params int[] symbols)        {            parse_table[(int) row].Add (col, symbols);        }        private static void TableAddRow (IDictionary<int, IDictionary<int, int[]>> parse_table, ParserToken rule)        {            parse_table.Add ((int) rule, new Dictionary<int, int[]> ());        }        #endregion        #region Private Methods        private void ProcessNumber (string number)        {            if (number.IndexOf ('.') != -1 ||                number.IndexOf ('e') != -1 ||                number.IndexOf ('E') != -1) {                double n_double;                if (double.TryParse (number, NumberStyles.Any, CultureInfo.InvariantCulture, out n_double)) {                    token = JsonToken.Double;                    token_value = n_double;                    return;                }            }            int n_int32;            if (int.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int32)) {                token = JsonToken.Int;                token_value = n_int32;                return;            }            long n_int64;            if (long.TryParse (number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_int64)) {                token = JsonToken.Long;                token_value = n_int64;                return;            }            ulong n_uint64;            if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out n_uint64))            {                token = JsonToken.Long;                token_value = n_uint64;                return;            }            // Shouldn't happen, but just in case, return something            token = JsonToken.Int;            token_value = 0;        }        private void ProcessSymbol ()        {            if (current_symbol == '[')  {                token = JsonToken.ArrayStart;                parser_return = true;            } else if (current_symbol == ']')  {                token = JsonToken.ArrayEnd;                parser_return = true;            } else if (current_symbol == '{')  {                token = JsonToken.ObjectStart;                parser_return = true;            } else if (current_symbol == '}')  {                token = JsonToken.ObjectEnd;                parser_return = true;            } else if (current_symbol == '"')  {                if (parser_in_string) {                    parser_in_string = false;                    parser_return = true;                } else {                    if (token == JsonToken.None)                        token = JsonToken.String;                    parser_in_string = true;                }            } else if (current_symbol == (int) ParserToken.CharSeq) {                token_value = lexer.StringValue;            } else if (current_symbol == (int) ParserToken.False)  {                token = JsonToken.Boolean;                token_value = false;                parser_return = true;            } else if (current_symbol == (int) ParserToken.Null)  {                token = JsonToken.Null;                parser_return = true;            } else if (current_symbol == (int) ParserToken.Number)  {                ProcessNumber (lexer.StringValue);                parser_return = true;            } else if (current_symbol == (int) ParserToken.Pair)  {                token = JsonToken.PropertyName;            } else if (current_symbol == (int) ParserToken.True)  {                token = JsonToken.Boolean;                token_value = true;                parser_return = true;            }        }        private bool ReadToken ()        {            if (end_of_input)                return false;            lexer.NextToken ();            if (lexer.EndOfInput) {                Close ();                return false;            }            current_input = lexer.Token;            return true;        }        #endregion        public void Close ()        {            if (end_of_input)                return;            end_of_input = true;            end_of_json  = true;            if (reader_is_owned)            {                using(reader){}            }            reader = null;        }        public bool Read ()        {            if (end_of_input)                return false;            if (end_of_json) {                end_of_json = false;                automaton_stack.Clear ();                automaton_stack.Push ((int) ParserToken.End);                automaton_stack.Push ((int) ParserToken.Text);            }            parser_in_string = false;            parser_return    = false;            token       = JsonToken.None;            token_value = null;            if (! read_started) {                read_started = true;                if (! ReadToken ())                    return false;            }            int[] entry_symbols;            while (true) {                if (parser_return) {                    if (automaton_stack.Peek () == (int) ParserToken.End)                        end_of_json = true;                    return true;                }                current_symbol = automaton_stack.Pop ();                ProcessSymbol ();                if (current_symbol == current_input) {                    if (! ReadToken ()) {                        if (automaton_stack.Peek () != (int) ParserToken.End)                            throw new JsonException (                                "Input doesn't evaluate to proper JSON text");                        if (parser_return)                            return true;                        return false;                    }                    continue;                }                try {                    entry_symbols =                        parse_table[current_symbol][current_input];                } catch (KeyNotFoundException e) {                    throw new JsonException ((ParserToken) current_input, e);                }                if (entry_symbols[0] == (int) ParserToken.Epsilon)                    continue;                for (int i = entry_symbols.Length - 1; i >= 0; i--)                    automaton_stack.Push (entry_symbols[i]);            }        }    }}
 |