|  |  | 
 |  |  | using System.Globalization; | 
 |  |  | using System.IO; | 
 |  |  | using System.Reflection; | 
 |  |  |  | 
 |  |  | using ILRuntime.Runtime.Intepreter; | 
 |  |  | using ILRuntime.Runtime.Stack; | 
 |  |  | using ILRuntime.CLR.Method; | 
 |  |  | using ILRuntime.CLR.Utils; | 
 |  |  |  | 
 |  |  | namespace LitJson | 
 |  |  | { | 
 |  |  | 
 |  |  |     public class JsonMapper | 
 |  |  |     { | 
 |  |  |         #region Fields | 
 |  |  |         private static readonly int max_nesting_depth; | 
 |  |  |         private static int max_nesting_depth; | 
 |  |  |  | 
 |  |  |         private static readonly IFormatProvider datetime_format; | 
 |  |  |         private static IFormatProvider datetime_format; | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, ExporterFunc> base_exporters_table; | 
 |  |  |         private static readonly IDictionary<Type, ExporterFunc> custom_exporters_table; | 
 |  |  |         private static IDictionary<Type, ExporterFunc> base_exporters_table; | 
 |  |  |         private static IDictionary<Type, ExporterFunc> custom_exporters_table; | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, | 
 |  |  |         private static IDictionary<Type, | 
 |  |  |                 IDictionary<Type, ImporterFunc>> base_importers_table; | 
 |  |  |         private static readonly IDictionary<Type, | 
 |  |  |         private static IDictionary<Type, | 
 |  |  |                 IDictionary<Type, ImporterFunc>> custom_importers_table; | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, ArrayMetadata> array_metadata; | 
 |  |  |         private static IDictionary<Type, ArrayMetadata> array_metadata; | 
 |  |  |         private static readonly object array_metadata_lock = new Object (); | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, | 
 |  |  |         private static IDictionary<Type, | 
 |  |  |                 IDictionary<Type, MethodInfo>> conv_ops; | 
 |  |  |         private static readonly object conv_ops_lock = new Object (); | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, ObjectMetadata> object_metadata; | 
 |  |  |         private static IDictionary<Type, ObjectMetadata> object_metadata; | 
 |  |  |         private static readonly object object_metadata_lock = new Object (); | 
 |  |  |  | 
 |  |  |         private static readonly IDictionary<Type, | 
 |  |  |         private static IDictionary<Type, | 
 |  |  |                 IList<PropertyMetadata>> type_properties; | 
 |  |  |         private static readonly object type_properties_lock = new Object (); | 
 |  |  |  | 
 |  |  |         private static readonly JsonWriter      static_writer; | 
 |  |  |         private static JsonWriter      static_writer; | 
 |  |  |         private static readonly object static_writer_lock = new Object (); | 
 |  |  |         #endregion | 
 |  |  |  | 
 |  |  | 
 |  |  |             if (type.GetInterface ("System.Collections.IList") != null) | 
 |  |  |                 data.IsList = true; | 
 |  |  |  | 
 |  |  |             foreach (PropertyInfo p_info in type.GetProperties ()) { | 
 |  |  |             if (type is ILRuntime.Reflection.ILRuntimeWrapperType) | 
 |  |  |             { | 
 |  |  |                 var wt = (ILRuntime.Reflection.ILRuntimeWrapperType)type; | 
 |  |  |                 if (data.IsArray) | 
 |  |  |                 { | 
 |  |  |                     data.ElementType = wt.CLRType.ElementType.ReflectionType;  | 
 |  |  |                 } | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     data.ElementType = wt.CLRType.GenericArguments[0].Value.ReflectionType; | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             else | 
 |  |  |             { | 
 |  |  |                 foreach (PropertyInfo p_info in type.GetProperties()) | 
 |  |  |                 { | 
 |  |  |                 if (p_info.Name != "Item") | 
 |  |  |                     continue; | 
 |  |  |  | 
 |  |  | 
 |  |  |                 if (parameters[0].ParameterType == typeof (int)) | 
 |  |  |                     data.ElementType = p_info.PropertyType; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             } | 
 |  |  |             lock (array_metadata_lock) { | 
 |  |  |                 try { | 
 |  |  |                     array_metadata.Add (type, data); | 
 |  |  | 
 |  |  |                 data.IsDictionary = true; | 
 |  |  |  | 
 |  |  |             data.Properties = new Dictionary<string, PropertyMetadata> (); | 
 |  |  |  | 
 |  |  |             foreach (PropertyInfo p_info in type.GetProperties ()) { | 
 |  |  |                 if (p_info.Name == "Item") { | 
 |  |  |                     ParameterInfo[] parameters = p_info.GetIndexParameters (); | 
 |  |  | 
 |  |  |                         continue; | 
 |  |  |  | 
 |  |  |                     if (parameters[0].ParameterType == typeof (string)) | 
 |  |  |                     { | 
 |  |  |                         if (type is ILRuntime.Reflection.ILRuntimeWrapperType) | 
 |  |  |                         { | 
 |  |  |                             data.ElementType = ((ILRuntime.Reflection.ILRuntimeWrapperType)type).CLRType.GenericArguments[1].Value.ReflectionType; | 
 |  |  |                         } | 
 |  |  |                         else | 
 |  |  |                         data.ElementType = p_info.PropertyType; | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                     continue; | 
 |  |  |                 } | 
 |  |  | 
 |  |  |             if (reader.Token == JsonToken.ArrayEnd) | 
 |  |  |                 return null; | 
 |  |  |  | 
 |  |  |             Type underlying_type = Nullable.GetUnderlyingType(inst_type); | 
 |  |  |             Type value_type = underlying_type ?? inst_type; | 
 |  |  |             //ILRuntime doesn't support nullable valuetype | 
 |  |  |             Type underlying_type = inst_type;//Nullable.GetUnderlyingType(inst_type); | 
 |  |  |             Type value_type = inst_type; | 
 |  |  |  | 
 |  |  |             if (reader.Token == JsonToken.Null) { | 
 |  |  |                 #if NETSTANDARD1_5 | 
 |  |  |                 if (inst_type.IsClass() || underlying_type != null) { | 
 |  |  |                     return null; | 
 |  |  |                 } | 
 |  |  |                 #else | 
 |  |  |                 if (inst_type.IsClass || underlying_type != null) { | 
 |  |  |                     return null; | 
 |  |  |                 } | 
 |  |  |                 #endif | 
 |  |  |  | 
 |  |  |                 throw new JsonException (String.Format ( | 
 |  |  |                             "Can't assign null to an instance of type {0}", | 
 |  |  | 
 |  |  |                 reader.Token == JsonToken.Boolean) { | 
 |  |  |  | 
 |  |  |                 Type json_type = reader.Value.GetType (); | 
 |  |  |                 var vt = value_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).CLRType.TypeForCLR : value_type; | 
 |  |  |  | 
 |  |  |                 if (value_type.IsAssignableFrom (json_type)) | 
 |  |  |                 if (vt.IsAssignableFrom(json_type)) | 
 |  |  |                     return reader.Value; | 
 |  |  |  | 
 |  |  |                 if (vt is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)vt).ILType.IsEnum) | 
 |  |  |                 { | 
 |  |  |                     if (json_type == typeof(int) || json_type == typeof(long) || json_type == typeof(short) || json_type == typeof(byte)) | 
 |  |  |                         return reader.Value; | 
 |  |  |                 } | 
 |  |  |                 // If there's a custom importer that fits, use it | 
 |  |  |                 if (custom_importers_table.ContainsKey (json_type) && | 
 |  |  |                     custom_importers_table[json_type].ContainsKey ( | 
 |  |  |                         value_type)) { | 
 |  |  |                         vt)) { | 
 |  |  |  | 
 |  |  |                     ImporterFunc importer = | 
 |  |  |                         custom_importers_table[json_type][value_type]; | 
 |  |  |                         custom_importers_table[json_type][vt]; | 
 |  |  |  | 
 |  |  |                     return importer (reader.Value); | 
 |  |  |                 } | 
 |  |  | 
 |  |  |                 // Maybe there's a base importer that works | 
 |  |  |                 if (base_importers_table.ContainsKey (json_type) && | 
 |  |  |                     base_importers_table[json_type].ContainsKey ( | 
 |  |  |                         value_type)) { | 
 |  |  |                         vt)) { | 
 |  |  |  | 
 |  |  |                     ImporterFunc importer = | 
 |  |  |                         base_importers_table[json_type][value_type]; | 
 |  |  |                         base_importers_table[json_type][vt]; | 
 |  |  |  | 
 |  |  |                     return importer (reader.Value); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 // Maybe it's an enum | 
 |  |  |                 #if NETSTANDARD1_5 | 
 |  |  |                 if (value_type.IsEnum()) | 
 |  |  |                     return Enum.ToObject (value_type, reader.Value); | 
 |  |  |                 #else | 
 |  |  |                 if (value_type.IsEnum) | 
 |  |  |                     return Enum.ToObject (value_type, reader.Value); | 
 |  |  |                 #endif | 
 |  |  |                 if (vt.IsEnum) | 
 |  |  |                     return Enum.ToObject (vt, reader.Value); | 
 |  |  |  | 
 |  |  |                 // Try using an implicit conversion operator | 
 |  |  |                 MethodInfo conv_op = GetConvOp (value_type, json_type); | 
 |  |  |                 MethodInfo conv_op = GetConvOp (vt, json_type); | 
 |  |  |  | 
 |  |  |                 if (conv_op != null) | 
 |  |  |                     return conv_op.Invoke (null, | 
 |  |  | 
 |  |  |                     elem_type = inst_type.GetElementType (); | 
 |  |  |                 } | 
 |  |  |                  | 
 |  |  |                 list.Clear(); | 
 |  |  |  | 
 |  |  |                 while (true) { | 
 |  |  |                     object item = ReadValue (elem_type, reader); | 
 |  |  |                     if (item == null && reader.Token == JsonToken.ArrayEnd) | 
 |  |  |                         break; | 
 |  |  |  | 
 |  |  |                     var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type; | 
 |  |  |                     rt = elem_type is ILRuntime.Reflection.ILRuntimeType ? ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.TypeForCLR : elem_type; | 
 |  |  |                     item = rt.CheckCLRTypes(item); | 
 |  |  |                     list.Add (item); | 
 |  |  |                 } | 
 |  |  |  | 
 |  |  |                 if (t_data.IsArray) { | 
 |  |  |                     int n = list.Count; | 
 |  |  |                     instance = Array.CreateInstance (elem_type, n); | 
 |  |  |                     var rt = elem_type is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)elem_type).RealType : elem_type; | 
 |  |  |                     rt = elem_type is ILRuntime.Reflection.ILRuntimeType ? ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.TypeForCLR : elem_type; | 
 |  |  |                     instance = Array.CreateInstance (rt, n); | 
 |  |  |  | 
 |  |  |                     for (int i = 0; i < n; i++) | 
 |  |  |                         ((Array) instance).SetValue (list[i], i); | 
 |  |  | 
 |  |  |             } else if (reader.Token == JsonToken.ObjectStart) { | 
 |  |  |                 AddObjectMetadata (value_type); | 
 |  |  |                 ObjectMetadata t_data = object_metadata[value_type]; | 
 |  |  |  | 
 |  |  |                 if (value_type is ILRuntime.Reflection.ILRuntimeType) | 
 |  |  |                     instance = ((ILRuntime.Reflection.ILRuntimeType)value_type).ILType.Instantiate(); | 
 |  |  |                 else | 
 |  |  |                 { | 
 |  |  |                     if (value_type is ILRuntime.Reflection.ILRuntimeWrapperType) | 
 |  |  |                         value_type = ((ILRuntime.Reflection.ILRuntimeWrapperType)value_type).RealType; | 
 |  |  |                 instance = Activator.CreateInstance (value_type); | 
 |  |  |  | 
 |  |  |                 } | 
 |  |  |                 while (true) { | 
 |  |  |                     reader.Read (); | 
 |  |  |  | 
 |  |  | 
 |  |  |                             } | 
 |  |  |                         } | 
 |  |  |  | 
 |  |  |                         var rt = t_data.ElementType is ILRuntime.Reflection.ILRuntimeWrapperType ? ((ILRuntime.Reflection.ILRuntimeWrapperType)t_data.ElementType).RealType : t_data.ElementType; | 
 |  |  |                         ((IDictionary) instance).Add ( | 
 |  |  |                             property, ReadValue ( | 
 |  |  |                                 t_data.ElementType, reader)); | 
 |  |  |                             property, rt.CheckCLRTypes(ReadValue ( | 
 |  |  |                                 t_data.ElementType, reader))); | 
 |  |  |                     } | 
 |  |  |  | 
 |  |  |                 } | 
 |  |  | 
 |  |  |                 delegate (object obj, JsonWriter writer) { | 
 |  |  |                     writer.Write ((ulong) obj); | 
 |  |  |                 }; | 
 |  |  |  | 
 |  |  |             base_exporters_table[typeof(DateTimeOffset)] = | 
 |  |  |                 delegate (object obj, JsonWriter writer) { | 
 |  |  |                     writer.Write(((DateTimeOffset)obj).ToString("yyyy-MM-ddTHH:mm:ss.fffffffzzz", datetime_format)); | 
 |  |  |                 }; | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         private static void RegisterBaseImporters () | 
 |  |  | 
 |  |  |                               typeof (ulong), importer); | 
 |  |  |  | 
 |  |  |             importer = delegate (object input) { | 
 |  |  |                 return Convert.ToInt64((int)input); | 
 |  |  |             }; | 
 |  |  |             RegisterImporter(base_importers_table, typeof(int), | 
 |  |  |                               typeof(long), importer); | 
 |  |  |  | 
 |  |  |             importer = delegate (object input) { | 
 |  |  |                 return Convert.ToSByte ((int) input); | 
 |  |  |             }; | 
 |  |  |             RegisterImporter (base_importers_table, typeof (int), | 
 |  |  | 
 |  |  |             }; | 
 |  |  |             RegisterImporter (base_importers_table, typeof (int), | 
 |  |  |                               typeof (short), importer); | 
 |  |  |  | 
 |  |  |             importer = delegate (object input) { | 
 |  |  |                 return Convert.ToInt64((int)input); | 
 |  |  |             }; | 
 |  |  |             RegisterImporter(base_importers_table, typeof(int), | 
 |  |  |                               typeof(long), importer); | 
 |  |  |  | 
 |  |  |             importer = delegate (object input) { | 
 |  |  |                 return Convert.ToUInt16 ((int) input); | 
 |  |  | 
 |  |  |             }; | 
 |  |  |             RegisterImporter (base_importers_table, typeof (string), | 
 |  |  |                               typeof (DateTime), importer); | 
 |  |  |  | 
 |  |  |             importer = delegate (object input) { | 
 |  |  |                 return DateTimeOffset.Parse((string)input, datetime_format); | 
 |  |  |             }; | 
 |  |  |             RegisterImporter(base_importers_table, typeof(string), | 
 |  |  |                 typeof(DateTimeOffset), importer); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         private static void RegisterImporter ( | 
 |  |  | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             if (obj is IDictionary dictionary) { | 
 |  |  |             if (obj is IDictionary) { | 
 |  |  |                 writer.WriteObjectStart (); | 
 |  |  |                 foreach (DictionaryEntry entry in dictionary) { | 
 |  |  |                     var propertyName = entry.Key is string key ? | 
 |  |  |                         key | 
 |  |  |                         : Convert.ToString(entry.Key, CultureInfo.InvariantCulture); | 
 |  |  |                     writer.WritePropertyName (propertyName); | 
 |  |  |                 foreach (DictionaryEntry entry in (IDictionary) obj) { | 
 |  |  |                     writer.WritePropertyName ((string) entry.Key); | 
 |  |  |                     WriteValue (entry.Value, writer, writer_is_private, | 
 |  |  |                                 depth + 1); | 
 |  |  |                 } | 
 |  |  | 
 |  |  |                 return; | 
 |  |  |             } | 
 |  |  |  | 
 |  |  |             Type obj_type = obj.GetType (); | 
 |  |  |             Type obj_type; | 
 |  |  |             if (obj is ILRuntime.Runtime.Intepreter.ILTypeInstance) | 
 |  |  |             { | 
 |  |  |                 obj_type = ((ILRuntime.Runtime.Intepreter.ILTypeInstance)obj).Type.ReflectionType; | 
 |  |  |             } | 
 |  |  |             else if(obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) | 
 |  |  |             { | 
 |  |  |                 obj_type = ((ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)obj).ILInstance.Type.ReflectionType; | 
 |  |  |             } | 
 |  |  |             else | 
 |  |  |                 obj_type = obj.GetType(); | 
 |  |  |  | 
 |  |  |             // See if there's a custom exporter for the object | 
 |  |  |             if (custom_exporters_table.ContainsKey (obj_type)) { | 
 |  |  | 
 |  |  |             return (T) ReadValue (typeof (T), reader); | 
 |  |  |         } | 
 |  |  |          | 
 |  |  |         public static object ToObject(string json, Type ConvertType ) | 
 |  |  |         { | 
 |  |  |             JsonReader reader = new JsonReader(json); | 
 |  |  |  | 
 |  |  |             return ReadValue(ConvertType, reader); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public static IJsonWrapper ToWrapper (WrapperFactory factory, | 
 |  |  |                                               JsonReader reader) | 
 |  |  |         { | 
 |  |  | 
 |  |  |         { | 
 |  |  |             custom_importers_table.Clear (); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public unsafe static void RegisterILRuntimeCLRRedirection(ILRuntime.Runtime.Enviorment.AppDomain appdomain) | 
 |  |  |         { | 
 |  |  |             foreach(var i in typeof(JsonMapper).GetMethods()) | 
 |  |  |             { | 
 |  |  |                 if(i.Name == "ToObject" && i.IsGenericMethodDefinition) | 
 |  |  |                 { | 
 |  |  |                     var param = i.GetParameters(); | 
 |  |  |                     if(param[0].ParameterType == typeof(string)) | 
 |  |  |                     { | 
 |  |  |                         appdomain.RegisterCLRMethodRedirection(i, JsonToObject); | 
 |  |  |                     } | 
 |  |  |                     else if(param[0].ParameterType == typeof(JsonReader)) | 
 |  |  |                     { | 
 |  |  |                         appdomain.RegisterCLRMethodRedirection(i, JsonToObject2); | 
 |  |  |                     } | 
 |  |  |                     else if (param[0].ParameterType == typeof(TextReader)) | 
 |  |  |                     { | 
 |  |  |                         appdomain.RegisterCLRMethodRedirection(i, JsonToObject3); | 
 |  |  |                     } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public unsafe static StackObject* JsonToObject(ILIntepreter intp, StackObject* esp, IList<object> mStack, CLRMethod method, bool isNewObj) | 
 |  |  |         { | 
 |  |  |             ILRuntime.Runtime.Enviorment.AppDomain __domain = intp.AppDomain; | 
 |  |  |             StackObject* ptr_of_this_method; | 
 |  |  |             StackObject* __ret = ILIntepreter.Minus(esp, 1); | 
 |  |  |             ptr_of_this_method = ILIntepreter.Minus(esp, 1); | 
 |  |  |             System.String json = (System.String)typeof(System.String).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, mStack)); | 
 |  |  |             intp.Free(ptr_of_this_method); | 
 |  |  |             var type = method.GenericArguments[0].ReflectionType; | 
 |  |  |             var result_of_this_method = ReadValue(type, new JsonReader(json)); | 
 |  |  |  | 
 |  |  |             return ILIntepreter.PushObject(__ret, mStack, result_of_this_method); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public unsafe static StackObject* JsonToObject2(ILIntepreter intp, StackObject* esp, IList<object> mStack, CLRMethod method, bool isNewObj) | 
 |  |  |         { | 
 |  |  |             ILRuntime.Runtime.Enviorment.AppDomain __domain = intp.AppDomain; | 
 |  |  |             StackObject* ptr_of_this_method; | 
 |  |  |             StackObject* __ret = ILIntepreter.Minus(esp, 1); | 
 |  |  |             ptr_of_this_method = ILIntepreter.Minus(esp, 1); | 
 |  |  |             JsonReader json = (JsonReader)typeof(JsonReader).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, mStack)); | 
 |  |  |             intp.Free(ptr_of_this_method); | 
 |  |  |             var type = method.GenericArguments[0].ReflectionType; | 
 |  |  |             var result_of_this_method = ReadValue(type, json); | 
 |  |  |  | 
 |  |  |             return ILIntepreter.PushObject(__ret, mStack, result_of_this_method); | 
 |  |  |         } | 
 |  |  |  | 
 |  |  |         public unsafe static StackObject* JsonToObject3(ILIntepreter intp, StackObject* esp, IList<object> mStack, CLRMethod method, bool isNewObj) | 
 |  |  |         { | 
 |  |  |             ILRuntime.Runtime.Enviorment.AppDomain __domain = intp.AppDomain; | 
 |  |  |             StackObject* ptr_of_this_method; | 
 |  |  |             StackObject* __ret = ILIntepreter.Minus(esp, 1); | 
 |  |  |             ptr_of_this_method = ILIntepreter.Minus(esp, 1); | 
 |  |  |             TextReader json = (TextReader)typeof(TextReader).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, mStack)); | 
 |  |  |             intp.Free(ptr_of_this_method); | 
 |  |  |             var type = method.GenericArguments[0].ReflectionType; | 
 |  |  |             var result_of_this_method = ReadValue(type, new JsonReader(json)); | 
 |  |  |  | 
 |  |  |             return ILIntepreter.PushObject(__ret, mStack, result_of_this_method); | 
 |  |  |         } | 
 |  |  |     } | 
 |  |  | } |