This commit is contained in:
2026-06-15 18:18:16 +08:00
parent 97c9fba14e
commit 2b9f134e5f
4164 changed files with 386922 additions and 79 deletions

View File

@@ -0,0 +1,492 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using Best.HTTP.Shared.PlatformSupport.Text;
namespace Best.HTTP.JSON
{
/// <summary>
/// Based on the download from http://techblog.procurios.nl/k/news/view/14605/14863/how-do-i-write-my-own-parser-%28for-json%29.html
/// This class encodes and decodes JSON strings.
/// Spec. details, see http://www.json.org/
///
/// JSON uses Arrays and Objects. These correspond here to the datatypes List and Dictionary.
/// All numbers are parsed to doubles.
/// </summary>
public class Json
{
private const int TOKEN_NONE = 0;
private const int TOKEN_CURLY_OPEN = 1;
private const int TOKEN_CURLY_CLOSE = 2;
private const int TOKEN_SQUARED_OPEN = 3;
private const int TOKEN_SQUARED_CLOSE = 4;
private const int TOKEN_COLON = 5;
private const int TOKEN_COMMA = 6;
private const int TOKEN_STRING = 7;
private const int TOKEN_NUMBER = 8;
private const int TOKEN_TRUE = 9;
private const int TOKEN_FALSE = 10;
private const int TOKEN_NULL = 11;
private const int BUILDER_CAPACITY = 2000;
/// <summary>
/// Parses the string json into a value
/// </summary>
/// <param name="json">A JSON string.</param>
/// <returns>A List, a Dictionary, a double, a string, null, true, or false</returns>
public static object Decode(string json)
{
bool success = true;
return Decode(json, ref success);
}
/// <summary>
/// Parses the string json into a value; and fills 'success' with the successfullness of the parse.
/// </summary>
/// <param name="json">A JSON string.</param>
/// <param name="success">Successful parse?</param>
/// <returns>A List, a Dictionary, a double, a string, null, true, or false</returns>
public static object Decode(string json, ref bool success)
{
success = true;
if (json != null) {
char[] charArray = json.ToCharArray();
int index = 0;
object value = ParseValue(charArray, ref index, ref success);
return value;
} else {
return null;
}
}
/// <summary>
/// Converts a Dictionary / List object into a JSON string
/// </summary>
/// <param name="json">A Dictionary / List</param>
/// <returns>A JSON encoded string, or null if object 'json' is not serializable</returns>
public static string Encode(object json)
{
StringBuilder builder = StringBuilderPool.Get(BUILDER_CAPACITY); //new StringBuilder(BUILDER_CAPACITY);
bool success = SerializeValue(json, builder);
return (success ? StringBuilderPool.ReleaseAndGrab(builder) : null);
}
protected static Dictionary<string, object> ParseObject(char[] json, ref int index, ref bool success)
{
Dictionary<string, object> table = new Dictionary<string, object>();
int token;
// {
NextToken(json, ref index);
bool done = false;
while (!done) {
token = LookAhead(json, index);
if (token == Json.TOKEN_NONE) {
success = false;
return null;
} else if (token == Json.TOKEN_COMMA) {
NextToken(json, ref index);
} else if (token == Json.TOKEN_CURLY_CLOSE) {
NextToken(json, ref index);
return table;
} else {
// name
string name = ParseString(json, ref index, ref success);
if (!success) {
success = false;
return null;
}
// :
token = NextToken(json, ref index);
if (token != Json.TOKEN_COLON) {
success = false;
return null;
}
// value
object value = ParseValue(json, ref index, ref success);
if (!success) {
success = false;
return null;
}
table[name] = value;
}
}
return table;
}
protected static List<object> ParseArray(char[] json, ref int index, ref bool success)
{
List<object> array = new List<object>();
// [
NextToken(json, ref index);
bool done = false;
while (!done) {
int token = LookAhead(json, index);
if (token == Json.TOKEN_NONE) {
success = false;
return null;
} else if (token == Json.TOKEN_COMMA) {
NextToken(json, ref index);
} else if (token == Json.TOKEN_SQUARED_CLOSE) {
NextToken(json, ref index);
break;
} else {
object value = ParseValue(json, ref index, ref success);
if (!success) {
return null;
}
array.Add(value);
}
}
return array;
}
protected static object ParseValue(char[] json, ref int index, ref bool success)
{
switch (LookAhead(json, index)) {
case Json.TOKEN_STRING:
return ParseString(json, ref index, ref success);
case Json.TOKEN_NUMBER:
return ParseNumber(json, ref index, ref success);
case Json.TOKEN_CURLY_OPEN:
return ParseObject(json, ref index, ref success);
case Json.TOKEN_SQUARED_OPEN:
return ParseArray(json, ref index, ref success);
case Json.TOKEN_TRUE:
NextToken(json, ref index);
return true;
case Json.TOKEN_FALSE:
NextToken(json, ref index);
return false;
case Json.TOKEN_NULL:
NextToken(json, ref index);
return null;
case Json.TOKEN_NONE:
break;
}
success = false;
return null;
}
protected static string ParseString(char[] json, ref int index, ref bool success)
{
StringBuilder s = StringBuilderPool.Get(BUILDER_CAPACITY); //new StringBuilder(BUILDER_CAPACITY);
char c;
EatWhitespace(json, ref index);
// "
c = json[index++];
bool complete = false;
while (!complete) {
if (index == json.Length) {
break;
}
c = json[index++];
if (c == '"') {
complete = true;
break;
} else if (c == '\\') {
if (index == json.Length) {
break;
}
c = json[index++];
if (c == '"') {
s.Append('"');
} else if (c == '\\') {
s.Append('\\');
} else if (c == '/') {
s.Append('/');
} else if (c == 'b') {
s.Append('\b');
} else if (c == 'f') {
s.Append('\f');
} else if (c == 'n') {
s.Append('\n');
} else if (c == 'r') {
s.Append('\r');
} else if (c == 't') {
s.Append('\t');
} else if (c == 'u') {
int remainingLength = json.Length - index;
if (remainingLength >= 4) {
// parse the 32 bit hex into an integer codepoint
uint codePoint;
if (!(success = UInt32.TryParse(new string(json, index, 4), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out codePoint))) {
return "";
}
// convert the integer codepoint to a unicode char and add to string
s.Append(Char.ConvertFromUtf32((int)codePoint));
// skip 4 chars
index += 4;
} else {
break;
}
}
} else {
s.Append(c);
}
}
if (!complete) {
success = false;
return null;
}
return StringBuilderPool.ReleaseAndGrab(s);
}
protected static double ParseNumber(char[] json, ref int index, ref bool success)
{
EatWhitespace(json, ref index);
int lastIndex = GetLastIndexOfNumber(json, index);
int charLength = (lastIndex - index) + 1;
double number;
success = Double.TryParse(new string(json, index, charLength), NumberStyles.Any, CultureInfo.InvariantCulture, out number);
index = lastIndex + 1;
return number;
}
protected static int GetLastIndexOfNumber(char[] json, int index)
{
int lastIndex;
for (lastIndex = index; lastIndex < json.Length; lastIndex++) {
if ("0123456789+-.eE".IndexOf(json[lastIndex]) == -1) {
break;
}
}
return lastIndex - 1;
}
protected static void EatWhitespace(char[] json, ref int index)
{
for (; index < json.Length; index++) {
if (" \t\n\r".IndexOf(json[index]) == -1) {
break;
}
}
}
protected static int LookAhead(char[] json, int index)
{
int saveIndex = index;
return NextToken(json, ref saveIndex);
}
protected static int NextToken(char[] json, ref int index)
{
EatWhitespace(json, ref index);
if (index == json.Length) {
return Json.TOKEN_NONE;
}
char c = json[index];
index++;
switch (c) {
case '{':
return Json.TOKEN_CURLY_OPEN;
case '}':
return Json.TOKEN_CURLY_CLOSE;
case '[':
return Json.TOKEN_SQUARED_OPEN;
case ']':
return Json.TOKEN_SQUARED_CLOSE;
case ',':
return Json.TOKEN_COMMA;
case '"':
return Json.TOKEN_STRING;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
case '-':
return Json.TOKEN_NUMBER;
case ':':
return Json.TOKEN_COLON;
}
index--;
int remainingLength = json.Length - index;
// false
if (remainingLength >= 5) {
if (json[index] == 'f' &&
json[index + 1] == 'a' &&
json[index + 2] == 'l' &&
json[index + 3] == 's' &&
json[index + 4] == 'e') {
index += 5;
return Json.TOKEN_FALSE;
}
}
// true
if (remainingLength >= 4) {
if (json[index] == 't' &&
json[index + 1] == 'r' &&
json[index + 2] == 'u' &&
json[index + 3] == 'e') {
index += 4;
return Json.TOKEN_TRUE;
}
}
// null
if (remainingLength >= 4) {
if (json[index] == 'n' &&
json[index + 1] == 'u' &&
json[index + 2] == 'l' &&
json[index + 3] == 'l') {
index += 4;
return Json.TOKEN_NULL;
}
}
return Json.TOKEN_NONE;
}
protected static bool SerializeValue(object value, StringBuilder builder)
{
bool success = true;
if (value is string) {
success = SerializeString((string)value, builder);
} else if (value is IDictionary) {
success = SerializeObject((IDictionary)value, builder);
} else if (value is IList) {
success = SerializeArray(value as IList, builder);
} else if ((value is Boolean) && ((Boolean)value == true)) {
builder.Append("true");
} else if ((value is Boolean) && ((Boolean)value == false)) {
builder.Append("false");
} else if (value is ValueType) {
// thanks to ritchie for pointing out ValueType to me
success = SerializeNumber(Convert.ToDouble(value), builder);
} else if (value == null) {
builder.Append("null");
} else {
success = false;
}
return success;
}
protected static bool SerializeObject(IDictionary anObject, StringBuilder builder)
{
builder.Append("{");
IDictionaryEnumerator e = anObject.GetEnumerator();
bool first = true;
while (e.MoveNext()) {
string key = e.Key.ToString();
object value = e.Value;
if (!first) {
builder.Append(", ");
}
SerializeString(key, builder);
builder.Append(":");
if (!SerializeValue(value, builder)) {
return false;
}
first = false;
}
builder.Append("}");
return true;
}
protected static bool SerializeArray(IList anArray, StringBuilder builder)
{
builder.Append("[");
bool first = true;
for (int i = 0; i < anArray.Count; i++) {
object value = anArray[i];
if (!first) {
builder.Append(", ");
}
if (!SerializeValue(value, builder)) {
return false;
}
first = false;
}
builder.Append("]");
return true;
}
protected static bool SerializeString(string aString, StringBuilder builder)
{
builder.Append("\"");
char[] charArray = aString.ToCharArray();
for (int i = 0; i < charArray.Length; i++) {
char c = charArray[i];
if (c == '"') {
builder.Append("\\\"");
} else if (c == '\\') {
builder.Append("\\\\");
} else if (c == '\b') {
builder.Append("\\b");
} else if (c == '\f') {
builder.Append("\\f");
} else if (c == '\n') {
builder.Append("\\n");
} else if (c == '\r') {
builder.Append("\\r");
} else if (c == '\t') {
builder.Append("\\t");
} else {
int codepoint = Convert.ToInt32(c);
if ((codepoint >= 32) && (codepoint <= 126)) {
builder.Append(c);
} else {
builder.Append("\\u" + Convert.ToString(codepoint, 16).PadLeft(4, '0'));
}
}
}
builder.Append("\"");
return true;
}
protected static bool SerializeNumber(double number, StringBuilder builder)
{
builder.Append(Convert.ToString(number, CultureInfo.InvariantCulture));
return true;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d0267f9e586a5f4aa0316a3914734bc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 593ed51040098bf49b7694632c40db69
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,73 @@
#region Header
/**
* IJsonWrapper.cs
* Interface that represents a type capable of handling all kinds of JSON
* data. This is mainly used when mapping objects through JsonMapper, and
* it's implemented by JsonData.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System.Collections;
using System.Collections.Specialized;
namespace Best.HTTP.JSON.LitJson
{
public enum JsonType
{
None,
Object,
Array,
String,
Int,
Long,
Double,
Boolean
}
public interface IOrderedDictionary : IDictionary
{
new IDictionaryEnumerator GetEnumerator();
void Insert(int index, object key, object value);
void RemoveAt(int index);
object this[int index]
{
get;
set;
}
}
public interface IJsonWrapper : IList, IOrderedDictionary
{
bool IsArray { get; }
bool IsBoolean { get; }
bool IsDouble { get; }
bool IsInt { get; }
bool IsLong { get; }
bool IsObject { get; }
bool IsString { get; }
bool GetBoolean ();
double GetDouble ();
int GetInt ();
JsonType GetJsonType ();
long GetLong ();
string GetString ();
void SetBoolean (bool val);
void SetDouble (double val);
void SetInt (int val);
void SetJsonType (JsonType type);
void SetLong (long val);
void SetString (string val);
string ToJson ();
void ToJson (JsonWriter writer);
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7b47b1ba30b5ba14884bc2464964048e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c970b3eb05a754649a5955b508c44965
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,60 @@
#region Header
/**
* JsonException.cs
* Base class throwed by LitJSON when a parsing error occurs.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
namespace Best.HTTP.JSON.LitJson
{
public class JsonException : Exception
{
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 (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

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 38d52ffffed49c84cafd90e1e233bf9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 62a878533312d60458cf706654ef9b9e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,105 @@
#region Header
/**
* JsonMockWrapper.cs
* Mock object implementing IJsonWrapper, to facilitate actions like
* skipping data more efficiently.
*
* 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;
using System.Collections.Specialized;
namespace Best.HTTP.JSON.LitJson
{
public sealed class JsonMockWrapper : IJsonWrapper
{
public bool IsArray { get { return false; } }
public bool IsBoolean { get { return false; } }
public bool IsDouble { get { return false; } }
public bool IsInt { get { return false; } }
public bool IsLong { get { return false; } }
public bool IsObject { get { return false; } }
public bool IsString { get { return false; } }
public bool GetBoolean () { return false; }
public double GetDouble () { return 0.0; }
public int GetInt () { return 0; }
public JsonType GetJsonType () { return JsonType.None; }
public long GetLong () { return 0L; }
public string GetString () { return ""; }
public void SetBoolean (bool val) {}
public void SetDouble (double val) {}
public void SetInt (int val) {}
public void SetJsonType (JsonType type) {}
public void SetLong (long val) {}
public void SetString (string val) {}
public string ToJson () { return ""; }
public void ToJson (JsonWriter writer) {}
bool IList.IsFixedSize { get { return true; } }
bool IList.IsReadOnly { get { return true; } }
object IList.this[int index] {
get { return null; }
set {}
}
int IList.Add (object value) { return 0; }
void IList.Clear () {}
bool IList.Contains (object value) { return false; }
int IList.IndexOf (object value) { return -1; }
void IList.Insert (int i, object v) {}
void IList.Remove (object value) {}
void IList.RemoveAt (int index) {}
int ICollection.Count { get { return 0; } }
bool ICollection.IsSynchronized { get { return false; } }
object ICollection.SyncRoot { get { return null; } }
void ICollection.CopyTo (Array array, int index) {}
IEnumerator IEnumerable.GetEnumerator () { return null; }
bool IDictionary.IsFixedSize { get { return true; } }
bool IDictionary.IsReadOnly { get { return true; } }
ICollection IDictionary.Keys { get { return null; } }
ICollection IDictionary.Values { get { return null; } }
object IDictionary.this[object key] {
get { return null; }
set {}
}
void IDictionary.Add (object k, object v) {}
void IDictionary.Clear () {}
bool IDictionary.Contains (object key) { return false; }
void IDictionary.Remove (object key) {}
IDictionaryEnumerator IDictionary.GetEnumerator () { return null; }
object IOrderedDictionary.this[int idx] {
get { return null; }
set {}
}
IDictionaryEnumerator IOrderedDictionary.GetEnumerator () {
return null;
}
void IOrderedDictionary.Insert (int i, object k, object v) {}
void IOrderedDictionary.RemoveAt (int i) {}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66a205f7a30eadc44a1ecf2aa6556081
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,563 @@
#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;
namespace Best.HTTP.JSON.LitJson
{
public enum JsonToken
{
None,
ObjectStart,
PropertyName,
ObjectEnd,
ArrayStart,
ArrayEnd,
Int,
Long,
ULong,
Double,
String,
Boolean,
Null
}
public sealed 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;
private bool keep_open;
private bool token_bool;
private int token_int;
private long token_long;
private ulong token_ulong;
private double token_double;
#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; }
}
public bool ValueBool { get { return token_bool; } }
public int ValueInt { get { return token_int; } }
public long ValueLong { get { return token_long; } }
public ulong ValueULong { get { return token_ulong; } }
public double ValueDouble { get { return token_double; } }
public ReadOnlyMemory<char> ValueString;
private char[] _charSeq;
#endregion
#region Constructors
static JsonReader()
{
parse_table = PopulateParseTable();
}
public JsonReader(string json_text) :
this(new StringReader(json_text), true, false)
{
}
public JsonReader(TextReader reader) :
this(reader, false, false)
{
}
public JsonReader(string json_text, bool keep_open) :
this(new StringReader(json_text), true, keep_open)
{
}
private JsonReader(TextReader reader, bool owned, bool keep_open)
{
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;
this.keep_open = keep_open;
}
#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(ReadOnlySpan<char> number)
{
if (number.IndexOf('.') != -1 ||
number.IndexOf('e') != -1 ||
number.IndexOf('E') != -1)
{
if (double.TryParse(number, NumberStyles.Any, CultureInfo.InvariantCulture, out token_double))
{
token = JsonToken.Double;
return;
}
}
if (int.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out token_int))
{
token = JsonToken.Int;
return;
}
if (long.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out token_long))
{
token = JsonToken.Long;
return;
}
if (ulong.TryParse(number, NumberStyles.Integer, CultureInfo.InvariantCulture, out token_ulong))
{
token = JsonToken.ULong;
return;
}
// Shouldn't happen
throw new JsonException($"Number(\"{new string(number)}\") couldn't parsed!");
}
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 = new String(lexer.StringValueAsCharSpan);
if (_charSeq == null || _charSeq.Length < lexer.StringValueAsCharSpan.Length)
_charSeq = new char[lexer.StringValueAsCharSpan.Length];
lexer.StringValueAsCharSpan.CopyTo(_charSeq);
ValueString = _charSeq.AsMemory(0, lexer.StringValueAsCharSpan.Length);
}
else if (current_symbol == (int)ParserToken.False)
{
token = JsonToken.Boolean;
//token_value = false;
token_bool = 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.StringValueAsCharSpan);
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;
token_bool = true;
parser_return = true;
}
}
private bool ReadToken()
{
if (end_of_input)
return false;
lexer.NextToken();
if (lexer.EndOfInput)
{
if (!keep_open)
Close();
return false;
}
current_input = lexer.Token;
return true;
}
#endregion
public void SetJson(string json_text)
{
parser_in_string = false;
parser_return = false;
read_started = false;
automaton_stack.Clear();
automaton_stack.Push((int)ParserToken.End);
automaton_stack.Push((int)ParserToken.Text);
end_of_input = false;
end_of_json = false;
skip_non_members = true;
lexer.Reset(this.reader = new StringReader(json_text));
reader_is_owned = true;
}
public void Close()
{
if (end_of_input)
return;
end_of_input = true;
end_of_json = true;
if (reader_is_owned)
{
using (reader) { }
}
lexer.Clear();
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

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e85f43df1930a4a428bfd56d7df0264f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,523 @@
#region Header
/**
* JsonWriter.cs
* Stream-like facility to output 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 Best.HTTP.JSON.LitJson
{
internal enum Condition
{
InArray,
InObject,
NotAProperty,
Property,
Value
}
internal class WriterContext
{
public int Count;
public bool InArray;
public bool InObject;
public bool ExpectingValue;
public int Padding;
internal void Reset()
{
Count = Padding = 0;
InArray = InObject = ExpectingValue = false;
}
}
public sealed class JsonWriter
{
#region Fields
private static readonly NumberFormatInfo number_format;
private WriterContext context;
private Stack<WriterContext> ctx_stack;
private bool has_reached_end;
private char[] hex_seq;
private int indentation;
private int indent_value;
private StringBuilder inst_string_builder;
private bool pretty_print;
private bool validate;
private bool lower_case_properties;
private TextWriter writer;
private Queue<WriterContext> _contextPool;
#endregion
#region Properties
public int IndentValue
{
get { return indent_value; }
set
{
indentation = (indentation / indent_value) * value;
indent_value = value;
}
}
public bool PrettyPrint
{
get { return pretty_print; }
set { pretty_print = value; }
}
public TextWriter TextWriter
{
get { return writer; }
}
public bool Validate
{
get { return validate; }
set { validate = value; }
}
public bool LowerCaseProperties
{
get { return lower_case_properties; }
set { lower_case_properties = value; }
}
#endregion
#region Constructors
static JsonWriter()
{
number_format = NumberFormatInfo.InvariantInfo;
}
public JsonWriter()
{
inst_string_builder = new StringBuilder();
writer = new StringWriter(inst_string_builder);
Init();
}
public JsonWriter(StringBuilder sb) :
this(new StringWriter(sb))
{
}
public JsonWriter(TextWriter writer)
{
if (writer == null)
throw new ArgumentNullException("writer");
this.writer = writer;
Init();
}
#endregion
#region Private Methods
private void DoValidation(Condition cond)
{
if (!context.ExpectingValue)
context.Count++;
if (!validate)
return;
if (has_reached_end)
throw new JsonException(
"A complete JSON symbol has already been written");
switch (cond)
{
case Condition.InArray:
if (!context.InArray)
throw new JsonException(
"Can't close an array here");
break;
case Condition.InObject:
if (!context.InObject || context.ExpectingValue)
throw new JsonException(
"Can't close an object here");
break;
case Condition.NotAProperty:
if (context.InObject && !context.ExpectingValue)
throw new JsonException(
"Expected a property");
break;
case Condition.Property:
if (!context.InObject || context.ExpectingValue)
throw new JsonException(
"Can't add a property here");
break;
case Condition.Value:
if (!context.InArray &&
(!context.InObject || !context.ExpectingValue))
throw new JsonException(
"Can't add a value here");
break;
}
}
private void Init()
{
_contextPool = new Queue<WriterContext>();
has_reached_end = false;
hex_seq = new char[4];
indentation = 0;
indent_value = 4;
pretty_print = false;
validate = true;
lower_case_properties = false;
ctx_stack = new Stack<WriterContext>();
context = new WriterContext();
ctx_stack.Push(context);
}
private static void IntToHex(int n, char[] hex)
{
int num;
for (int i = 0; i < 4; i++)
{
num = n % 16;
if (num < 10)
hex[3 - i] = (char)('0' + num);
else
hex[3 - i] = (char)('A' + (num - 10));
n >>= 4;
}
}
private void Indent()
{
if (pretty_print)
indentation += indent_value;
}
private void Put(string str)
{
if (pretty_print && !context.ExpectingValue)
for (int i = 0; i < indentation; i++)
writer.Write(' ');
writer.Write(str);
}
private void PutNewline()
{
PutNewline(true);
}
private void PutNewline(bool add_comma)
{
if (add_comma && !context.ExpectingValue &&
context.Count > 1)
writer.Write(',');
if (pretty_print && !context.ExpectingValue)
writer.Write(Environment.NewLine);
}
private void PutString(string str)
{
Put(String.Empty);
writer.Write('"');
int n = str.Length;
for (int i = 0; i < n; i++)
{
switch (str[i])
{
case '\n':
writer.Write("\\n");
continue;
case '\r':
writer.Write("\\r");
continue;
case '\t':
writer.Write("\\t");
continue;
case '"':
case '\\':
writer.Write('\\');
writer.Write(str[i]);
continue;
case '\f':
writer.Write("\\f");
continue;
case '\b':
writer.Write("\\b");
continue;
}
if ((int)str[i] >= 32 && (int)str[i] <= 126)
{
writer.Write(str[i]);
continue;
}
// Default, turn into a \uXXXX sequence
IntToHex((int)str[i], hex_seq);
writer.Write("\\u");
writer.Write(hex_seq);
}
writer.Write('"');
}
private void Unindent()
{
if (pretty_print)
indentation -= indent_value;
}
#endregion
public override string ToString()
{
if (inst_string_builder == null)
return String.Empty;
return inst_string_builder.ToString();
}
public void Reset()
{
has_reached_end = false;
while (ctx_stack.Count > 0)
_contextPool.Enqueue(ctx_stack.Pop());
if (_contextPool.TryDequeue(out context))
context.Reset();
else
context = new WriterContext();
ctx_stack.Push(context);
if (inst_string_builder != null)
inst_string_builder.Remove(0, inst_string_builder.Length);
}
public void Write(bool boolean)
{
DoValidation(Condition.Value);
PutNewline();
Put(boolean ? "true" : "false");
context.ExpectingValue = false;
}
public void Write(decimal number)
{
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
context.ExpectingValue = false;
}
public void Write(double number)
{
DoValidation(Condition.Value);
PutNewline();
string str = Convert.ToString(number, number_format);
Put(str);
if (str.IndexOf('.') == -1 &&
str.IndexOf('E') == -1)
writer.Write(".0");
context.ExpectingValue = false;
}
public void Write(float number)
{
DoValidation(Condition.Value);
PutNewline();
string str = Convert.ToString(number, number_format);
Put(str);
context.ExpectingValue = false;
}
public void Write(int number)
{
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
context.ExpectingValue = false;
}
public void Write(long number)
{
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
context.ExpectingValue = false;
}
public void Write(string str)
{
DoValidation(Condition.Value);
PutNewline();
if (str == null)
Put("null");
else
PutString(str);
context.ExpectingValue = false;
}
//[CLSCompliant(false)]
public void Write(ulong number)
{
DoValidation(Condition.Value);
PutNewline();
Put(Convert.ToString(number, number_format));
context.ExpectingValue = false;
}
public void WriteArrayEnd()
{
DoValidation(Condition.InArray);
PutNewline(false);
_contextPool.Enqueue(ctx_stack.Pop());
if (ctx_stack.Count == 1)
has_reached_end = true;
else
{
context = ctx_stack.Peek();
context.ExpectingValue = false;
}
Unindent();
Put("]");
}
public void WriteArrayStart()
{
DoValidation(Condition.NotAProperty);
PutNewline();
Put("[");
if (_contextPool.TryDequeue(out context))
context.Reset();
else
context = new WriterContext();
context.InArray = true;
ctx_stack.Push(context);
Indent();
}
public void WriteObjectEnd()
{
DoValidation(Condition.InObject);
PutNewline(false);
_contextPool.Enqueue(ctx_stack.Pop());
if (ctx_stack.Count == 1)
has_reached_end = true;
else
{
context = ctx_stack.Peek();
context.ExpectingValue = false;
}
Unindent();
Put("}");
}
public void WriteObjectStart()
{
DoValidation(Condition.NotAProperty);
PutNewline();
Put("{");
if (_contextPool.TryDequeue(out context))
context.Reset();
else
context = new WriterContext();
context.InObject = true;
ctx_stack.Push(context);
Indent();
}
public void WritePropertyName(string property_name)
{
DoValidation(Condition.Property);
PutNewline();
string propertyName = (property_name == null || !lower_case_properties)
? property_name
: property_name.ToLowerInvariant();
PutString(propertyName);
if (pretty_print)
{
if (propertyName.Length > context.Padding)
context.Padding = propertyName.Length;
for (int i = context.Padding - propertyName.Length;
i >= 0; i--)
writer.Write(' ');
writer.Write(": ");
}
else
writer.Write(':');
context.ExpectingValue = true;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: db6b37e84eef6d94fb7cdd8cf5878c5d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,993 @@
#region Header
/**
* Lexer.cs
* JSON lexer implementation based on a finite state machine.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
using System;
using System.IO;
using System.Text;
namespace Best.HTTP.JSON.LitJson
{
internal sealed class FsmContext
{
public bool Return;
public int NextState;
public Lexer L;
public int StateStack;
}
internal sealed class Lexer
{
#region Fields
private delegate bool StateHandler(FsmContext ctx);
private static readonly int[] fsm_return_table;
private static readonly StateHandler[] fsm_handler_table;
private bool allow_comments;
private bool allow_single_quoted_strings;
private bool end_of_input;
private FsmContext fsm_context;
private int input_buffer;
private int input_char;
private TextReader reader;
private int state;
private StringBuilder string_buffer;
private int token;
private int unichar;
private char[] char_buffer;
private int char_buffer_length;
#endregion
#region Properties
public bool AllowComments
{
get { return allow_comments; }
set { allow_comments = value; }
}
public bool AllowSingleQuotedStrings
{
get { return allow_single_quoted_strings; }
set { allow_single_quoted_strings = value; }
}
public bool EndOfInput
{
get { return end_of_input; }
}
public int Token
{
get { return token; }
}
public ReadOnlySpan<char> StringValueAsCharSpan => char_buffer.AsSpan(0, char_buffer_length);
#endregion
#region Constructors
static Lexer()
{
PopulateFsmTables(out fsm_handler_table, out fsm_return_table);
}
public Lexer(TextReader reader)
{
allow_comments = true;
allow_single_quoted_strings = true;
input_buffer = 0;
string_buffer = new StringBuilder(128);
state = 1;
end_of_input = false;
this.reader = reader;
fsm_context = new FsmContext();
fsm_context.L = this;
}
public void Reset(TextReader reader)
{
input_buffer = 0;
state = 1;
end_of_input = false;
this.reader = reader;
fsm_context.L = this;
fsm_context.Return = false;
fsm_context.StateStack = fsm_context.NextState = 0;
this.string_buffer.Clear();
}
#endregion
#region Static Methods
private static int HexValue(int digit)
{
switch (digit)
{
case 'a':
case 'A':
return 10;
case 'b':
case 'B':
return 11;
case 'c':
case 'C':
return 12;
case 'd':
case 'D':
return 13;
case 'e':
case 'E':
return 14;
case 'f':
case 'F':
return 15;
default:
return digit - '0';
}
}
private static void PopulateFsmTables(out StateHandler[] fsm_handler_table, out int[] fsm_return_table)
{
// See section A.1. of the manual for details of the finite
// state machine.
fsm_handler_table = new StateHandler[28] {
State1,
State2,
State3,
State4,
State5,
State6,
State7,
State8,
State9,
State10,
State11,
State12,
State13,
State14,
State15,
State16,
State17,
State18,
State19,
State20,
State21,
State22,
State23,
State24,
State25,
State26,
State27,
State28
};
fsm_return_table = new int[28] {
(int) ParserToken.Char,
0,
(int) ParserToken.Number,
(int) ParserToken.Number,
0,
(int) ParserToken.Number,
0,
(int) ParserToken.Number,
0,
0,
(int) ParserToken.True,
0,
0,
0,
(int) ParserToken.False,
0,
0,
(int) ParserToken.Null,
(int) ParserToken.CharSeq,
(int) ParserToken.Char,
0,
0,
(int) ParserToken.CharSeq,
(int) ParserToken.Char,
0,
0,
0,
0
};
}
private static char ProcessEscChar(int esc_char)
{
switch (esc_char)
{
case '"':
case '\'':
case '\\':
case '/':
return Convert.ToChar(esc_char);
case 'n':
return '\n';
case 't':
return '\t';
case 'r':
return '\r';
case 'b':
return '\b';
case 'f':
return '\f';
default:
// Unreachable
return '?';
}
}
private static bool State1(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
continue;
if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 3;
return true;
}
switch (ctx.L.input_char)
{
case '"':
ctx.NextState = 19;
ctx.Return = true;
return true;
case ',':
case ':':
case '[':
case ']':
case '{':
case '}':
ctx.NextState = 1;
ctx.Return = true;
return true;
case '-':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 2;
return true;
case '0':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 4;
return true;
case 'f':
ctx.NextState = 12;
return true;
case 'n':
ctx.NextState = 16;
return true;
case 't':
ctx.NextState = 9;
return true;
case '\'':
if (!ctx.L.allow_single_quoted_strings)
return false;
ctx.L.input_char = '"';
ctx.NextState = 23;
ctx.Return = true;
return true;
case '/':
if (!ctx.L.allow_comments)
return false;
ctx.NextState = 25;
return true;
default:
return false;
}
}
return true;
}
private static bool State2(FsmContext ctx)
{
ctx.L.GetChar();
if (ctx.L.input_char >= '1' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 3;
return true;
}
switch (ctx.L.input_char)
{
case '0':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 4;
return true;
default:
return false;
}
}
private static bool State3(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
{
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char)
{
case ',':
case ']':
case '}':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 1;
return true;
case '.':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 5;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
return true;
}
private static bool State4(FsmContext ctx)
{
ctx.L.GetChar();
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
{
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char)
{
case ',':
case ']':
case '}':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 1;
return true;
case '.':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 5;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
private static bool State5(FsmContext ctx)
{
ctx.L.GetChar();
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 6;
return true;
}
return false;
}
private static bool State6(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
{
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char)
{
case ',':
case ']':
case '}':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 1;
return true;
case 'e':
case 'E':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 7;
return true;
default:
return false;
}
}
return true;
}
private static bool State7(FsmContext ctx)
{
ctx.L.GetChar();
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 8;
return true;
}
switch (ctx.L.input_char)
{
case '+':
case '-':
ctx.L.string_buffer.Append((char)ctx.L.input_char);
ctx.NextState = 8;
return true;
default:
return false;
}
}
private static bool State8(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9')
{
ctx.L.string_buffer.Append((char)ctx.L.input_char);
continue;
}
if (ctx.L.input_char == ' ' ||
ctx.L.input_char >= '\t' && ctx.L.input_char <= '\r')
{
ctx.Return = true;
ctx.NextState = 1;
return true;
}
switch (ctx.L.input_char)
{
case ',':
case ']':
case '}':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
return true;
}
private static bool State9(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'r':
ctx.NextState = 10;
return true;
default:
return false;
}
}
private static bool State10(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'u':
ctx.NextState = 11;
return true;
default:
return false;
}
}
private static bool State11(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'e':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State12(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'a':
ctx.NextState = 13;
return true;
default:
return false;
}
}
private static bool State13(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'l':
ctx.NextState = 14;
return true;
default:
return false;
}
}
private static bool State14(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 's':
ctx.NextState = 15;
return true;
default:
return false;
}
}
private static bool State15(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'e':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State16(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'u':
ctx.NextState = 17;
return true;
default:
return false;
}
}
private static bool State17(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'l':
ctx.NextState = 18;
return true;
default:
return false;
}
}
private static bool State18(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'l':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State19(FsmContext ctx)
{
while (ctx.L.GetChar())
{
switch (ctx.L.input_char)
{
case '"':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 20;
return true;
case '\\':
ctx.StateStack = 19;
ctx.NextState = 21;
return true;
default:
ctx.L.string_buffer.Append((char)ctx.L.input_char);
continue;
}
}
return true;
}
private static bool State20(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case '"':
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State21(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case 'u':
ctx.NextState = 22;
return true;
case '"':
case '\'':
case '/':
case '\\':
case 'b':
case 'f':
case 'n':
case 'r':
case 't':
ctx.L.string_buffer.Append(
ProcessEscChar(ctx.L.input_char));
ctx.NextState = ctx.StateStack;
return true;
default:
return false;
}
}
private static bool State22(FsmContext ctx)
{
int counter = 0;
int mult = 4096;
ctx.L.unichar = 0;
while (ctx.L.GetChar())
{
if (ctx.L.input_char >= '0' && ctx.L.input_char <= '9' ||
ctx.L.input_char >= 'A' && ctx.L.input_char <= 'F' ||
ctx.L.input_char >= 'a' && ctx.L.input_char <= 'f')
{
ctx.L.unichar += HexValue(ctx.L.input_char) * mult;
counter++;
mult /= 16;
if (counter == 4)
{
ctx.L.string_buffer.Append(
Convert.ToChar(ctx.L.unichar));
ctx.NextState = ctx.StateStack;
return true;
}
continue;
}
return false;
}
return true;
}
private static bool State23(FsmContext ctx)
{
while (ctx.L.GetChar())
{
switch (ctx.L.input_char)
{
case '\'':
ctx.L.UngetChar();
ctx.Return = true;
ctx.NextState = 24;
return true;
case '\\':
ctx.StateStack = 23;
ctx.NextState = 21;
return true;
default:
ctx.L.string_buffer.Append((char)ctx.L.input_char);
continue;
}
}
return true;
}
private static bool State24(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case '\'':
ctx.L.input_char = '"';
ctx.Return = true;
ctx.NextState = 1;
return true;
default:
return false;
}
}
private static bool State25(FsmContext ctx)
{
ctx.L.GetChar();
switch (ctx.L.input_char)
{
case '*':
ctx.NextState = 27;
return true;
case '/':
ctx.NextState = 26;
return true;
default:
return false;
}
}
private static bool State26(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char == '\n')
{
ctx.NextState = 1;
return true;
}
}
return true;
}
private static bool State27(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char == '*')
{
ctx.NextState = 28;
return true;
}
}
return true;
}
private static bool State28(FsmContext ctx)
{
while (ctx.L.GetChar())
{
if (ctx.L.input_char == '*')
continue;
if (ctx.L.input_char == '/')
{
ctx.NextState = 1;
return true;
}
ctx.NextState = 27;
return true;
}
return true;
}
#endregion
private bool GetChar()
{
if ((input_char = NextChar()) != -1)
return true;
end_of_input = true;
return false;
}
private int NextChar()
{
if (input_buffer != 0)
{
int tmp = input_buffer;
input_buffer = 0;
return tmp;
}
return reader.Read();
}
public bool NextToken()
{
StateHandler handler;
fsm_context.Return = false;
while (true)
{
handler = fsm_handler_table[state - 1];
if (!handler(fsm_context))
throw new JsonException(input_char);
if (end_of_input)
return false;
if (fsm_context.Return)
{
if (char_buffer == null || char_buffer.Length < string_buffer.Length)
char_buffer = new char[string_buffer.Length];
char_buffer_length = string_buffer.Length;
string_buffer.CopyTo(0, char_buffer, string_buffer.Length);
//string_value = string_buffer.ToString();
string_buffer.Remove(0, string_buffer.Length);
token = fsm_return_table[state - 1];
if (token == (int)ParserToken.Char)
token = input_char;
state = fsm_context.NextState;
return true;
}
state = fsm_context.NextState;
}
}
private void UngetChar()
{
input_buffer = input_char;
}
public void Clear()
{
this.string_buffer.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: efb84fcc579b1fb49b5c9157bad4e2d7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,44 @@
#region Header
/**
* ParserToken.cs
* Internal representation of the tokens used by the lexer and the parser.
*
* The authors disclaim copyright to this source code. For more details, see
* the COPYING file included with this distribution.
**/
#endregion
namespace Best.HTTP.JSON.LitJson
{
internal enum ParserToken
{
// Lexer tokens (see section A.1.1. of the manual)
None = System.Char.MaxValue + 1,
Number,
True,
False,
Null,
CharSeq,
// Single char
Char,
// Parser Rules (see section A.2.1 of the manual)
Text,
Object,
ObjectPrime,
Pair,
PairRest,
Array,
ArrayPrime,
Value,
ValueRest,
String,
// End of input
End,
// The empty rule
Epsilon
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35dc4d2d98300944b8d59272de90def2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: