/* 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 { /// /// The wrapper for JSON value. /// 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; } } /// /// Gets / sets the current value /// 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."); } } /// /// Get the type of value /// public ValueType type { get { return _type; } } /// /// Constructor /// /// Value public RealWorldTerrainJsonValue(object value) { this.value = value; } /// /// Constructor /// /// Value /// Type of value 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 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(); } /// /// Type of value /// public enum ValueType { DOUBLE, LONG, STRING, BOOLEAN, NULL } } }