Please disclose if your mod was created primarily using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of Item Link v1.2.1
kg.ItemLink.dll
Decompiled 11 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.Diagnostics; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Xml.Serialization; using BepInEx; using BepInEx.Configuration; using GUIFramework; using HarmonyLib; using JetBrains.Annotations; using Jewelcrafting; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; using fastJSON; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ItemLink")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ItemLink")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("6C07200A-3881-4C2A-8EBF-370A00F20A6E")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ItemLink { [BepInPlugin("kg.ItemLink", "ItemLink", "1.2.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("redseiko.valheim.chatter")] public class ItemLink : BaseUnityPlugin { [HarmonyPatch(typeof(ItemData), "GetTooltip", new Type[] { typeof(ItemData), typeof(int), typeof(bool), typeof(float), typeof(int) })] public static class PatchTooltip { public static bool SkipPatch; private static void Postfix(ItemData item, bool crafting, ref string __result) { if (!crafting && Object.op_Implicit((Object)(object)Player.m_localPlayer) && ((Humanoid)Player.m_localPlayer).m_inventory.ContainsItem(item) && !SkipPatch) { __result += "\n\n<color=yellow>[L.Shift + L.Control]</color> Link in <color=#808080>General</color> chat\n<color=yellow>[L.Shift + L.Alt]</color> Link in <color=yellow>Shout</color> chat"; } } } [HarmonyPatch(typeof(TextInput), "IsVisible")] private static class Menu_Patch { [UsedImplicitly] private static void Postfix(ref bool __result) { bool num = __result; Chat instance = Chat.instance; __result = num | (instance != null && ((Behaviour)((Terminal)instance).m_input).isActiveAndEnabled); } } private const string GUID = "kg.ItemLink"; private const string NAME = "ItemLink"; private const string VERSION = "1.2.1"; private static ItemLink _thistype; private static AssetBundle asset; public static GameObject TooltipTrick; private void Awake() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) JSON.Parameters = new JSONParameters { UseExtensions = false, SerializeNullValues = false, DateTimeMilliseconds = false, UseUTCDateTime = true, UseOptimizedDatasetSchema = true, UseValuesOfEnums = true }; _thistype = this; TooltipTrick = new GameObject("kg_ItemLink_TooltipTrick") { hideFlags = (HideFlags)61 }; TooltipTrick.AddComponent<UITooltip>(); TooltipTrick.SetActive(false); asset = GetAssetBundle("kg_itemlink"); ItemLinkProcessor.TooltipPrefab = asset.LoadAsset<GameObject>("kg_InventoryTooltipLink"); new Harmony("kg.ItemLink").PatchAll(); } private static AssetBundle GetAssetBundle(string filename) { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string name = executingAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(filename)); using Stream stream = executingAssembly.GetManifestResourceStream(name); return AssetBundle.LoadFromStream(stream); } } public static class LinkContainer { private static readonly List<ItemLink_Data> _itemLinks; private static int _lastLink; private static int _lastLinkIndex; static LinkContainer() { _itemLinks = new List<ItemLink_Data>(50); _lastLink = -1; _lastLinkIndex = -1; for (int i = 0; i < 50; i++) { _itemLinks.Add(null); } } public static int AddLink(ItemLink_Data itemLinkData) { _lastLink = (_lastLink + 1) % 50; _itemLinks[_lastLink] = itemLinkData; return _lastLink; } public static ItemLink_Data GetLink(int index) { if (_lastLinkIndex == index) { return null; } return _itemLinks[index]; } public static void SetLastLinkIndex(int index) { _lastLinkIndex = index; } public static void ResetLastLinkIndex() { _lastLinkIndex = -1; } } public class ItemLink_Data { public string Prefab; public int Count; public int Quality; public int Variant; public string CustomData = "{}"; public string CrafterName = ""; public long CrafterID; public byte DurabilityPercent; } [HarmonyPatch(typeof(Chat), "Awake")] public static class Chat_Awake_Patch { [UsedImplicitly] private static void Postfix(Chat __instance) { GuiInputField input = ((Terminal)Chat.instance).m_input; if (input != null && !Object.op_Implicit((Object)(object)((Component)input).GetComponent<ItemLinkProcessor>())) { ((Graphic)((Terminal)__instance).m_output).raycastTarget = true; ((Component)input).gameObject.AddComponent<ItemLinkProcessor>(); } } } [HarmonyPatch(typeof(InventoryGrid), "OnLeftClick")] public static class InventoryGrid_OnLeftClick_Patch { [UsedImplicitly] private static bool Prefix(InventoryGrid __instance, UIInputHandler clickHandler) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKey((KeyCode)304) && (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)308))) { Type val = (Type)(Input.GetKey((KeyCode)306) ? 1 : 2); Vector2i buttonPos = __instance.GetButtonPos(((Component)clickHandler).gameObject); ItemData itemAt = __instance.m_inventory.GetItemAt(buttonPos.x, buttonPos.y); if (itemAt == null) { return true; } ItemLink_Data obj = new ItemLink_Data { Prefab = ((Object)itemAt.m_dropPrefab).name, Count = itemAt.m_stack, Quality = itemAt.m_quality, Variant = itemAt.m_variant, CustomData = JSON.ToJSON(itemAt.m_customData), CrafterName = itemAt.m_crafterName, CrafterID = itemAt.m_crafterID, DurabilityPercent = (byte)(itemAt.m_durability / itemAt.GetMaxDurability() * 100f) }; string text = JSON.ToJSON(obj); UserInfo localUser = UserInfo.GetLocalUser(); localUser.Name += $" [{val}]"; ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "RPC_KG_ItemLink", new object[2] { localUser, text }); return false; } return true; } } [HarmonyPatch(typeof(ZNetScene), "Awake")] public static class ZNetScene_Awake_Patch { private static void Postfix(ZNetScene __instance) { ZRoutedRpc.instance.Register<UserInfo, string>("RPC_KG_ItemLink", (Action<long, UserInfo, string>)RPC_Receiver.ReceiveItemLink); } } public static class RPC_Receiver { public const string KEY = "kg.ItemLinkChatKey:"; public static void ReceiveItemLink(long sender, UserInfo userInfo, string json) { string text = ""; try { ItemLink_Data itemLink_Data = JSON.ToObject<ItemLink_Data>(json); int num = LinkContainer.AddLink(itemLink_Data); string text2 = ((itemLink_Data.Count > 1) ? $" x{itemLink_Data.Count}" : ""); ItemLinkProcessor.GetItemData(itemLink_Data, out var topic, out var _, out var _, out var _); text = string.Format("<link=\"{0}{1}\"><color=#ffbf00><u><b>[•{2}{3}]</b></u></color></link>", "kg.ItemLinkChatKey:", num, topic, text2); } catch (Exception arg) { text = "<color=red>[kg.ItemLink] Wrong Data</color>"; MonoBehaviour.print((object)$"[kg.ItemLink] Error: {arg}"); } Chat.instance.m_hideTimer = 0f; ((Terminal)Chat.instance).AddString(userInfo.Name, text, (Type)1, false); } } public class ItemLinkProcessor : MonoBehaviour { public static GameObject TooltipPrefab; private static GameObject CurrentTooltip; private static List<GameObject> CompareTooltips = new List<GameObject>(); private int linkStartTextIndex = -1; private int linkTextLength; private TMP_Text _text; private TMP_InputField _input; private List<Color> _oldColors; private Color defaultHoverColor = new Color(1f, 0.96f, 0.99f); private bool changeColor { get { if (linkStartTextIndex != -1) { return linkTextLength != 0; } return false; } } private void Awake() { _text = ((Component)((Terminal)Chat.instance).m_output).GetComponent<TMP_Text>(); _input = ((Component)((Terminal)Chat.instance).m_input).GetComponent<TMP_InputField>(); } private void OnDisable() { if (changeColor) { ChangeVertexColors(isHover: false); } linkStartTextIndex = -1; linkTextLength = 0; LinkContainer.ResetLastLinkIndex(); if (Object.op_Implicit((Object)(object)CurrentTooltip)) { Object.Destroy((Object)(object)CurrentTooltip); } CompareTooltips.ForEach((Action<GameObject>)Object.Destroy); CompareTooltips.Clear(); } public static List<ItemData> GetCompareItems(ItemData item) { if (!Object.op_Implicit((Object)(object)Player.m_localPlayer)) { return null; } return ((Humanoid)Player.m_localPlayer).m_inventory.m_inventory.Where((ItemData x) => x.m_equipped && x.m_shared.m_itemType == item.m_shared.m_itemType).ToList(); } private void ProcessTMP(int tryFindLink) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) TMP_LinkInfo val = _text.textInfo.linkInfo[tryFindLink]; string linkID = ((TMP_LinkInfo)(ref val)).GetLinkID(); if (!linkID.Contains("kg.ItemLinkChatKey:")) { return; } try { int num = int.Parse(linkID.Split(new char[1] { ':' })[1]); ItemLink_Data link = LinkContainer.GetLink(num); if (link != null) { if (changeColor) { ChangeVertexColors(isHover: false); } if (Object.op_Implicit((Object)(object)CurrentTooltip)) { Object.Destroy((Object)(object)CurrentTooltip); } CompareTooltips.ForEach((Action<GameObject>)Object.Destroy); CompareTooltips.Clear(); LinkContainer.SetLastLinkIndex(num); linkStartTextIndex = val.linkTextfirstCharacterIndex; linkTextLength = val.linkTextLength; CurrentTooltip = CreateTooltipForItemLinkData(link); ChangeVertexColors(isHover: true); } } catch (Exception arg) { linkStartTextIndex = -1; linkTextLength = 0; MonoBehaviour.print((object)$"[ItemLink] Error: {arg}"); } } private void LateUpdate() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (!((Behaviour)_input).isActiveAndEnabled) { return; } int num = TMP_TextUtilities.FindIntersectingLink(_text, Input.mousePosition, (Camera)null); if (num == -1) { OnDisable(); return; } if (Input.GetKeyDown((KeyCode)304) || Input.GetKeyUp((KeyCode)304)) { OnDisable(); } ProcessTMP(num); } private GameObject CreateTooltipForItemLinkData(ItemLink_Data itemLinkData, string additionalText = "") { GetItemData(itemLinkData, out var topic, out var text, out var icon, out var item); GameObject val = Object.Instantiate<GameObject>(TooltipPrefab, ((Component)((Terminal)Chat.instance).m_chatWindow).transform); ((Component)val.transform.Find("Bkg/Icon")).GetComponent<Image>().sprite = icon; ((Component)val.transform.Find("Bkg/Icon")).GetComponent<Image>().type = (Type)1; ((Component)val.transform.Find("Bkg/Topic")).GetComponent<Text>().text = Localization.instance.Localize(topic) + additionalText; ((Component)val.transform.Find("Bkg/Text")).GetComponent<Text>().text = Localization.instance.Localize(text); Transform val2 = val.transform.Find("Bkg/TrannyHoles"); bool active = API.FillItemContainerTooltip(item, val2.parent, showInteract: false); ((Component)val2).gameObject.SetActive(active); Transform transform = ((Component)val.transform.GetChild(0)).transform; AdjustPosition((RectTransform)(object)((transform is RectTransform) ? transform : null)); if (Input.GetKey((KeyCode)304)) { List<ItemData> compareItems = GetCompareItems(item); if (compareItems != null) { for (int i = 0; i < compareItems.Count; i++) { GameObject item2 = CreateCompareTooltip(compareItems[i], i, " <color=green><b>[Equipped]</b></color>"); CompareTooltips.Add(item2); } } } return val; } private GameObject CreateCompareTooltip(ItemData item, int index, string additionalText = "") { //IL_0104: Unknown result type (might be due to invalid IL or missing references) GetItemData(item, out var topic, out var text, out var icon); GameObject val = Object.Instantiate<GameObject>(TooltipPrefab, ((Component)Hud.instance).transform.parent); ((Component)val.transform.Find("Bkg/Icon")).GetComponent<Image>().sprite = icon; ((Component)val.transform.Find("Bkg/Icon")).GetComponent<Image>().type = (Type)1; ((Component)val.transform.Find("Bkg/Topic")).GetComponent<Text>().text = Localization.instance.Localize(topic) + additionalText; ((Component)val.transform.Find("Bkg/Text")).GetComponent<Text>().text = Localization.instance.Localize(text); Transform val2 = val.transform.Find("Bkg/TrannyHoles"); bool active = API.FillItemContainerTooltip(item, val2.parent, showInteract: false); ((Component)val2).gameObject.SetActive(active); Transform transform = ((Component)val.transform.GetChild(0)).transform; AdjustPosition((RectTransform)(object)((transform is RectTransform) ? transform : null), (0f - ((Component)val.transform.GetChild(0)).GetComponent<RectTransform>().sizeDelta.x) * (float)(index + 1) - 4f); return val; } public static void GetItemData(ItemLink_Data itemLinkData, out string topic, out string text, out Sprite icon, out ItemData item) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown GameObject prefab = ZNetScene.instance.GetPrefab(itemLinkData.Prefab); if (!Object.op_Implicit((Object)(object)prefab)) { item = null; topic = "Unknown"; text = "Unknown"; icon = null; return; } ItemData itemData = prefab.GetComponent<ItemDrop>().m_itemData; SharedData shared = itemData.m_shared; Dictionary<string, string> customData = itemData.m_customData; itemData.m_shared = (SharedData)AccessTools.DeclaredMethod(typeof(object), "MemberwiseClone", (Type[])null, (Type[])null).Invoke(shared, Array.Empty<object>()); itemData.m_customData = JSON.ToObject<Dictionary<string, string>>(itemLinkData.CustomData); item = itemData.Clone(); itemData.m_customData = customData; itemData.m_shared = shared; item.m_stack = itemLinkData.Count; item.m_quality = itemLinkData.Quality; item.m_variant = itemLinkData.Variant; item.m_crafterID = itemLinkData.CrafterID; item.m_crafterName = itemLinkData.CrafterName; item.m_durability = item.GetMaxDurability() * (float)(int)itemLinkData.DurabilityPercent / 100f; UITooltip component = ItemLink.TooltipTrick.GetComponent<UITooltip>(); bool canBeReparied = item.m_shared.m_canBeReparied; item.m_shared.m_canBeReparied = false; InventoryGui.instance.m_playerGrid.CreateItemTooltip(item, component); item.m_shared.m_canBeReparied = canBeReparied; topic = Localization.instance.Localize(component.m_topic); text = Localization.instance.Localize(component.m_text); icon = item.GetIcon(); MonoBehaviour.print((object)("Custom data of tooltip is: " + JSON.ToNiceJSON(item.m_customData))); } public static void GetItemData(ItemData item, out string topic, out string text, out Sprite icon) { ItemLink.PatchTooltip.SkipPatch = true; UITooltip component = ItemLink.TooltipTrick.GetComponent<UITooltip>(); bool canBeReparied = item.m_shared.m_canBeReparied; item.m_shared.m_canBeReparied = false; InventoryGui.instance.m_playerGrid.CreateItemTooltip(item, component); item.m_shared.m_canBeReparied = canBeReparied; ItemLink.PatchTooltip.SkipPatch = false; topic = Localization.instance.Localize(component.m_topic); text = Localization.instance.Localize(component.m_text); icon = item.GetIcon(); } private void AdjustPosition(RectTransform bkg, float minusX = 0f) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) ContentSizeFitter component = ((Component)bkg).GetComponent<ContentSizeFitter>(); ((Behaviour)component).enabled = false; ((Behaviour)component).enabled = true; Canvas.ForceUpdateCanvases(); Vector3 val = _text.transform.TransformPoint(_text.textInfo.characterInfo[linkStartTextIndex].topLeft); Vector3 val2 = _text.transform.TransformPoint(_text.textInfo.characterInfo[linkStartTextIndex + linkTextLength - 1].topRight); Vector3 position = default(Vector3); ((Vector3)(ref position))..ctor((val.x + val2.x) / 2f, val.y, 0f); ((Component)bkg).transform.parent.position = position; Transform parent = ((Component)bkg).transform.parent; Transform obj = ((parent is RectTransform) ? parent : null); ((RectTransform)obj).anchoredPosition = ((RectTransform)obj).anchoredPosition + new Vector2(minusX, bkg.sizeDelta.y); } private void ChangeVertexColors(bool isHover) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) if (isHover) { _oldColors = new List<Color>(linkTextLength); } for (int i = 0; i < linkTextLength; i++) { int num = linkStartTextIndex + i; if (_text.textInfo.characterInfo[num].character == ' ') { _oldColors.Add(defaultHoverColor); _oldColors.Add(defaultHoverColor); _oldColors.Add(defaultHoverColor); _oldColors.Add(defaultHoverColor); continue; } int materialReferenceIndex = _text.textInfo.characterInfo[num].materialReferenceIndex; int vertexIndex = _text.textInfo.characterInfo[num].vertexIndex; Color32[] colors = _text.textInfo.meshInfo[materialReferenceIndex].colors32; if (isHover) { _oldColors.Add(Color32.op_Implicit(colors[vertexIndex])); _oldColors.Add(Color32.op_Implicit(colors[vertexIndex + 1])); _oldColors.Add(Color32.op_Implicit(colors[vertexIndex + 2])); _oldColors.Add(Color32.op_Implicit(colors[vertexIndex + 3])); colors[vertexIndex] = Color32.op_Implicit(defaultHoverColor); colors[vertexIndex + 1] = Color32.op_Implicit(defaultHoverColor); colors[vertexIndex + 2] = Color32.op_Implicit(defaultHoverColor); colors[vertexIndex + 3] = Color32.op_Implicit(defaultHoverColor); } else { colors[vertexIndex] = Color32.op_Implicit(_oldColors[i * 4]); colors[vertexIndex + 1] = Color32.op_Implicit(_oldColors[i * 4 + 1]); colors[vertexIndex + 2] = Color32.op_Implicit(_oldColors[i * 4 + 2]); colors[vertexIndex + 3] = Color32.op_Implicit(_oldColors[i * 4 + 3]); } } _text.UpdateVertexData((TMP_VertexDataUpdateFlags)16); } } } namespace fastJSON { internal class DynamicJson : DynamicObject, IEnumerable { private IDictionary<string, object> _dictionary { get; set; } private List<object> _list { get; set; } public DynamicJson(string json) { object obj = JSON.Parse(json); if (obj is IDictionary<string, object>) { _dictionary = (IDictionary<string, object>)obj; } else { _list = (List<object>)obj; } } private DynamicJson(object dictionary) { if (dictionary is IDictionary<string, object>) { _dictionary = (IDictionary<string, object>)dictionary; } } public override IEnumerable<string> GetDynamicMemberNames() { return _dictionary.Keys.ToList(); } public override bool TryGetIndex(GetIndexBinder binder, object[] indexes, out object result) { object obj = indexes[0]; if (obj is int) { result = _list[(int)obj]; } else { result = _dictionary[(string)obj]; } if (result is IDictionary<string, object>) { result = new DynamicJson(result as IDictionary<string, object>); } return true; } public override bool TryGetMember(GetMemberBinder binder, out object result) { if (!_dictionary.TryGetValue(binder.Name, out result) && !_dictionary.TryGetValue(binder.Name.ToLowerInvariant(), out result)) { return false; } if (result is IDictionary<string, object>) { result = new DynamicJson(result as IDictionary<string, object>); } else if (result is List<object>) { List<object> list = new List<object>(); foreach (object item in (List<object>)result) { if (item is IDictionary<string, object>) { list.Add(new DynamicJson(item as IDictionary<string, object>)); } else { list.Add(item); } } result = list; } return _dictionary.ContainsKey(binder.Name); } IEnumerator IEnumerable.GetEnumerator() { foreach (object item in _list) { yield return new DynamicJson(item as IDictionary<string, object>); } } } public sealed class DatasetSchema { public List<string> Info; public string Name; } public class DataMemberAttribute : Attribute { public string Name { get; set; } } internal static class Formatter { private static void AppendIndent(StringBuilder sb, int count, string indent) { while (count > 0) { sb.Append(indent); count--; } } public static string PrettyPrint(string input) { return PrettyPrint(input, new string(' ', JSON.Parameters.FormatterIndentSpaces)); } public static string PrettyPrint(string input, string spaces) { StringBuilder stringBuilder = new StringBuilder(); int num = 0; int length = input.Length; char[] array = input.ToCharArray(); for (int i = 0; i < length; i++) { char c = array[i]; if (c == '"') { bool flag = true; while (flag) { stringBuilder.Append(c); c = array[++i]; switch (c) { case '\\': stringBuilder.Append(c); c = array[++i]; break; case '"': flag = false; break; } } } switch (c) { case '[': case '{': stringBuilder.Append(c); stringBuilder.AppendLine(); AppendIndent(stringBuilder, ++num, spaces); break; case ']': case '}': stringBuilder.AppendLine(); AppendIndent(stringBuilder, --num, spaces); stringBuilder.Append(c); break; case ',': stringBuilder.Append(c); stringBuilder.AppendLine(); AppendIndent(stringBuilder, num, spaces); break; case ':': stringBuilder.Append(" : "); break; default: if (!char.IsWhiteSpace(c)) { stringBuilder.Append(c); } break; } } return stringBuilder.ToString(); } } public class Helper { public static bool IsNullable(Type t) { if (!t.IsGenericType) { return false; } Type genericTypeDefinition = t.GetGenericTypeDefinition(); return genericTypeDefinition.Equals(typeof(Nullable<>)); } public static Type UnderlyingTypeOf(Type t) { return Reflection.Instance.GetGenericArguments(t)[0]; } public static DateTimeOffset CreateDateTimeOffset(int year, int month, int day, int hour, int min, int sec, int milli, int extraTicks, TimeSpan offset) { DateTimeOffset dateTimeOffset = new DateTimeOffset(year, month, day, hour, min, sec, milli, offset); if (extraTicks > 0) { return dateTimeOffset + TimeSpan.FromTicks(extraTicks); } return dateTimeOffset; } public static bool BoolConv(object v) { bool result = false; if (v is bool) { result = (bool)v; } else if (v is long) { result = (((long)v > 0) ? true : false); } else if (v is string) { string text = (string)v; switch (text.ToLowerInvariant()) { case "1": case "true": case "yes": case "on": result = true; break; } } return result; } public static long AutoConv(object value, JSONParameters param) { if (value is string) { if (param.AutoConvertStringToNumbers) { string text = (string)value; return CreateLong(text, 0, text.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (value is long) { return (long)value; } return Convert.ToInt64(value); } public unsafe static long CreateLong(string s, int index, int count) { long num = 0L; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public unsafe static long CreateLong(char[] s, int index, int count) { long num = 0L; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public unsafe static int CreateInteger(string s, int index, int count) { int num = 0; int num2 = 1; fixed (char* ptr = s) { char* ptr2 = ptr; ptr2 += index; if (*ptr2 == '-') { num2 = -1; ptr2++; count--; } if (*ptr2 == '+') { ptr2++; count--; } while (count > 0) { num = num * 10 + (*ptr2 - 48); ptr2++; count--; } } return num * num2; } public static object CreateEnum(Type pt, object v) { return Enum.Parse(pt, v.ToString(), ignoreCase: true); } public static Guid CreateGuid(string s) { if (s.Length > 30) { return new Guid(s); } return new Guid(Convert.FromBase64String(s)); } public static StringDictionary CreateSD(Dictionary<string, object> d) { StringDictionary stringDictionary = new StringDictionary(); foreach (KeyValuePair<string, object> item in d) { stringDictionary.Add(item.Key, (string)item.Value); } return stringDictionary; } public static NameValueCollection CreateNV(Dictionary<string, object> d) { NameValueCollection nameValueCollection = new NameValueCollection(); foreach (KeyValuePair<string, object> item in d) { nameValueCollection.Add(item.Key, (string)item.Value); } return nameValueCollection; } public static object CreateDateTimeOffset(string value) { int milli = 0; int extraTicks = 0; int num = 0; int num2 = 0; int year = CreateInteger(value, 0, 4); int month = CreateInteger(value, 5, 2); int day = CreateInteger(value, 8, 2); int hour = CreateInteger(value, 11, 2); int min = CreateInteger(value, 14, 2); int sec = CreateInteger(value, 17, 2); int num3 = 20; if (value.Length > 21 && value[19] == '.') { milli = CreateInteger(value, num3, 3); num3 = 23; if (value.Length > 25 && char.IsDigit(value[num3])) { extraTicks = CreateInteger(value, num3, 4); num3 = 27; } } if (value[num3] == 'Z') { return CreateDateTimeOffset(year, month, day, hour, min, sec, milli, extraTicks, TimeSpan.Zero); } if (value[num3] == ' ') { num3++; } num = CreateInteger(value, num3 + 1, 2); num2 = CreateInteger(value, num3 + 1 + 2 + 1, 2); if (value[num3] == '-') { num = -num; } return CreateDateTimeOffset(year, month, day, hour, min, sec, milli, extraTicks, new TimeSpan(num, num2, 0)); } public static DateTime CreateDateTime(string value, bool UseUTCDateTime) { if (value.Length < 19) { return DateTime.MinValue; } bool flag = false; int millisecond = 0; int year = CreateInteger(value, 0, 4); int month = CreateInteger(value, 5, 2); int day = CreateInteger(value, 8, 2); int hour = CreateInteger(value, 11, 2); int minute = CreateInteger(value, 14, 2); int second = CreateInteger(value, 17, 2); if (value.Length > 21 && value[19] == '.') { millisecond = CreateInteger(value, 20, 3); } if (value[value.Length - 1] == 'Z') { flag = true; } if (!UseUTCDateTime && !flag) { return new DateTime(year, month, day, hour, minute, second, millisecond); } return new DateTime(year, month, day, hour, minute, second, millisecond, DateTimeKind.Utc).ToLocalTime(); } } internal sealed class JSONSerializer { private StringBuilder _output = new StringBuilder(); private int _before; private int _MAX_DEPTH = 20; private int _current_depth; private Dictionary<string, int> _globalTypes = new Dictionary<string, int>(); private Dictionary<object, int> _cirobj; private JSONParameters _params; private bool _useEscapedUnicode; private bool _TypesWritten; internal JSONSerializer(JSONParameters param) { if (param.OverrideObjectHashCodeChecking) { _cirobj = new Dictionary<object, int>(10, ReferenceEqualityComparer.Default); } else { _cirobj = new Dictionary<object, int>(); } _params = param; _useEscapedUnicode = _params.UseEscapedUnicode; _MAX_DEPTH = _params.SerializerMaxDepth; } internal string ConvertToJSON(object obj) { WriteValue(obj); if (_params.UsingGlobalTypes && _globalTypes != null && _globalTypes.Count > 0) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("\"$types\":{"); bool flag = false; foreach (KeyValuePair<string, int> globalType in _globalTypes) { if (flag) { stringBuilder.Append(','); } flag = true; stringBuilder.Append('"'); stringBuilder.Append(globalType.Key); stringBuilder.Append("\":\""); stringBuilder.Append(globalType.Value); stringBuilder.Append('"'); } stringBuilder.Append("},"); _output.Insert(_before, stringBuilder.ToString()); } return _output.ToString(); } private void WriteValue(object obj) { if (obj == null || obj is DBNull) { _output.Append("null"); } else if (obj is string || obj is char) { WriteString(obj.ToString()); } else if (obj is Guid) { WriteGuid((Guid)obj); } else if (obj is bool) { _output.Append(((bool)obj) ? "true" : "false"); } else if (obj is int || obj is long || obj is decimal || obj is byte || obj is short || obj is sbyte || obj is ushort || obj is uint || obj is ulong) { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } else if (obj is double || obj is double) { double d = (double)obj; if (double.IsNaN(d)) { _output.Append("\"NaN\""); } else if (double.IsInfinity(d)) { _output.Append('"'); _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); _output.Append('"'); } else { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } } else if (obj is float || obj is float) { float f = (float)obj; if (float.IsNaN(f)) { _output.Append("\"NaN\""); } else if (float.IsInfinity(f)) { _output.Append('"'); _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); _output.Append('"'); } else { _output.Append(((IConvertible)obj).ToString(NumberFormatInfo.InvariantInfo)); } } else if (obj is DateTime) { WriteDateTime((DateTime)obj); } else if (obj is DateTimeOffset) { WriteDateTimeOffset((DateTimeOffset)obj); } else if (obj is TimeSpan) { _output.Append(((TimeSpan)obj).Ticks); } else if (!_params.KVStyleStringDictionary && obj is IEnumerable<KeyValuePair<string, object>>) { WriteStringDictionary((IEnumerable<KeyValuePair<string, object>>)obj); } else if (!_params.KVStyleStringDictionary && obj is IDictionary && obj.GetType().IsGenericType && Reflection.Instance.GetGenericArguments(obj.GetType())[0] == typeof(string)) { WriteStringDictionary((IDictionary)obj); } else if (obj is IDictionary) { WriteDictionary((IDictionary)obj); } else if (obj is byte[]) { WriteBytes((byte[])obj); } else if (obj is StringDictionary) { WriteSD((StringDictionary)obj); } else if (obj is NameValueCollection) { WriteNV((NameValueCollection)obj); } else if (obj is Array) { WriteArrayRanked((Array)obj); } else if (obj is IEnumerable) { WriteArray((IEnumerable)obj); } else if (obj is Enum) { WriteEnum((Enum)obj); } else if (Reflection.Instance.IsTypeRegistered(obj.GetType())) { WriteCustom(obj); } else { WriteObject(obj); } } private void WriteDateTimeOffset(DateTimeOffset d) { DateTime dt = (_params.UseUTCDateTime ? d.UtcDateTime : d.DateTime); write_date_value(dt); long num = dt.Ticks % 10000000; _output.Append('.'); _output.Append(num.ToString("0000000", NumberFormatInfo.InvariantInfo)); if (_params.UseUTCDateTime) { _output.Append('Z'); } else { if (d.Offset.Hours > 0) { _output.Append('+'); } else { _output.Append('-'); } _output.Append(d.Offset.Hours.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(d.Offset.Minutes.ToString("00", NumberFormatInfo.InvariantInfo)); } _output.Append('"'); } private void WriteNV(NameValueCollection nameValueCollection) { _output.Append('{'); bool flag = false; foreach (string item in nameValueCollection) { if (_params.SerializeNullValues || nameValueCollection[item] != null) { if (flag) { _output.Append(','); } if (_params.SerializeToLowerCaseNames) { WritePair(item.ToLowerInvariant(), nameValueCollection[item]); } else { WritePair(item, nameValueCollection[item]); } flag = true; } } _output.Append('}'); } private void WriteSD(StringDictionary stringDictionary) { _output.Append('{'); bool flag = false; foreach (DictionaryEntry item in stringDictionary) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string text = (string)item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(text.ToLowerInvariant(), item.Value); } else { WritePair(text, item.Value); } flag = true; } } _output.Append('}'); } private void WriteCustom(object obj) { Reflection.Instance._customSerializer.TryGetValue(obj.GetType(), out var value); WriteStringFast(value(obj)); } private void WriteEnum(Enum e) { if (_params.UseValuesOfEnums) { WriteValue(Convert.ToInt32(e)); } else { WriteStringFast(e.ToString()); } } private void WriteGuid(Guid g) { if (!_params.UseFastGuid) { WriteStringFast(g.ToString()); } else { WriteBytes(g.ToByteArray()); } } private void WriteBytes(byte[] bytes) { WriteStringFast(Convert.ToBase64String(bytes, 0, bytes.Length, Base64FormattingOptions.None)); } private void WriteDateTime(DateTime dateTime) { DateTime dt = dateTime; if (_params.UseUTCDateTime) { dt = dateTime.ToUniversalTime(); } write_date_value(dt); if (_params.DateTimeMilliseconds) { _output.Append('.'); _output.Append(dt.Millisecond.ToString("000", NumberFormatInfo.InvariantInfo)); } if (_params.UseUTCDateTime) { _output.Append('Z'); } _output.Append('"'); } private void write_date_value(DateTime dt) { _output.Append('"'); _output.Append(dt.Year.ToString("0000", NumberFormatInfo.InvariantInfo)); _output.Append('-'); _output.Append(dt.Month.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append('-'); _output.Append(dt.Day.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append('T'); _output.Append(dt.Hour.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(dt.Minute.ToString("00", NumberFormatInfo.InvariantInfo)); _output.Append(':'); _output.Append(dt.Second.ToString("00", NumberFormatInfo.InvariantInfo)); } private void WriteObject(object obj) { int value = 0; if (!_cirobj.TryGetValue(obj, out value)) { _cirobj.Add(obj, _cirobj.Count + 1); } else if (_current_depth > 0 && !_params.InlineCircularReferences) { _output.Append("{\"$i\":"); _output.Append(value.ToString()); _output.Append('}'); return; } if (!_params.UsingGlobalTypes) { _output.Append('{'); } else if (!_TypesWritten) { _output.Append('{'); _before = _output.Length; } else { _output.Append('{'); } _TypesWritten = true; _current_depth++; if (_current_depth > _MAX_DEPTH) { throw new Exception("Serializer encountered maximum depth of " + _MAX_DEPTH); } Dictionary<string, string> dictionary = new Dictionary<string, string>(); Type type = obj.GetType(); bool flag = false; if (_params.UseExtensions) { if (!_params.UsingGlobalTypes) { WritePairFast("$type", Reflection.Instance.GetTypeAssemblyName(type)); } else { int value2 = 0; string typeAssemblyName = Reflection.Instance.GetTypeAssemblyName(type); if (!_globalTypes.TryGetValue(typeAssemblyName, out value2)) { value2 = _globalTypes.Count + 1; _globalTypes.Add(typeAssemblyName, value2); } WritePairFast("$type", value2.ToString()); } flag = true; } Getters[] getters = Reflection.Instance.GetGetters(type, _params.IgnoreAttributes); int num = getters.Length; for (int i = 0; i < num; i++) { Getters getters2 = getters[i]; if (!_params.ShowReadOnlyProperties && getters2.ReadOnly) { continue; } object obj2 = getters2.Getter(obj); if (!_params.SerializeNullValues && (obj2 == null || obj2 is DBNull)) { continue; } if (flag) { _output.Append(','); } if (getters2.memberName != null) { WritePair(getters2.memberName, obj2); } else if (_params.SerializeToLowerCaseNames) { WritePair(getters2.lcName, obj2); } else { WritePair(getters2.Name, obj2); } if (obj2 != null && _params.UseExtensions) { Type type2 = obj2.GetType(); if (type2 == typeof(object)) { dictionary.Add(getters2.Name, type2.ToString()); } } flag = true; } if (dictionary.Count > 0 && _params.UseExtensions) { _output.Append(",\"$map\":"); WriteStringDictionary(dictionary); } _output.Append('}'); _current_depth--; } private void WritePairFast(string name, string value) { WriteStringFast(name); _output.Append(':'); WriteStringFast(value); } private void WritePair(string name, object value) { WriteString(name); _output.Append(':'); WriteValue(value); } private void WriteArray(IEnumerable array) { _output.Append('['); bool flag = false; foreach (object item in array) { if (flag) { _output.Append(','); } WriteValue(item); flag = true; } _output.Append(']'); } private void WriteArrayRanked(Array array) { if (array.Rank == 1) { WriteArray(array); return; } _output.Append('['); bool flag = false; foreach (object item in array) { if (flag) { _output.Append(','); } WriteValue(item); flag = true; } _output.Append(']'); } private void WriteStringDictionary(IDictionary dic) { _output.Append('{'); bool flag = false; foreach (DictionaryEntry item in dic) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string text = (string)item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(text.ToLowerInvariant(), item.Value); } else { WritePair(text, item.Value); } flag = true; } } _output.Append('}'); } private void WriteStringDictionary(IEnumerable<KeyValuePair<string, object>> dic) { _output.Append('{'); bool flag = false; foreach (KeyValuePair<string, object> item in dic) { if (_params.SerializeNullValues || item.Value != null) { if (flag) { _output.Append(','); } string key = item.Key; if (_params.SerializeToLowerCaseNames) { WritePair(key.ToLowerInvariant(), item.Value); } else { WritePair(key, item.Value); } flag = true; } } _output.Append('}'); } private void WriteDictionary(IDictionary dic) { _output.Append('['); bool flag = false; foreach (DictionaryEntry item in dic) { if (flag) { _output.Append(','); } _output.Append('{'); WritePair("k", item.Key); _output.Append(','); WritePair("v", item.Value); _output.Append('}'); flag = true; } _output.Append(']'); } private void WriteStringFast(string s) { _output.Append('"'); _output.Append(s); _output.Append('"'); } private void WriteString(string s) { _output.Append('"'); int num = -1; int length = s.Length; for (int i = 0; i < length; i++) { char c = s[i]; if (_useEscapedUnicode) { if (c >= ' ' && c < '\u0080' && c != '"' && c != '\\') { if (num == -1) { num = i; } continue; } } else if (c != '\t' && c != '\n' && c != '\r' && c != '"' && c != '\\' && c != 0) { if (num == -1) { num = i; } continue; } if (num != -1) { _output.Append(s, num, i - num); num = -1; } switch (c) { case '\t': _output.Append('\\').Append('t'); continue; case '\r': _output.Append('\\').Append('r'); continue; case '\n': _output.Append('\\').Append('n'); continue; case '"': case '\\': _output.Append('\\'); _output.Append(c); continue; case '\0': _output.Append("\\u0000"); continue; } if (_useEscapedUnicode) { _output.Append("\\u"); StringBuilder output = _output; int num2 = c; output.Append(num2.ToString("X4", NumberFormatInfo.InvariantInfo)); } else { _output.Append(c); } } if (num != -1) { _output.Append(s, num, s.Length - num); } _output.Append('"'); } } public sealed class JSONParameters { public bool UseOptimizedDatasetSchema = true; public bool UseFastGuid = true; public bool SerializeNullValues = true; public bool UseUTCDateTime = true; public bool ShowReadOnlyProperties; public bool UsingGlobalTypes = true; [Obsolete("Not needed anymore and will always match")] public bool IgnoreCaseOnDeserialize; public bool EnableAnonymousTypes; public bool UseExtensions = true; public bool UseEscapedUnicode = true; public bool KVStyleStringDictionary; public bool UseValuesOfEnums; public List<Type> IgnoreAttributes = new List<Type> { typeof(XmlIgnoreAttribute), typeof(NonSerializedAttribute) }; public bool ParametricConstructorOverride; public bool DateTimeMilliseconds; public byte SerializerMaxDepth = 20; public bool InlineCircularReferences; public bool SerializeToLowerCaseNames; public byte FormatterIndentSpaces = 3; public bool AllowNonQuotedKeys; public bool AutoConvertStringToNumbers = true; public bool OverrideObjectHashCodeChecking; [Obsolete("Racist term removed, please use BadListTypeChecking")] public bool BlackListTypeChecking = true; public bool BadListTypeChecking = true; public bool FullyQualifiedDataSetSchema; public void FixValues() { if (!UseExtensions) { UsingGlobalTypes = false; InlineCircularReferences = true; } if (EnableAnonymousTypes) { ShowReadOnlyProperties = true; } } public JSONParameters MakeCopy() { return new JSONParameters { AllowNonQuotedKeys = AllowNonQuotedKeys, DateTimeMilliseconds = DateTimeMilliseconds, EnableAnonymousTypes = EnableAnonymousTypes, FormatterIndentSpaces = FormatterIndentSpaces, IgnoreAttributes = new List<Type>(IgnoreAttributes), InlineCircularReferences = InlineCircularReferences, KVStyleStringDictionary = KVStyleStringDictionary, ParametricConstructorOverride = ParametricConstructorOverride, SerializeNullValues = SerializeNullValues, SerializerMaxDepth = SerializerMaxDepth, SerializeToLowerCaseNames = SerializeToLowerCaseNames, ShowReadOnlyProperties = ShowReadOnlyProperties, UseEscapedUnicode = UseEscapedUnicode, UseExtensions = UseExtensions, UseFastGuid = UseFastGuid, UseOptimizedDatasetSchema = UseOptimizedDatasetSchema, UseUTCDateTime = UseUTCDateTime, UseValuesOfEnums = UseValuesOfEnums, UsingGlobalTypes = UsingGlobalTypes, AutoConvertStringToNumbers = AutoConvertStringToNumbers, OverrideObjectHashCodeChecking = OverrideObjectHashCodeChecking, FullyQualifiedDataSetSchema = FullyQualifiedDataSetSchema, BadListTypeChecking = BadListTypeChecking }; } } public static class JSON { public static JSONParameters Parameters = new JSONParameters(); public static string ToNiceJSON(object obj) { string input = ToJSON(obj, Parameters); return Beautify(input); } public static string ToNiceJSON(object obj, JSONParameters param) { string input = ToJSON(obj, param); return Beautify(input, param.FormatterIndentSpaces); } public static string ToJSON(object obj) { return ToJSON(obj, Parameters); } public static string ToJSON(object obj, JSONParameters param) { param.FixValues(); param = param.MakeCopy(); Type c = null; if (obj == null) { return "null"; } if (obj.GetType().IsGenericType) { c = Reflection.Instance.GetGenericTypeDefinition(obj.GetType()); } if (typeof(IDictionary).IsAssignableFrom(c) || typeof(List<>).IsAssignableFrom(c)) { param.UsingGlobalTypes = false; } if (param.EnableAnonymousTypes) { param.UseExtensions = false; param.UsingGlobalTypes = false; } return new JSONSerializer(param).ConvertToJSON(obj); } public static object Parse(string json) { return new JsonParser(json, Parameters.AllowNonQuotedKeys).Decode(null); } public static dynamic ToDynamic(string json) { return new DynamicJson(json); } public static T ToObject<T>(string json) { return new deserializer(Parameters).ToObject<T>(json); } public static T ToObject<T>(string json, JSONParameters param) { return new deserializer(param).ToObject<T>(json); } public static object ToObject(string json) { return new deserializer(Parameters).ToObject(json, null); } public static object ToObject(string json, JSONParameters param) { return new deserializer(param).ToObject(json, null); } public static object ToObject(string json, Type type) { return new deserializer(Parameters).ToObject(json, type); } public static object ToObject(string json, Type type, JSONParameters par) { return new deserializer(par).ToObject(json, type); } public static object FillObject(object input, string json) { if (!(new JsonParser(json, Parameters.AllowNonQuotedKeys).Decode(input.GetType()) is Dictionary<string, object> d)) { return null; } return new deserializer(Parameters).ParseDictionary(d, null, input.GetType(), input); } public static object DeepCopy(object obj) { return new deserializer(Parameters).ToObject(ToJSON(obj)); } public static T DeepCopy<T>(T obj) { return new deserializer(Parameters).ToObject<T>(ToJSON(obj)); } public static string Beautify(string input) { string spaces = new string(' ', Parameters.FormatterIndentSpaces); return Formatter.PrettyPrint(input, spaces); } public static string Beautify(string input, byte spaces) { string spaces2 = new string(' ', spaces); return Formatter.PrettyPrint(input, spaces2); } public static void RegisterCustomType(Type type, Reflection.Serialize serializer, Reflection.Deserialize deserializer) { Reflection.Instance.RegisterCustomType(type, serializer, deserializer); } public static void ClearReflectionCache() { Reflection.Instance.ClearReflectionCache(); } } internal class deserializer { private JSONParameters _params; private bool _usingglobals; private Dictionary<object, int> _circobj; private Dictionary<int, object> _cirrev = new Dictionary<int, object>(); public deserializer(JSONParameters param) { if (param.OverrideObjectHashCodeChecking) { _circobj = new Dictionary<object, int>(10, ReferenceEqualityComparer.Default); } else { _circobj = new Dictionary<object, int>(); } param.FixValues(); _params = param.MakeCopy(); } public T ToObject<T>(string json) { Type typeFromHandle = typeof(T); object obj = ToObject(json, typeFromHandle); if (typeFromHandle.IsArray) { if ((obj as ICollection).Count == 0) { Type elementType = typeFromHandle.GetElementType(); object obj2 = Array.CreateInstance(elementType, 0); return (T)obj2; } return (T)obj; } return (T)obj; } public object ToObject(string json) { return ToObject(json, null); } public object ToObject(string json, Type type) { Type type2 = null; if (type != null && type.IsGenericType) { type2 = Reflection.Instance.GetGenericTypeDefinition(type); } _usingglobals = _params.UsingGlobalTypes; if (typeof(IDictionary).IsAssignableFrom(type2) || typeof(List<>).IsAssignableFrom(type2)) { _usingglobals = false; } object obj = new JsonParser(json, _params.AllowNonQuotedKeys).Decode(type); if (obj == null) { return null; } if (obj is IDictionary) { if (type != null && typeof(Dictionary<, >).IsAssignableFrom(type2)) { return RootDictionary(obj, type); } return ParseDictionary(obj as Dictionary<string, object>, null, type, null); } if (obj is List<object>) { if (!(type != null)) { List<object> list = (List<object>)obj; if (list.Count > 0 && list[0].GetType() == typeof(Dictionary<string, object>)) { Dictionary<string, object> globaltypes = new Dictionary<string, object>(); List<object> list2 = new List<object>(); { foreach (object item in list) { list2.Add(ParseDictionary((Dictionary<string, object>)item, globaltypes, null, null)); } return list2; } } return list.ToArray(); } if (typeof(Dictionary<, >).IsAssignableFrom(type2)) { return RootDictionary(obj, type); } if (type2 == typeof(List<>)) { return RootList(obj, type); } if (type.IsArray) { return RootArray(obj, type); } if (type == typeof(Hashtable)) { return RootHashTable((List<object>)obj); } } else if (type != null && obj.GetType() != type) { return ChangeType(obj, type); } return obj; } private object RootHashTable(List<object> o) { Hashtable hashtable = new Hashtable(); foreach (Dictionary<string, object> item in o) { object obj = item["k"]; object obj2 = item["v"]; if (obj is Dictionary<string, object>) { obj = ParseDictionary((Dictionary<string, object>)obj, null, typeof(object), null); } if (obj2 is Dictionary<string, object>) { obj2 = ParseDictionary((Dictionary<string, object>)obj2, null, typeof(object), null); } hashtable.Add(obj, obj2); } return hashtable; } private object ChangeType(object value, Type conversionType) { if (conversionType == typeof(object)) { return value; } if (conversionType == typeof(int)) { if (!(value is string text)) { return (int)(long)value; } if (_params.AutoConvertStringToNumbers) { return Helper.CreateInteger(text, 0, text.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (conversionType == typeof(long)) { if (!(value is string text2)) { return (long)value; } if (_params.AutoConvertStringToNumbers) { return Helper.CreateLong(text2, 0, text2.Length); } throw new Exception("AutoConvertStringToNumbers is disabled for converting string : " + value); } if (conversionType == typeof(string)) { return (string)value; } if (conversionType.IsEnum) { return Helper.CreateEnum(conversionType, value); } if (conversionType == typeof(DateTime)) { return Helper.CreateDateTime((string)value, _params.UseUTCDateTime); } if (conversionType == typeof(DateTimeOffset)) { return Helper.CreateDateTimeOffset((string)value); } if (Reflection.Instance.IsTypeRegistered(conversionType)) { return Reflection.Instance.CreateCustom((string)value, conversionType); } if (Helper.IsNullable(conversionType)) { if (value == null) { return value; } conversionType = Helper.UnderlyingTypeOf(conversionType); } if (conversionType == typeof(Guid)) { return Helper.CreateGuid((string)value); } if (conversionType == typeof(byte[])) { return Convert.FromBase64String((string)value); } if (conversionType == typeof(TimeSpan)) { return new TimeSpan((long)value); } return Convert.ChangeType(value, conversionType, CultureInfo.InvariantCulture); } private object RootList(object parse, Type type) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type); IList list = (IList)Reflection.Instance.FastCreateList(type, ((IList)parse).Count); DoParseList((IList)parse, genericArguments[0], list); return list; } private void DoParseList(IList parse, Type it, IList o) { Dictionary<string, object> globaltypes = new Dictionary<string, object>(); foreach (object item in parse) { _usingglobals = false; object obj = item; obj = ((!(item is Dictionary<string, object> d)) ? ChangeType(item, it) : ParseDictionary(d, globaltypes, it, null)); o.Add(obj); } } private object RootArray(object parse, Type type) { Type elementType = type.GetElementType(); IList list = (IList)Reflection.Instance.FastCreateInstance(typeof(List<>).MakeGenericType(elementType)); DoParseList((IList)parse, elementType, list); Array array = Array.CreateInstance(elementType, list.Count); list.CopyTo(array, 0); return array; } private object RootDictionary(object parse, Type type) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type); Type type2 = null; Type type3 = null; bool flag = false; if (genericArguments != null) { type2 = genericArguments[0]; type3 = genericArguments[1]; if (type3 != null) { flag = type3.Name.StartsWith("Dictionary"); } } Type elementType = type3.GetElementType(); if (parse is Dictionary<string, object>) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(type); { foreach (KeyValuePair<string, object> item in (Dictionary<string, object>)parse) { object key = ChangeType(item.Key, type2); object value = ((!flag) ? ((!(item.Value is Dictionary<string, object>)) ? ((type3.IsArray && type3 != typeof(byte[])) ? CreateArray((List<object>)item.Value, type3, elementType, null) : ((!(item.Value is IList)) ? ChangeType(item.Value, type3) : CreateGenericList((List<object>)item.Value, type3, type2, null))) : ParseDictionary(item.Value as Dictionary<string, object>, null, type3, null)) : RootDictionary(item.Value, type3)); dictionary.Add(key, value); } return dictionary; } } if (parse is List<object>) { return CreateDictionary(parse as List<object>, type, genericArguments, null); } return null; } internal object ParseDictionary(Dictionary<string, object> d, Dictionary<string, object> globaltypes, Type type, object input) { object value = ""; if (type == typeof(NameValueCollection)) { return Helper.CreateNV(d); } if (type == typeof(StringDictionary)) { return Helper.CreateSD(d); } if (d.TryGetValue("$i", out value)) { object value2 = null; _cirrev.TryGetValue((int)(long)value, out value2); return value2; } if (d.TryGetValue("$types", out value)) { _usingglobals = true; if (globaltypes == null) { globaltypes = new Dictionary<string, object>(); } foreach (KeyValuePair<string, object> item in (Dictionary<string, object>)value) { globaltypes.Add((string)item.Value, item.Key); } } if (globaltypes != null) { _usingglobals = true; } bool flag = d.TryGetValue("$type", out value); if (!flag && type == typeof(object)) { return d; } if (flag) { if (_usingglobals) { object value3 = ""; if (globaltypes != null && globaltypes.TryGetValue((string)value, out value3)) { value = value3; } } type = Reflection.Instance.GetTypeFromCache((string)value, _params.BadListTypeChecking); } if (type == null) { throw new Exception("Cannot determine type : " + value); } string fullName = type.FullName; object obj = input; if (obj == null) { obj = ((!_params.ParametricConstructorOverride) ? Reflection.Instance.FastCreateInstance(type) : FormatterServices.GetUninitializedObject(type)); } int value4 = 0; if (!_circobj.TryGetValue(obj, out value4)) { value4 = _circobj.Count + 1; _circobj.Add(obj, value4); _cirrev.Add(value4, obj); } Dictionary<string, myPropInfo> dictionary = Reflection.Instance.Getproperties(type, fullName, _params.ShowReadOnlyProperties); foreach (KeyValuePair<string, object> item2 in d) { string key = item2.Key; object value5 = item2.Value; string text = key; if (text == "$map") { ProcessMap(obj, dictionary, (Dictionary<string, object>)d[text]); } else { if ((!dictionary.TryGetValue(text, out var value6) && !dictionary.TryGetValue(text.ToLowerInvariant(), out value6)) || !value6.CanWrite) { continue; } object value7 = null; if (value5 != null) { switch (value6.Type) { case myPropInfoType.Int: value7 = (int)Helper.AutoConv(value5, _params); break; case myPropInfoType.Long: value7 = Helper.AutoConv(value5, _params); break; case myPropInfoType.String: value7 = value5.ToString(); break; case myPropInfoType.Bool: value7 = Helper.BoolConv(value5); break; case myPropInfoType.DateTime: value7 = Helper.CreateDateTime((string)value5, _params.UseUTCDateTime); break; case myPropInfoType.Enum: value7 = Helper.CreateEnum(value6.pt, value5); break; case myPropInfoType.Guid: value7 = Helper.CreateGuid((string)value5); break; case myPropInfoType.Array: if (!value6.IsValueType) { value7 = CreateArray((List<object>)value5, value6.pt, value6.bt, globaltypes); } break; case myPropInfoType.ByteArray: value7 = Convert.FromBase64String((string)value5); break; case myPropInfoType.Dictionary: value7 = CreateDictionary((List<object>)value5, value6.pt, value6.GenericTypes, globaltypes); break; case myPropInfoType.StringKeyDictionary: value7 = CreateStringKeyDictionary((Dictionary<string, object>)value5, value6.pt, value6.GenericTypes, globaltypes); break; case myPropInfoType.NameValue: value7 = Helper.CreateNV((Dictionary<string, object>)value5); break; case myPropInfoType.StringDictionary: value7 = Helper.CreateSD((Dictionary<string, object>)value5); break; case myPropInfoType.Custom: value7 = Reflection.Instance.CreateCustom((string)value5, value6.pt); break; default: value7 = ((value6.IsGenericType && !value6.IsValueType && value5 is List<object>) ? CreateGenericList((List<object>)value5, value6.pt, value6.bt, globaltypes) : (((value6.IsClass || value6.IsStruct || value6.IsInterface) && value5 is Dictionary<string, object>) ? ParseDictionary((Dictionary<string, object>)value5, globaltypes, value6.pt, null) : ((!(value5 is List<object>)) ? ((!value6.IsValueType) ? value5 : ChangeType(value5, value6.changeType)) : CreateArray((List<object>)value5, value6.pt, typeof(object), globaltypes)))); break; } } obj = value6.setter(obj, value7); } } return obj; } private static void ProcessMap(object obj, Dictionary<string, myPropInfo> props, Dictionary<string, object> dic) { foreach (KeyValuePair<string, object> item in dic) { myPropInfo myPropInfo2 = props[item.Key]; object obj2 = myPropInfo2.getter(obj); Type typeFromCache = Reflection.Instance.GetTypeFromCache((string)item.Value, badlistChecking: true); if (typeFromCache == typeof(Guid)) { myPropInfo2.setter(obj, Helper.CreateGuid((string)obj2)); } } } private object CreateArray(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes) { if (bt == null) { bt = typeof(object); } Array array = Array.CreateInstance(bt, data.Count); Type elementType = bt.GetElementType(); for (int i = 0; i < data.Count; i++) { object obj = data[i]; if (obj != null) { if (obj is IDictionary) { array.SetValue(ParseDictionary((Dictionary<string, object>)obj, globalTypes, bt, null), i); } else if (obj is ICollection) { array.SetValue(CreateArray((List<object>)obj, bt, elementType, globalTypes), i); } else { array.SetValue(ChangeType(obj, bt), i); } } } return array; } private object CreateGenericList(List<object> data, Type pt, Type bt, Dictionary<string, object> globalTypes) { if (pt != typeof(object)) { IList list = (IList)Reflection.Instance.FastCreateList(pt, data.Count); Type type = Reflection.Instance.GetGenericArguments(pt)[0]; { foreach (object datum in data) { if (datum is IDictionary) { list.Add(ParseDictionary((Dictionary<string, object>)datum, globalTypes, type, null)); } else if (datum is List<object>) { if (bt.IsGenericType) { list.Add((List<object>)datum); } else { list.Add(((List<object>)datum).ToArray()); } } else { list.Add(ChangeType(datum, type)); } } return list; } } return data; } private object CreateStringKeyDictionary(Dictionary<string, object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(pt); Type type = null; Type type2 = null; if (types != null) { type2 = types[1]; } Type bt = null; Type[] genericArguments = Reflection.Instance.GetGenericArguments(type2); if (genericArguments.Length != 0) { bt = genericArguments[0]; } type = type2.GetElementType(); foreach (KeyValuePair<string, object> item in reader) { string key = item.Key; object obj = null; obj = ((!(item.Value is Dictionary<string, object>)) ? ((types != null && type2.IsArray) ? ((!(item.Value is Array)) ? CreateArray((List<object>)item.Value, type2, type, globalTypes) : item.Value) : ((!(item.Value is IList)) ? ChangeType(item.Value, type2) : CreateGenericList((List<object>)item.Value, type2, bt, globalTypes))) : ParseDictionary((Dictionary<string, object>)item.Value, globalTypes, type2, null)); dictionary.Add(key, obj); } return dictionary; } private object CreateDictionary(List<object> reader, Type pt, Type[] types, Dictionary<string, object> globalTypes) { IDictionary dictionary = (IDictionary)Reflection.Instance.FastCreateInstance(pt); Type type = null; Type type2 = null; Type bt = null; if (types != null) { type = types[0]; type2 = types[1]; } Type bt2 = type2; if (type2 != null) { Type[] genericArguments = Reflection.Instance.GetGenericArguments(type2); if (genericArguments.Length != 0) { bt = genericArguments[0]; } bt2 = type2.GetElementType(); } bool flag = typeof(IDictionary).IsAssignableFrom(type2); foreach (Dictionary<string, object> item in reader) { object obj = item["k"]; object obj2 = item["v"]; obj = ((!(obj is Dictionary<string, object>)) ? ChangeType(obj, type) : ParseDictionary((Dictionary<string, object>)obj, globalTypes, type, null)); obj2 = ((!flag) ? ((!(obj2 is Dictionary<string, object>)) ? ((types != null && type2.IsArray) ? CreateArray((List<object>)obj2, type2, bt2, globalTypes) : ((!(obj2 is IList)) ? ChangeType(obj2, type2) : CreateGenericList((List<object>)obj2, type2, bt, globalTypes))) : ParseDictionary((Dictionary<string, object>)obj2, globalTypes, type2, null)) : RootDictionary(obj2, type2)); dictionary.Add(obj, obj2); } return dictionary; } } internal sealed class JsonParser { private enum Token { None = -1, Curly_Open, Curly_Close, Squared_Open, Squared_Close, Colon, Comma, String, Number, True, False, Null, PosInfinity, NegInfinity, NaN } private readonly char[] json; private readonly StringBuilder s = new StringBuilder(); private Token lookAheadToken = Token.None; private int index; private bool allownonquotedkey; private int _len; private SafeDictionary<string, bool> _lookup; private SafeDictionary<Type, bool> _seen; private bool _parseJsonType; private bool _parseType; internal JsonParser(string json, bool AllowNonQuotedKeys) { allownonquotedkey = AllowNonQuotedKeys; this.json = json.ToCharArray(); _len = json.Length; } private void SetupLookup() { _lookup = new SafeDictionary<string, bool>(); _seen = new SafeDictionary<Type, bool>(); _lookup.Add("$types", value: true); _lookup.Add("$type", value: true); _lookup.Add("$i", value: true); _lookup.Add("$map", value: true); _lookup.Add("$schema", value: true); _lookup.Add("k", value: true); _lookup.Add("v", value: true); } public unsafe object Decode(Type objtype) { fixed (char* p = json) { if (objtype != null && !CheckForTypeInJson(p)) { _parseJsonType = true; SetupLookup(); BuildLookup(objtype); if (!_parseJsonType || _lookup.Count() == 7) { _lookup = null; } } return ParseValue(p); } } private unsafe bool CheckForTypeInJson(char* p) { int i = 0; for (int num = ((_len > 1000) ? 1000 : _len); i < num; i++) { if (p[i] == '$' && p[i + 1] == 't' && p[i + 2] == 'y' && p[i + 3] == 'p' && p[i + 4] == 'e' && p[i + 5] == 's') { return true; } } return false; } private void BuildGenericTypeLookup(Type t) { if (_seen.TryGetValue(t, out var _)) { return; } Type[] genericArguments = t.GetGenericArguments(); foreach (Type type in genericArguments) { if (!type.IsPrimitive) { bool flag = type.IsValueType && !type.IsEnum; if ((type.IsClass || flag || type.IsAbstract) && type != typeof(string) && type != typeof(DateTime) && type != typeof(Guid)) { BuildLookup(type); } } } } private void BuildArrayTypeLookup(Type t) { if (!_seen.TryGetValue(t, out var _)) { bool flag = t.IsValueType && !t.IsEnum; if ((t.IsClass || flag) && t != typeof(string) && t != typeof(DateTime) && t != typeof(Guid)) { BuildLookup(t.GetElementType()); } } } private void BuildLookup(Type objtype) { if (objtype == null || objtype == typeof(NameValueCollection) || objtype == typeof(StringDictionary) || typeof(IDictionary).IsAssignableFrom(objtype) || _seen.TryGetValue(objtype, out var _)) { return; } if (objtype.IsGenericType) { BuildGenericTypeLookup(objtype); return; } if (objtype.IsArray) { BuildArrayTypeLookup(objtype); return; } _seen.Add(objtype, value: true); foreach (KeyValuePair<string, myPropInfo> item in Reflection.Instance.Getproperties(objtype, objtype.FullName, ShowReadOnlyProperties: true)) { Type pt = item.Value.pt; _lookup.Add(item.Key, value: true); if (pt.IsArray) { BuildArrayTypeLookup(pt); } if (pt.IsGenericType) { if (typeof(IDictionary).IsAssignableFrom(pt)) { _parseJsonType = false; break; } BuildGenericTypeLookup(pt); } if (pt.FullName.IndexOf("System.") == -1) { BuildLookup(pt); } } } private bool InLookup(string name) { if (_lookup == null) { return true; } bool value; return _lookup.TryGetValue(name.ToLowerInvariant(), out value); } private unsafe Dictionary<string, object> ParseObject(char* p) { Dictionary<string, object> dictionary = new Dictionary<string, object>(); ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); continue; case Token.Curly_Close: ConsumeToken(); return dictionary; } string text = ParseKey(p); Token token = NextToken(p); if (token != Token.Colon) { throw new Exception("Expected colon at index " + index); } if (_parseJsonType) { if (text == "$types") { _parseType = true; Dictionary<string, object> dictionary2 = (Dictionary<string, object>)ParseValue(p); _parseType = false; if (_lookup == null) { SetupLookup(); } foreach (string key in dictionary2.Keys) { BuildLookup(Reflection.Instance.GetTypeFromCache(key, badlistChecking: true)); } dictionary[text] = dictionary2; } else if (text == "$schema") { _parseType = true; object value = ParseValue(p); _parseType = false; dictionary[text] = value; } else if (_parseType || InLookup(text)) { dictionary[text] = ParseValue(p); } else { SkipValue(p); } } else { dictionary[text] = ParseValue(p); } } } private unsafe void SkipValue(char* p) { switch (LookAhead(p)) { case Token.Number: ParseNumber(p, skip: true); break; case Token.String: SkipString(p); break; case Token.Curly_Open: SkipObject(p); break; case Token.Squared_Open: SkipArray(p); break; case Token.True: case Token.False: case Token.Null: case Token.PosInfinity: case Token.NegInfinity: case Token.NaN: ConsumeToken(); break; case Token.Curly_Close: case Token.Squared_Close: case Token.Colon: case Token.Comma: break; } } private unsafe void SkipObject(char* p) { ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); continue; case Token.Curly_Close: ConsumeToken(); return; } SkipString(p); Token token = NextToken(p); if (token != Token.Colon) { throw new Exception("Expected colon at index " + index); } SkipValue(p); } } private unsafe void SkipArray(char* p) { ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); break; case Token.Squared_Close: ConsumeToken(); return; default: SkipValue(p); break; } } } private unsafe void SkipString(char* p) { ConsumeToken(); int len = _len; while (index < len) { switch (p[index++]) { case '"': return; case '\\': { char c = p[index++]; if (c == 'u') { index += 4; } break; } } } } private unsafe List<object> ParseArray(char* p) { List<object> list = new List<object>(); ConsumeToken(); while (true) { switch (LookAhead(p)) { case Token.Comma: ConsumeToken(); break; case Token.Squared_Close: ConsumeToken(); return list; default: list.Add(ParseValue(p)); break; } } } private unsafe object ParseValue(char* p) { switch (LookAhead(p)) { case Token.Number: return ParseNumber(p, skip: false); case Token.String: return ParseString(p); case Token.Curly_Open: return ParseObject(p); case Token.Squared_Open: return ParseArray(p); case Token.True: ConsumeToken(); return true; case Token.False: ConsumeToken(); return false; case Token.Null: ConsumeToken(); return null; case Token.PosInfinity: ConsumeToken(); return double.PositiveInfinity; case Token.NegInfinity: ConsumeToken(); return double.NegativeInfinity; case Token.NaN: ConsumeToken(); return double.NaN; default: throw new Exception("Unrecognized token at index " + index); } } private unsafe string ParseKey(char* p) { if (!allownonquotedkey || p[index - 1] == '"') { return ParseString(p); } ConsumeToken(); int len = _len; int num = 0; while (index + num < len) { char c = p[index + num++]; if (c == ':') { string result = UnsafeSubstring(p, index, num - 1).Trim(); index += num - 1; return result; } } throw new Exception("Unable to read key"); } private unsafe string ParseString(char* p) { char c = p[index - 1]; ConsumeToken(); if (s.Length > 0) { s.Length = 0; } int len = _len; int num = 0; while (index + num < len) { char c2 = p[index + num++]; if (c2 == '\\') { break; } if (c2 == c) { string result = UnsafeSubstring(p, index, num - 1); index += num; return result; } } while (index < len) { char c3 = p[index++]; if (c3 == c) { return s.ToString(); } if (c3 != '\\') { s.Append(c3); continue; } c3 = p[index++]; switch (c3) { case 'b': s.Append('\b'); continue; case 'f': s.Append('\f'); continue; case 'n': s.Append('\n'); continue; case 'r': s.Append('\r'); continue; case 't': s.Append('\t'); continue; case 'u': { uint num2 = ParseUnicode(p[index], p[index + 1], p[index + 2], p[index + 3]); s.Append((char)num2); index += 4; continue; } } if (c3 == '\r' || c3 == '\n' || c3 == ' ' || c3 == '\t') { while (c3 == '\r' || c3 == '\n' || c3 == ' ' || c3 == '\t') { index++; c3 = p[index]; if (c3 == '\r' || c3 == '\n') { c3 = p[index + 1]; if (c3 == '\r' || c3 == '\n') { index += 2; c3 = p[index]; } break; } } } else { s.Append(c3); } } return s.ToString(); } private unsafe string ParseJson5String(char* p) { throw new NotImplementedException(); } private uint ParseSingleChar(char c1, uint multipliyer) { uint result = 0u; if (c1 >= '0' && c1 <= '9') { result = (uint)(c1 - 48) * multipliyer; } else if (c1 >= 'A' && c1 <= 'F') { result = (uint)(c1 - 65 + 10) * multipliyer; } else if (c1 >= 'a' && c1 <= 'f') { result = (uint)(c1 - 97 + 10) * multipliyer; } return result; } private uint ParseUnicode(char c1, char c2, char c3, char c4) { uint num = ParseSingleChar(c1, 4096u); uint num2 = ParseSingleChar(c2, 256u); uint num3 = ParseSingleChar(c3, 16u); uint num4 = ParseSingleChar(c4, 1u); return num + num2 + num3 + num4; } private unsafe object ParseNumber(char* p, bool skip) { ConsumeToken(); int num = index - 1; bool flag = false; bool flag2 = false; bool flag3 = true; if (p[num] == '.') { flag = true; } while (index != _len) { switch (p[index]) { case 'X': case 'x': index++; return ReadHexNumber(p); case '+': case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index++; break; case 'E': case 'e': flag2 = true; index++; break; case '.': index++; flag = true; break; case 'N': case 'n': index += 3; return double.NaN; default: flag3 = false; break; } if (index == _len) { flag3 = false; } if (!flag3) { break; } } if (skip) { return 0; } int num2 = index - num; if (flag2 || num2 > 31) { string text = UnsafeSubstring(p, num, num2); return double.Parse(text, NumberFormatInfo.InvariantInfo); } if (!flag && num2 < 20) { return Helper.CreateLong(json, num, num2); } string text2 = UnsafeSubstring(p, num, num2); return decimal.Parse(text2, NumberFormatInfo.InvariantInfo); } private unsafe object ReadHexNumber(char* p) { long num = 0L; bool flag = true; while (flag && index < _len) { char c = p[index]; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': index++; num = (num << 4) + (c - 48); break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': index++; num = (num << 4) + (c - 97) + 10; break; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': index++; num = (num << 4) + (c - 65) + 10; break; default: flag = false; break; } } return num; } private unsafe Token LookAhead(char* p) { if (lookAheadToken != Token.None) { return lookAheadToken; } return lookAheadToken = NextTokenCore(p); } private void ConsumeToken() { lookAheadToken = Token.None; } private unsafe Token NextToken(char* p) { Token result = ((lookAheadToken != Token.None) ? lookAheadToken : NextTokenCore(p)); lookAheadToken = Token.None; return result; } private unsafe void SkipWhitespace(char* p) { char c; do { c = p[index]; if (c == '/' && p[index + 1] == '/') { index++; index++; do { c = p[index]; } while (c != '\r' && c != '\n' && ++index < _len); } if (c != '/' || p[index + 1] != '*') { continue; } index++; index++; do { c = p[index]; if (c == '*' && p[index + 1] == '/') { index += 2; c = p[index]; break; } } while (++index < _len); } while ((c == ' ' || c == '\t' || c == '\n' || c == '\r') && ++index < _len); } private unsafe Token NextTokenCore(char* p) { int len = _len; SkipWhitespace(p); if (index == len) { throw new Exception("Reached end of string unexpectedly"); } char c = p[index]; index++; switch (c) { case '{': return Token.Curly_Open; case '}': return Token.Curly_Close; case '[': return Token.Squared_Open; case ']': return Token.Squared_Close; case ',': return Token.Comma; case '"': case '\'': return Token.String; case '-': if (p[index] == 'i' || p[index] == 'I') { index += 8; return Token.NegInfinity; } return Token.Number; case '+': if (p[index] == 'i' || p[index] == 'I') { index += 8; return Token.PosInfinity; } return Token.Number; case '.': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return Token.Number; case ':': return Token.Colon; case 'I': case 'i': index += 7; return Token.PosInfinity; case 'f': if (len - index >= 4 && p[index] == 'a' && p[index + 1] == 'l' && p[index + 2] == 's' && p[index + 3] == 'e') { index += 4; return Token.False; } break; case 't': if (len - index >= 3 && p[index] == 'r' && p[index + 1] == 'u' && p[index + 2] == 'e') { index += 3; return Token.True; } break; case 'N': case 'n': if (len - index >= 3 && p[index] == 'u' && p[index + 1] == 'l' && p[index + 2] == 'l') { index += 3; return Token.Null; } if (len - index >= 2 && p[index] == 'a' && (p[index + 1] == 'n' || p[index + 1] == 'N')) { index += 2; return Token.NaN; } break; } if (allownonquotedkey) { index--; return Token.String; } throw new Exception("Could not find token at index " + --index + " got '" + p[index].ToString() + "'"); } private unsafe static string UnsafeSubstring(char* p, int startIndex, int length) { return new string(p, startIndex, length); } } public struct Getters { public string Name; public string lcName; public string memberName; public Reflection.GenericGetter Getter; public bool ReadOnly; } public enum myPropInfoType { Int, Long, String, Bool, DateTime, Enum, Guid, Array, ByteArray, Dictionary, StringKeyDictionary, NameValue, StringDictionary, Hashtable, DataSet, DataTable, Custom, Unknown } public class myPropInfo { public Type pt; public Type bt; public Type changeType; public Reflection.GenericSetter setter; public Reflection.GenericGetter getter; public Type[] GenericTypes; public string Name; public string memberName; public myPropInfoType Type; public bool CanWrite; public bool IsClass; public bool IsValueType; public bool IsGenericType; public bool IsStruct; public bool IsInterface; } public sealed class Reflection { public delegate string Serialize(object data); public delegate object Deserialize(string data); public delegate object GenericSetter(object target, object value); public delegate object GenericGetter(object obj); private delegate object CreateObject(); private delegate object CreateList(int capacity); private static readonly Reflection instance; public static bool RDBMode; private SafeDictionary<Type, string> _tyname = new SafeDictionary<Type, string>(10); private SafeDictionary<string, Type> _typecache = new SafeDictionary<string, Type>(10); private SafeDictionary<Type, CreateObject> _constrcache = new SafeDictionary<Type, CreateObject>(10); private SafeDictionary<Type, CreateList> _conlistcache = new SafeDictionary<Type, CreateList>(10); private SafeDictionary<Type, Getters[]> _getterscache = new SafeDictionary<Type, Getters[]>(10); private SafeDictionary<string, Dictionary<string, myPropInfo>> _propertycache = new SafeDictionary<string, Dictionary<string, myPropInfo>>(10); private SafeDictionary<Type, Type[]> _genericTypes = new SafeDictionary<Type, Type[]>(10); private SafeDictionary<Type, Type> _genericTypeDef = new SafeDictionary<Type, Type>(10); private static SafeDictionary<short, OpCode> _opCodes; private static List<string> _badlistTypes; private static UTF8Encoding utf8; internal SafeDictionary<Type, Serialize> _customSerializer = new SafeDictionary<Type, Serialize>(); internal SafeDictionary<Type, Deserialize> _customDeserializer = new SafeDictionary<Type, Deserialize>(); public static Reflection Instance => instance; static Reflection() { instance = new Reflection(); RDBMode = false; _badlistTypes = new List<string> { "system.configuration.install.assemblyinstaller", "system.activities.presentation.workflowdesigner", "system.windows.resourcedictionary", "system.windows.data.objectdataprovider", "system.windows.forms.bindingsource", "microsoft.exchange.management.systemmanager.winforms.exchangesettingsprovider" }; utf8 = new UTF8Encoding(); } private Reflection() { } private static bool TryGetOpCode(short code, out OpCode opCode) { if (_opCodes != null) { return _opCodes.TryGetValue(code, out opCode); } SafeDictionary<short, OpCode> safeDictionary = new SafeDictionary<short, OpCode>(); FieldInfo[] fields = typeof(OpCodes).GetFields(BindingFlags.Static | BindingFlags.Public); foreach (FieldInfo fieldInfo in fields) { if (typeof(OpCode).IsAssignableFrom(fieldInfo.FieldType)) { OpCode value = (OpCode)fieldInfo.GetValue(null); if (value.OpCodeType != OpCodeType.Nternal) { safeDictionary.Add(value.Value, value); } } } _opCodes = safeDictionary; return _opCodes.TryGetValue(code, out opCode); } public static byte[] UTF8GetBytes(string str) { return utf8.GetBytes(str); } public static string UTF8GetString(byte[] bytes, int offset, int len) { return utf8.GetString(bytes, offset, len); } public unsafe static byte[] UnicodeGetBytes(string str) { int num = str.Length * 2; byte[] array = new byte[num]; fixed (void* value = str) { Marshal.Copy(new IntPtr(value), array, 0, num); } return array; } public static string UnicodeGetString(byte[] b) { return UnicodeGetString(b, 0, b.Length); } public unsafe static string UnicodeGetString(byte[] bytes, int offset, int buflen) { string text = ""; fixed (byte* ptr = bytes) { char* value = (char*)(ptr + offset); text = new string(value, 0, buflen / 2); } return text; } internal object CreateCustom(string v, Type type) { _customDeserializer.TryGetValue(type, out var value); return value(v); } internal void RegisterCustomType(Type type, Serialize serializer, Deserialize deserializer) { if (type != null && serializer != null && deserializer != null) { _customSerializer.Add(type, serializer); _customDeserializer.Add(type, deserializer); Instance.ResetPropertyCache(); } } internal bool IsTypeRegistered(Type t) { if (_customSerializer.Count() == 0) { return false; } Serialize value; return _customSerializer.TryGetValue(t, out value); } public Type GetGenericTypeDefinition(Type t) { Type value = null; if (_genericTypeDef.TryGetValue(t, out value)) { return value; } value = t.GetGenericTypeDefinition(); _genericTypeDef.Add(t, value); return value; } public Type[] GetGenericArguments(Type t) { Type[] value = null; if (_genericTypes.TryGetValue(t, out value)) { return value; } value = t.GetGenericArguments(); _genericTypes.Add(t, value); return value; } public Dictionary<string, myPropInfo> Getproperties(Type type, string typename, bool ShowReadOnlyProperties) { Dictionary<string, myPropInfo> value = null; if (_propertycache.TryGetValue(typename, out value)) { return value; } value = new Dictionary<string, myPropInfo>(10); BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public; PropertyInfo[] properties = type.GetProperties(bindingAttr); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (propertyInfo.GetIndexParameters().Length != 0) { continue; } myPropInfo myPropInfo2 = CreateMyProp(propertyInfo.PropertyType, propertyInfo.Name); myPropInfo2.setter = CreateSetMethod(type, propertyInfo, ShowReadOnlyProperties); if (myPropInfo2.setter != null) { myPropInfo2.CanWrite = true; } myPropInfo2.getter = CreateGetMethod(type, propertyInfo); object[] customAttributes = propertyInfo.GetCustomAttributes(inherit: true); object[] array2 = customAttributes; foreach (object obj in array2) { if (obj is DataMemberAttribute) { DataMemberAttribute dataMemberAttribute = (DataMemberAttribute)obj; if (dataMemberAttribute.Name != "") { myPropInfo2.memberName = dataMemberAttribute.Name; } } } if (myPropInfo2.memberName != null) { value.Add(myPropInfo2.memberName, myPropInfo2); } else { value.Add(propertyInfo.Name.ToLowerInvariant(), myPropInfo2); } } FieldInfo[] fields = type.GetFields(bindingAttr); FieldInfo[] array3 = fields; foreach (FieldInfo fieldInfo in array3) { myPropInfo myPropInfo3 = CreateMyProp(fieldInfo.FieldType, fieldInfo.Name); if (fieldInfo.IsLiteral) { continue; } if (!fieldInfo.IsInitOnly) { myPropInfo3.setter = CreateSetField(type, fieldInfo); } if (myPropInfo3.setter != null) { myPropInfo3.CanWrite = true; } myPropInfo3.getter = CreateGetField(type, fieldInfo); object[] customAttributes2 = fieldInfo.GetCustomAttributes(inherit: true); object[] array4 = customAttributes2; foreach (object obj2 in array4) { if (obj2 is DataMemberAttribute) { DataMemberAttribute dataMemberAttribute2 = (DataMemberAttribute)obj2; if (dataMemberAttribute2.Name != "") { myPropInfo3.memberName = dataMemberAttribute2.Name; } } } if (myPropInfo3.memberName != null) { value.Add(myPropInfo3.memberName, myPropInfo3); } else { value.Add(fieldInfo.Name.ToLowerInvariant(), myPropInfo3); } } _propertycache.Add(typename, value); return value; } private myPropInfo CreateMyProp(Type t, string name) { myPropInfo myPropInfo2 = new myPropInfo(); myPropInfoType type = myPropInfoType.Unknown; if (t == typeof(int) || t == typeof(int?)) { type = myPropInfoType.Int; } else if (t == typeof(long) || t == typeof(long?)) { type = myPropInfoType.Long; } else if (t == typeof(string)) { type = myPropInfoType.String; } else if (t == typeof(bool) || t == typeof(bool?)) { type = myPropInfoType.Bool; } else if (t == typeof(DateTime) || t == typeof(DateTime?)) { type = myPropInfoType.DateTime; } else if (t.IsEnum) { type = myPropInfoType.Enum; } else if (t == typeof(Guid) || t == typeof(Guid?)) { type = myPropInfoType.Guid; } else if (t == typeof(StringDictionary)) { type = myPropInfoType.StringDictionary; } else if (t == typeof(NameValueCollection)) { type = myPropInfoType.NameValue; } else if (t.IsArray) { myPropInfo2.bt = t.GetElementType(); type = ((!(t == typeof(byte[]))) ? myPropInfoType.Array : myPropInfoType.ByteArray); } else if (t.Name.Contains("Dictionary")) { myPropInfo2.GenericTypes = Instance.GetGenericArguments(t); type = ((myPropInfo2.GenericTypes.Length == 0 || !(myPropInfo2.GenericTypes[0] == typeof(string))) ? myPropInfoType.Dictionary : myPropInfoType.StringKeyDictionary); } else if (IsTypeRegistered(t)) { type = myPropInfoType.Custom; } if (t.IsValueType && !t.IsPrimitive && !t.IsEnum && t != typeof(decimal)) { myPropInfo2.IsStruct = true; } myPropInfo2.IsInterface = t.IsInterface; myPropInfo2.IsClass = t.IsClass; myPropInfo2.IsValueType = t.IsValueType; if (t.IsGenericType) { myPropInfo2.IsGenericType = true; myPropInfo2.bt = Instance.GetGenericArguments(t)[0]; } myPropInfo2.pt = t; myPropInfo2.Name = name; myPropInfo2.changeType = GetChangeType(t); myPropInfo2.Type = type; return myPropInfo2; } private Type GetChangeType(Type conversionType) { if (conversionType.IsGenericType && conversionType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))) { return Instance.GetGenericArguments(conversionType)[0]; } return conversionType; } public string GetTypeAssemblyName(Type t) { string value = ""; if (_tyname.TryGetValue(t, out value)) { return value; } string assemblyQualifiedName = t.AssemblyQualifiedName; _tyname.Add(t, assemblyQualifiedName); return assemblyQualifiedName; } internal Type GetTypeFromCache(string typename, bool badlistChecking) { Type value = null; if (_typecache.TryGetValue(typename, out value)) { return value; } if (badlistChecking) { string text = typename.Trim().ToLowerInvariant(); foreach (string badlistType in _badlistTypes) { if (text.StartsWith(badlistType, StringComparison.Ordinal)) { throw new Exception("Black list type encountered, possible attack vector when using $type : " + typename); } } } Type type = Type.GetType(typename); _typecache.Add(typename, type); return type; } internal object FastCreateList(Type objtype, int capacity) { try { int capacity2 = 10; if (capacity > 10) { capacity2 = capacity; } CreateList value = null; if (_conlistcache.TryGetValue(objtype, out value)) { if (value != null) { return value(capacity2); } return FastCreateInstance(objtype); } ConstructorInfo constructor = objtype.GetConstructor(new Type[1] { typeof(int) }); if (constructor != null) { DynamicMethod dynamicMethod = new DynamicMethod("_fcil", objtype, new Type[1] { typeof(int) }, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Ldarg_0); iLGenerator.Emit(OpCodes.Newobj, objtype.GetConstructor(new Type[1] { typeof(int) })); iLGenerator.Emit(OpCodes.Ret); value = (CreateList)dynamicMethod.CreateDelegate(typeof(CreateList)); _conlistcache.Add(objtype, value); return value(capacity2); } _conlistcache.Add(objtype, null); return FastCreateInstance(objtype); } catch (Exception innerException) { throw new Exception($"Failed to fast create instance for type '{objtype.FullName}' from assembly '{objtype.AssemblyQualifiedName}'", innerException); } } internal object FastCreateInstance(Type objtype) { try { CreateObject value = null; if (_constrcache.TryGetValue(objtype, out value)) { return value(); } if (objtype.IsClass) { DynamicMethod dynamicMethod = new DynamicMethod("_fcic", objtype, null, restrictedSkipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); iLGenerator.Emit(OpCodes.Newobj, objtype.GetConstructor(Type.EmptyTypes)); iLGenerator.Emit(OpCodes.Ret); value = (CreateObject)dynamicMethod.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, value); } else { DynamicMethod dynamicMethod2 = new DynamicMethod("_fcis", typeof(object), null, restrictedSkipVisibility: true); ILGenerator iLGenerator2 = dynamicMethod2.GetILGenerator(); LocalBuilder local = iLGenerator2.DeclareLocal(objtype); iLGenerator2.Emit(OpCodes.Ldloca_S, local); iLGenerator2.Emit(OpCodes.Initobj, objtype); iLGenerator2.Emit(OpCodes.Ldloc_0); iLGenerator2.Emit(OpCodes.Box, objtype); iLGenerator2.Emit(OpCodes.Ret); value = (CreateObject)dynamicMethod2.CreateDelegate(typeof(CreateObject)); _constrcache.Add(objtype, value); } return value(); } catch (Exception innerException) { throw new Exception($"Failed to fast create instance for type '{objtype.FullName}' from assembly '{objtype.AssemblyQualifiedName}'", innerException); } } internal static GenericSetter CreateSetField(Type type, FieldInfo fieldInfo) { Type[] array = new Type[2]; array[0] = (array[1] = typeof(object)); DynamicMethod dynamicMethod = new DynamicMethod("_csf", typeof(object), array, type, skipVisibility: true); ILGenerator iLGenerator = dynamicMethod.GetILGenerator(); if (!type.IsClass) { LocalBuilder local = iLGenerat