diff --git "a/C:\\Users\\user\\AppData\\Local\\Temp\\JSO9D79.tmp\\JSON-901a0de-left.cs" "b/C:\\Mount\\B\\SourceCode\\_json\\fastjson\\fastJSON\\JSON.cs" index 8ea0a9d..4a27678 100644 --- "a/C:\\Users\\user\\AppData\\Local\\Temp\\JSO9D79.tmp\\JSON-901a0de-left.cs" +++ "b/C:\\Mount\\B\\SourceCode\\_json\\fastjson\\fastJSON\\JSON.cs" @@ -1,4 +1,5 @@ -using System; +#define MY_PROP_INFO_USE_ENUMS +using System; using System.Collections; using System.Collections.Generic; #if !SILVERLIGHT @@ -68,6 +69,7 @@ namespace fastJSON public sealed class JSON { + //static JSON() { Console.WriteLine("myPropInfo: {0}", System.Runtime.InteropServices.Marshal.SizeOf(typeof(myPropInfo)).ToString("X8")); } //public readonly static JSON Instance = new JSON(); [ThreadStatic] private static JSON _instance; @@ -229,39 +231,95 @@ namespace fastJSON #region [ JSON specific reflection ] +#if MY_PROP_INFO_USE_ENUMS + private enum myPropInfoType + { + Int, + Long, + String, + Bool, + DateTime, + Enum, + Guid, + + Array, + ByteArray, + Dictionary, + StringDictionary, +#if !SILVERLIGHT + Hashtable, + DataSet, + DataTable, +#endif +#if CUSTOMTYPE + Custom, +#endif + + Unknown, + }; + [Flags] + private enum myPropInfoFlags + { + Filled = 1<<0, + CanWrite = 1<<1, + Class = 1<<2, + ValueType = 1<<3, + GenericType = 1<<4, + }; +#else + private static class myPropInfoType + { + public const int Int = 0; + public const int Long = Int + 1; + public const int String = Long + 1; + public const int Bool = String + 1; + public const int DateTime = Bool + 1; + public const int Enum = DateTime + 1; + public const int Guid = Enum + 1; + + public const int Array = Guid + 1; + public const int ByteArray = Array + 1; + public const int Dictionary = ByteArray + 1; + public const int StringDictionary = Dictionary + 1; +//#if !SILVERLIGHT + public const int Hashtable = StringDictionary + 1; + public const int DataSet = Hashtable + 1; + public const int DataTable = DataSet + 1; +//#endif +//#if CUSTOMTYPE + public const int Custom = DataTable + 1; +//#endif + + public const int Unknown = Custom + 1; + }; + private static class myPropInfoFlags + { + public const int Filled = 1<<0; + public const int CanWrite = 1<<1; + public const int Class = 1<<2; + public const int ValueType = 1<<3; + public const int GenericType = 1<<4; + }; +#endif private struct myPropInfo { - public bool filled; public Type pt; public Type bt; public Type changeType; - public bool isDictionary; - public bool isValueType; - public bool isGenericType; - public bool isArray; - public bool isByteArray; - public bool isGuid; -#if !SILVERLIGHT - public bool isDataSet; - public bool isDataTable; - public bool isHashtable; -#endif - public Reflection.GenericSetter setter; - public bool isEnum; - public bool isDateTime; - public Type[] GenericTypes; - public bool isInt; - public bool isLong; - public bool isString; - public bool isBool; - public bool isClass; - public Reflection.GenericGetter getter; - public bool isStringDictionary; - public string Name; -#if CUSTOMTYPE - public bool isCustomType; + public Reflection.GenericSetter setter; + public Reflection.GenericGetter getter; + public Type[] GenericTypes; + public string Name; +#if MY_PROP_INFO_USE_ENUMS + public myPropInfoType Type; + public myPropInfoFlags Flags; +#else + public int Type, Flags; #endif - public bool CanWrite; + + public bool IsClass { get { return (Flags & myPropInfoFlags.Class) != 0; } } + public bool IsValueType { get { return (Flags & myPropInfoFlags.ValueType) != 0; } } + public bool IsGenericType { get { return (Flags & myPropInfoFlags.GenericType) != 0; } } } SafeDictionary> _propertycache = new SafeDictionary>(); @@ -279,7 +337,7 @@ namespace fastJSON foreach (PropertyInfo p in pr) { myPropInfo d = CreateMyProp(p.PropertyType, p.Name); - d.CanWrite = p.CanWrite; + d.Flags |= myPropInfoFlags.CanWrite; d.setter = Reflection.CreateSetMethod(type, p); d.getter = Reflection.CreateGetMethod(type, p); sd.Add(p.Name, d); @@ -301,44 +359,55 @@ namespace fastJSON private myPropInfo CreateMyProp(Type t, string name) { myPropInfo d = new myPropInfo(); - d.filled = true; - d.CanWrite = true; - d.pt = t; - d.Name = name; - d.isDictionary = t.Name.Contains("Dictionary"); - if (d.isDictionary) - d.GenericTypes = t.GetGenericArguments(); - d.isValueType = t.IsValueType; - d.isGenericType = t.IsGenericType; - d.isArray = t.IsArray; - if (d.isArray) - d.bt = t.GetElementType(); - if (d.isGenericType) - d.bt = t.GetGenericArguments()[0]; - d.isByteArray = t == typeof(byte[]); - d.isGuid = (t == typeof(Guid) || t == typeof(Guid?)); + var d_type = myPropInfoType.Unknown; + var d_flags = myPropInfoFlags.Filled | myPropInfoFlags.CanWrite; + + if (t == typeof(int) || t == typeof(int?)) d_type = myPropInfoType.Int; + else if (t == typeof(long) || t == typeof(long?)) d_type = myPropInfoType.Long; + else if (t == typeof(string)) d_type = myPropInfoType.String; + else if (t == typeof(bool) || t == typeof(bool?)) d_type = myPropInfoType.Bool; + else if (t == typeof(DateTime) || t == typeof(DateTime?)) d_type = myPropInfoType.DateTime; + else if (t.IsEnum) d_type = myPropInfoType.Enum; + else if (t == typeof(Guid) || t == typeof(Guid?)) d_type = myPropInfoType.Guid; + else if (t.IsArray) + { + d.bt = t.GetElementType(); + if (t == typeof(byte[])) + d_type = myPropInfoType.ByteArray; + else + d_type = myPropInfoType.Array; + } + else if (t.Name.Contains("Dictionary")) + { + d.GenericTypes = t.GetGenericArguments(); + if(d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string)) + d_type = myPropInfoType.StringDictionary; + else + d_type = myPropInfoType.Dictionary; + } #if !SILVERLIGHT - d.isHashtable = t == typeof(Hashtable); - d.isDataSet = t == typeof(DataSet); - d.isDataTable = t == typeof(DataTable); + else if (t == typeof(Hashtable)) d_type = myPropInfoType.Hashtable; + else if (t == typeof(DataSet)) d_type = myPropInfoType.DataSet; + else if (t == typeof(DataTable)) d_type = myPropInfoType.DataTable; +#endif +#if CUSTOMTYPE + else if (IsTypeRegistered(t)) d_type = myPropInfoType.Custom; #endif - d.changeType = GetChangeType(t); - d.isEnum = t.IsEnum; - d.isDateTime = t == typeof(DateTime) || t == typeof(DateTime?); - d.isInt = t == typeof(int) || t == typeof(int?); - d.isLong = t == typeof(long) || t == typeof(long?); - d.isString = t == typeof(string); - d.isBool = t == typeof(bool) || t == typeof(bool?); - d.isClass = t.IsClass; + if (t.IsClass) d_flags |= myPropInfoFlags.Class; + if (t.IsValueType) d_flags |= myPropInfoFlags.ValueType; + if (t.IsGenericType) + { + d_flags |= myPropInfoFlags.GenericType; + d.bt = t.GetGenericArguments()[0]; + } - if (d.isDictionary && d.GenericTypes.Length > 0 && d.GenericTypes[0] == typeof(string)) - d.isStringDictionary = true; + d.pt = t; + d.Name = name; + d.changeType = GetChangeType(t); + d.Type = d_type; + d.Flags = d_flags; -#if CUSTOMTYPE - if (IsTypeRegistered(t)) - d.isCustomType = true; -#endif return d; } @@ -469,74 +538,59 @@ namespace fastJSON myPropInfo pi; if (props.TryGetValue(name, out pi) == false) continue; - if (pi.filled && pi.CanWrite) + if ((pi.Flags & (myPropInfoFlags.Filled|myPropInfoFlags.CanWrite)) != 0) { object v = d[name]; if (v != null) { - object oset = null; - - if (pi.isInt) - oset = (int)((long)v); -#if CUSTOMTYPE - else if (pi.isCustomType) - oset = CreateCustom((string)v, pi.pt); -#endif - else if (pi.isLong) - oset = (long)v; - - else if (pi.isString) - oset = (string)v; - - else if (pi.isBool) - oset = (bool)v; - - else if (pi.isGenericType && pi.isValueType == false && pi.isDictionary == false && v is List) - oset = CreateGenericList((List)v, pi.pt, pi.bt, globaltypes); - - else if (pi.isByteArray) - oset = Convert.FromBase64String((string)v); - - else if (pi.isArray && pi.isValueType == false) - oset = CreateArray((List)v, pi.pt, pi.bt, globaltypes); - - else if (pi.isGuid) - oset = CreateGuid((string)v); + object oset = null; + + switch (pi.Type) + { + case myPropInfoType.Int: oset = (int)((long)v); break; + case myPropInfoType.Long: oset = (long)v; break; + case myPropInfoType.String: oset = (string)v; break; + case myPropInfoType.Bool: oset = (bool)v; break; + case myPropInfoType.DateTime: oset = CreateDateTime((string)v); break; + case myPropInfoType.Enum: oset = CreateEnum(pi.pt, (string)v); break; + case myPropInfoType.Guid: oset = CreateGuid((string)v); break; + + case myPropInfoType.Array: + if(!pi.IsValueType) + oset = CreateArray((List)v, pi.pt, pi.bt, globaltypes); + // what about 'else'? + break; + case myPropInfoType.ByteArray: oset = Convert.FromBase64String((string)v); break; #if !SILVERLIGHT - else if (pi.isDataSet) - oset = CreateDataset((Dictionary)v, globaltypes); - - else if (pi.isDataTable) - oset = this.CreateDataTable((Dictionary)v, globaltypes); + case myPropInfoType.DataSet: oset = CreateDataset((Dictionary)v, globaltypes); break; + case myPropInfoType.DataTable: oset = this.CreateDataTable((Dictionary)v, globaltypes); break; + case myPropInfoType.Hashtable: // same case as Dictionary #endif - - else if (pi.isStringDictionary) - oset = CreateStringKeyDictionary((Dictionary)v, pi.pt, pi.GenericTypes, globaltypes); -#if !SILVERLIGHT - else if (pi.isDictionary || pi.isHashtable) -#else - else if (pi.isDictionary) + case myPropInfoType.Dictionary: oset = CreateDictionary((List)v, pi.pt, pi.GenericTypes, globaltypes); break; + case myPropInfoType.StringDictionary: oset = CreateStringKeyDictionary((Dictionary)v, pi.pt, pi.GenericTypes, globaltypes); break; +#if CUSTOMTYPE + case myPropInfoType.Custom: oset = CreateCustom((string)v, pi.pt); break; #endif - oset = CreateDictionary((List)v, pi.pt, pi.GenericTypes, globaltypes); - - else if (pi.isEnum) - oset = CreateEnum(pi.pt, (string)v); - - else if (pi.isDateTime) - oset = CreateDateTime((string)v); + default: + { + if (pi.IsGenericType && pi.IsValueType == false && v is List) + oset = CreateGenericList((List)v, pi.pt, pi.bt, globaltypes); - else if (pi.isClass && v is Dictionary) - oset = ParseDictionary((Dictionary)v, globaltypes, pi.pt, pi.getter(o)); + else if (pi.IsClass && v is Dictionary) + oset = ParseDictionary((Dictionary)v, globaltypes, pi.pt, pi.getter(o)); - else if (pi.isValueType) - oset = ChangeType(v, pi.changeType); + else if (v is List) + oset = CreateArray((List)v, pi.pt, typeof(object), globaltypes); - else if (v is List) - oset = CreateArray((List)v, pi.pt, typeof(object), globaltypes); + else if (pi.IsValueType) + oset = ChangeType(v, pi.changeType); - else - oset = v; + else + oset = v; + } + break; + } o = pi.setter(o, oset); } @@ -566,6 +620,72 @@ namespace fastJSON } } + static int CreateInteger(out int num, string s, int index, int count) + { + num = 0; + bool neg = false; + for (int x = 0; x < count; x++, index++) + { + char cc = s[index]; + + if (cc == '-') + neg = true; + else if (cc == '+') + neg = false; + else + { + num *= 10; + num += (int)(cc - '0'); + } + } + if(neg) num = -num; + + return num; + } + static long CreateInteger(out long num, string s, int index, int count) + { + num = 0; + bool neg = false; + for (int x = 0; x < count; x++, index++) + { + char cc = s[index]; + + if (cc == '-') + neg = true; + else if (cc == '+') + neg = false; + else + { + num *= 10; + num += (int)(cc - '0'); + } + } + if (neg) num = -num; + + return num; + } + internal static long CreateInteger(out long num, char[] s, int index, int count) + { + num = 0; + bool neg = false; + for (int x = 0; x < count; x++, index++) + { + char cc = s[index]; + + if (cc == '-') + neg = true; + else if (cc == '+') + neg = false; + else + { + num *= 10; + num += (int)(cc - '0'); + } + } + if (neg) num = -num; + + return num; + } private long CreateLong(string s) { long num = 0; @@ -609,14 +729,21 @@ namespace fastJSON bool utc = false; // 0123456789012345678 // datetime format = yyyy-MM-dd HH:mm:ss - int year = (int)CreateLong(value.Substring(0, 4)); - int month = (int)CreateLong(value.Substring(5, 2)); - int day = (int)CreateLong(value.Substring(8, 2)); - int hour = (int)CreateLong(value.Substring(11, 2)); - int min = (int)CreateLong(value.Substring(14, 2)); - int sec = (int)CreateLong(value.Substring(17, 2)); - - if (value.EndsWith("Z")) + int year;// = (int)CreateLong(value.Substring(0, 4)); + int month;// = (int)CreateLong(value.Substring(5, 2)); + int day;// = (int)CreateLong(value.Substring(8, 2)); + int hour;// = (int)CreateLong(value.Substring(11, 2)); + int min;// = (int)CreateLong(value.Substring(14, 2)); + int sec;// = (int)CreateLong(value.Substring(17, 2)); + CreateInteger(out year, value, 0, 4); + CreateInteger(out month, value, 5, 2); + CreateInteger(out day, value, 8, 2); + CreateInteger(out hour, value, 11, 2); + CreateInteger(out min, value, 14, 2); + CreateInteger(out sec, value, 17, 2); + + //if (value.EndsWith("Z")) + if (value[value.Length-1] == 'Z') utc = true; if (_params.UseUTCDateTime == false && utc == false)