The BepInEx console will not appear when launching like it does for other games on Thunderstore. This is normal (and helps prevent crashes during startup). You can turn it back on in your BepInEx.cfg file.
Decompiled source of SettingsSaver v1.0.5
BepInEx/plugins/SettingsSaver.dll
Decompiled 10 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using SimpleJSON; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("SettingsSaver")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("SettingsSaver")] [assembly: AssemblyTitle("SettingsSaver")] [assembly: AssemblyVersion("1.0.0.0")] [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; } } } [BepInPlugin("com.peak.settingssaver", "SettingsSaver", "1.0.0")] public class SettingsSaver : BaseUnityPlugin { [CompilerGenerated] private sealed class <FirstTimeSettingsCapture>d__10 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SettingsSaver <>4__this; private int <i>5__1; private object <handler>5__2; private FieldInfo <settingsField>5__3; private IEnumerable <list>5__4; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <FirstTimeSettingsCapture>d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <handler>5__2 = null; <settingsField>5__3 = null; <list>5__4 = null; <>1__state = -2; } private bool MoveNext() { //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[SettingsSaver] Waiting for SettingsHandler to become ready for initial capture..."); <i>5__1 = 0; break; case 1: <>1__state = -1; <handler>5__2 = null; <i>5__1++; break; } if (<i>5__1 < 30) { <handler>5__2 = FindSettingsHandler(); if (<handler>5__2 != null) { <settingsField>5__3 = <handler>5__2.GetType().GetField("settings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = <settingsField>5__3?.GetValue(<handler>5__2); <list>5__4 = obj as IEnumerable; if (<list>5__4 != null && <list>5__4.GetEnumerator().MoveNext()) { <>4__this.CaptureAndSaveInitialValues(<handler>5__2); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[SettingsSaver] Initial values captured from SettingsHandler."); return false; } <settingsField>5__3 = null; <list>5__4 = null; } <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } ((BaseUnityPlugin)<>4__this).Logger.LogWarning((object)"[SettingsSaver] Failed to capture initial settings — handler never became ready."); return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MainMenuWatcher>d__9 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SettingsSaver <>4__this; private object <handler>5__1; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MainMenuWatcher>d__9(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <handler>5__1 = null; <>1__state = -2; } private bool MoveNext() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; if (<>4__this._appliedOnce) { return false; } <handler>5__1 = FindSettingsHandler(); if (<handler>5__1 != null) { ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)"[SettingsSaver] Detected SettingsHandler in scene, applying saved settings."); ApplySavedSettings(<handler>5__1); <>4__this._appliedOnce = true; return false; } <handler>5__1 = null; break; } <>2__current = (object)new WaitForSeconds(7f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <MonitorSettings>d__18 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public SettingsSaver <>4__this; private MonoBehaviour[] <>s__1; private int <>s__2; private MonoBehaviour <mb>5__3; private Type <type>5__4; private FieldInfo <field>5__5; private object <setting>5__6; private string <key>5__7; private PropertyInfo <valProp>5__8; private object <currentValue>5__9; private string <saveString>5__10; private string <oldVal>5__11; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <MonitorSettings>d__18(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>s__1 = null; <mb>5__3 = null; <type>5__4 = null; <field>5__5 = null; <setting>5__6 = null; <key>5__7 = null; <valProp>5__8 = null; <currentValue>5__9 = null; <saveString>5__10 = null; <oldVal>5__11 = null; <>1__state = -2; } private bool MoveNext() { //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bf: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } <>s__1 = Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0); for (<>s__2 = 0; <>s__2 < <>s__1.Length; <>s__2++) { <mb>5__3 = <>s__1[<>s__2]; <type>5__4 = ((object)<mb>5__3).GetType(); if (<type>5__4.Name.Contains("SettingUI")) { <field>5__5 = <type>5__4.GetField("_listeningSetting", BindingFlags.Instance | BindingFlags.NonPublic); if (!(<field>5__5 == null)) { <setting>5__6 = <field>5__5.GetValue(<mb>5__3); if (<setting>5__6 != null) { <key>5__7 = <setting>5__6.GetType().Name; <valProp>5__8 = <setting>5__6.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); if (!(<valProp>5__8 == null) && <valProp>5__8.CanRead) { <currentValue>5__9 = <valProp>5__8.GetValue(<setting>5__6); if (<currentValue>5__9 != null) { <saveString>5__10 = (<valProp>5__8.PropertyType.IsEnum ? Enum.GetName(<valProp>5__8.PropertyType, <currentValue>5__9) : <currentValue>5__9.ToString()); if (!<>4__this._lastKnownValues.TryGetValue(<key>5__7, out <oldVal>5__11) || <oldVal>5__11 != <saveString>5__10) { SavedSettings[<key>5__7] = <saveString>5__10; <>4__this._lastKnownValues[<key>5__7] = <saveString>5__10; <>4__this.SaveSettingsToDisk(); ((BaseUnityPlugin)<>4__this).Logger.LogInfo((object)("[SettingsSaver] Change saved: " + <key>5__7 + " = " + <saveString>5__10)); } <type>5__4 = null; <field>5__5 = null; <setting>5__6 = null; <key>5__7 = null; <valProp>5__8 = null; <currentValue>5__9 = null; <saveString>5__10 = null; <oldVal>5__11 = null; <mb>5__3 = null; } } } } } } <>s__1 = null; <>2__current = (object)new WaitForSeconds(2f); <>1__state = 1; return true; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private const string SaveFileName = "SettingsSaver.json"; public static Dictionary<string, string> SavedSettings = new Dictionary<string, string>(); private static SettingsSaver Instance; private Coroutine monitor; private bool _appliedOnce = false; private Dictionary<string, string> _lastKnownValues = new Dictionary<string, string>(); public static string SaveFilePath => Path.Combine(Paths.ConfigPath, "SettingsSaver.json"); private void Awake() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) Instance = this; ((BaseUnityPlugin)this).Logger.LogInfo((object)"[SettingsSaver] Loading saved settings..."); LoadSettingsFromDisk(); ((BaseUnityPlugin)this).Logger.LogInfo((object)("[SettingsSaver] Loaded saved settings. Ready. " + SavedSettings.Count + " settings loaded.")); if (SavedSettings.Count == 0) { ((MonoBehaviour)this).StartCoroutine(FirstTimeSettingsCapture()); } ((MonoBehaviour)this).StartCoroutine(MainMenuWatcher()); new Harmony("com.peak.settingssaver").PatchAll(); } [IteratorStateMachine(typeof(<MainMenuWatcher>d__9))] private IEnumerator MainMenuWatcher() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MainMenuWatcher>d__9(0) { <>4__this = this }; } [IteratorStateMachine(typeof(<FirstTimeSettingsCapture>d__10))] private IEnumerator FirstTimeSettingsCapture() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <FirstTimeSettingsCapture>d__10(0) { <>4__this = this }; } private void CaptureAndSaveInitialValues(object settingsHandler) { if (!(settingsHandler.GetType().GetField("settings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(settingsHandler) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { if (item == null) { continue; } string name = item.GetType().Name; PropertyInfo property = item.GetType().GetProperty("Value", BindingFlags.Instance | BindingFlags.Public); if (property == null || !property.CanRead) { continue; } object value = property.GetValue(item); if (value != null) { string value2 = (property.PropertyType.IsEnum ? Enum.GetName(property.PropertyType, value) : value.ToString()); if (!SavedSettings.ContainsKey(name)) { SavedSettings[name] = value2; _lastKnownValues[name] = value2; } } } SaveSettingsToDisk(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[SettingsSaver] Initial settings captured and saved."); } public static void ApplySavedSettings(object settingsHandler) { if (!(settingsHandler.GetType().GetField("settings", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(settingsHandler) is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { if (item == null) { continue; } string name = item.GetType().Name; if (!SavedSettings.TryGetValue(name, out var value)) { continue; } MethodInfo[] methods = item.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); MethodInfo methodInfo = null; MethodInfo[] array = methods; foreach (MethodInfo methodInfo2 in array) { ParameterInfo[] parameters = methodInfo2.GetParameters(); if (methodInfo2.Name == "SetValue" && parameters.Length == 3 && parameters[1].ParameterType.Name.Contains("ISettingHandler")) { methodInfo = methodInfo2; break; } } if (!(methodInfo == null)) { Type parameterType = methodInfo.GetParameters()[0].ParameterType; object obj = null; try { obj = ((parameterType == typeof(int)) ? ((object)int.Parse(value)) : ((parameterType == typeof(float)) ? ((object)float.Parse(value)) : ((parameterType == typeof(bool)) ? ((object)bool.Parse(value)) : ((!parameterType.IsEnum) ? Convert.ChangeType(value, parameterType) : Enum.Parse(parameterType, value, ignoreCase: true))))); methodInfo.Invoke(item, new object[3] { obj, settingsHandler, false }); item.GetType().GetMethod("ApplyValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(item, null); } catch { } } } } public static object FindSettingsHandler() { MonoBehaviour[] array = Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0); foreach (MonoBehaviour val in array) { Type type = ((object)val).GetType(); if (type.Name == "GameHandler") { object obj = type.GetProperty("SettingsHandler", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); if (obj != null) { return obj; } object obj2 = type.GetField("SettingsHandler", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(val); if (obj2 != null) { return obj2; } } } MonoBehaviour[] array2 = Object.FindObjectsByType<MonoBehaviour>((FindObjectsSortMode)0); foreach (MonoBehaviour val2 in array2) { if (((object)val2).GetType().Name.Contains("SettingsHandler")) { return val2; } } return null; } private void SaveSettingsToDisk() { try { JSONObject jSONObject = new JSONObject(); foreach (KeyValuePair<string, string> savedSetting in SavedSettings) { jSONObject[savedSetting.Key] = savedSetting.Value; } File.WriteAllText(SaveFilePath, jSONObject.ToString(2)); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[SettingsSaver] Saved settings to disk."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[SettingsSaver] Failed to save: " + ex.Message)); } } private void LoadSettingsFromDisk() { if (!File.Exists(SaveFilePath)) { return; } try { string aJSON = File.ReadAllText(SaveFilePath); JSONObject asObject = JSON.Parse(aJSON).AsObject; SavedSettings.Clear(); JSONNode.KeyEnumerator enumerator = asObject.Keys.GetEnumerator(); while (enumerator.MoveNext()) { string current = enumerator.Current; SavedSettings[current] = asObject[current]; } ((BaseUnityPlugin)this).Logger.LogInfo((object)"[SettingsSaver] Loaded saved settings."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[SettingsSaver] Failed to load: " + ex.Message)); } } public static void StartWatching() { if (Instance.monitor == null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[SettingsSaver] Settings menu opened. Starting watcher..."); Instance.monitor = ((MonoBehaviour)Instance).StartCoroutine(Instance.MonitorSettings()); } } public static void StopWatching() { if (Instance.monitor != null) { ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"[SettingsSaver] Settings menu closed. Stopping watcher."); ((MonoBehaviour)Instance).StopCoroutine(Instance.monitor); Instance.monitor = null; } } [IteratorStateMachine(typeof(<MonitorSettings>d__18))] private IEnumerator MonitorSettings() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <MonitorSettings>d__18(0) { <>4__this = this }; } } [HarmonyPatch(typeof(SharedSettingsMenu), "OnEnable")] public static class PatchOnEnable { [HarmonyPostfix] public static void OnOpen() { SettingsSaver.StartWatching(); } } [HarmonyPatch(typeof(SharedSettingsMenu), "OnDisable")] public static class PatchOnDisable { [HarmonyPostfix] public static void OnClose() { SettingsSaver.StopWatching(); } } namespace SimpleJSON { public enum JSONNodeType { Array = 1, Object = 2, String = 3, Number = 4, NullValue = 5, Boolean = 6, None = 7, Custom = 255 } public enum JSONTextMode { Compact, Indent } public abstract class JSONNode { public struct Enumerator { private enum Type { None, Array, Object } private Type type; private Dictionary<string, JSONNode>.Enumerator m_Object; private List<JSONNode>.Enumerator m_Array; public bool IsValid => type != Type.None; public KeyValuePair<string, JSONNode> Current { get { if (type == Type.Array) { return new KeyValuePair<string, JSONNode>(string.Empty, m_Array.Current); } if (type == Type.Object) { return m_Object.Current; } return new KeyValuePair<string, JSONNode>(string.Empty, null); } } public Enumerator(List<JSONNode>.Enumerator aArrayEnum) { type = Type.Array; m_Object = default(Dictionary<string, JSONNode>.Enumerator); m_Array = aArrayEnum; } public Enumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) { type = Type.Object; m_Object = aDictEnum; m_Array = default(List<JSONNode>.Enumerator); } public bool MoveNext() { if (type == Type.Array) { return m_Array.MoveNext(); } if (type == Type.Object) { return m_Object.MoveNext(); } return false; } } public struct ValueEnumerator { private Enumerator m_Enumerator; public JSONNode Current => m_Enumerator.Current.Value; public ValueEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public ValueEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public ValueEnumerator GetEnumerator() { return this; } } public struct KeyEnumerator { private Enumerator m_Enumerator; public string Current => m_Enumerator.Current.Key; public KeyEnumerator(List<JSONNode>.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } public KeyEnumerator(Dictionary<string, JSONNode>.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } public bool MoveNext() { return m_Enumerator.MoveNext(); } public KeyEnumerator GetEnumerator() { return this; } } public class LinqEnumerator : IEnumerator<KeyValuePair<string, JSONNode>>, IDisposable, IEnumerator, IEnumerable<KeyValuePair<string, JSONNode>>, IEnumerable { private JSONNode m_Node; private Enumerator m_Enumerator; public KeyValuePair<string, JSONNode> Current => m_Enumerator.Current; object IEnumerator.Current => m_Enumerator.Current; internal LinqEnumerator(JSONNode aNode) { m_Node = aNode; if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } public bool MoveNext() { return m_Enumerator.MoveNext(); } public void Dispose() { m_Node = null; m_Enumerator = default(Enumerator); } public IEnumerator<KeyValuePair<string, JSONNode>> GetEnumerator() { return new LinqEnumerator(m_Node); } public void Reset() { if (m_Node != null) { m_Enumerator = m_Node.GetEnumerator(); } } IEnumerator IEnumerable.GetEnumerator() { return new LinqEnumerator(m_Node); } } [CompilerGenerated] private sealed class <get_Children>d__43 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator { private int <>1__state; private JSONNode <>2__current; private int <>l__initialThreadId; public JSONNode <>4__this; JSONNode IEnumerator<JSONNode>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Children>d__43(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { if (<>1__state != 0) { return false; } <>1__state = -1; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator() { <get_Children>d__43 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Children>d__43(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<JSONNode>)this).GetEnumerator(); } } [CompilerGenerated] private sealed class <get_DeepChildren>d__45 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator { private int <>1__state; private JSONNode <>2__current; private int <>l__initialThreadId; public JSONNode <>4__this; private IEnumerator<JSONNode> <>s__1; private JSONNode <C>5__2; private IEnumerator<JSONNode> <>s__3; private JSONNode <D>5__4; JSONNode IEnumerator<JSONNode>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_DeepChildren>d__45(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if ((uint)(num - -4) <= 1u || num == 1) { try { if (num == -4 || num == 1) { try { } finally { <>m__Finally2(); } } } finally { <>m__Finally1(); } } <>s__1 = null; <C>5__2 = null; <>s__3 = null; <D>5__4 = null; <>1__state = -2; } private bool MoveNext() { try { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -4; <D>5__4 = null; goto IL_00b5; } <>1__state = -1; <>s__1 = <>4__this.Children.GetEnumerator(); <>1__state = -3; goto IL_00d7; IL_00b5: if (<>s__3.MoveNext()) { <D>5__4 = <>s__3.Current; <>2__current = <D>5__4; <>1__state = 1; return true; } <>m__Finally2(); <>s__3 = null; <C>5__2 = null; goto IL_00d7; IL_00d7: if (<>s__1.MoveNext()) { <C>5__2 = <>s__1.Current; <>s__3 = <C>5__2.DeepChildren.GetEnumerator(); <>1__state = -4; goto IL_00b5; } <>m__Finally1(); <>s__1 = null; return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if (<>s__1 != null) { <>s__1.Dispose(); } } private void <>m__Finally2() { <>1__state = -3; if (<>s__3 != null) { <>s__3.Dispose(); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator() { <get_DeepChildren>d__45 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_DeepChildren>d__45(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<JSONNode>)this).GetEnumerator(); } } public static bool forceASCII = false; public static bool longAsString = false; public static bool allowLineComments = true; [ThreadStatic] private static StringBuilder m_EscapeBuilder; public abstract JSONNodeType Tag { get; } public virtual JSONNode this[int aIndex] { get { return null; } set { } } public virtual JSONNode this[string aKey] { get { return null; } set { } } public virtual string Value { get { return ""; } set { } } public virtual int Count => 0; public virtual bool IsNumber => false; public virtual bool IsString => false; public virtual bool IsBoolean => false; public virtual bool IsNull => false; public virtual bool IsArray => false; public virtual bool IsObject => false; public virtual bool Inline { get { return false; } set { } } public virtual IEnumerable<JSONNode> Children { [IteratorStateMachine(typeof(<get_Children>d__43))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() <get_Children>d__43 <get_Children>d__ = new <get_Children>d__43(-2); <get_Children>d__.<>4__this = this; return <get_Children>d__; } } public IEnumerable<JSONNode> DeepChildren { [IteratorStateMachine(typeof(<get_DeepChildren>d__45))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() <get_DeepChildren>d__45 <get_DeepChildren>d__ = new <get_DeepChildren>d__45(-2); <get_DeepChildren>d__.<>4__this = this; return <get_DeepChildren>d__; } } public IEnumerable<KeyValuePair<string, JSONNode>> Linq => new LinqEnumerator(this); public KeyEnumerator Keys => new KeyEnumerator(GetEnumerator()); public ValueEnumerator Values => new ValueEnumerator(GetEnumerator()); public virtual double AsDouble { get { double result = 0.0; if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out result)) { return result; } return 0.0; } set { Value = value.ToString(CultureInfo.InvariantCulture); } } public virtual int AsInt { get { return (int)AsDouble; } set { AsDouble = value; } } public virtual float AsFloat { get { return (float)AsDouble; } set { AsDouble = value; } } public virtual bool AsBool { get { bool result = false; if (bool.TryParse(Value, out result)) { return result; } return !string.IsNullOrEmpty(Value); } set { Value = (value ? "true" : "false"); } } public virtual long AsLong { get { long result = 0L; if (long.TryParse(Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { return result; } return 0L; } set { Value = value.ToString(CultureInfo.InvariantCulture); } } public virtual ulong AsULong { get { ulong result = 0uL; if (ulong.TryParse(Value, NumberStyles.Integer, CultureInfo.InvariantCulture, out result)) { return result; } return 0uL; } set { Value = value.ToString(CultureInfo.InvariantCulture); } } public virtual JSONArray AsArray => this as JSONArray; public virtual JSONObject AsObject => this as JSONObject; internal static StringBuilder EscapeBuilder { get { if (m_EscapeBuilder == null) { m_EscapeBuilder = new StringBuilder(); } return m_EscapeBuilder; } } public virtual void Add(string aKey, JSONNode aItem) { } public virtual void Add(JSONNode aItem) { Add("", aItem); } public virtual JSONNode Remove(string aKey) { return null; } public virtual JSONNode Remove(int aIndex) { return null; } public virtual JSONNode Remove(JSONNode aNode) { return aNode; } public virtual void Clear() { } public virtual JSONNode Clone() { return null; } public virtual bool HasKey(string aKey) { return false; } public virtual JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) { return aDefault; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, 0, JSONTextMode.Compact); return stringBuilder.ToString(); } public virtual string ToString(int aIndent) { StringBuilder stringBuilder = new StringBuilder(); WriteToStringBuilder(stringBuilder, 0, aIndent, JSONTextMode.Indent); return stringBuilder.ToString(); } internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); public abstract Enumerator GetEnumerator(); public static implicit operator JSONNode(string s) { return (s == null) ? ((JSONNode)JSONNull.CreateOrGet()) : ((JSONNode)new JSONString(s)); } public static implicit operator string(JSONNode d) { return (d == null) ? null : d.Value; } public static implicit operator JSONNode(double n) { return new JSONNumber(n); } public static implicit operator double(JSONNode d) { return (d == null) ? 0.0 : d.AsDouble; } public static implicit operator JSONNode(float n) { return new JSONNumber(n); } public static implicit operator float(JSONNode d) { return (d == null) ? 0f : d.AsFloat; } public static implicit operator JSONNode(int n) { return new JSONNumber(n); } public static implicit operator int(JSONNode d) { return (!(d == null)) ? d.AsInt : 0; } public static implicit operator JSONNode(long n) { if (longAsString) { return new JSONString(n.ToString(CultureInfo.InvariantCulture)); } return new JSONNumber(n); } public static implicit operator long(JSONNode d) { return (d == null) ? 0 : d.AsLong; } public static implicit operator JSONNode(ulong n) { if (longAsString) { return new JSONString(n.ToString(CultureInfo.InvariantCulture)); } return new JSONNumber(n); } public static implicit operator ulong(JSONNode d) { return (d == null) ? 0 : d.AsULong; } public static implicit operator JSONNode(bool b) { return new JSONBool(b); } public static implicit operator bool(JSONNode d) { return !(d == null) && d.AsBool; } public static implicit operator JSONNode(KeyValuePair<string, JSONNode> aKeyValue) { return aKeyValue.Value; } public static bool operator ==(JSONNode a, object b) { if ((object)a == b) { return true; } bool flag = a is JSONNull || (object)a == null || a is JSONLazyCreator; bool flag2 = b is JSONNull || b == null || b is JSONLazyCreator; if (flag && flag2) { return true; } return !flag && a.Equals(b); } public static bool operator !=(JSONNode a, object b) { return !(a == b); } public override bool Equals(object obj) { return (object)this == obj; } public override int GetHashCode() { return base.GetHashCode(); } internal static string Escape(string aText) { StringBuilder escapeBuilder = EscapeBuilder; escapeBuilder.Length = 0; if (escapeBuilder.Capacity < aText.Length + aText.Length / 10) { escapeBuilder.Capacity = aText.Length + aText.Length / 10; } foreach (char c in aText) { switch (c) { case '\\': escapeBuilder.Append("\\\\"); continue; case '"': escapeBuilder.Append("\\\""); continue; case '\n': escapeBuilder.Append("\\n"); continue; case '\r': escapeBuilder.Append("\\r"); continue; case '\t': escapeBuilder.Append("\\t"); continue; case '\b': escapeBuilder.Append("\\b"); continue; case '\f': escapeBuilder.Append("\\f"); continue; } if (c < ' ' || (forceASCII && c > '\u007f')) { ushort num = c; escapeBuilder.Append("\\u").Append(num.ToString("X4")); } else { escapeBuilder.Append(c); } } string result = escapeBuilder.ToString(); escapeBuilder.Length = 0; return result; } private static JSONNode ParseElement(string token, bool quoted) { if (quoted) { return token; } if (token.Length <= 5) { string text = token.ToLower(); if (text == "false" || text == "true") { return text == "true"; } if (text == "null") { return JSONNull.CreateOrGet(); } } if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return token; } public static JSONNode Parse(string aJSON) { Stack<JSONNode> stack = new Stack<JSONNode>(); JSONNode jSONNode = null; int i = 0; StringBuilder stringBuilder = new StringBuilder(); string aKey = ""; bool flag = false; bool flag2 = false; bool flag3 = false; for (; i < aJSON.Length; i++) { switch (aJSON[i]) { case '{': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONObject()); if (jSONNode != null) { jSONNode.Add(aKey, stack.Peek()); } aKey = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); flag3 = false; break; case '[': if (flag) { stringBuilder.Append(aJSON[i]); break; } stack.Push(new JSONArray()); if (jSONNode != null) { jSONNode.Add(aKey, stack.Peek()); } aKey = ""; stringBuilder.Length = 0; jSONNode = stack.Peek(); flag3 = false; break; case ']': case '}': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stack.Count == 0) { throw new Exception("JSON Parse: Too many closing brackets"); } stack.Pop(); if (stringBuilder.Length > 0 || flag2) { jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2)); } if (jSONNode != null) { jSONNode.Inline = !flag3; } flag2 = false; aKey = ""; stringBuilder.Length = 0; if (stack.Count > 0) { jSONNode = stack.Peek(); } break; case ':': if (flag) { stringBuilder.Append(aJSON[i]); break; } aKey = stringBuilder.ToString(); stringBuilder.Length = 0; flag2 = false; break; case '"': flag = !flag; flag2 = flag2 || flag; break; case ',': if (flag) { stringBuilder.Append(aJSON[i]); break; } if (stringBuilder.Length > 0 || flag2) { jSONNode.Add(aKey, ParseElement(stringBuilder.ToString(), flag2)); } flag2 = false; aKey = ""; stringBuilder.Length = 0; flag2 = false; break; case '\n': case '\r': flag3 = true; break; case '\t': case ' ': if (flag) { stringBuilder.Append(aJSON[i]); } break; case '\\': i++; if (flag) { char c = aJSON[i]; switch (c) { case 't': stringBuilder.Append('\t'); break; case 'r': stringBuilder.Append('\r'); break; case 'n': stringBuilder.Append('\n'); break; case 'b': stringBuilder.Append('\b'); break; case 'f': stringBuilder.Append('\f'); break; case 'u': { string s = aJSON.Substring(i + 1, 4); stringBuilder.Append((char)int.Parse(s, NumberStyles.AllowHexSpecifier)); i += 4; break; } default: stringBuilder.Append(c); break; } } break; case '/': if (allowLineComments && !flag && i + 1 < aJSON.Length && aJSON[i + 1] == '/') { while (++i < aJSON.Length && aJSON[i] != '\n' && aJSON[i] != '\r') { } } else { stringBuilder.Append(aJSON[i]); } break; default: stringBuilder.Append(aJSON[i]); break; case '\ufeff': break; } } if (flag) { throw new Exception("JSON Parse: Quotation marks seems to be messed up."); } if (jSONNode == null) { return ParseElement(stringBuilder.ToString(), flag2); } return jSONNode; } } public class JSONArray : JSONNode { [CompilerGenerated] private sealed class <get_Children>d__24 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator { private int <>1__state; private JSONNode <>2__current; private int <>l__initialThreadId; public JSONArray <>4__this; private List<JSONNode>.Enumerator <>s__1; private JSONNode <N>5__2; JSONNode IEnumerator<JSONNode>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Children>d__24(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = default(List<JSONNode>.Enumerator); <N>5__2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = <>4__this.m_List.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <N>5__2 = null; break; } if (<>s__1.MoveNext()) { <N>5__2 = <>s__1.Current; <>2__current = <N>5__2; <>1__state = 1; return true; } <>m__Finally1(); <>s__1 = default(List<JSONNode>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator() { <get_Children>d__24 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Children>d__24(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<JSONNode>)this).GetEnumerator(); } } private List<JSONNode> m_List = new List<JSONNode>(); private bool inline = false; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Array; public override bool IsArray => true; public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_List.Count) { return new JSONLazyCreator(this); } return m_List[aIndex]; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex < 0 || aIndex >= m_List.Count) { m_List.Add(value); } else { m_List[aIndex] = value; } } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this); } set { if (value == null) { value = JSONNull.CreateOrGet(); } m_List.Add(value); } } public override int Count => m_List.Count; public override IEnumerable<JSONNode> Children { [IteratorStateMachine(typeof(<get_Children>d__24))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() <get_Children>d__24 <get_Children>d__ = new <get_Children>d__24(-2); <get_Children>d__.<>4__this = this; return <get_Children>d__; } } public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } m_List.Add(aItem); } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_List.Count) { return null; } JSONNode result = m_List[aIndex]; m_List.RemoveAt(aIndex); return result; } public override JSONNode Remove(JSONNode aNode) { m_List.Remove(aNode); return aNode; } public override void Clear() { m_List.Clear(); } public override JSONNode Clone() { JSONArray jSONArray = new JSONArray(); jSONArray.m_List.Capacity = m_List.Capacity; foreach (JSONNode item in m_List) { if (item != null) { jSONArray.Add(item.Clone()); } else { jSONArray.Add(null); } } return jSONArray; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('['); int count = m_List.Count; if (inline) { aMode = JSONTextMode.Compact; } for (int i = 0; i < count; i++) { if (i > 0) { aSB.Append(','); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } m_List[i].WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append(']'); } } public class JSONObject : JSONNode { [CompilerGenerated] private sealed class <get_Children>d__27 : IEnumerable<JSONNode>, IEnumerable, IEnumerator<JSONNode>, IDisposable, IEnumerator { private int <>1__state; private JSONNode <>2__current; private int <>l__initialThreadId; public JSONObject <>4__this; private Dictionary<string, JSONNode>.Enumerator <>s__1; private KeyValuePair<string, JSONNode> <N>5__2; JSONNode IEnumerator<JSONNode>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <get_Children>d__27(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || num == 1) { try { } finally { <>m__Finally1(); } } <>s__1 = default(Dictionary<string, JSONNode>.Enumerator); <N>5__2 = default(KeyValuePair<string, JSONNode>); <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>s__1 = <>4__this.m_Dict.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <N>5__2 = default(KeyValuePair<string, JSONNode>); break; } if (<>s__1.MoveNext()) { <N>5__2 = <>s__1.Current; <>2__current = <N>5__2.Value; <>1__state = 1; return true; } <>m__Finally1(); <>s__1 = default(Dictionary<string, JSONNode>.Enumerator); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>s__1).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<JSONNode> IEnumerable<JSONNode>.GetEnumerator() { <get_Children>d__27 result; if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; result = this; } else { result = new <get_Children>d__27(0) { <>4__this = <>4__this }; } return result; } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<JSONNode>)this).GetEnumerator(); } } private Dictionary<string, JSONNode> m_Dict = new Dictionary<string, JSONNode>(); private bool inline = false; public override bool Inline { get { return inline; } set { inline = value; } } public override JSONNodeType Tag => JSONNodeType.Object; public override bool IsObject => true; public override JSONNode this[string aKey] { get { if (m_Dict.TryGetValue(aKey, out var value)) { return value; } return new JSONLazyCreator(this, aKey); } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = value; } else { m_Dict.Add(aKey, value); } } } public override JSONNode this[int aIndex] { get { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } return m_Dict.ElementAt(aIndex).Value; } set { if (value == null) { value = JSONNull.CreateOrGet(); } if (aIndex >= 0 && aIndex < m_Dict.Count) { string key = m_Dict.ElementAt(aIndex).Key; m_Dict[key] = value; } } } public override int Count => m_Dict.Count; public override IEnumerable<JSONNode> Children { [IteratorStateMachine(typeof(<get_Children>d__27))] get { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() <get_Children>d__27 <get_Children>d__ = new <get_Children>d__27(-2); <get_Children>d__.<>4__this = this; return <get_Children>d__; } } public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } public override void Add(string aKey, JSONNode aItem) { if (aItem == null) { aItem = JSONNull.CreateOrGet(); } if (aKey != null) { if (m_Dict.ContainsKey(aKey)) { m_Dict[aKey] = aItem; } else { m_Dict.Add(aKey, aItem); } } else { m_Dict.Add(Guid.NewGuid().ToString(), aItem); } } public override JSONNode Remove(string aKey) { if (!m_Dict.ContainsKey(aKey)) { return null; } JSONNode result = m_Dict[aKey]; m_Dict.Remove(aKey); return result; } public override JSONNode Remove(int aIndex) { if (aIndex < 0 || aIndex >= m_Dict.Count) { return null; } KeyValuePair<string, JSONNode> keyValuePair = m_Dict.ElementAt(aIndex); m_Dict.Remove(keyValuePair.Key); return keyValuePair.Value; } public override JSONNode Remove(JSONNode aNode) { try { KeyValuePair<string, JSONNode> keyValuePair = m_Dict.Where((KeyValuePair<string, JSONNode> k) => k.Value == aNode).First(); m_Dict.Remove(keyValuePair.Key); return aNode; } catch { return null; } } public override void Clear() { m_Dict.Clear(); } public override JSONNode Clone() { JSONObject jSONObject = new JSONObject(); foreach (KeyValuePair<string, JSONNode> item in m_Dict) { jSONObject.Add(item.Key, item.Value.Clone()); } return jSONObject; } public override bool HasKey(string aKey) { return m_Dict.ContainsKey(aKey); } public override JSONNode GetValueOrDefault(string aKey, JSONNode aDefault) { if (m_Dict.TryGetValue(aKey, out var value)) { return value; } return aDefault; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('{'); bool flag = true; if (inline) { aMode = JSONTextMode.Compact; } foreach (KeyValuePair<string, JSONNode> item in m_Dict) { if (!flag) { aSB.Append(','); } flag = false; if (aMode == JSONTextMode.Indent) { aSB.AppendLine(); } if (aMode == JSONTextMode.Indent) { aSB.Append(' ', aIndent + aIndentInc); } aSB.Append('"').Append(JSONNode.Escape(item.Key)).Append('"'); if (aMode == JSONTextMode.Compact) { aSB.Append(':'); } else { aSB.Append(" : "); } item.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); } if (aMode == JSONTextMode.Indent) { aSB.AppendLine().Append(' ', aIndent); } aSB.Append('}'); } } public class JSONString : JSONNode { private string m_Data; public override JSONNodeType Tag => JSONNodeType.String; public override bool IsString => true; public override string Value { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONString(string aData) { m_Data = aData; } public override JSONNode Clone() { return new JSONString(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append('"').Append(JSONNode.Escape(m_Data)).Append('"'); } public override bool Equals(object obj) { if (base.Equals(obj)) { return true; } if (obj is string text) { return m_Data == text; } JSONString jSONString = obj as JSONString; if (jSONString != null) { return m_Data == jSONString.m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = ""; } } public class JSONNumber : JSONNode { private double m_Data; public override JSONNodeType Tag => JSONNodeType.Number; public override bool IsNumber => true; public override string Value { get { return m_Data.ToString(CultureInfo.InvariantCulture); } set { if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { m_Data = result; } } } public override double AsDouble { get { return m_Data; } set { m_Data = value; } } public override long AsLong { get { return (long)m_Data; } set { m_Data = value; } } public override ulong AsULong { get { return (ulong)m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONNumber(double aData) { m_Data = aData; } public JSONNumber(string aData) { Value = aData; } public override JSONNode Clone() { return new JSONNumber(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(Value.ToString(CultureInfo.InvariantCulture)); } private static bool IsNumeric(object value) { return value is int || value is uint || value is float || value is double || value is decimal || value is long || value is ulong || value is short || value is ushort || value is sbyte || value is byte; } public override bool Equals(object obj) { if (obj == null) { return false; } if (base.Equals(obj)) { return true; } JSONNumber jSONNumber = obj as JSONNumber; if (jSONNumber != null) { return m_Data == jSONNumber.m_Data; } if (IsNumeric(obj)) { return Convert.ToDouble(obj) == m_Data; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = 0.0; } } public class JSONBool : JSONNode { private bool m_Data; public override JSONNodeType Tag => JSONNodeType.Boolean; public override bool IsBoolean => true; public override string Value { get { return m_Data.ToString(); } set { if (bool.TryParse(value, out var result)) { m_Data = result; } } } public override bool AsBool { get { return m_Data; } set { m_Data = value; } } public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONBool(bool aData) { m_Data = aData; } public JSONBool(string aData) { Value = aData; } public override JSONNode Clone() { return new JSONBool(m_Data); } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append(m_Data ? "true" : "false"); } public override bool Equals(object obj) { if (obj == null) { return false; } if (obj is bool) { return m_Data == (bool)obj; } return false; } public override int GetHashCode() { return m_Data.GetHashCode(); } public override void Clear() { m_Data = false; } } public class JSONNull : JSONNode { private static JSONNull m_StaticInstance = new JSONNull(); public static bool reuseSameInstance = true; public override JSONNodeType Tag => JSONNodeType.NullValue; public override bool IsNull => true; public override string Value { get { return "null"; } set { } } public override bool AsBool { get { return false; } set { } } public static JSONNull CreateOrGet() { if (reuseSameInstance) { return m_StaticInstance; } return new JSONNull(); } private JSONNull() { } public override Enumerator GetEnumerator() { return default(Enumerator); } public override JSONNode Clone() { return CreateOrGet(); } public override bool Equals(object obj) { if ((object)this == obj) { return true; } return obj is JSONNull; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } internal class JSONLazyCreator : JSONNode { private JSONNode m_Node = null; private string m_Key = null; public override JSONNodeType Tag => JSONNodeType.None; public override JSONNode this[int aIndex] { get { return new JSONLazyCreator(this); } set { Set(new JSONArray()).Add(value); } } public override JSONNode this[string aKey] { get { return new JSONLazyCreator(this, aKey); } set { Set(new JSONObject()).Add(aKey, value); } } public override int AsInt { get { Set(new JSONNumber(0.0)); return 0; } set { Set(new JSONNumber(value)); } } public override float AsFloat { get { Set(new JSONNumber(0.0)); return 0f; } set { Set(new JSONNumber(value)); } } public override double AsDouble { get { Set(new JSONNumber(0.0)); return 0.0; } set { Set(new JSONNumber(value)); } } public override long AsLong { get { if (JSONNode.longAsString) { Set(new JSONString("0")); } else { Set(new JSONNumber(0.0)); } return 0L; } set { if (JSONNode.longAsString) { Set(new JSONString(value.ToString(CultureInfo.InvariantCulture))); } else { Set(new JSONNumber(value)); } } } public override ulong AsULong { get { if (JSONNode.longAsString) { Set(new JSONString("0")); } else { Set(new JSONNumber(0.0)); } return 0uL; } set { if (JSONNode.longAsString) { Set(new JSONString(value.ToString(CultureInfo.InvariantCulture))); } else { Set(new JSONNumber(value)); } } } public override bool AsBool { get { Set(new JSONBool(aData: false)); return false; } set { Set(new JSONBool(value)); } } public override JSONArray AsArray => Set(new JSONArray()); public override JSONObject AsObject => Set(new JSONObject()); public override Enumerator GetEnumerator() { return default(Enumerator); } public JSONLazyCreator(JSONNode aNode) { m_Node = aNode; m_Key = null; } public JSONLazyCreator(JSONNode aNode, string aKey) { m_Node = aNode; m_Key = aKey; } private T Set<T>(T aVal) where T : JSONNode { if (m_Key == null) { m_Node.Add(aVal); } else { m_Node.Add(m_Key, aVal); } m_Node = null; return aVal; } public override void Add(JSONNode aItem) { Set(new JSONArray()).Add(aItem); } public override void Add(string aKey, JSONNode aItem) { Set(new JSONObject()).Add(aKey, aItem); } public static bool operator ==(JSONLazyCreator a, object b) { if (b == null) { return true; } return (object)a == b; } public static bool operator !=(JSONLazyCreator a, object b) { return !(a == b); } public override bool Equals(object obj) { if (obj == null) { return true; } return (object)this == obj; } public override int GetHashCode() { return 0; } internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) { aSB.Append("null"); } } public static class JSON { public static JSONNode Parse(string aJSON) { return JSONNode.Parse(aJSON); } } }