This commit is contained in:
2025-06-09 00:11:54 +08:00
parent d8c6eb0bd6
commit c773a6bb8d
11207 changed files with 48929 additions and 304 deletions

View File

@@ -0,0 +1,794 @@
/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using InfinityCode.RealWorldTerrain.Utils;
using UnityEngine;
namespace InfinityCode.RealWorldTerrain.JSON
{
/// <summary>
/// Class for working with JSON. It is used for parsing of string, serialization and deserialization of object.
/// </summary>
public class RealWorldTerrainJson
{
private string json;
private int index = 0;
private Token lookAheadToken = Token.None;
private StringBuilder s;
private int length;
protected RealWorldTerrainJson(string json)
{
s = new StringBuilder();
this.json = json;
length = json.Length;
}
/// <summary>
/// Deserialize string into object.
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <param name="json">JSON string</param>
/// <returns>Deserialized object</returns>
public static T Deserialize<T>(string json)
{
object obj = ParseDirect(json);
if (obj is IDictionary) return (T) DeserializeObject(typeof(T), obj as Dictionary<string, object>);
if (obj is IList) return (T) DeserializeArray(typeof(T), obj as List<object>);
return (T) DeserializeValue(typeof(T), obj);
}
private static object DeserializeValue(Type type, object obj)
{
if (obj == null) return null;
try
{
return Convert.ChangeType(obj, type);
}
catch (Exception exception)
{
Debug.Log(exception.Message + "\n" + exception.StackTrace);
}
return null;
}
private static object DeserializeArray(Type type, List<object> list)
{
if (list == null || list.Count == 0) return null;
if (type.IsArray)
{
Type elementType = type.GetElementType();
Array v = Array.CreateInstance(elementType, list.Count);
for (int i = 0; i < list.Count; i++)
{
object child = list[i];
object item;
if (child is IDictionary) item = DeserializeObject(elementType, child as Dictionary<string, object>);
else if (child is IList) item = DeserializeArray(elementType, child as List<object>);
else item = DeserializeValue(elementType, child);
v.SetValue(item, i);
}
return v;
}
if (RealWorldTerrainReflectionHelper.IsGenericType(type))
{
Type listType = RealWorldTerrainReflectionHelper.GetGenericArguments(type)[0];
object v = Activator.CreateInstance(type);
for (int i = 0; i < list.Count; i++)
{
object child = list[i];
object item;
if (child is IDictionary) item = DeserializeObject(listType, child as Dictionary<string, object>);
else if (child is IList) item = DeserializeArray(listType, child as List<object>);
else item = DeserializeValue(listType, child);
try
{
MethodInfo methodInfo = RealWorldTerrainReflectionHelper.GetMethod(type, "Add");
if (methodInfo != null) methodInfo.Invoke(v, new[] {item});
}
catch
{
}
}
return v;
}
return null;
}
private static object DeserializeObject(Type type, Dictionary<string, object> table)
{
IEnumerable<MemberInfo> members = RealWorldTerrainReflectionHelper.GetMembers(type, BindingFlags.Instance | BindingFlags.Public);
object v = Activator.CreateInstance(type);
foreach (MemberInfo member in members)
{
#if !NETFX_CORE
MemberTypes memberType = member.MemberType;
if (memberType != MemberTypes.Field && memberType != MemberTypes.Property) continue;
#else
MemberTypes memberType;
if (member is PropertyInfo) memberType = MemberTypes.Property;
else if (member is FieldInfo) memberType = MemberTypes.Field;
else continue;
#endif
if (memberType == MemberTypes.Property && !((PropertyInfo) member).CanWrite) continue;
object item;
#if !NETFX_CORE
object[] attributes = member.GetCustomAttributes(typeof(AliasAttribute), true);
AliasAttribute alias = attributes.Length > 0 ? attributes[0] as AliasAttribute : null;
#else
IEnumerable<Attribute> attributes = member.GetCustomAttributes(typeof(AliasAttribute), true);
AliasAttribute alias = null;
foreach (Attribute a in attributes)
{
alias = a as AliasAttribute;
break;
}
#endif
if (alias == null || !alias.ignoreFieldName)
{
if (table.TryGetValue(member.Name, out item))
{
DeserializeValue(memberType, member, item, v);
continue;
}
}
if (alias != null)
{
for (int j = 0; j < alias.aliases.Length; j++)
{
if (table.TryGetValue(alias.aliases[j], out item))
{
DeserializeValue(memberType, member, item, v);
break;
}
}
}
}
return v;
}
private static void DeserializeValue(MemberTypes memberType, MemberInfo member, object item, object v)
{
object cv;
Type t = memberType == MemberTypes.Field ? ((FieldInfo) member).FieldType : ((PropertyInfo) member).PropertyType;
if (t == typeof(System.Object)) cv = item;
else if (item is IDictionary) cv = DeserializeObject(t, item as Dictionary<string, object>);
else if (item is IList) cv = DeserializeArray(t, item as List<object>);
else cv = DeserializeValue(t, item);
if (memberType == MemberTypes.Field) ((FieldInfo) member).SetValue(v, cv);
else ((PropertyInfo) member).SetValue(v, cv, null);
}
private Token LookAhead()
{
if (lookAheadToken != Token.None) return lookAheadToken;
return lookAheadToken = NextTokenCore();
}
private Token NextToken()
{
Token result = lookAheadToken != Token.None ? lookAheadToken : NextTokenCore();
lookAheadToken = Token.None;
return result;
}
private Token NextTokenCore()
{
char c;
do
{
c = json[index];
if (c == '/' && json[index + 1] == '/')
{
index += 2;
do
{
c = json[index];
if (c == '\r' || c == '\n') break;
} while (++index < length);
}
if (c > ' ') break;
if (c != ' ' && c != '\t' && c != '\n' && c != '\r') break;
} while (++index < length);
if (index == length) throw new Exception("Reached end of string unexpectedly");
c = json[index];
index++;
switch (c)
{
case '{':
return Token.Curly_Open;
case '}':
return Token.Curly_Close;
case '[':
return Token.Squared_Open;
case ']':
return Token.Squared_Close;
case ',':
return Token.Comma;
case '"':
return Token.String;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '-':
case '+':
case '.':
return Token.Number;
case ':':
return Token.Colon;
case 'f':
if (length - index >= 4 &&
json[index + 0] == 'a' &&
json[index + 1] == 'l' &&
json[index + 2] == 's' &&
json[index + 3] == 'e')
{
index += 4;
return Token.False;
}
break;
case 't':
if (length - index >= 3 &&
json[index + 0] == 'r' &&
json[index + 1] == 'u' &&
json[index + 2] == 'e')
{
index += 3;
return Token.True;
}
break;
case 'n':
if (length - index >= 3 &&
json[index + 0] == 'u' &&
json[index + 1] == 'l' &&
json[index + 2] == 'l')
{
index += 3;
return Token.Null;
}
break;
}
throw new Exception("Could not find token at index " + --index);
}
/// <summary>
/// Parse JSON string into RealWorldTerrainJsonItem
/// </summary>
/// <param name="json">JSON string</param>
/// <returns>Root object</returns>
public static RealWorldTerrainJsonItem Parse(string json)
{
RealWorldTerrainJson instance = new RealWorldTerrainJson(json);
return instance.ParseValue();
}
/// <summary>
/// Parse JSON string into Dictonary, List and Object
/// </summary>
/// <param name="json">JSON string</param>
/// <returns>Root object</returns>
public static object ParseDirect(string json)
{
RealWorldTerrainJson instance = new RealWorldTerrainJson(json);
return instance.ParseValueDirect();
}
private RealWorldTerrainJsonArray ParseArray()
{
RealWorldTerrainJsonArray array = new RealWorldTerrainJsonArray();
lookAheadToken = Token.None;
while (true)
{
switch (LookAhead())
{
case Token.Comma:
lookAheadToken = Token.None;
break;
case Token.Squared_Close:
lookAheadToken = Token.None;
return array;
default:
array.Add(ParseValue());
break;
}
}
}
private List<object> ParseArrayDirect()
{
List<object> array = new List<object>();
lookAheadToken = Token.None;
while (true)
{
switch (LookAhead())
{
case Token.Comma:
lookAheadToken = Token.None;
break;
case Token.Squared_Close:
lookAheadToken = Token.None;
return array;
default:
array.Add(ParseValueDirect());
break;
}
}
}
private object ParseNumber()
{
lookAheadToken = Token.None;
index--;
long n = 0;
bool neg = false;
long decimalV = 0;
long exp = 0;
bool negExp = false;
while (index < length)
{
char c = json[index];
if (c >= '0' && c <= '9')
{
n = n * 10 + (c - '0');
decimalV *= 10;
}
else if (c == '.')
{
decimalV = 1;
}
else if (c == '-') neg = true;
else if (c == '+') neg = false;
else if (c == 'e' || c == 'E')
{
if (decimalV == 0) decimalV = 1;
index++;
exp = 0;
while (index < length)
{
c = json[index];
if (c >= '0' && c <= '9') exp = exp * 10 + (c - '0');
else if (c == '-') negExp = true;
else if (c == '+') negExp = false;
else break;
index++;
}
break;
}
else break;
index++;
}
if (neg) n = -n;
if (decimalV != 0)
{
double v = n / (double) decimalV;
if (exp > 0)
{
if (negExp) v /= Math.Pow(10, exp);
else v *= Math.Pow(10, exp);
}
return v;
}
return n;
}
private RealWorldTerrainJsonObject ParseObject()
{
RealWorldTerrainJsonObject obj = new RealWorldTerrainJsonObject();
lookAheadToken = Token.None;
while (true)
{
switch (LookAhead())
{
case Token.Comma:
lookAheadToken = Token.None;
break;
case Token.Curly_Close:
lookAheadToken = Token.None;
return obj;
default:
{
string name = ParseString();
if (NextToken() != Token.Colon) throw new Exception("Expected colon at index " + index);
obj.Add(name, ParseValue());
}
break;
}
}
}
private Dictionary<string, object> ParseObjectDirect()
{
Dictionary<string, object> obj = new Dictionary<string, object>();
lookAheadToken = Token.None;
while (true)
{
switch (LookAhead())
{
case Token.Comma:
lookAheadToken = Token.None;
break;
case Token.Curly_Close:
lookAheadToken = Token.None;
return obj;
default:
{
string name = ParseString();
if (NextToken() != Token.Colon) throw new Exception("Expected colon at index " + index);
obj.Add(name, ParseValueDirect());
}
break;
}
}
}
private uint ParseSingleChar(char c1, uint multipliyer)
{
uint p1 = 0;
if (c1 >= '0' && c1 <= '9') p1 = (uint) (c1 - '0') * multipliyer;
else if (c1 >= 'A' && c1 <= 'F') p1 = (uint) (c1 - 'A' + 10) * multipliyer;
else if (c1 >= 'a' && c1 <= 'f') p1 = (uint) (c1 - 'a' + 10) * multipliyer;
return p1;
}
private string ParseString()
{
lookAheadToken = Token.None;
s.Length = 0;
int runIndex = -1;
int l = length;
string p = json;
{
while (index < l)
{
char c = p[index++];
if (c == '"')
{
if (runIndex != -1)
{
if (s.Length == 0) return p.Substring(runIndex, index - runIndex - 1);
s.Append(p, runIndex, index - runIndex - 1);
}
return s.ToString();
}
if (c != '\\')
{
if (runIndex == -1) runIndex = index - 1;
continue;
}
if (index == l) break;
if (runIndex != -1)
{
s.Append(p, runIndex, index - runIndex - 1);
runIndex = -1;
}
switch (p[index++])
{
case '"':
s.Append('"');
break;
case '\\':
s.Append('\\');
break;
case '/':
s.Append('/');
break;
case 'b':
s.Append('\b');
break;
case 'f':
s.Append('\f');
break;
case 'n':
s.Append('\n');
break;
case 'r':
s.Append('\r');
break;
case 't':
s.Append('\t');
break;
case 'u':
{
int remainingLength = l - index;
if (remainingLength < 4) break;
uint codePoint = ParseUnicode(p[index], p[index + 1], p[index + 2], p[index + 3]);
s.Append((char) codePoint);
index += 4;
}
break;
}
}
}
throw new Exception("Unexpectedly reached end of string");
}
private uint ParseUnicode(char c1, char c2, char c3, char c4)
{
uint p1 = ParseSingleChar(c1, 0x1000);
uint p2 = ParseSingleChar(c2, 0x100);
uint p3 = ParseSingleChar(c3, 0x10);
uint p4 = ParseSingleChar(c4, 1);
return p1 + p2 + p3 + p4;
}
private RealWorldTerrainJsonItem ParseValue()
{
switch (LookAhead())
{
case Token.Number:
object number = ParseNumber();
return new RealWorldTerrainJsonValue(number, number is double ? RealWorldTerrainJsonValue.ValueType.DOUBLE : RealWorldTerrainJsonValue.ValueType.LONG);
case Token.String:
return new RealWorldTerrainJsonValue(ParseString(), RealWorldTerrainJsonValue.ValueType.STRING);
case Token.Curly_Open:
return ParseObject();
case Token.Squared_Open:
return ParseArray();
case Token.True:
lookAheadToken = Token.None;
return new RealWorldTerrainJsonValue(true, RealWorldTerrainJsonValue.ValueType.BOOLEAN);
case Token.False:
lookAheadToken = Token.None;
return new RealWorldTerrainJsonValue(false, RealWorldTerrainJsonValue.ValueType.BOOLEAN);
case Token.Null:
lookAheadToken = Token.None;
return new RealWorldTerrainJsonValue(null, RealWorldTerrainJsonValue.ValueType.NULL);
}
throw new Exception("Unrecognized token at index" + index);
}
private object ParseValueDirect()
{
switch (LookAhead())
{
case Token.Number:
return ParseNumber();
case Token.String:
return ParseString();
case Token.Curly_Open:
return ParseObjectDirect();
case Token.Squared_Open:
return ParseArrayDirect();
case Token.True:
lookAheadToken = Token.None;
return true;
case Token.False:
lookAheadToken = Token.None;
return false;
case Token.Null:
lookAheadToken = Token.None;
return null;
}
throw new Exception("Unrecognized token at index" + index);
}
/// <summary>
/// Serializes an object to JSON.
/// </summary>
/// <param name="obj">Object</param>
/// <param name="bindingFlags">A bitmask comprised of one or more BindingFlags that specify how the search is conducted.</param>
/// <returns>JSON</returns>
public static RealWorldTerrainJsonItem Serialize(object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
#if !UNITY_WP_8_1 || UNITY_EDITOR
if (obj == null || obj is DBNull) return new RealWorldTerrainJsonValue(obj, RealWorldTerrainJsonValue.ValueType.NULL);
#else
if (obj == null) return new RealWorldTerrainJsonValue(obj, RealWorldTerrainJsonValue.ValueType.NULL);
#endif
if (obj is string || obj is bool || obj is int || obj is long || obj is short || obj is float || obj is double) return new RealWorldTerrainJsonValue(obj);
if (obj is UnityEngine.Object)
{
if (!(obj is Component || obj is ScriptableObject)) return new RealWorldTerrainJsonValue((obj as UnityEngine.Object).GetInstanceID());
}
if (obj is IDictionary)
{
IDictionary d = obj as IDictionary;
RealWorldTerrainJsonObject dv = new RealWorldTerrainJsonObject();
ICollection keys = d.Keys;
ICollection values = d.Values;
IEnumerator keysEnum = keys.GetEnumerator();
IEnumerator valuesEnum = values.GetEnumerator();
while (keysEnum.MoveNext() && valuesEnum.MoveNext())
{
object k = keysEnum.Current;
object v = valuesEnum.Current;
dv.Add(k as string, Serialize(v, bindingFlags));
}
return dv;
}
if (obj is IEnumerable)
{
IEnumerable v = (IEnumerable) obj;
RealWorldTerrainJsonArray array = new RealWorldTerrainJsonArray();
foreach (var item in v) array.Add(Serialize(item, bindingFlags));
return array;
}
RealWorldTerrainJsonObject o = new RealWorldTerrainJsonObject();
Type type = obj.GetType();
if (RealWorldTerrainReflectionHelper.CheckIfAnonymousType(type)) bindingFlags |= BindingFlags.NonPublic;
IEnumerable<FieldInfo> fields = RealWorldTerrainReflectionHelper.GetFields(type, bindingFlags);
foreach (FieldInfo field in fields)
{
string fieldName = field.Name;
if (field.Attributes == (FieldAttributes.Private | FieldAttributes.InitOnly))
{
int startIndex = fieldName.IndexOf('<') + 1;
int endIndex = fieldName.IndexOf('>', startIndex);
if (endIndex != -1 && startIndex != -1) fieldName = fieldName.Substring(startIndex, endIndex - startIndex);
else fieldName = fieldName.Trim('<', '>');
}
o.Add(fieldName, Serialize(field.GetValue(obj)));
}
return o;
}
private enum Token
{
None = -1,
Curly_Open,
Curly_Close,
Squared_Open,
Squared_Close,
Colon,
Comma,
String,
Number,
True,
False,
Null
}
/// <summary>
/// Alias of field used during deserialization.
/// </summary>
public class AliasAttribute : Attribute
{
/// <summary>
/// Aliases
/// </summary>
public readonly string[] aliases;
/// <summary>
/// If true, the original field name will be ignored.
/// </summary>
public readonly bool ignoreFieldName;
/// <summary>
/// Constructor
/// </summary>
/// <param name="ignoreFieldName">If true, the original field name will be ignored.</param>
/// <param name="aliases">Aliases</param>
public AliasAttribute(bool ignoreFieldName, params string[] aliases)
{
if (aliases == null || aliases.Length == 0) throw new Exception("You must use at least one alias.");
this.ignoreFieldName = ignoreFieldName;
this.aliases = aliases;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="aliases">Aliases</param>
public AliasAttribute(params string[] aliases) : this(false, aliases)
{
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: caeec121996ee584c9fa1e236d7947b4
timeCreated: 1564669254
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,274 @@
/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using InfinityCode.RealWorldTerrain.Utils;
namespace InfinityCode.RealWorldTerrain.JSON
{
/// <summary>
/// The wrapper for an array of JSON elements.
/// </summary>
public class RealWorldTerrainJsonArray : RealWorldTerrainJsonItem
{
private List<RealWorldTerrainJsonItem> _items;
private int _count;
public List<RealWorldTerrainJsonItem> items
{
get { return _items; }
}
/// <summary>
/// Count elements
/// </summary>
public int count
{
get { return _count; }
}
public override RealWorldTerrainJsonItem this[int index]
{
get
{
if (index < 0 || index >= _count) return null;
return _items[index];
}
}
public override RealWorldTerrainJsonItem this[string key]
{
get { return Get(key); }
}
/// <summary>
/// Constructor
/// </summary>
public RealWorldTerrainJsonArray()
{
_items = new List<RealWorldTerrainJsonItem>();
}
/// <summary>
/// Adds an element to the array.
/// </summary>
/// <param name="item">Element</param>
public void Add(RealWorldTerrainJsonItem item)
{
_items.Add(item);
_count++;
}
/// <summary>
/// Adds an elements to the array.
/// </summary>
/// <param name="collection">Array of elements</param>
public void AddRange(RealWorldTerrainJsonArray collection)
{
if (collection == null) return;
_items.AddRange(collection._items);
_count += collection._count;
}
public void AddRange(RealWorldTerrainJsonItem collection)
{
AddRange(collection as RealWorldTerrainJsonArray);
}
public RealWorldTerrainJsonObject CreateObject()
{
RealWorldTerrainJsonObject obj = new RealWorldTerrainJsonObject();
Add(obj);
return obj;
}
public override object Deserialize(Type type, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
if (_count == 0) return null;
if (type.IsArray)
{
Type elementType = type.GetElementType();
Array v = Array.CreateInstance(elementType, _count);
if (_items[0] is RealWorldTerrainJsonObject)
{
IEnumerable<MemberInfo> members = RealWorldTerrainReflectionHelper.GetMembers(elementType, bindingFlags);
for (int i = 0; i < _count; i++)
{
RealWorldTerrainJsonItem child = _items[i];
object item = (child as RealWorldTerrainJsonObject).Deserialize(elementType, members, bindingFlags);
v.SetValue(item, i);
}
}
else
{
for (int i = 0; i < _count; i++)
{
RealWorldTerrainJsonItem child = _items[i];
object item = child.Deserialize(elementType, bindingFlags);
v.SetValue(item, i);
}
}
return v;
}
if (RealWorldTerrainReflectionHelper.IsGenericType(type))
{
Type listType = RealWorldTerrainReflectionHelper.GetGenericArguments(type)[0];
object v = Activator.CreateInstance(type);
if (_items[0] is RealWorldTerrainJsonObject)
{
IEnumerable<MemberInfo> members = RealWorldTerrainReflectionHelper.GetMembers(listType, BindingFlags.Instance | BindingFlags.Public);
for (int i = 0; i < _count; i++)
{
RealWorldTerrainJsonItem child = _items[i];
object item = (child as RealWorldTerrainJsonObject).Deserialize(listType, members);
try
{
MethodInfo methodInfo = RealWorldTerrainReflectionHelper.GetMethod(type, "Add");
if (methodInfo != null) methodInfo.Invoke(v, new[] { item });
}
catch
{
}
}
}
else
{
for (int i = 0; i < _count; i++)
{
RealWorldTerrainJsonItem child = _items[i];
object item = child.Deserialize(listType);
try
{
MethodInfo methodInfo = RealWorldTerrainReflectionHelper.GetMethod(type, "Add");
if (methodInfo != null) methodInfo.Invoke(v, new[] { item });
}
catch
{
}
}
}
return v;
}
return null;
}
private RealWorldTerrainJsonItem Get(string key)
{
if (string.IsNullOrEmpty(key)) return null;
if (key.StartsWith("//"))
{
string k = key.Substring(2);
if (string.IsNullOrEmpty(k) || k.StartsWith("//")) return null;
return GetAll(k);
}
return GetThis(key);
}
private RealWorldTerrainJsonItem GetThis(string key)
{
int kindex;
if (key.Contains("/"))
{
int index = key.IndexOf("/");
string k = key.Substring(0, index);
string nextPart = key.Substring(index + 1);
if (k == "*")
{
RealWorldTerrainJsonArray arr = new RealWorldTerrainJsonArray();
for (int i = 0; i < _count; i++)
{
RealWorldTerrainJsonItem item = _items[i][nextPart];
if (item != null) arr.Add(item);
}
return arr;
}
if (int.TryParse(k, out kindex))
{
if (kindex < 0 || kindex >= _count) return null;
RealWorldTerrainJsonItem item = _items[kindex];
return item[nextPart];
}
}
if (key == "*") return this;
if (int.TryParse(key, out kindex)) return this[kindex];
return null;
}
public override RealWorldTerrainJsonItem GetAll(string k)
{
RealWorldTerrainJsonItem item = GetThis(k);
RealWorldTerrainJsonArray arr = null;
if (item != null)
{
arr = new RealWorldTerrainJsonArray();
arr.Add(item);
}
for (int i = 0; i < _count; i++)
{
item = _items[i];
RealWorldTerrainJsonArray subArr = item.GetAll(k) as RealWorldTerrainJsonArray;
if (subArr != null)
{
if (arr == null) arr = new RealWorldTerrainJsonArray();
arr.AddRange(subArr);
}
}
return arr;
}
public override IEnumerator<RealWorldTerrainJsonItem> GetEnumerator()
{
return _items.GetEnumerator();
}
/// <summary>
/// Parse a string that contains an array
/// </summary>
/// <param name="json">JSON string</param>
/// <returns>Instance</returns>
public static RealWorldTerrainJsonArray ParseArray(string json)
{
return RealWorldTerrainJson.Parse(json) as RealWorldTerrainJsonArray;
}
public override void ToJSON(StringBuilder b)
{
b.Append("[");
for (int i = 0; i < _count; i++)
{
if (i != 0) b.Append(",");
_items[i].ToJSON(b);
}
b.Append("]");
}
public override object Value(Type type)
{
if (RealWorldTerrainReflectionHelper.IsValueType(type)) return Activator.CreateInstance(type);
return null;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 4051daf2706fd35499b6795639764db5
timeCreated: 1564669254
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,145 @@
/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
namespace InfinityCode.RealWorldTerrain.JSON
{
/// <summary>
/// The base class of JSON elements.
/// </summary>
public abstract class RealWorldTerrainJsonItem : IEnumerable<RealWorldTerrainJsonItem>
{
/// <summary>
/// Get the element by index
/// </summary>
/// <param name="index">Index of element</param>
/// <returns>Element</returns>
public abstract RealWorldTerrainJsonItem this[int index] { get; }
/// <summary>
/// Get the element by key.\n
/// Supports XPath like selectors:\n
/// ["key"] - get element by key.\n
/// ["key1/key2"] - get element key2, which is a child of the element key1.\n
/// ["key/N"] - where N is number. Get array element by index N, which is a child of the element key1.\n
/// ["key/*"] - get all array elements, which is a child of the element key1.\n
/// ["//key"] - get all elements with the key on the first or the deeper levels of the current element. \n
/// </summary>
/// <param name="key">Element key</param>
/// <returns>Element</returns>
public abstract RealWorldTerrainJsonItem this[string key] { get; }
/// <summary>
/// Serializes the object and adds to the current json node.
/// </summary>
/// <param name="obj">Object</param>
/// <returns>Current json node</returns>
public virtual RealWorldTerrainJsonItem AppendObject(object obj)
{
throw new Exception("AppendObject is only allowed for RealWorldTerrainJsonObject.");
}
/// <summary>
/// Returns the value of the child element, converted to the specified type.
/// </summary>
/// <typeparam name="T">Type of variable</typeparam>
/// <param name="childName">Child element key</param>
/// <returns>Value</returns>
public T ChildValue<T>(string childName)
{
RealWorldTerrainJsonItem el = this[childName];
if (el == null) return default(T);
return el.Value<T>();
}
/// <summary>
/// Deserializes current element
/// </summary>
/// <typeparam name="T">Type</typeparam>
/// <returns>Object</returns>
public T Deserialize<T>(BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
return (T) Deserialize(typeof(T), bindingFlags);
}
/// <summary>
/// Deserializes current element
/// </summary>
/// <param name="type">Type</param>
/// <returns>Object</returns>
public abstract object Deserialize(Type type, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public);
/// <summary>
/// Get all elements with the key on the first or the deeper levels of the current element.
/// </summary>
/// <param name="key">Key</param>
/// <returns>Elements</returns>
public abstract RealWorldTerrainJsonItem GetAll(string key);
/// <summary>
/// Converts the current and the child elements to JSON string.
/// </summary>
/// <param name="b">StringBuilder instance</param>
public abstract void ToJSON(StringBuilder b);
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public virtual IEnumerator<RealWorldTerrainJsonItem> GetEnumerator()
{
return null;
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
ToJSON(b);
return b.ToString();
}
/// <summary>
/// Returns the value of the element, converted to the specified type.
/// </summary>
/// <param name="type">Type of variable</param>
/// <returns>Value</returns>
public abstract object Value(Type type);
/// <summary>
/// Returns the value of the element, converted to the specified type.
/// </summary>
/// <typeparam name="T">Type of variable</typeparam>
/// <returns>Value</returns>
public virtual T Value<T>()
{
return (T) Value(typeof(T));
}
/// <summary>
/// Returns the value of the element, converted to the specified type.
/// </summary>
/// <typeparam name="T">Type of variable</typeparam>
/// <returns>Value</returns>
public T V<T>()
{
return Value<T>();
}
/// <summary>
/// Returns the value of the child element, converted to the specified type.
/// </summary>
/// <typeparam name="T">Type of variable</typeparam>
/// <param name="childName">Child element key</param>
/// <returns>Value</returns>
public T V<T>(string childName)
{
return ChildValue<T>(childName);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: f76b4b0f8b1c1b54d8656a77ca5d340c
timeCreated: 1564669254
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,325 @@
/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using InfinityCode.RealWorldTerrain.Utils;
using UnityEngine;
namespace InfinityCode.RealWorldTerrain.JSON
{
/// <summary>
/// The wrapper for JSON dictonary.
/// </summary>
public class RealWorldTerrainJsonObject : RealWorldTerrainJsonItem
{
private Dictionary<string, RealWorldTerrainJsonItem> _table;
/// <summary>
/// Dictionary of items
/// </summary>
public Dictionary<string, RealWorldTerrainJsonItem> table
{
get { return _table; }
}
public override RealWorldTerrainJsonItem this[string key]
{
get { return Get(key); }
}
public override RealWorldTerrainJsonItem this[int index]
{
get
{
if (index < 0) return null;
int i = 0;
foreach (KeyValuePair<string, RealWorldTerrainJsonItem> pair in _table)
{
if (i == index) return pair.Value;
i++;
}
return null;
}
}
/// <summary>
/// Constructor
/// </summary>
public RealWorldTerrainJsonObject()
{
_table = new Dictionary<string, RealWorldTerrainJsonItem>();
}
/// <summary>
/// Adds element to the dictionary
/// </summary>
/// <param name="name">Key</param>
/// <param name="value">Value</param>
public void Add(string name, RealWorldTerrainJsonItem value)
{
_table[name] = value;
}
public void Add(string name, object value)
{
if (value is string || value is bool || value is int || value is long || value is short || value is float || value is double) _table[name] = new RealWorldTerrainJsonValue(value);
else if (value is UnityEngine.Object)
{
_table[name] = new RealWorldTerrainJsonValue((value as UnityEngine.Object).GetInstanceID());
}
else _table[name] = RealWorldTerrainJson.Serialize(value, BindingFlags.Instance | BindingFlags.Public);
}
public void Add(string name, object value, RealWorldTerrainJsonValue.ValueType valueType)
{
_table[name] = new RealWorldTerrainJsonValue(value, valueType);
}
public override RealWorldTerrainJsonItem AppendObject(object obj)
{
Combine(RealWorldTerrainJson.Serialize(obj));
return this;
}
/// <summary>
/// Combines two JSON Object.
/// </summary>
/// <param name="other">Other JSON Object</param>
/// <param name="overwriteExistingValues">Overwrite the existing values?</param>
public void Combine(RealWorldTerrainJsonItem other, bool overwriteExistingValues = false)
{
RealWorldTerrainJsonObject otherObj = other as RealWorldTerrainJsonObject;
if (otherObj == null) throw new Exception("Only RealWorldTerrainJsonObject is allowed to be combined.");
Dictionary<string, RealWorldTerrainJsonItem> otherDict = otherObj.table;
foreach (KeyValuePair<string, RealWorldTerrainJsonItem> pair in otherDict)
{
if (overwriteExistingValues || !_table.ContainsKey(pair.Key)) _table[pair.Key] = pair.Value;
}
}
public bool Contains(string key)
{
return _table.ContainsKey(key);
}
public RealWorldTerrainJsonArray CreateArray(string name)
{
RealWorldTerrainJsonArray array = new RealWorldTerrainJsonArray();
Add(name, array);
return array;
}
public RealWorldTerrainJsonObject CreateObject(string name)
{
RealWorldTerrainJsonObject obj = new RealWorldTerrainJsonObject();
Add(name, obj);
return obj;
}
public override object Deserialize(Type type, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
IEnumerable<MemberInfo> members = RealWorldTerrainReflectionHelper.GetMembers(type, bindingFlags);
return Deserialize(type, members, bindingFlags);
}
/// <summary>
/// Deserializes current element
/// </summary>
/// <param name="type">Type</param>
/// <param name="members">Members of variable</param>
/// <returns>Object</returns>
public object Deserialize(Type type, IEnumerable<MemberInfo> members, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
object v = Activator.CreateInstance(type);
DeserializeObject(v, members, bindingFlags);
return v;
}
public void DeserializeObject(object obj, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
IEnumerable<MemberInfo> members = RealWorldTerrainReflectionHelper.GetMembers(obj.GetType(), bindingFlags);
DeserializeObject(obj, members);
}
public void DeserializeObject(object obj, IEnumerable<MemberInfo> members, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
foreach (MemberInfo member in members)
{
#if !NETFX_CORE
MemberTypes memberType = member.MemberType;
if (memberType != MemberTypes.Field && memberType != MemberTypes.Property) continue;
#else
MemberTypes memberType;
if (member is PropertyInfo) memberType = MemberTypes.Property;
else if (member is FieldInfo) memberType = MemberTypes.Field;
else continue;
#endif
if (memberType == MemberTypes.Property && !((PropertyInfo) member).CanWrite) continue;
RealWorldTerrainJsonItem item;
#if !NETFX_CORE
object[] attributes = member.GetCustomAttributes(typeof(RealWorldTerrainJson.AliasAttribute), true);
RealWorldTerrainJson.AliasAttribute alias = attributes.Length > 0 ? attributes[0] as RealWorldTerrainJson.AliasAttribute : null;
#else
IEnumerable<Attribute> attributes = member.GetCustomAttributes(typeof(RealWorldTerrainJson.AliasAttribute), true);
RealWorldTerrainJson.AliasAttribute alias = null;
foreach (Attribute a in attributes)
{
alias = a as RealWorldTerrainJson.AliasAttribute;
break;
}
#endif
if (alias == null || !alias.ignoreFieldName)
{
if (_table.TryGetValue(member.Name, out item))
{
Type t = memberType == MemberTypes.Field ? ((FieldInfo) member).FieldType : ((PropertyInfo) member).PropertyType;
if (memberType == MemberTypes.Field) ((FieldInfo) member).SetValue(obj, item.Deserialize(t, bindingFlags));
else ((PropertyInfo) member).SetValue(obj, item.Deserialize(t, bindingFlags), null);
continue;
}
}
if (alias != null)
{
for (int j = 0; j < alias.aliases.Length; j++)
{
if (_table.TryGetValue(alias.aliases[j], out item))
{
Type t = memberType == MemberTypes.Field ? ((FieldInfo) member).FieldType : ((PropertyInfo) member).PropertyType;
if (memberType == MemberTypes.Field) ((FieldInfo) member).SetValue(obj, item.Deserialize(t, bindingFlags));
else ((PropertyInfo) member).SetValue(obj, item.Deserialize(t, bindingFlags), null);
break;
}
}
}
}
}
private RealWorldTerrainJsonItem Get(string key)
{
if (string.IsNullOrEmpty(key)) return null;
if (key.Length > 2 && key[0] == '/' && key[1] == '/')
{
string k = key.Substring(2);
if (string.IsNullOrEmpty(k) || k.StartsWith("//")) return null;
return GetAll(k);
}
return GetThis(key);
}
private RealWorldTerrainJsonItem GetThis(string key)
{
RealWorldTerrainJsonItem item;
int index = -1;
for (int i = 0; i < key.Length; i++)
{
if (key[i] == '/')
{
index = i;
break;
}
}
if (index != -1)
{
string k = key.Substring(0, index);
if (!string.IsNullOrEmpty(k))
{
if (_table.TryGetValue(k, out item))
{
string nextPart = key.Substring(index + 1);
return item[nextPart];
}
}
return null;
}
if (_table.TryGetValue(key, out item)) return item;
return null;
}
public override RealWorldTerrainJsonItem GetAll(string k)
{
RealWorldTerrainJsonItem item = GetThis(k);
RealWorldTerrainJsonArray arr = null;
if (item != null)
{
arr = new RealWorldTerrainJsonArray();
arr.Add(item);
}
var enumerator = _table.GetEnumerator();
while (enumerator.MoveNext())
{
item = enumerator.Current.Value;
RealWorldTerrainJsonArray subArr = item.GetAll(k) as RealWorldTerrainJsonArray;
if (subArr != null)
{
if (arr == null) arr = new RealWorldTerrainJsonArray();
arr.AddRange(subArr);
}
}
return arr;
}
public override IEnumerator<RealWorldTerrainJsonItem> GetEnumerator()
{
return _table.Values.GetEnumerator();
}
/// <summary>
/// Parse a string that contains JSON dictonary
/// </summary>
/// <param name="json">String that contains JSON dictonary</param>
/// <returns>Instance</returns>
public static RealWorldTerrainJsonObject ParseObject(string json)
{
return RealWorldTerrainJson.Parse(json) as RealWorldTerrainJsonObject;
}
public RealWorldTerrainJsonItem Remove(string key)
{
RealWorldTerrainJsonItem item;
if (_table.TryGetValue(key, out item))
{
_table.Remove(key);
return item;
}
return null;
}
public override void ToJSON(StringBuilder b)
{
b.Append("{");
bool hasChilds = false;
foreach (KeyValuePair<string, RealWorldTerrainJsonItem> pair in _table)
{
b.Append("\"").Append(pair.Key).Append("\"").Append(":");
pair.Value.ToJSON(b);
b.Append(",");
hasChilds = true;
}
if (hasChilds) b.Remove(b.Length - 1, 1);
b.Append("}");
}
public override object Value(Type type)
{
if (RealWorldTerrainReflectionHelper.IsValueType(type)) return Activator.CreateInstance(type);
return Deserialize(type);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: e795b994aaf01f2478404364e8b3b62a
timeCreated: 1564669254
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,263 @@
/* INFINITY CODE 2013-2019 */
/* http://www.infinity-code.com */
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Text;
using InfinityCode.RealWorldTerrain.Utils;
using UnityEngine;
namespace InfinityCode.RealWorldTerrain.JSON
{
/// <summary>
/// The wrapper for JSON value.
/// </summary>
public class RealWorldTerrainJsonValue : RealWorldTerrainJsonItem
{
private ValueType _type;
private object _value;
public override RealWorldTerrainJsonItem this[string key]
{
get { return null; }
}
public override RealWorldTerrainJsonItem this[int index]
{
get { return null; }
}
/// <summary>
/// Gets / sets the current value
/// </summary>
public object value
{
get { return _value; }
set
{
#if !UNITY_WP_8_1 || UNITY_EDITOR
if (value == null || value is DBNull)
#else
if (value == null)
#endif
{
_type = ValueType.NULL;
_value = value;
}
else if (value is string)
{
_type = ValueType.STRING;
_value = value;
}
else if (value is double)
{
_type = ValueType.DOUBLE;
_value = (double) value;
}
else if (value is float)
{
_type = ValueType.DOUBLE;
_value = (double) (float) value;
}
else if (value is bool)
{
_type = ValueType.BOOLEAN;
_value = value;
}
else if (value is long)
{
_type = ValueType.LONG;
_value = value;
}
else if (value is int || value is short || value is byte)
{
_type = ValueType.LONG;
_value = Convert.ChangeType(value, typeof(long));
}
else throw new Exception("Unknown type of value.");
}
}
/// <summary>
/// Get the type of value
/// </summary>
public ValueType type
{
get { return _type; }
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="value">Value</param>
public RealWorldTerrainJsonValue(object value)
{
this.value = value;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="value">Value</param>
/// <param name="type">Type of value</param>
public RealWorldTerrainJsonValue(object value, ValueType type)
{
_value = value;
_type = type;
}
public override object Deserialize(Type type, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public)
{
return Value(type);
}
public override RealWorldTerrainJsonItem GetAll(string key)
{
return null;
}
public override void ToJSON(StringBuilder b)
{
if (_type == ValueType.STRING) WriteString(b);
else if (_type == ValueType.NULL) b.Append("null");
else if (_type == ValueType.BOOLEAN) b.Append((bool) _value ? "true" : "false");
else if (_type == ValueType.DOUBLE) b.Append(((double) value).ToString(RealWorldTerrainCultureInfo.cultureInfo));
else b.Append(value);
}
public override IEnumerator<RealWorldTerrainJsonItem> GetEnumerator()
{
yield return this;
}
public override string ToString()
{
if (type == ValueType.DOUBLE) return ((double) value).ToString(RealWorldTerrainCultureInfo.cultureInfo);
return value.ToString();
}
public override object Value(Type t)
{
if (_type == ValueType.NULL || _value == null)
{
if (RealWorldTerrainReflectionHelper.IsValueType(t)) return Activator.CreateInstance(t);
return null;
}
if (t == typeof(string)) return Convert.ChangeType(_value, t);
if (_type == ValueType.BOOLEAN)
{
if (t == typeof(bool)) return Convert.ChangeType(_value, t);
}
else if (_type == ValueType.DOUBLE)
{
if (t == typeof(double)) return Convert.ChangeType(_value, t, RealWorldTerrainCultureInfo.numberFormat);
if (t == typeof(float)) return Convert.ChangeType((double) _value, t, RealWorldTerrainCultureInfo.numberFormat);
}
else if (_type == ValueType.LONG)
{
if (t == typeof(long)) return Convert.ChangeType(_value, t);
#if UNITY_EDITOR
if (t.IsSubclassOf(typeof(UnityEngine.Object)))
{
return UnityEditor.EditorUtility.InstanceIDToObject((int) (long) _value);
}
#endif
try
{
return Convert.ChangeType((long) _value, t);
}
catch (Exception e)
{
Debug.Log(e.Message + "\n" + e.StackTrace);
return null;
}
}
else if (_type == ValueType.STRING)
{
MethodInfo method = RealWorldTerrainReflectionHelper.GetMethod(t, "Parse", new[] {typeof(string), typeof(IFormatProvider)});
if (method != null) return method.Invoke(null, new object[] {value, RealWorldTerrainCultureInfo.numberFormat});
method = RealWorldTerrainReflectionHelper.GetMethod(t, "Parse", new[] {typeof(string)});
return method.Invoke(null, new[] {value});
}
StringBuilder builder = new StringBuilder();
ToJSON(builder);
throw new InvalidCastException(t.FullName + "\n" + builder);
}
private void WriteString(StringBuilder b)
{
b.Append('\"');
string s = value as string;
int runIndex = -1;
int l = s.Length;
for (var index = 0; index < l; ++index)
{
var c = s[index];
if (c >= ' ' && c < 128 && c != '\"' && c != '\\')
{
if (runIndex == -1) runIndex = index;
continue;
}
if (runIndex != -1)
{
b.Append(s, runIndex, index - runIndex);
runIndex = -1;
}
switch (c)
{
case '\t':
b.Append("\\t");
break;
case '\r':
b.Append("\\r");
break;
case '\n':
b.Append("\\n");
break;
case '"':
case '\\':
b.Append('\\');
b.Append(c);
break;
default:
b.Append("\\u");
b.Append(((int) c).ToString("X4", NumberFormatInfo.InvariantInfo));
break;
}
}
if (runIndex != -1) b.Append(s, runIndex, s.Length - runIndex);
b.Append('\"');
}
public static implicit operator string(RealWorldTerrainJsonValue val)
{
return val.ToString();
}
/// <summary>
/// Type of value
/// </summary>
public enum ValueType
{
DOUBLE,
LONG,
STRING,
BOOLEAN,
NULL
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 978ceaf2c164ae545bfd24fb23c24135
timeCreated: 1564669254
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: