Refactoring and fixing a bug when add json text

This commit is contained in:
BlubbFish 2019-07-24 17:07:28 +02:00
parent aae12f70d3
commit cab3ec2d06
8 changed files with 1467 additions and 1626 deletions

View File

@ -11,50 +11,47 @@
#endregion #endregion
using System;
using System.Collections; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
namespace LitJson namespace LitJson {
{ public enum JsonType {
public enum JsonType None,
{ Object,
None, Array,
String,
Object, Int,
Array, Long,
String, Double,
Int, Boolean
Long, }
Double,
Boolean public interface IJsonWrapper : IList, IOrderedDictionary {
} Boolean IsArray { get; }
Boolean IsBoolean { get; }
public interface IJsonWrapper : IList, IOrderedDictionary Boolean IsDouble { get; }
{ Boolean IsInt { get; }
bool IsArray { get; } Boolean IsLong { get; }
bool IsBoolean { get; } Boolean IsObject { get; }
bool IsDouble { get; } Boolean IsString { get; }
bool IsInt { get; }
bool IsLong { get; } Boolean GetBoolean();
bool IsObject { get; } Double GetDouble();
bool IsString { get; } Int32 GetInt();
JsonType GetJsonType();
bool GetBoolean (); Int64 GetLong();
double GetDouble (); String GetString();
int GetInt ();
JsonType GetJsonType (); void SetBoolean(Boolean val);
long GetLong (); void SetDouble(Double val);
string GetString (); void SetInt(Int32 val);
void SetJsonType(JsonType type);
void SetBoolean (bool val); void SetLong(Int64 val);
void SetDouble (double val); void SetString(String val);
void SetInt (int val);
void SetJsonType (JsonType type); String ToJson();
void SetLong (long val); void ToJson(JsonWriter writer);
void SetString (string val); }
string ToJson ();
void ToJson (JsonWriter writer);
}
} }

View File

@ -1,65 +1,37 @@
#region Header #region Header
/** /**
* JsonException.cs * JsonException.cs
* Base class throwed by LitJSON when a parsing error occurs. * Base class throwed by LitJSON when a parsing error occurs.
* *
* The authors disclaim copyright to this source code. For more details, see * The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution. * the COPYING file included with this distribution.
**/ **/
#endregion #endregion
using System; using System;
namespace LitJson namespace LitJson {
{ public class JsonException :
public class JsonException : #if NETSTANDARD1_5
#if NETSTANDARD1_5 Exception
Exception #else
#else ApplicationException
ApplicationException #endif
#endif {
{ public JsonException() : base() { }
public JsonException () : base ()
{ internal JsonException(ParserToken token) : base(String.Format("Invalid token '{0}' in input string", token)) { }
}
internal JsonException(ParserToken token, Exception inner_exception) : base(String.Format("Invalid token '{0}' in input string", token), inner_exception) { }
internal JsonException (ParserToken token) :
base (String.Format ( internal JsonException(Int32 c) : base(String.Format("Invalid character '{0}' in input string", (Char)c)) { }
"Invalid token '{0}' in input string", token))
{ internal JsonException(Int32 c, Exception inner_exception) : base(String.Format("Invalid character '{0}' in input string", (Char)c), inner_exception) { }
}
public JsonException(String message) : base(message) { }
internal JsonException (ParserToken token,
Exception inner_exception) : public JsonException(String message, Exception inner_exception) : base(message, inner_exception) { }
base (String.Format ( }
"Invalid token '{0}' in input string", token), }
inner_exception)
{
}
internal JsonException (int c) :
base (String.Format (
"Invalid character '{0}' in input string", (char) c))
{
}
internal JsonException (int c, Exception inner_exception) :
base (String.Format (
"Invalid character '{0}' in input string", (char) c),
inner_exception)
{
}
public JsonException (string message) : base (message)
{
}
public JsonException (string message, Exception inner_exception) :
base (message, inner_exception)
{
}
}
}

View File

@ -436,7 +436,7 @@ namespace LitJson {
} }
private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) { private static IJsonWrapper ReadValue(WrapperFactory factory, JsonReader reader) {
reader.Read(); _ = reader.Read();
if (reader.Token == JsonToken.ArrayEnd || if (reader.Token == JsonToken.ArrayEnd ||
reader.Token == JsonToken.Null) { reader.Token == JsonToken.Null) {
@ -478,13 +478,13 @@ namespace LitJson {
if (item == null && reader.Token == JsonToken.ArrayEnd) { if (item == null && reader.Token == JsonToken.ArrayEnd) {
break; break;
} }
instance.Add(item); _ = instance.Add(item);
} }
} else if (reader.Token == JsonToken.ObjectStart) { } else if (reader.Token == JsonToken.ObjectStart) {
instance.SetJsonType(JsonType.Object); instance.SetJsonType(JsonType.Object);
while (true) { while (true) {
reader.Read(); _ = reader.Read();
if (reader.Token == JsonToken.ObjectEnd) { if (reader.Token == JsonToken.ObjectEnd) {
break; break;
@ -627,7 +627,10 @@ namespace LitJson {
if (obj is IJsonWrapper) { if (obj is IJsonWrapper) {
if (writer_is_private) { if (writer_is_private) {
writer.TextWriter.Write(((IJsonWrapper)obj).ToJson()); String t = ((IJsonWrapper)obj).ToJson();
writer.WriteJson(t);
//writer.TextWriter.Write(t);
//this.context.ExpectingValue = false;
} else { } else {
((IJsonWrapper)obj).ToJson(writer); ((IJsonWrapper)obj).ToJson(writer);
} }
@ -783,9 +786,9 @@ namespace LitJson {
public static IJsonWrapper ToWrapper(WrapperFactory factory, String json) => ReadValue(factory, new JsonReader(json)); public static IJsonWrapper ToWrapper(WrapperFactory factory, String json) => ReadValue(factory, new JsonReader(json));
public static void RegisterExporter<T>(ExporterFunc<T> exporter) => custom_exporters_table[typeof(T)] = (Object obj, JsonWriter writer) => { exporter((T)obj, writer); }; public static void RegisterExporter<T>(ExporterFunc<T> exporter) => custom_exporters_table[typeof(T)] = (Object obj, JsonWriter writer) => exporter((T)obj, writer);
public static void RegisterImporter<TJson, TValue>(ImporterFunc<TJson, TValue> importer) => RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), (Object input) => { return importer((TJson)input); }); public static void RegisterImporter<TJson, TValue>(ImporterFunc<TJson, TValue> importer) => RegisterImporter(custom_importers_table, typeof(TJson), typeof(TValue), (Object input) => importer((TJson)input));
public static void UnregisterExporters() => custom_exporters_table.Clear(); public static void UnregisterExporters() => custom_exporters_table.Clear();

View File

@ -1,105 +1,132 @@
#region Header #region Header
/** /**
* JsonMockWrapper.cs * JsonMockWrapper.cs
* Mock object implementing IJsonWrapper, to facilitate actions like * Mock object implementing IJsonWrapper, to facilitate actions like
* skipping data more efficiently. * skipping data more efficiently.
* *
* The authors disclaim copyright to this source code. For more details, see * The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution. * the COPYING file included with this distribution.
**/ **/
#endregion #endregion
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
namespace LitJson namespace LitJson {
{ public class JsonMockWrapper : IJsonWrapper {
public class JsonMockWrapper : IJsonWrapper public Boolean IsArray => false;
{
public bool IsArray { get { return false; } } public Boolean IsBoolean => false;
public bool IsBoolean { get { return false; } }
public bool IsDouble { get { return false; } } public Boolean IsDouble => false;
public bool IsInt { get { return false; } }
public bool IsLong { get { return false; } } public Boolean IsInt => false;
public bool IsObject { get { return false; } }
public bool IsString { get { return false; } } public Boolean IsLong => false;
public bool GetBoolean () { return false; } public Boolean IsObject => false;
public double GetDouble () { return 0.0; }
public int GetInt () { return 0; } public Boolean IsString => false;
public JsonType GetJsonType () { return JsonType.None; }
public long GetLong () { return 0L; } public Boolean GetBoolean() => false;
public string GetString () { return ""; }
public Double GetDouble() => 0.0;
public void SetBoolean (bool val) {}
public void SetDouble (double val) {} public Int32 GetInt() => 0;
public void SetInt (int val) {}
public void SetJsonType (JsonType type) {} public JsonType GetJsonType() => JsonType.None;
public void SetLong (long val) {}
public void SetString (string val) {} public Int64 GetLong() => 0L;
public string ToJson () { return ""; } public String GetString() => "";
public void ToJson (JsonWriter writer) {}
public void SetBoolean(Boolean val) { }
bool IList.IsFixedSize { get { return true; } } public void SetDouble(Double val) { }
bool IList.IsReadOnly { get { return true; } }
public void SetInt(Int32 val) { }
object IList.this[int index] {
get { return null; } public void SetJsonType(JsonType type) { }
set {}
} public void SetLong(Int64 val) { }
int IList.Add (object value) { return 0; } public void SetString(String val) { }
void IList.Clear () {}
bool IList.Contains (object value) { return false; } public String ToJson() => "";
int IList.IndexOf (object value) { return -1; }
void IList.Insert (int i, object v) {} public void ToJson(JsonWriter writer) { }
void IList.Remove (object value) {}
void IList.RemoveAt (int index) {} Boolean IList.IsFixedSize => true;
Boolean IList.IsReadOnly => true;
int ICollection.Count { get { return 0; } }
bool ICollection.IsSynchronized { get { return false; } } Object IList.this[Int32 index] {
object ICollection.SyncRoot { get { return null; } } get => null;
set {
void ICollection.CopyTo (Array array, int index) {} }
}
IEnumerator IEnumerable.GetEnumerator () { return null; } Int32 IList.Add(Object value) => 0;
void IList.Clear() { }
bool IDictionary.IsFixedSize { get { return true; } }
bool IDictionary.IsReadOnly { get { return true; } } Boolean IList.Contains(Object value) => false;
ICollection IDictionary.Keys { get { return null; } } Int32 IList.IndexOf(Object value) => -1;
ICollection IDictionary.Values { get { return null; } }
void IList.Insert(Int32 i, Object v) { }
object IDictionary.this[object key] {
get { return null; } void IList.Remove(Object value) { }
set {}
} void IList.RemoveAt(Int32 index) { }
void IDictionary.Add (object k, object v) {} Int32 ICollection.Count => 0;
void IDictionary.Clear () {}
bool IDictionary.Contains (object key) { return false; } Boolean ICollection.IsSynchronized => false;
void IDictionary.Remove (object key) {}
Object ICollection.SyncRoot => null;
IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
void ICollection.CopyTo(Array array, Int32 index) { }
object IOrderedDictionary.this[int idx] { IEnumerator IEnumerable.GetEnumerator() => null;
get { return null; }
set {} Boolean IDictionary.IsFixedSize => true;
}
Boolean IDictionary.IsReadOnly => true;
IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
return null; ICollection IDictionary.Keys => null;
}
void IOrderedDictionary.Insert (int i, object k, object v) {} ICollection IDictionary.Values => null;
void IOrderedDictionary.RemoveAt (int i) {}
} Object IDictionary.this[Object key] {
} get => null;
set {
}
}
void IDictionary.Add(Object k, Object v) { }
void IDictionary.Clear() { }
Boolean IDictionary.Contains(Object key) => false;
void IDictionary.Remove(Object key) { }
IDictionaryEnumerator IDictionary.GetEnumerator() => null;
Object IOrderedDictionary.this[Int32 idx] {
get => null;
set {
}
}
IDictionaryEnumerator IOrderedDictionary.GetEnumerator() => null;
void IOrderedDictionary.Insert(Int32 i, Object k, Object v) { }
void IOrderedDictionary.RemoveAt(Int32 i) { }
}
}

View File

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

View File

@ -51,14 +51,14 @@ namespace LitJson
public Int32 IndentValue { public Int32 IndentValue {
get => this.indent_value; get => this.indent_value;
set { set {
this.indentation = (this.indentation / this.indent_value) * value; this.indentation = this.indentation / this.indent_value * value;
this.indent_value = value; this.indent_value = value;
} }
} }
public Boolean PrettyPrint { get; set; } public Boolean PrettyPrint { get; set; }
public TextWriter TextWriter { get; } private TextWriter TextWriter { get; }
public Boolean Validate { get; set; } public Boolean Validate { get; set; }
@ -249,7 +249,7 @@ namespace LitJson
this.ctx_stack.Push(this.context); this.ctx_stack.Push(this.context);
if (this.inst_string_builder != null) { if (this.inst_string_builder != null) {
this.inst_string_builder.Remove(0, this.inst_string_builder.Length); _ = this.inst_string_builder.Remove(0, this.inst_string_builder.Length);
} }
} }
@ -316,6 +316,19 @@ namespace LitJson
this.context.ExpectingValue = false; this.context.ExpectingValue = false;
} }
public void WriteJson(String str) {
this.DoValidation(Condition.Value);
this.PutNewline();
if(str == null) {
this.Put("null");
} else {
this.TextWriter.Write(str);
}
this.context.ExpectingValue = false;
}
public void Write(UInt64 number) { public void Write(UInt64 number) {
this.DoValidation(Condition.Value); this.DoValidation(Condition.Value);
this.PutNewline(); this.PutNewline();
@ -329,7 +342,7 @@ namespace LitJson
this.DoValidation(Condition.InArray); this.DoValidation(Condition.InArray);
this.PutNewline(false); this.PutNewline(false);
this.ctx_stack.Pop(); _ = this.ctx_stack.Pop();
if (this.ctx_stack.Count == 1) { if (this.ctx_stack.Count == 1) {
this.has_reached_end = true; this.has_reached_end = true;
} else { } else {
@ -359,7 +372,7 @@ namespace LitJson
this.DoValidation(Condition.InObject); this.DoValidation(Condition.InObject);
this.PutNewline(false); this.PutNewline(false);
this.ctx_stack.Pop(); _ = this.ctx_stack.Pop();
if (this.ctx_stack.Count == 1) { if (this.ctx_stack.Count == 1) {
this.has_reached_end = true; this.has_reached_end = true;
} else { } else {

File diff suppressed because it is too large Load Diff

View File

@ -9,36 +9,34 @@
#endregion #endregion
namespace LitJson namespace LitJson {
{ internal enum ParserToken {
internal enum ParserToken // Lexer tokens (see section A.1.1. of the manual)
{ None = System.Char.MaxValue + 1,
// Lexer tokens (see section A.1.1. of the manual) Number,
None = System.Char.MaxValue + 1, True,
Number, False,
True, Null,
False, CharSeq,
Null, // Single char
CharSeq, Char,
// Single char
Char, // Parser Rules (see section A.2.1 of the manual)
Text,
// Parser Rules (see section A.2.1 of the manual) Object,
Text, ObjectPrime,
Object, Pair,
ObjectPrime, PairRest,
Pair, Array,
PairRest, ArrayPrime,
Array, Value,
ArrayPrime, ValueRest,
Value, String,
ValueRest,
String, // End of input
End,
// End of input
End, // The empty rule
Epsilon
// The empty rule }
Epsilon
}
} }