/* 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 { /// /// The wrapper for an array of JSON elements. /// public class RealWorldTerrainJsonArray : RealWorldTerrainJsonItem { private List _items; private int _count; public List items { get { return _items; } } /// /// Count elements /// 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); } } /// /// Constructor /// public RealWorldTerrainJsonArray() { _items = new List(); } /// /// Adds an element to the array. /// /// Element public void Add(RealWorldTerrainJsonItem item) { _items.Add(item); _count++; } /// /// Adds an elements to the array. /// /// Array of elements 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 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 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 GetEnumerator() { return _items.GetEnumerator(); } /// /// Parse a string that contains an array /// /// JSON string /// Instance 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; } } }