summaryrefslogtreecommitdiff
path: root/Assets/ThirdParty/LitJson/JsonReader.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Assets/ThirdParty/LitJson/JsonReader.cs')
-rw-r--r--Assets/ThirdParty/LitJson/JsonReader.cs478
1 files changed, 478 insertions, 0 deletions
diff --git a/Assets/ThirdParty/LitJson/JsonReader.cs b/Assets/ThirdParty/LitJson/JsonReader.cs
new file mode 100644
index 00000000..e47eabc5
--- /dev/null
+++ b/Assets/ThirdParty/LitJson/JsonReader.cs
@@ -0,0 +1,478 @@
+#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.
+ **/
+#endregion
+
+
+using 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]);
+ }
+ }
+
+ }
+}