JsonParser.cs 75 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Diagnostics.CodeAnalysis;
  5. using System.Globalization;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Reflection;
  9. using System.Text;
  10. using System.Text.RegularExpressions;
  11. using System.Threading.Tasks;
  12. namespace TEAMModelOS.SDK.Helper.Common.JsonHelper
  13. {
  14. public static class JsonPathExtensions
  15. {
  16. public static T As<T>(this JsonPathNode node) { return As(node, default(T)); }
  17. public static T As<T>(this JsonPathNode node, T prototype) { return (T)node.Value; }
  18. public static T[] As<T>(this JsonPathNode[] nodes) { return As(nodes, default(T)); }
  19. public static T[] As<T>(this JsonPathNode[] nodes, T prototype) { return nodes.Select(node => node.As<T>()).ToArray(); }
  20. }
  21. public delegate object JsonPathScriptEvaluator(string script, object value, IJsonPathContext context);
  22. public sealed class JsonPathSelection
  23. {
  24. public readonly JsonPathContext Context;
  25. public JsonPathSelection(object data) : this(data, null as IJsonPathValueSystem) { }
  26. public JsonPathSelection(object data, IJsonPathValueSystem valueSystem) : this(data, valueSystem, null) { }
  27. public JsonPathSelection(object data, JsonPathScriptEvaluator evaluator) : this(data, null, evaluator) { }
  28. public JsonPathSelection(object data, IJsonPathValueSystem valueSystem, JsonPathScriptEvaluator evaluator) { Context = new JsonPathContext(data, (valueSystem ?? new JsonPathValueSystem()), evaluator); }
  29. public JsonPathNode[] SelectNodes(string expression, params JsonPathScriptEvaluator[] lambdas) { return Context.Evaluate(expression, lambdas); }
  30. public T[] SelectNodes<T>(string expression, params JsonPathScriptEvaluator[] lambdas) { return SelectNodes(default(T), expression, lambdas); }
  31. public T[] SelectNodes<T>(T prototype, string expression, params JsonPathScriptEvaluator[] lambdas) { return SelectNodes(expression, lambdas).As<T>(); }
  32. }
  33. internal class JsonPathValueSystem : IJsonPathValueSystem
  34. {
  35. private readonly IDictionary<Type, Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]>> cache = new Dictionary<Type, Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]>>();
  36. private Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]> GetEntry(Type type)
  37. {
  38. Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]> entry;
  39. if (cache.TryGetValue(type, out entry)) return entry;
  40. var propertyInfos = type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
  41. var properties = propertyInfos.ToDictionary(propertyInfo => propertyInfo.Name);
  42. cache.Add(type, entry = new Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]>(properties, properties.Keys.ToArray()));
  43. return entry;
  44. }
  45. private System.Reflection.PropertyInfo GetProperty(Type type, string propertyName)
  46. {
  47. Tuple<IDictionary<string, System.Reflection.PropertyInfo>, string[]> entry = GetEntry(type);
  48. System.Reflection.PropertyInfo propertyInfo;
  49. return (entry.Item1.TryGetValue(propertyName, out propertyInfo) ? propertyInfo : null);
  50. }
  51. private string[] GetPropertyNames(Type type)
  52. {
  53. return GetEntry(type).Item2;
  54. }
  55. public bool HasMember(object value, string member)
  56. {
  57. if (value != null)
  58. {
  59. if (IsArray(value))
  60. {
  61. int index = ParseInt(member, -1);
  62. return ((index >= 0) && (index < ((IList)value).Count));
  63. }
  64. if (IsObject(value))
  65. return ((value is IDictionary) ? ((IDictionary)value).Contains(member) : (GetProperty(value.GetType(), member) != null));
  66. return false;
  67. }
  68. return false;
  69. }
  70. public object GetMemberValue(object value, string member)
  71. {
  72. if (value == null) return null;
  73. if (IsArray(value))
  74. {
  75. int index = ParseInt(member, -1);
  76. return (((index >= 0) && (index < ((IList)value).Count)) ? ((IList)value)[index] : null);
  77. }
  78. if (IsObject(value))
  79. return ((value is IDictionary) ? ((IDictionary)value)[member] : GetProperty(value.GetType(), member).GetValue(value, null));
  80. return null;
  81. }
  82. public IEnumerable GetMembers(object value)
  83. {
  84. return ((value is IDictionary) ? ((IDictionary)value).Keys : GetPropertyNames(value.GetType()));
  85. }
  86. public bool IsObject(object value)
  87. {
  88. return ((value is IDictionary) || (!IsArray(value) && !IsPrimitive(value)));
  89. }
  90. public bool IsArray(object value)
  91. {
  92. return (value is IList);
  93. }
  94. public bool IsPrimitive(object value)
  95. {
  96. return ((value is string) || ((value != null) && value.GetType().IsValueType));
  97. }
  98. private int ParseInt(string s, int defaultValue)
  99. {
  100. int result;
  101. return int.TryParse(s, out result) ? result : defaultValue;
  102. }
  103. }
  104. public sealed class JsonParserOptions
  105. {
  106. internal bool Validate()
  107. {
  108. return ((StringBufferLength > byte.MaxValue) && (TypeCacheCapacity > byte.MaxValue));
  109. }
  110. public int StringBufferLength { get; set; }
  111. public int TypeCacheCapacity { get; set; }
  112. }
  113. [SuppressMessage("ReSharper", "UnusedParameter.Local")]
  114. public class JsonParser
  115. {
  116. private const string TypeTag1 = "__type";
  117. private const string TypeTag2 = "$type";
  118. private static readonly byte[] HEX = new byte[128];
  119. private static readonly bool[] HXD = new bool[128];
  120. private static readonly char[] ESC = new char[128];
  121. private static readonly bool[] IDF = new bool[128];
  122. private static readonly bool[] IDN = new bool[128];
  123. private const int EOF = (char.MaxValue + 1);
  124. private const int ANY = 0;
  125. private readonly IDictionary<Type, int> rtti = new Dictionary<Type, int>();
  126. private readonly TypeInfo[] types;
  127. private readonly Func<int, object>[] parse = new Func<int, object>[128];
  128. private readonly StringBuilder lsb = new StringBuilder();
  129. private readonly char[] stc = new char[1];
  130. private readonly char[] lbf;
  131. private TextReader str;
  132. private Func<int, int> Char;
  133. private Action<int> Next;
  134. private Func<int> Read;
  135. private Func<int> Space;
  136. private string txt;
  137. private readonly int lbs;
  138. private int len;
  139. private int lln;
  140. private int chr;
  141. private int at;
  142. internal class EnumInfo
  143. {
  144. internal string Name;
  145. internal object Value;
  146. internal int Len;
  147. }
  148. internal class ItemInfo
  149. {
  150. internal string Name;
  151. internal Action<object, JsonParser, int, int> Set;
  152. internal Type Type;
  153. internal int Outer;
  154. internal int Len;
  155. internal int Atm;
  156. }
  157. internal class TypeInfo
  158. {
  159. private static readonly HashSet<Type> WellKnown = new HashSet<Type>();
  160. internal Func<Type, object, object, int, Func<object, object>> Select;
  161. internal Func<JsonParser, int, object> Parse;
  162. internal Func<object> Ctor;
  163. internal EnumInfo[] Enums;
  164. internal ItemInfo[] Props;
  165. #if FASTER_GETPROPINFO
  166. internal char[] Mlk;
  167. internal int Mnl;
  168. #endif
  169. internal ItemInfo Dico;
  170. internal ItemInfo List;
  171. internal bool IsAnonymous;
  172. internal bool IsNullable;
  173. internal bool IsStruct;
  174. internal bool IsEnum;
  175. internal bool Closed;
  176. internal Type VType;
  177. internal Type EType;
  178. internal Type Type;
  179. internal int Inner;
  180. internal int Key;
  181. internal int T;
  182. static TypeInfo()
  183. {
  184. WellKnown.Add(typeof(bool));
  185. WellKnown.Add(typeof(char));
  186. WellKnown.Add(typeof(sbyte));
  187. WellKnown.Add(typeof(byte));
  188. WellKnown.Add(typeof(short));
  189. WellKnown.Add(typeof(ushort));
  190. WellKnown.Add(typeof(int));
  191. WellKnown.Add(typeof(uint));
  192. WellKnown.Add(typeof(long));
  193. WellKnown.Add(typeof(ulong));
  194. WellKnown.Add(typeof(float));
  195. WellKnown.Add(typeof(double));
  196. WellKnown.Add(typeof(decimal));
  197. WellKnown.Add(typeof(Guid));
  198. WellKnown.Add(typeof(DateTime));
  199. WellKnown.Add(typeof(DateTimeOffset));
  200. WellKnown.Add(typeof(string));
  201. }
  202. private static Func<object> GetCtor(Type clr, bool list)
  203. {
  204. var type = (!list ? ((clr == typeof(object)) ? typeof(Dictionary<string, object>) : clr) : typeof(List<>).MakeGenericType(clr));
  205. var ctor = type.GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.CreateInstance, null, System.Type.EmptyTypes, null);
  206. if (ctor != null)
  207. {
  208. var dyn = new System.Reflection.Emit.DynamicMethod("", typeof(object), null, typeof(string), true);
  209. var il = dyn.GetILGenerator();
  210. il.Emit(System.Reflection.Emit.OpCodes.Newobj, ctor);
  211. il.Emit(System.Reflection.Emit.OpCodes.Ret);
  212. return (Func<object>)dyn.CreateDelegate(typeof(Func<object>));
  213. }
  214. return null;
  215. }
  216. private static Func<object> GetCtor(Type clr, Type key, Type value)
  217. {
  218. var type = typeof(Dictionary<,>).MakeGenericType(key, value);
  219. var ctor = (((type != clr) && clr.IsClass) ? clr : type).GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.CreateInstance, null, System.Type.EmptyTypes, null);
  220. var dyn = new System.Reflection.Emit.DynamicMethod("", typeof(object), null, typeof(string), true);
  221. var il = dyn.GetILGenerator();
  222. il.Emit(System.Reflection.Emit.OpCodes.Newobj, ctor);
  223. il.Emit(System.Reflection.Emit.OpCodes.Ret);
  224. return (Func<object>)dyn.CreateDelegate(typeof(Func<object>));
  225. }
  226. private static EnumInfo[] GetEnumInfos(Type type)
  227. {
  228. var actual = (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>)) ? type.GetGenericArguments()[0] : type);
  229. var einfo = System.Enum.GetNames(actual).ToDictionary(name => name, name => new EnumInfo { Name = name, Value = System.Enum.Parse(actual, name), Len = name.Length });
  230. return einfo.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToArray();
  231. }
  232. private ItemInfo GetItemInfo(Type type, string name, System.Reflection.MethodInfo setter)
  233. {
  234. var method = new System.Reflection.Emit.DynamicMethod("Set" + name, null, new[] { typeof(object), typeof(JsonParser), typeof(int), typeof(int) }, typeof(string), true);
  235. var nType = (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>)) ? new[] { type.GetGenericArguments()[0] } : null);
  236. var parse = GetParserParse(GetParseName(type));
  237. var il = method.GetILGenerator();
  238. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
  239. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  240. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_2);
  241. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, parse);
  242. if (type.IsValueType && (parse.ReturnType == typeof(object)))
  243. il.Emit(System.Reflection.Emit.OpCodes.Unbox_Any, type);
  244. if (parse.ReturnType.IsValueType && (type == typeof(object)))
  245. il.Emit(System.Reflection.Emit.OpCodes.Box, parse.ReturnType);
  246. if (nType != null)
  247. {
  248. var con = typeof(Nullable<>).MakeGenericType(nType).GetConstructor(nType);
  249. if (con != null)
  250. il.Emit(System.Reflection.Emit.OpCodes.Newobj, con);
  251. }
  252. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, setter);
  253. il.Emit(System.Reflection.Emit.OpCodes.Ret);
  254. return new ItemInfo { Type = type, Name = name, Set = (Action<object, JsonParser, int, int>)method.CreateDelegate(typeof(Action<object, JsonParser, int, int>)), Len = name.Length };
  255. }
  256. private ItemInfo GetItemInfo(Type type, Type key, Type value, System.Reflection.MethodInfo setter)
  257. {
  258. var method = new System.Reflection.Emit.DynamicMethod("Add", null, new[] { typeof(object), typeof(JsonParser), typeof(int), typeof(int) }, typeof(string), true);
  259. var sBrace = typeof(JsonParser).GetMethod("SBrace", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  260. var eBrace = typeof(JsonParser).GetMethod("EBrace", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  261. var kColon = typeof(JsonParser).GetMethod("KColon", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  262. var sComma = typeof(JsonParser).GetMethod("SComma", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  263. var vnType = (value.IsGenericType && (value.GetGenericTypeDefinition() == typeof(Nullable<>)) ? new[] { value.GetGenericArguments()[0] } : null);
  264. var knType = (key.IsGenericType && (key.GetGenericTypeDefinition() == typeof(Nullable<>)) ? new[] { key.GetGenericArguments()[0] } : null);
  265. var vParse = GetParserParse(GetParseName(value));
  266. var kParse = GetParserParse(GetParseName(key));
  267. var il = method.GetILGenerator();
  268. il.DeclareLocal(key);
  269. il.DeclareLocal(value);
  270. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  271. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, sBrace);
  272. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  273. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, kColon);
  274. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  275. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_3);
  276. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, kParse);
  277. if (key.IsValueType && (kParse.ReturnType == typeof(object)))
  278. il.Emit(System.Reflection.Emit.OpCodes.Unbox_Any, key);
  279. if (kParse.ReturnType.IsValueType && (key == typeof(object)))
  280. il.Emit(System.Reflection.Emit.OpCodes.Box, kParse.ReturnType);
  281. if (knType != null)
  282. {
  283. var con = typeof(Nullable<>).MakeGenericType(knType).GetConstructor(knType);
  284. if (con!=null)
  285. il.Emit(System.Reflection.Emit.OpCodes.Newobj, con);
  286. }
  287. il.Emit(System.Reflection.Emit.OpCodes.Stloc_0);
  288. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  289. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, sComma);
  290. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  291. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, kColon);
  292. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  293. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_2);
  294. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, vParse);
  295. if (value.IsValueType && (vParse.ReturnType == typeof(object)))
  296. il.Emit(System.Reflection.Emit.OpCodes.Unbox_Any, value);
  297. if (vParse.ReturnType.IsValueType && (value == typeof(object)))
  298. il.Emit(System.Reflection.Emit.OpCodes.Box, vParse.ReturnType);
  299. if (vnType != null)
  300. {
  301. var con = typeof(Nullable<>).MakeGenericType(vnType).GetConstructor(vnType);
  302. if (con != null)
  303. il.Emit(System.Reflection.Emit.OpCodes.Newobj, con);
  304. }
  305. il.Emit(System.Reflection.Emit.OpCodes.Stloc_1);
  306. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  307. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, eBrace);
  308. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
  309. il.Emit(System.Reflection.Emit.OpCodes.Ldloc_0);
  310. il.Emit(System.Reflection.Emit.OpCodes.Ldloc_1);
  311. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, setter);
  312. il.Emit(System.Reflection.Emit.OpCodes.Ret);
  313. return new ItemInfo { Type = type, Name = String.Empty, Set = (Action<object, JsonParser, int, int>)method.CreateDelegate(typeof(Action<object, JsonParser, int, int>)) };
  314. }
  315. private static Type GetEnumUnderlyingType(Type enumType)
  316. {
  317. return enumType.GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic)[0].FieldType;
  318. }
  319. protected string GetParseName(Type type)
  320. {
  321. var actual = (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>)) ? type.GetGenericArguments()[0] : type);
  322. var name = (!WellKnown.Contains(actual) ? ((actual.IsEnum && WellKnown.Contains(GetEnumUnderlyingType(actual))) ? GetEnumUnderlyingType(actual).Name : null) : actual.Name);
  323. return ((name != null) ? String.Concat("Parse", name) : null);
  324. }
  325. protected System.Reflection.MethodInfo GetParserParse(string pName)
  326. {
  327. return typeof(JsonParser).GetMethod((pName ?? "Val"), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
  328. }
  329. protected TypeInfo(Type type, int self, Type eType, Type kType, Type vType)
  330. {
  331. var props = ((self > 2) ? type.GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public) : new System.Reflection.PropertyInfo[] { });
  332. var infos = new Dictionary<string, ItemInfo>();
  333. IsAnonymous = ((eType == null) && (type.Name[0] == '<') && type.IsSealed);
  334. IsStruct = type.IsValueType;
  335. IsNullable = type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>);
  336. IsEnum = IsNullable ? (VType = type.GetGenericArguments()[0]).IsEnum : type.IsEnum;
  337. EType = eType;
  338. Type = type;
  339. T = self;
  340. if (!IsAnonymous)
  341. {
  342. Ctor = (((kType != null) && (vType != null)) ? GetCtor(Type, kType, vType) : GetCtor((EType ?? Type), (EType != null)));
  343. foreach (PropertyInfo property in props)
  344. {
  345. System.Reflection.PropertyInfo pi;
  346. System.Reflection.MethodInfo set;
  347. if ((pi = property).CanWrite && ((set = pi.GetSetMethod()).GetParameters().Length == 1))
  348. infos.Add(pi.Name, GetItemInfo(pi.PropertyType, pi.Name, set));
  349. }
  350. Dico = (((kType != null) && (vType != null)) ? GetItemInfo(Type, kType, vType, typeof(Dictionary<,>).MakeGenericType(kType, vType).GetMethod("Add", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) : null);
  351. List = ((EType != null) ? GetItemInfo(EType, String.Empty, typeof(List<>).MakeGenericType(EType).GetMethod("Add", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)) : null);
  352. Enums = (IsEnum ? GetEnumInfos(Type) : null);
  353. }
  354. else
  355. {
  356. var args = type.GetConstructors()[0].GetParameters();
  357. for (var i = 0; i < args.Length; i++) infos.Add(args[i].Name, new ItemInfo { Type = args[i].ParameterType, Name = args[i].Name, Atm = i, Len = args[i].Name.Length });
  358. }
  359. Props = infos.OrderBy(pair => pair.Key).Select(pair => pair.Value).ToArray();
  360. #if FASTER_GETPROPINFO
  361. if (Props.Length > 0)
  362. {
  363. Mnl = Props.Max(p => p.Name.Length) + 1;
  364. Mlk = new char[Mnl * (Props.Length + 1)];
  365. for (var i = 0; i < Props.Length; i++)
  366. {
  367. var p = Props[i]; var n = p.Name; var l = n.Length;
  368. n.CopyTo(0, Mlk, Mnl * i, l);
  369. }
  370. }
  371. else
  372. {
  373. Mnl = 1;
  374. Mlk = new char[1];
  375. }
  376. #endif
  377. }
  378. }
  379. internal class TypeInfo<T> : TypeInfo
  380. {
  381. internal Func<JsonParser, int, T> Value;
  382. private Func<JsonParser, int, R> GetParseFunc<R>(string pName)
  383. {
  384. var parse = GetParserParse(pName ?? "Key");
  385. if (parse != null)
  386. {
  387. var method = new System.Reflection.Emit.DynamicMethod(parse.Name, typeof(R), new[] { typeof(JsonParser), typeof(int) }, typeof(string), true);
  388. var il = method.GetILGenerator();
  389. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0);
  390. il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1);
  391. il.Emit(System.Reflection.Emit.OpCodes.Callvirt, parse);
  392. il.Emit(System.Reflection.Emit.OpCodes.Ret);
  393. return (Func<JsonParser, int, R>)method.CreateDelegate(typeof(Func<JsonParser, int, R>));
  394. }
  395. return null;
  396. }
  397. internal TypeInfo(int self, Type eType, Type kType, Type vType)
  398. : base(typeof(T), self, eType, kType, vType)
  399. {
  400. var value = (Value = GetParseFunc<T>(GetParseName(typeof(T))));
  401. Parse = (parser, outer) => value(parser, outer);
  402. }
  403. }
  404. static JsonParser()
  405. {
  406. for (char c = '0'; c <= '9'; c++) { HXD[c] = true; HEX[c] = (byte)(c - 48); }
  407. for (char c = 'A'; c <= 'F'; c++) { HXD[c] = HXD[c + 32] = true; HEX[c] = HEX[c + 32] = (byte)(c - 55); }
  408. ESC['/'] = '/'; ESC['\\'] = '\\';
  409. ESC['b'] = '\b'; ESC['f'] = '\f'; ESC['n'] = '\n'; ESC['r'] = '\r'; ESC['t'] = '\t'; ESC['u'] = 'u';
  410. for (int c = ANY; c < 128; c++) if (ESC[c] == ANY) ESC[c] = (char)c;
  411. for (int c = '0'; c <= '9'; c++) IDN[c] = true;
  412. IDF['_'] = IDN['_'] = true;
  413. for (int c = 'A'; c <= 'Z'; c++) IDF[c] = IDN[c] = IDF[c + 32] = IDN[c + 32] = true;
  414. }
  415. private Exception Error(string message) { return new Exception(System.String.Format("{0} at {1} (found: '{2}')", message, at, ((chr < EOF) ? ("\\" + chr) : "EOF"))); }
  416. private void Reset(Func<int> read, Action<int> next, Func<int, int> achar, Func<int> space) { at = -1; chr = ANY; Read = read; Next = next; Char = achar; Space = space; }
  417. private int StreamSpace()
  418. {
  419. if (chr > ' ')
  420. return chr;
  421. while ((chr = (str.Read(stc, 0, 1) > 0) ? stc[0] : EOF) <= ' ')
  422. {
  423. }
  424. return chr;
  425. }
  426. private int StreamRead()
  427. {
  428. return (chr = (str.Read(stc, 0, 1) > 0) ? stc[0] : EOF);
  429. }
  430. private void StreamNext(int ch)
  431. {
  432. if (chr != ch) throw Error("Unexpected character");
  433. chr = ((str.Read(stc, 0, 1) > 0) ? stc[0] : EOF);
  434. }
  435. private int StreamChar(int ch)
  436. {
  437. if (lln >= lbs)
  438. {
  439. if (lsb.Length == 0)
  440. lsb.Append(new string(lbf, 0, lln));
  441. lsb.Append((char)ch);
  442. }
  443. else
  444. lbf[lln++] = (char)ch;
  445. return (chr = (str.Read(stc, 0, 1) > 0) ? stc[0] : EOF);
  446. }
  447. private int StringSpace()
  448. {
  449. if (chr > ' ') return chr;
  450. while ((++at < len) && ((chr = txt[at]) <= ' '))
  451. {
  452. }
  453. return chr;
  454. }
  455. private int StringRead() { return (chr = (++at < len) ? txt[at] : EOF); }
  456. private void StringNext(int ch) { if (chr != ch) throw Error("Unexpected character"); chr = ((++at < len) ? txt[at] : EOF); }
  457. private int StringChar(int ch)
  458. {
  459. if (lln >= lbs)
  460. {
  461. if (lsb.Length == 0)
  462. lsb.Append(new string(lbf, 0, lln));
  463. lsb.Append((char)ch);
  464. }
  465. else
  466. lbf[lln++] = (char)ch;
  467. return (chr = (++at < len) ? txt[at] : EOF);
  468. }
  469. private int Esc(int ec)
  470. {
  471. int cp = 0, ic = -1, ch;
  472. if (ec == 'u')
  473. {
  474. while ((++ic < 4) && ((ch = Read()) <= 'f') && HXD[ch]) { cp *= 16; cp += HEX[ch]; }
  475. if (ic < 4) throw Error("Invalid Unicode character");
  476. ch = cp;
  477. }
  478. else
  479. ch = ESC[ec];
  480. Read();
  481. return ch;
  482. }
  483. private void CharEsc(int ec)
  484. {
  485. int cp = 0, ic = -1, ch;
  486. if (ec == 'u')
  487. {
  488. while ((++ic < 4) && ((ch = Read()) <= 'f') && HXD[ch]) { cp *= 16; cp += HEX[ch]; }
  489. if (ic < 4) throw Error("Invalid Unicode character");
  490. ch = cp;
  491. }
  492. else
  493. ch = ESC[ec];
  494. Char(ch);
  495. }
  496. private EnumInfo GetEnumInfo(TypeInfo type)
  497. {
  498. var a = type.Enums;
  499. int n = a.Length, c = 0, i = 0;
  500. if (n <= 0)
  501. return null;
  502. while (true)
  503. {
  504. int ch;
  505. if ((ch = chr) == '"')
  506. {
  507. Read();
  508. return (((i < n) && (c > 0)) ? a[i] : null);
  509. }
  510. bool e = ch == '\\';
  511. if (e)
  512. ch = Read();
  513. if (ch < EOF)
  514. {
  515. if (!e || (ch >= 128))
  516. Read();
  517. else
  518. ch = Esc(ch);
  519. }
  520. else
  521. break;
  522. EnumInfo ei;
  523. while ((i < n) && ((c >= (ei = a[i]).Len) || (ei.Name[c] != ch))) i++;
  524. c++;
  525. }
  526. return null;
  527. }
  528. private bool ParseBoolean(int outer)
  529. {
  530. int ch = Space();
  531. bool k = (outer > 0) && (ch == '"');
  532. if (k)
  533. ch = Read();
  534. switch (ch)
  535. {
  536. case 'f': Read(); Next('a'); Next('l'); Next('s'); Next('e'); if (k) Next('"'); return false;
  537. case 't': Read(); Next('r'); Next('u'); Next('e'); if (k) Next('"'); return true;
  538. default: throw Error("Bad boolean");
  539. }
  540. }
  541. private char ParseChar(int outer)
  542. {
  543. int ch = Space();
  544. if (ch == '"')
  545. {
  546. ch = Read();
  547. lln = 0;
  548. switch (ch) { case '\\': ch = Read(); CharEsc(ch); Next('"'); break; default: Char(ch); Next('"'); break; }
  549. return lbf[0];
  550. }
  551. throw Error("Bad character");
  552. }
  553. private short ParseSByte(int outer)
  554. {
  555. sbyte it = 1;
  556. sbyte n = 0;
  557. int ch = Space();
  558. bool k = (outer > 0) && (ch == '"');
  559. if (k)
  560. {
  561. ch = Read();
  562. TypeInfo t;
  563. if ((t = types[outer]).IsEnum && (ch != '-') && ((ch < '0') || (ch > '9')))
  564. {
  565. var e = GetEnumInfo(t);
  566. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  567. return (sbyte)e.Value;
  568. }
  569. }
  570. if (ch == '-') { ch = Read(); it = (sbyte)-it; }
  571. var b = (ch >= '0') && (ch <= '9');
  572. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (sbyte)(it * (ch - 48)); } ch = Read(); }
  573. if (!b) throw Error("Bad number (sbyte)"); if (k) Next('"');
  574. return n;
  575. }
  576. private byte ParseByte(int outer)
  577. {
  578. int ch = Space();
  579. bool k = (outer > 0) && (ch == '"');
  580. byte n = 0;
  581. if (k)
  582. {
  583. ch = Read();
  584. TypeInfo t;
  585. if ((t = types[outer]).IsEnum && ((ch < '0') || (ch > '9')))
  586. {
  587. var e = GetEnumInfo(t);
  588. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  589. return (byte)e.Value;
  590. }
  591. }
  592. var b = (ch >= '0') && (ch <= '9');
  593. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (byte)(ch - 48); } ch = Read(); }
  594. if (!b) throw Error("Bad number (byte)"); if (k) Next('"');
  595. return n;
  596. }
  597. private short ParseInt16(int outer)
  598. {
  599. short it = 1, n = 0;
  600. int ch = Space();
  601. bool k = (outer > 0) && (ch == '"');
  602. if (k)
  603. {
  604. ch = Read();
  605. TypeInfo t;
  606. if ((t = types[outer]).IsEnum && (ch != '-') && ((ch < '0') || (ch > '9')))
  607. {
  608. var e = GetEnumInfo(t);
  609. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  610. return (short)e.Value;
  611. }
  612. }
  613. if (ch == '-') { ch = Read(); it = (short)-it; }
  614. var b = (ch >= '0') && (ch <= '9');
  615. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (short)(it * (ch - 48)); } ch = Read(); }
  616. if (!b) throw Error("Bad number (short)"); if (k) Next('"');
  617. return n;
  618. }
  619. private ushort ParseUInt16(int outer)
  620. {
  621. ushort n = 0;
  622. int ch = Space();
  623. bool k = (outer > 0) && (ch == '"');
  624. if (k)
  625. {
  626. ch = Read();
  627. TypeInfo t;
  628. if ((t = types[outer]).IsEnum && ((ch < '0') || (ch > '9')))
  629. {
  630. var e = GetEnumInfo(t);
  631. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  632. return (ushort)e.Value;
  633. }
  634. }
  635. var b = (ch >= '0') && (ch <= '9');
  636. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (ushort)(ch - 48); } ch = Read(); }
  637. if (!b) throw Error("Bad number (ushort)"); if (k) Next('"');
  638. return n;
  639. }
  640. private int ParseInt32(int outer)
  641. {
  642. int it = 1;
  643. int n = 0;
  644. int ch = Space();
  645. bool k = (outer > 0) && (ch == '"');
  646. if (k)
  647. {
  648. ch = Read();
  649. TypeInfo t;
  650. if ((t = types[outer]).IsEnum && (ch != '-') && ((ch < '0') || (ch > '9')))
  651. {
  652. var e = GetEnumInfo(t);
  653. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  654. return (int)e.Value;
  655. }
  656. }
  657. if (ch == '-') { ch = Read(); it = -it; }
  658. var b = (ch >= '0') && (ch <= '9');
  659. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (it * (ch - 48)); } ch = Read(); }
  660. if (!b) throw Error("Bad number (int)"); if (k) Next('"');
  661. return n;
  662. }
  663. private uint ParseUInt32(int outer)
  664. {
  665. int ch = Space();
  666. bool k = (outer > 0) && (ch == '"');
  667. uint n = 0;
  668. if (k)
  669. {
  670. ch = Read();
  671. TypeInfo t;
  672. if ((t = types[outer]).IsEnum && ((ch < '0') || (ch > '9')))
  673. {
  674. var e = GetEnumInfo(t);
  675. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  676. return (uint)e.Value;
  677. }
  678. }
  679. var b = (ch >= '0') && (ch <= '9');
  680. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (uint)(ch - 48); } ch = Read(); }
  681. if (!b) throw Error("Bad number (uint)"); if (k) Next('"');
  682. return n;
  683. }
  684. private long ParseInt64(int outer)
  685. {
  686. long it = 1, n = 0;
  687. int ch = Space();
  688. bool k = (outer > 0) && (ch == '"');
  689. if (k)
  690. {
  691. ch = Read();
  692. TypeInfo t;
  693. if ((t = types[outer]).IsEnum && (ch != '-') && ((ch < '0') || (ch > '9')))
  694. {
  695. var e = GetEnumInfo(t);
  696. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  697. return (long)e.Value;
  698. }
  699. }
  700. if (ch == '-') { ch = Read(); it = -it; }
  701. var b = (ch >= '0') && (ch <= '9');
  702. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += it * (ch - 48); } ch = Read(); }
  703. if (!b) throw Error("Bad number (long)"); if (k) Next('"');
  704. return n;
  705. }
  706. private ulong ParseUInt64(int outer)
  707. {
  708. int ch = Space();
  709. bool k = (outer > 0) && (ch == '"');
  710. ulong n = 0;
  711. if (k)
  712. {
  713. ch = Read();
  714. TypeInfo t;
  715. if ((t = types[outer]).IsEnum && ((ch < '0') || (ch > '9')))
  716. {
  717. var e = GetEnumInfo(t);
  718. if (e == null) throw Error(System.String.Format("Bad enum value ({0})", t.Type.FullName));
  719. return (ulong)e.Value;
  720. }
  721. }
  722. var b = (ch >= '0') && (ch <= '9');
  723. if (b) while ((ch >= '0') && (ch <= '9')) { checked { n *= 10; n += (ulong)(ch - 48); } ch = Read(); }
  724. if (!b) throw Error("Bad number (ulong)"); if (k) Next('"');
  725. return n;
  726. }
  727. private float ParseSingle(int outer)
  728. {
  729. int ch = Space();
  730. bool k = (outer > 0) && (ch == '"');
  731. lsb.Length = 0;
  732. lln = 0;
  733. if (k)
  734. ch = Read();
  735. if (ch == '-') ch = Char(ch);
  736. var b = (ch >= '0') && (ch <= '9');
  737. if (b) while ((ch >= '0') && (ch <= '9')) ch = Char(ch);
  738. if (ch == '.') { ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  739. if ((ch == 'e') || (ch == 'E')) { ch = Char(ch); if ((ch == '-') || (ch == '+')) ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  740. if (!b) throw Error("Bad number (float)"); if (k) Next('"');
  741. var s = ((lsb.Length > 0) ? lsb.ToString() : new string(lbf, 0, lln));
  742. return float.Parse(s, CultureInfo.InvariantCulture);
  743. }
  744. private double ParseDouble(int outer)
  745. {
  746. int ch = Space();
  747. bool k = (outer > 0) && (ch == '"');
  748. lsb.Length = 0; lln = 0;
  749. if (k)
  750. ch = Read();
  751. if (ch == '-') ch = Char(ch);
  752. var b = (ch >= '0') && (ch <= '9');
  753. if (b) while ((ch >= '0') && (ch <= '9')) ch = Char(ch);
  754. if (ch == '.') { ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  755. if ((ch == 'e') || (ch == 'E')) { ch = Char(ch); if ((ch == '-') || (ch == '+')) ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  756. if (!b) throw Error("Bad number (double)"); if (k) Next('"');
  757. var s = ((lsb.Length > 0) ? lsb.ToString() : new string(lbf, 0, lln));
  758. return double.Parse(s, CultureInfo.InvariantCulture);
  759. }
  760. private decimal ParseDecimal(int outer)
  761. {
  762. int ch = Space();
  763. bool k = (outer > 0) && (ch == '"');
  764. lsb.Length = 0; lln = 0;
  765. if (k)
  766. ch = Read();
  767. if (ch == '-') ch = Char(ch);
  768. var b = (ch >= '0') && (ch <= '9');
  769. if (b) while ((ch >= '0') && (ch <= '9')) ch = Char(ch);
  770. if (ch == '.') { ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  771. if (!b) throw Error("Bad number (decimal)"); if (k) Next('"');
  772. var s = ((lsb.Length > 0) ? lsb.ToString() : new string(lbf, 0, lln));
  773. return decimal.Parse(s, CultureInfo.InvariantCulture);
  774. }
  775. private Guid ParseGuid(int outer)
  776. {
  777. var s = ParseString(0);
  778. if (!String.IsNullOrWhiteSpace(s))
  779. return new Guid(s);
  780. throw Error("Bad GUID");
  781. }
  782. private DateTime ParseDateTime(int outer)
  783. {
  784. DateTime dateTime;
  785. if (!DateTime.TryParse(ParseString(0), System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.RoundtripKind, out dateTime))
  786. throw Error("Bad date/time");
  787. return dateTime;
  788. }
  789. private DateTimeOffset ParseDateTimeOffset(int outer)
  790. {
  791. DateTimeOffset dateTimeOffset;
  792. if (!DateTimeOffset.TryParse(ParseString(0), System.Globalization.CultureInfo.CurrentCulture, System.Globalization.DateTimeStyles.RoundtripKind, out dateTimeOffset))
  793. throw Error("Bad date/time offset");
  794. return dateTimeOffset;
  795. }
  796. private string ParseString(int outer)
  797. {
  798. var ch = Space();
  799. if (ch == '"')
  800. {
  801. Read();
  802. lsb.Length = 0;
  803. lln = 0;
  804. while (true)
  805. {
  806. if ((ch = chr) == '"')
  807. {
  808. Read();
  809. return ((lsb.Length > 0) ? lsb.ToString() : new string(lbf, 0, lln));
  810. }
  811. bool e = ch == '\\';
  812. if (e)
  813. ch = Read();
  814. if (ch < EOF)
  815. {
  816. if (!e || (ch >= 128))
  817. Char(ch);
  818. else
  819. CharEsc(ch);
  820. }
  821. else
  822. break;
  823. }
  824. }
  825. if (ch == 'n')
  826. return (string)Null(0);
  827. throw Error((outer >= 0) ? "Bad string" : "Bad key");
  828. }
  829. private void PastKey()
  830. {
  831. var ch = Space();
  832. if (ch != '"') throw Error("Bad key");
  833. Read();
  834. while (true)
  835. {
  836. if ((ch = chr) == '"')
  837. {
  838. Read();
  839. return;
  840. }
  841. bool e = ch == '\\';
  842. if (e)
  843. ch = Read();
  844. if (ch < EOF)
  845. {
  846. if (!e || (ch >= 128))
  847. Read();
  848. else
  849. {
  850. Esc(ch);
  851. }
  852. }
  853. else break;
  854. }
  855. throw Error("Bad key");
  856. }
  857. #if !FASTER_GETPROPINFO
  858. private ItemInfo GetPropInfo(ItemInfo[] a)
  859. {
  860. int ch = Space(), n = a.Length, c = 0, i = 0;
  861. if (ch == '"')
  862. {
  863. Read();
  864. while (true)
  865. {
  866. if ((ch = chr) == '"')
  867. {
  868. Read();
  869. return (((i < n) && (c > 0)) ? a[i] : null);
  870. }
  871. bool e = ch == '\\';
  872. if (e)
  873. ch = Read();
  874. if (ch < EOF)
  875. {
  876. if (!e || (ch >= 128)) Read();
  877. else
  878. {
  879. ch = Esc(ch);
  880. }
  881. }
  882. else break;
  883. ItemInfo pi;
  884. while ((i < n) && ((c >= (pi = a[i]).Len) || (pi.Name[c] != ch))) i++;
  885. c++;
  886. }
  887. }
  888. throw Error("Bad key");
  889. }
  890. #else
  891. private unsafe ItemInfo FasterGetPropInfo(TypeInfo type)
  892. {
  893. var p = type.Props; var m = type.Mlk; int ch = Space(), l = type.Mnl, n = p.Length, i = 0;
  894. if (ch == '"')
  895. {
  896. fixed (char* c = m)
  897. {
  898. char* a = c, z = c + n * l;
  899. while (i <= n)
  900. {
  901. if ((ch = Read()) == '"') { Read(); return i < n && c < a ? p[i] : null; }
  902. while (*a != ch) { if (z <= a) break; a += l; i++; }
  903. a++;
  904. }
  905. return null;
  906. }
  907. }
  908. throw Error("Bad key");
  909. }
  910. #endif
  911. private object Error(int outer) { throw Error("Bad value"); }
  912. private object Null(int outer) { Read(); Next('u'); Next('l'); Next('l'); return null; }
  913. private object False(int outer) { Read(); Next('a'); Next('l'); Next('s'); Next('e'); return false; }
  914. private object True(int outer) { Read(); Next('r'); Next('u'); Next('e'); return true; }
  915. private object Num(int outer)
  916. {
  917. var ch = chr;
  918. lsb.Length = 0; lln = 0;
  919. if (ch == '-') ch = Char(ch);
  920. var b = (ch >= '0') && (ch <= '9');
  921. if (b) while ((ch >= '0') && (ch <= '9')) ch = Char(ch);
  922. if (ch == '.') { ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  923. if ((ch == 'e') || (ch == 'E')) { ch = Char(ch); if ((ch == '-') || (ch == '+')) ch = Char(ch); while ((ch >= '0') && (ch <= '9')) ch = Char(ch); }
  924. if (!b) throw Error("Bad number");
  925. return ((lsb.Length > 0) ? lsb.ToString() : new string(lbf, 0, lln));
  926. }
  927. private object Key(int outer) { return ParseString(-1); }
  928. private object Str(int outer)
  929. {
  930. var s = ParseString(0);
  931. if ((outer != 2) || ((s != null) && (s.Length == 1)))
  932. return ((outer == 2) ? (object)s[0] : s);
  933. throw Error("Bad character");
  934. }
  935. private static object Cat(TypeInfo atinfo, object[] atargs)
  936. {
  937. foreach (var prop in atinfo.Props.Where(prop => prop.Type.IsValueType && (atargs[prop.Atm] == null)))
  938. {
  939. atargs[prop.Atm] = Activator.CreateInstance(prop.Type);
  940. }
  941. return Activator.CreateInstance(atinfo.Type, atargs);
  942. }
  943. private object Parse(int typed)
  944. {
  945. if ((Space() != 'n') || !types[typed].IsNullable)
  946. return (types[typed].Type.IsValueType ? (types[typed].IsNullable ? types[types[typed].Inner].Parse(this, types[typed].Inner) : types[typed].Parse(this, typed)) : Val(typed));
  947. return Null(0);
  948. }
  949. private object Obj(int outer)
  950. {
  951. var cached = types[outer]; var isAnon = cached.IsAnonymous; var hash = types[cached.Key]; var select = cached.Select; var props = cached.Props; var ctor = cached.Ctor;
  952. var atargs = (isAnon ? new object[props.Length] : null);
  953. var mapper = (null as Func<object, object>);
  954. var typed = ((outer > 0) && (cached.Dico == null) && ((ctor != null) || isAnon));
  955. var keyed = hash.T;
  956. var ch = chr;
  957. if (ch != '{') throw Error("Bad object");
  958. Read();
  959. ch = Space();
  960. if (ch == '}')
  961. {
  962. Read();
  963. return (isAnon ? Cat(cached, atargs) : ctor());
  964. }
  965. object obj = null;
  966. while (ch < EOF)
  967. {
  968. #if FASTER_GETPROPINFO
  969. var prop = (typed ? FasterGetPropInfo(cached) : null);
  970. #else
  971. var prop = (typed ? GetPropInfo(props) : null);
  972. #endif
  973. var slot = (!typed ? Parse(keyed) : null);
  974. Func<object, object> read = null;
  975. Space();
  976. Next(':');
  977. if (slot != null)
  978. {
  979. if ((@select == null) || ((read = @select(cached.Type, obj, slot, -1)) != null))
  980. {
  981. var val = Parse(cached.Inner);
  982. var key = (slot as string);
  983. if (obj == null)
  984. {
  985. if ((key != null) && ((String.CompareOrdinal(key, TypeTag1) == 0) || (String.CompareOrdinal(key, TypeTag2) == 0)))
  986. {
  987. obj = (((key = (val as string)) != null) ? (cached = types[Entry(Type.GetType(key, true))]).Ctor() : ctor());
  988. typed = !(obj is IDictionary);
  989. }
  990. else
  991. obj = ctor();
  992. }
  993. if (!typed)
  994. ((IDictionary)obj).Add(slot, val);
  995. }
  996. else
  997. Val(0);
  998. }
  999. else if (prop != null)
  1000. {
  1001. if (!isAnon)
  1002. {
  1003. if ((@select == null) || ((read = @select(cached.Type, obj, prop.Name, -1)) != null))
  1004. {
  1005. if ((Space() != 'n') || !types[prop.Outer].IsNullable)
  1006. {
  1007. obj = (obj ?? ctor());
  1008. prop.Set(obj, this, prop.Outer, 0);
  1009. }
  1010. else
  1011. Null(0);
  1012. }
  1013. else
  1014. Val(0);
  1015. }
  1016. else
  1017. atargs[prop.Atm] = Parse(prop.Outer);
  1018. }
  1019. else
  1020. Val(0);
  1021. mapper = (mapper ?? read);
  1022. ch = Space();
  1023. if (ch == '}')
  1024. {
  1025. mapper = (mapper ?? Identity);
  1026. Read();
  1027. return mapper(isAnon ? Cat(cached, atargs) : (obj ?? ctor()));
  1028. }
  1029. Next(',');
  1030. ch = Space();
  1031. }
  1032. throw Error("Bad object");
  1033. }
  1034. private void SBrace() { Next('{'); }
  1035. private void EBrace() { Space(); Next('}'); }
  1036. private void KColon() { PastKey(); Space(); Next(':'); }
  1037. private void SComma() { Space(); Next(','); }
  1038. private object Arr(int outer)
  1039. {
  1040. var cached = types[(outer != 0) ? outer : 1]; var select = cached.Select; var dico = (cached.Dico != null);
  1041. var mapper = (null as Func<object, object>);
  1042. var items = (dico ? cached.Dico : cached.List);
  1043. var val = cached.Inner;
  1044. var key = cached.Key;
  1045. var ch = chr;
  1046. var i = -1;
  1047. if (ch != '[') throw Error("Bad array");
  1048. Read();
  1049. ch = Space();
  1050. var obj = cached.Ctor();
  1051. if (ch == ']')
  1052. {
  1053. Read();
  1054. if (!cached.Type.IsArray) return obj;
  1055. IList list = (IList)obj;
  1056. var array = Array.CreateInstance(cached.EType, list.Count);
  1057. list.CopyTo(array, 0);
  1058. return array;
  1059. }
  1060. while (ch < EOF)
  1061. {
  1062. Func<object, object> read = null;
  1063. i++;
  1064. if ((ch == 'n') && types[val].IsNullable && !dico)
  1065. {
  1066. Null(0);
  1067. ((IList)obj).Add(null);
  1068. }
  1069. else if (dico || (@select == null) || ((read = @select(cached.Type, obj, null, i)) != null))
  1070. items.Set(obj, this, (types[val].IsNullable ? types[val].Inner : val), (types[key].IsNullable ? types[key].Inner : key));
  1071. else
  1072. Val(0);
  1073. mapper = (mapper ?? read);
  1074. ch = Space();
  1075. if (ch == ']')
  1076. {
  1077. mapper = (mapper ?? Identity);
  1078. Read();
  1079. if (!cached.Type.IsArray) return mapper(obj);
  1080. IList list = (IList)obj;
  1081. var array = Array.CreateInstance(cached.EType, list.Count);
  1082. list.CopyTo(array, 0);
  1083. return mapper(array);
  1084. }
  1085. Next(',');
  1086. ch = Space();
  1087. }
  1088. throw Error("Bad array");
  1089. }
  1090. private object Val(int outer)
  1091. {
  1092. return parse[Space() & 0x7f](outer);
  1093. }
  1094. private static Type GetElementType(Type type)
  1095. {
  1096. if (type.IsArray)
  1097. return type.GetElementType();
  1098. if ((type != typeof(string)) && typeof(System.Collections.IEnumerable).IsAssignableFrom(type))
  1099. return (type.IsGenericType ? type.GetGenericArguments()[0] : typeof(object));
  1100. return null;
  1101. }
  1102. private static Type Realizes(Type type, Type generic)
  1103. {
  1104. while (true)
  1105. {
  1106. var itfs = type.GetInterfaces();
  1107. if (itfs.Any(it => it.IsGenericType && it.GetGenericTypeDefinition() == generic))
  1108. {
  1109. return type;
  1110. }
  1111. if (type.IsGenericType && type.GetGenericTypeDefinition() == generic)
  1112. return type;
  1113. if (type.BaseType == null) return null;
  1114. type = type.BaseType;
  1115. }
  1116. }
  1117. private static bool GetKeyValueTypes(Type type, out Type key, out Type value)
  1118. {
  1119. var generic = (Realizes(type, typeof(Dictionary<,>)) ?? Realizes(type, typeof(IDictionary<,>)));
  1120. var kvPair = ((generic != null) && (generic.GetGenericArguments().Length == 2));
  1121. value = (kvPair ? generic.GetGenericArguments()[1] : null);
  1122. key = (kvPair ? generic.GetGenericArguments()[0] : null);
  1123. return kvPair;
  1124. }
  1125. private int Closure(int outer, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> filter)
  1126. {
  1127. if (types[outer].Closed) return outer;
  1128. var prop = types[outer].Props;
  1129. types[outer].Closed = true;
  1130. foreach (ItemInfo p in prop)
  1131. p.Outer = Entry(p.Type, filter);
  1132. return outer;
  1133. }
  1134. private int Entry(Type type, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> filter = null)
  1135. {
  1136. Func<Type, object, object, int, Func<object, object>> select;
  1137. int outer;
  1138. if (!rtti.TryGetValue(type, out outer))
  1139. {
  1140. Type kt, vt;
  1141. bool dico = GetKeyValueTypes(type, out kt, out vt);
  1142. var et = (!dico ? GetElementType(type) : null);
  1143. outer = rtti.Count;
  1144. types[outer] = (TypeInfo)Activator.CreateInstance(typeof(TypeInfo<>).MakeGenericType(type), System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic, null, new object[] { outer, et, kt, vt }, null);
  1145. rtti.Add(type, outer);
  1146. types[outer].Inner = ((et != null) ? Entry(et, filter) : (dico ? Entry(vt, filter) : (types[outer].IsNullable ? Entry(types[outer].VType, filter) : 0)));
  1147. if (dico) types[outer].Key = Entry(kt, filter);
  1148. }
  1149. if ((filter != null) && filter.TryGetValue(type, out select))
  1150. types[outer].Select = select;
  1151. return Closure(outer, filter);
  1152. }
  1153. private T DoParse<T>(string input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> filter)
  1154. {
  1155. var outer = Entry(typeof(T), filter);
  1156. len = input.Length;
  1157. txt = input;
  1158. Reset(StringRead, StringNext, StringChar, StringSpace);
  1159. return (typeof(T).IsValueType ? ((TypeInfo<T>)types[outer]).Value(this, outer) : (T)Val(outer));
  1160. }
  1161. private T DoParse<T>(TextReader input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> filter)
  1162. {
  1163. var outer = Entry(typeof(T), filter);
  1164. str = input;
  1165. Reset(StreamRead, StreamNext, StreamChar, StreamSpace);
  1166. return (typeof(T).IsValueType ? ((TypeInfo<T>)types[outer]).Value(this, outer) : (T)Val(outer));
  1167. }
  1168. public static object Identity(object obj) { return obj; }
  1169. public static readonly Func<object, object> Skip = null;
  1170. public JsonParser() : this(null) { }
  1171. public JsonParser(JsonParserOptions options)
  1172. {
  1173. options = (options ?? new JsonParserOptions { StringBufferLength = (byte.MaxValue + 1), TypeCacheCapacity = (byte.MaxValue + 1) });
  1174. if (!options.Validate()) throw new ArgumentException("Invalid JSON parser options", "options");
  1175. lbf = new char[lbs = options.StringBufferLength];
  1176. types = new TypeInfo[options.TypeCacheCapacity];
  1177. parse['n'] = Null; parse['f'] = False; parse['t'] = True;
  1178. parse['0'] = parse['1'] = parse['2'] = parse['3'] = parse['4'] =
  1179. parse['5'] = parse['6'] = parse['7'] = parse['8'] = parse['9'] =
  1180. parse['-'] = Num; parse['"'] = Str; parse['{'] = Obj; parse['['] = Arr;
  1181. for (var input = 0; input < 128; input++) parse[input] = (parse[input] ?? Error);
  1182. Entry(typeof(object));
  1183. Entry(typeof(List<object>));
  1184. Entry(typeof(char));
  1185. }
  1186. public object Parse(string input) { return Parse<object>(input); }
  1187. public object Parse(string input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse<object>(input, mappers); }
  1188. public object Parse(TextReader input) { return Parse<object>(input); }
  1189. public object Parse(TextReader input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse<object>(input, mappers); }
  1190. public object Parse(Stream input) { return Parse<object>(input); }
  1191. public object Parse(Stream input, Encoding encoding) { return Parse<object>(input, encoding); }
  1192. public object Parse(Stream input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse<object>(input, mappers); }
  1193. public object Parse(Stream input, Encoding encoding, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse<object>(input, encoding, mappers); }
  1194. public T Parse<T>(string input) { return Parse(default(T), input); }
  1195. public T Parse<T>(T prototype, string input) { return Parse<T>(input, null); }
  1196. public T Parse<T>(string input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse(default(T), input, mappers); }
  1197. public T Parse<T>(T prototype, string input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers)
  1198. {
  1199. if (input == null) throw new ArgumentNullException("input", "cannot be null");
  1200. return DoParse<T>(input, mappers);
  1201. }
  1202. public T Parse<T>(TextReader input) { return Parse(default(T), input); }
  1203. public T Parse<T>(T prototype, TextReader input) { return Parse<T>(input, null); }
  1204. public T Parse<T>(TextReader input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse(default(T), input, mappers); }
  1205. public T Parse<T>(T prototype, TextReader input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers)
  1206. {
  1207. if (input == null) throw new ArgumentNullException("input", "cannot be null");
  1208. return DoParse<T>(input, mappers);
  1209. }
  1210. public T Parse<T>(Stream input) { return Parse(default(T), input); }
  1211. public T Parse<T>(T prototype, Stream input) { return Parse<T>(input, null as Encoding); }
  1212. public T Parse<T>(Stream input, Encoding encoding) { return Parse(default(T), input, encoding); }
  1213. public T Parse<T>(T prototype, Stream input, Encoding encoding) { return Parse<T>(input, encoding, null); }
  1214. public T Parse<T>(Stream input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse(default(T), input, mappers); }
  1215. public T Parse<T>(T prototype, Stream input, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse<T>(input, null, mappers); }
  1216. public T Parse<T>(Stream input, Encoding encoding, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers) { return Parse(default(T), input, encoding, mappers); }
  1217. public T Parse<T>(T prototype, Stream input, Encoding encoding, IDictionary<Type, Func<Type, object, object, int, Func<object, object>>> mappers)
  1218. {
  1219. if (input == null) throw new ArgumentNullException("input", "cannot be null");
  1220. return DoParse<T>((encoding != null) ? new StreamReader(input, encoding) : new StreamReader(input), mappers);
  1221. }
  1222. }
  1223. public delegate void JsonPathResultAccumulator(object value, string[] indicies);
  1224. public interface IJsonPathValueSystem
  1225. {
  1226. bool HasMember(object value, string member);
  1227. object GetMemberValue(object value, string member);
  1228. IEnumerable GetMembers(object value);
  1229. bool IsObject(object value);
  1230. bool IsArray(object value);
  1231. bool IsPrimitive(object value);
  1232. }
  1233. public interface IJsonPathContext
  1234. {
  1235. JsonPathNode[] SelectNodes(string expression);
  1236. }
  1237. [Serializable]
  1238. public sealed class JsonPathNode
  1239. {
  1240. private readonly object value;
  1241. private readonly string path;
  1242. public JsonPathNode(object value) : this(value, null) { }
  1243. public JsonPathNode(object value, string path)
  1244. {
  1245. if (path != null)
  1246. {
  1247. if (path.Length == 0)
  1248. throw new ArgumentException("path");
  1249. }
  1250. this.value = value;
  1251. this.path = (path ?? "(dynamic)");
  1252. }
  1253. public object Value
  1254. {
  1255. get { return value; }
  1256. }
  1257. public string Path
  1258. {
  1259. get { return path; }
  1260. }
  1261. public override string ToString()
  1262. {
  1263. return Path + " = " + Value;
  1264. }
  1265. public static object[] ValuesFrom(ICollection nodes)
  1266. {
  1267. object[] values = new object[nodes != null ? nodes.Count : 0];
  1268. if (values.Length <= 0) return values;
  1269. int i = 0;
  1270. foreach (JsonPathNode node in nodes)
  1271. values[i++] = node.Value;
  1272. return values;
  1273. }
  1274. public static string[] PathsFrom(ICollection nodes)
  1275. {
  1276. string[] paths = new string[nodes != null ? nodes.Count : 0];
  1277. if (paths.Length <= 0) return paths;
  1278. int i = 0;
  1279. foreach (JsonPathNode node in nodes)
  1280. paths[i++] = node.Path;
  1281. return paths;
  1282. }
  1283. }
  1284. public sealed class JsonPathContext : IJsonPathContext
  1285. {
  1286. public static readonly JsonPathContext Default = new JsonPathContext();
  1287. public readonly IDictionary<string, Delegate> Lambdas = new Dictionary<string, Delegate>();
  1288. public JsonPathContext() : this(new object()) { }
  1289. public JsonPathContext(object data) : this(data, null) { }
  1290. public JsonPathContext(object data, IJsonPathValueSystem system) : this(data, system, null) { }
  1291. public JsonPathContext(object data, IJsonPathValueSystem system, JsonPathScriptEvaluator eval) { Data = data; ValueSystem = system; ScriptEvaluator = eval; }
  1292. #region IJsonPathContext implementation
  1293. public JsonPathNode[] SelectNodes(string expression)
  1294. {
  1295. return (new JsonPathContext(Data, ValueSystem, ScriptEvaluator)).Evaluate(expression);
  1296. }
  1297. #endregion
  1298. public JsonPathScriptEvaluator ScriptEvaluator { get; private set; }
  1299. public IJsonPathValueSystem ValueSystem { get; private set; }
  1300. public object Data { get; private set; }
  1301. internal JsonPathNode[] Evaluate(string expression, params JsonPathScriptEvaluator[] lambdas)
  1302. {
  1303. IList<JsonPathNode> result = new List<JsonPathNode>();
  1304. SelectTo(expression, result, lambdas);
  1305. return result.ToArray();
  1306. }
  1307. private void SelectTo(string expression, IList<JsonPathNode> result, params JsonPathScriptEvaluator[] lambdas)
  1308. {
  1309. ListAccumulator accumulator = new ListAccumulator(result);
  1310. SelectTo(expression, accumulator.Put, lambdas);
  1311. }
  1312. private void SelectTo(string expression, JsonPathResultAccumulator output, params JsonPathScriptEvaluator[] lambdas)
  1313. {
  1314. if (output == null)
  1315. throw new ArgumentNullException("output");
  1316. Interpreter i = new Interpreter(this, output, ValueSystem, ScriptEvaluator);
  1317. expression = Normalize(expression);
  1318. if (expression.Length >= 1 && expression[0] == '$') // ^\$:?
  1319. expression = expression.Substring(expression.Length >= 2 && expression[1] == ';' ? 2 : 1);
  1320. i.Trace(expression, Data, "$", (lambdas ?? new JsonPathScriptEvaluator[] { }));
  1321. }
  1322. private static Regex RegExp(string pattern) { return RegExp(pattern, false); }
  1323. private static Regex RegExp(string pattern, bool compiled)
  1324. {
  1325. return new Regex(pattern, (compiled ? RegexOptions.Compiled | RegexOptions.ECMAScript : RegexOptions.ECMAScript));
  1326. }
  1327. private static string Normalize(string expr)
  1328. {
  1329. NormalizationSwap swap = new NormalizationSwap();
  1330. expr = RegExp(@"[\['](\??\(.*?\))[\]']").Replace(expr, swap.Capture);
  1331. expr = RegExp(@"'?\.'?|\['?").Replace(expr, ";");
  1332. expr = RegExp(@";;;|;;").Replace(expr, ";..;");
  1333. expr = RegExp(@";$|'?\]|'$").Replace(expr, string.Empty);
  1334. expr = RegExp(@"#([0-9]+)").Replace(expr, swap.Yield);
  1335. return expr;
  1336. }
  1337. private sealed class NormalizationSwap
  1338. {
  1339. private readonly List<string> subx = new List<string>(4);
  1340. public string Capture(Match match)
  1341. {
  1342. subx.Add(match.Groups[1].Value);
  1343. return "[#" + (subx.Count - 1).ToString(CultureInfo.InvariantCulture) + "]";
  1344. }
  1345. public string Yield(Match match)
  1346. {
  1347. var index = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
  1348. return subx[index];
  1349. }
  1350. }
  1351. public static string AsBracketNotation(string[] indicies)
  1352. {
  1353. if (indicies == null)
  1354. throw new ArgumentNullException("indicies");
  1355. StringBuilder sb = new StringBuilder();
  1356. foreach (string index in indicies)
  1357. {
  1358. if (sb.Length == 0)
  1359. {
  1360. sb.Append('$');
  1361. }
  1362. else
  1363. {
  1364. sb.Append('[');
  1365. if (Interpreter.REGEXP_BRACKET.IsMatch(index))
  1366. sb.Append(index);
  1367. else
  1368. sb.Append('\'').Append(index).Append('\'');
  1369. sb.Append(']');
  1370. }
  1371. }
  1372. return sb.ToString();
  1373. }
  1374. private static int ParseInt(string str, int defaultValue = 0)
  1375. {
  1376. if (string.IsNullOrEmpty(str))
  1377. return defaultValue;
  1378. try
  1379. {
  1380. return int.Parse(str, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture);
  1381. }
  1382. catch (FormatException)
  1383. {
  1384. return defaultValue;
  1385. }
  1386. }
  1387. private sealed class Interpreter
  1388. {
  1389. private static readonly Regex REGEXP_SEGMENTED = RegExp(@"^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$", true);
  1390. private static readonly Regex REGEXP_ITEMIZED = RegExp(@"'?,'?", true);
  1391. public static readonly Regex REGEXP_BRACKET = RegExp(@"^[0-9*]+$", true);
  1392. private static readonly Regex REGEXP_FILTER = RegExp(@"^\?\((.*?)\)$", true);
  1393. private readonly JsonPathResultAccumulator output;
  1394. private readonly JsonPathScriptEvaluator eval;
  1395. private readonly IJsonPathValueSystem system;
  1396. private readonly Regex filter;
  1397. private static readonly char[] colon = { ':' };
  1398. private static readonly char[] semicolon = { ';' };
  1399. private delegate void WalkCallback(object member, string loc, string expr, object value, string path, Delegate[] lambdas, int clambda);
  1400. private readonly JsonPathContext Bindings;
  1401. public Interpreter(JsonPathContext bindings, JsonPathResultAccumulator output, IJsonPathValueSystem valueSystem, JsonPathScriptEvaluator eval)
  1402. {
  1403. Bindings = bindings;
  1404. this.output = output;
  1405. this.eval = (eval ?? NullEval);
  1406. system = valueSystem;
  1407. filter = REGEXP_FILTER;
  1408. }
  1409. public void Trace(string expression, object value, string path, Delegate[] lambdas)
  1410. {
  1411. if (string.IsNullOrEmpty(expression))
  1412. {
  1413. Store(path, value);
  1414. return;
  1415. }
  1416. int i = expression.IndexOf(';');
  1417. string atom = i >= 0 ? expression.Substring(0, i) : expression;
  1418. string tail = i >= 0 ? expression.Substring(i + 1) : String.Empty;
  1419. if (value != null && system.HasMember(value, atom))
  1420. {
  1421. Trace(tail, Index(value, atom), path + ";" + atom, lambdas);
  1422. }
  1423. else if (atom == "*")
  1424. {
  1425. Walk(atom, tail, value, path, WalkWild, lambdas, -1);
  1426. }
  1427. else if (atom == "..")
  1428. {
  1429. Trace(tail, value, path, lambdas);
  1430. Walk(atom, tail, value, path, WalkTree, lambdas, -1);
  1431. }
  1432. else if (atom.Length > 2 && atom[0] == '(' && atom[atom.Length - 1] == ')') // [(exp)]
  1433. {
  1434. Trace(Eval(atom, value, path.Substring(path.LastIndexOf(';') + 1)) + ";" + tail, value, path, lambdas);
  1435. }
  1436. else if (atom.Length > 2 && atom[0] == '{' && atom[atom.Length - 1] == '}') // [{N}]
  1437. {
  1438. var lambda = lambdas[int.Parse(atom.Substring(1, atom.Length - 2), CultureInfo.InvariantCulture)];
  1439. Trace(lambda.DynamicInvoke(atom, value, Bindings) + ";" + tail, value, path, lambdas);
  1440. }
  1441. else if (atom.Length > 3 && atom[0] == '?' && atom[1] == '(' && atom[atom.Length - 1] == ')') // [?(exp)]
  1442. {
  1443. Walk(atom, tail, value, path, WalkFiltered, lambdas, -1);
  1444. }
  1445. else if (atom.Length > 3 && atom[0] == '?' && atom[1] == '{' && atom[atom.Length - 1] == '}') // [?{N}]
  1446. {
  1447. Walk(atom, tail, value, path, WalkFiltered, lambdas, int.Parse(atom.Substring(2, atom.Length - 3), CultureInfo.InvariantCulture));
  1448. }
  1449. else if (REGEXP_SEGMENTED.IsMatch(atom)) // [start:end:step] Phyton slice syntax
  1450. {
  1451. Slice(atom, tail, value, path, lambdas);
  1452. }
  1453. else if (atom.IndexOf(',') >= 0) // [name1,name2,...]
  1454. {
  1455. foreach (string part in REGEXP_ITEMIZED.Split(atom))
  1456. Trace(part + ";" + tail, value, path, lambdas);
  1457. }
  1458. }
  1459. private void Store(string path, object value)
  1460. {
  1461. if (path != null)
  1462. output(value, path.Split(semicolon));
  1463. }
  1464. private void Walk(string loc, string expression, object value, string path, WalkCallback callback, Delegate[] lambdas, int clambda)
  1465. {
  1466. if (system.IsPrimitive(value))
  1467. return;
  1468. if (system.IsArray(value))
  1469. {
  1470. IList list = (IList)value;
  1471. for (int i = 0; i < list.Count; i++)
  1472. callback(i, loc, expression, value, path, lambdas, clambda);
  1473. }
  1474. else if (system.IsObject(value))
  1475. {
  1476. foreach (string key in system.GetMembers(value))
  1477. callback(key, loc, expression, value, path, lambdas, clambda);
  1478. }
  1479. }
  1480. private void WalkWild(object member, string loc, string expression, object value, string path, Delegate[] lambdas, int clambda)
  1481. {
  1482. Trace(member + ";" + expression, value, path, lambdas);
  1483. }
  1484. private void WalkTree(object member, string loc, string expression, object value, string path, Delegate[] lambdas, int clambda)
  1485. {
  1486. object result = Index(value, member.ToString());
  1487. if (result != null && !system.IsPrimitive(result))
  1488. Trace("..;" + expression, result, path + ";" + member, lambdas);
  1489. }
  1490. private void WalkFiltered(object member, string loc, string expression, object value, string path, Delegate[] lambdas, int clambda)
  1491. {
  1492. string script = filter.Replace(loc, "$1");
  1493. object result = ((clambda < 0) ? Eval(script, value, member.ToString(), true) : lambdas[clambda].DynamicInvoke(script, value, Bindings));
  1494. if ((result != null) && (result as bool? ?? ((!(result is string)) || !String.IsNullOrEmpty((string)result))))
  1495. Trace(member + ";" + expression, value, path, lambdas);
  1496. }
  1497. private void Slice(string loc, string expression, object value, string path, Delegate[] lambdas)
  1498. {
  1499. IList list = value as IList;
  1500. if (list == null)
  1501. return;
  1502. int length = list.Count;
  1503. string[] parts = loc.Split(colon);
  1504. int start = ParseInt(parts[0]);
  1505. int end = ParseInt(parts[1], list.Count);
  1506. int step = parts.Length > 2 ? ParseInt(parts[2], 1) : 1;
  1507. start = (start < 0) ? Math.Max(0, start + length) : Math.Min(length, start);
  1508. end = (end < 0) ? Math.Max(0, end + length) : Math.Min(length, end);
  1509. for (int i = start; i < end; i += step)
  1510. Trace(i + ";" + expression, value, path, lambdas);
  1511. }
  1512. private object Index(object obj, string member)
  1513. {
  1514. return system.GetMemberValue(obj, member);
  1515. }
  1516. private object Eval(string script, object value, string member, bool forFilter = false)
  1517. {
  1518. object target = (forFilter ? Index(value, member) : value);
  1519. Type type = ((target != null) ? target.GetType() : typeof(object));
  1520. Delegate func;
  1521. if (!Bindings.Lambdas.TryGetValue(script, out func))
  1522. {
  1523. string lambda = String.Format("(string script, ~ value, IJsonPathContext context) => (object)({0})", script.Replace("@", "value"));
  1524. type = typeof(Func<,,,>).MakeGenericType(typeof(string), (forFilter ? type : (target is IEnumerable ? type : typeof(object))), typeof(IJsonPathContext), typeof(object));
  1525. func = (eval(lambda, type, Bindings) as Delegate);
  1526. if (func != null) Bindings.Lambdas.Add(script, func);
  1527. }
  1528. return ((func != null) ? func.DynamicInvoke(script, target, Bindings) : eval(script, target, Bindings));
  1529. }
  1530. private static object NullEval(string expression, object value, IJsonPathContext context)
  1531. {
  1532. //
  1533. // @ symbol in expression must be interpreted specially to resolve
  1534. // to value. In JavaScript, the implementation would look
  1535. // like:
  1536. //
  1537. // return obj && value && eval(expression.replace(/@/g, "value"));
  1538. //
  1539. return null;
  1540. }
  1541. }
  1542. private sealed class ListAccumulator
  1543. {
  1544. private readonly IList<JsonPathNode> list;
  1545. public ListAccumulator(IList<JsonPathNode> list)
  1546. {
  1547. this.list = list;
  1548. }
  1549. public void Put(object value, string[] indicies)
  1550. {
  1551. list.Add(new JsonPathNode(value, AsBracketNotation(indicies)));
  1552. }
  1553. }
  1554. }
  1555. }
  1556. //
  1557. // C# implementation of JSONPath[1]
  1558. //
  1559. // Copyright (c) 2007 Atif Aziz (http://www.raboof.com/)
  1560. // Licensed under The MIT License
  1561. //
  1562. // Supported targets:
  1563. //
  1564. // - Mono 1.1 or later
  1565. // - Microsoft .NET Framework 1.0 or later
  1566. //
  1567. // [1] JSONPath - XPath for JSON
  1568. // http://code.google.com/p/jsonpath/
  1569. // Copyright (c) 2007 Stefan Goessner (goessner.net)
  1570. // Licensed under The MIT License
  1571. //
  1572. #region The MIT License
  1573. //
  1574. // The MIT License
  1575. //
  1576. // Copyright (c) 2007 Atif Aziz (http://www.raboof.com/)
  1577. //
  1578. // Permission is hereby granted, free of charge, to any person obtaining a copy
  1579. // of this software and associated documentation files (the "Software"), to deal
  1580. // in the Software without restriction, including without limitation the rights
  1581. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  1582. // copies of the Software, and to permit persons to whom the Software is
  1583. // furnished to do so, subject to the following conditions:
  1584. //
  1585. // The above copyright notice and this permission notice shall be included in
  1586. // all copies or substantial portions of the Software.
  1587. //
  1588. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  1589. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  1590. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  1591. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  1592. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  1593. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  1594. // THE SOFTWARE.
  1595. //
  1596. #endregion