diff --git a/IPA/Program.cs b/IPA/Program.cs index 01533313..f8997253 100644 --- a/IPA/Program.cs +++ b/IPA/Program.cs @@ -18,7 +18,7 @@ namespace IPA { Unknown } - private static Version Version => new Version(Application.ProductVersion); + private static Version Version => Assembly.GetEntryAssembly().GetName().Version; static void Main(string[] args) { diff --git a/IPA/Properties/AssemblyInfo.cs b/IPA/Properties/AssemblyInfo.cs index 9632dccc..fb912cd2 100644 --- a/IPA/Properties/AssemblyInfo.cs +++ b/IPA/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("3.8.5")] -[assembly: AssemblyFileVersion("3.8.5")] +[assembly: AssemblyVersion("3.8.6.*")] +[assembly: AssemblyFileVersion("3.8.6")] diff --git a/IllusionInjector/IllusionInjector.csproj b/IllusionInjector/IllusionInjector.csproj index 9063611c..f0298718 100644 --- a/IllusionInjector/IllusionInjector.csproj +++ b/IllusionInjector/IllusionInjector.csproj @@ -47,6 +47,9 @@ ..\packages\Ionic.Zip.1.9.1.8\lib\Ionic.Zip.dll + + ..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll + @@ -84,7 +87,6 @@ - @@ -96,7 +98,12 @@ - + + + RequiredMonoLibs\System.Runtime.Serialization.dll + Always + + diff --git a/IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs b/IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs index 747b292a..6465f381 100644 --- a/IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs +++ b/IllusionInjector/Updating/ModsaberML/ApiEndpoint.cs @@ -1,6 +1,9 @@ -using IllusionInjector.Utilities; -using SimpleJSON; +using IllusionInjector.Logging; +using IllusionInjector.Utilities; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using System; +using System.Collections; using System.Collections.Generic; using System.Linq; using System.Text; @@ -18,61 +21,101 @@ namespace IllusionInjector.Updating.ModsaberML public const string GetApprovedEndpoint = "registry/{0}"; #endif + class HexArrayConverter : JsonConverter + { + public override bool CanConvert(Type objectType) + { + return objectType == typeof(byte[]); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + if (reader.TokenType == JsonToken.Null) + { + return null; + } + if (reader.TokenType == JsonToken.String) + { + try + { + return LoneFunctions.StringToByteArray((string)reader.Value); + } + catch (Exception ex) + { + throw new Exception(string.Format("Error parsing version string: {0}", reader.Value), ex); + } + } + throw new Exception(string.Format("Unexpected token or value when parsing hex string. Token: {0}, Value: {1}", reader.TokenType, reader.Value)); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + if (value == null) + { + writer.WriteNull(); + } + else + { + if (!(value is byte[])) + { + throw new JsonSerializationException("Expected byte[] object value"); + } + writer.WriteValue(LoneFunctions.ByteArrayToString(value as byte[])); + } + } + } + + [Serializable] public class Mod { +#pragma warning disable CS0649 + [JsonProperty("name")] public string Name; + [JsonProperty("version"), + JsonConverter(typeof(VersionConverter))] public Version Version; + [JsonProperty("approved")] public bool Approved; + [JsonProperty("title")] public string Title; + [JsonProperty("gameVersion"), + JsonConverter(typeof(VersionConverter))] public Version GameVersion; + [JsonProperty("author")] public string Author; - +#pragma warning restore CS0649 + [Serializable] public class PlatformFile { - public byte[] Hash = new byte[20]; // 20 byte because sha1 is fucky + [JsonProperty("hash"), + JsonConverter(typeof(HexArrayConverter))] + public byte[] Hash = new byte[20]; + [JsonProperty("files", ItemConverterType = typeof(HexArrayConverter))] public Dictionary FileHashes = new Dictionary(); + [JsonProperty("url")] public string DownloadPath = null; - } - public PlatformFile SteamFile = null; - public PlatformFile OculusFile = null; - - public static Mod DecodeJSON(JSONObject obj) - { - var outp = new Mod + public override string ToString() { - Name = obj["name"], - Version = new Version(obj["version"]), - Approved = obj["approved"].AsBool, - Title = obj["title"], - GameVersion = new Version(obj["gameVersion"]), - Author = obj["author"] - }; - - foreach (var item in obj["files"]) - { - var key = item.Key; - var pfile = new PlatformFile() - { - DownloadPath = item.Value["url"], - Hash = LoneFunctions.StringToByteArray(item.Value["hash"]) - }; - - foreach (var file in item.Value["files"]) - pfile.FileHashes.Add(file.Key, LoneFunctions.StringToByteArray(file.Value)); - - if (key == "steam") - outp.SteamFile = pfile; - if (key == "oculus") - outp.OculusFile = pfile; + return $"{LoneFunctions.ByteArrayToString(Hash)}@{DownloadPath}({string.Join(",",FileHashes.Select(o=>$"\"{o.Key}\":\"{LoneFunctions.ByteArrayToString(o.Value)}\""))})"; } - - return outp; } + [Serializable] + public class FilesObject + { + [JsonProperty("steam")] + public PlatformFile Steam = null; + [JsonProperty("oculus")] + public PlatformFile Oculus = null; + } + + [JsonProperty("files")] + public FilesObject Files = null; + public override string ToString() { - return $"{{\"{Title} ({Name})\"v{Version} for {GameVersion} by {Author} with \"{SteamFile}\" and \"{OculusFile}\"}}"; + return $"{{\"{Title} ({Name})\"v{Version} for {GameVersion} by {Author} with \"{Files.Steam}\" and \"{Files.Oculus}\"}}"; } } diff --git a/IllusionInjector/Updating/ModsaberML/Updater.cs b/IllusionInjector/Updating/ModsaberML/Updater.cs index 5318d54a..26a5c653 100644 --- a/IllusionInjector/Updating/ModsaberML/Updater.cs +++ b/IllusionInjector/Updating/ModsaberML/Updater.cs @@ -1,7 +1,7 @@ using IllusionInjector.Updating.Backup; using IllusionInjector.Utilities; using Ionic.Zip; -using SimpleJSON; +using Newtonsoft.Json; using System; using System.Collections; using System.Collections.Generic; @@ -89,28 +89,11 @@ namespace IllusionInjector.Updating.ModsaberML var json = request.downloadHandler.text; - JSONObject obj = null; - try - { - obj = JSON.Parse(json).AsObject; - } - catch (InvalidCastException) - { - Logger.log.Error($"Parse error while trying to update mods"); - Logger.log.Error($"Response doesn't seem to be a JSON object"); - continue; - } - catch (Exception e) - { - Logger.log.Error($"Parse error while trying to update mods"); - Logger.log.Error(e); - continue; - } - ApiEndpoint.Mod modRegistry; try { - modRegistry = ApiEndpoint.Mod.DecodeJSON(obj); + modRegistry = JsonConvert.DeserializeObject(json); + Logger.log.Debug(modRegistry.ToString()); } catch (Exception e) { @@ -290,10 +273,10 @@ namespace IllusionInjector.Updating.ModsaberML Logger.log.Debug($"Steam avaliable: {SteamCheck.IsAvailable}"); ApiEndpoint.Mod.PlatformFile platformFile; - if (SteamCheck.IsAvailable || item.externInfo.OculusFile == null) - platformFile = item.externInfo.SteamFile; + if (SteamCheck.IsAvailable || item.externInfo.Files.Oculus == null) + platformFile = item.externInfo.Files.Steam; else - platformFile = item.externInfo.OculusFile; + platformFile = item.externInfo.Files.Oculus; string url = platformFile.DownloadPath; diff --git a/IllusionInjector/Updating/SelfPlugin.cs b/IllusionInjector/Updating/SelfPlugin.cs index b6a22cc3..5bc844cd 100644 --- a/IllusionInjector/Updating/SelfPlugin.cs +++ b/IllusionInjector/Updating/SelfPlugin.cs @@ -12,7 +12,7 @@ namespace IllusionInjector.Updating internal class SelfPlugin : IBeatSaberPlugin { internal const string IPA_Name = "Beat Saber IPA"; - internal const string IPA_Version = "3.8.5"; + internal const string IPA_Version = "3.8.6"; public string Name => IPA_Name; diff --git a/IllusionInjector/Utilities/LoneFunctions.cs b/IllusionInjector/Utilities/LoneFunctions.cs index 3077e13e..c270f6e8 100644 --- a/IllusionInjector/Utilities/LoneFunctions.cs +++ b/IllusionInjector/Utilities/LoneFunctions.cs @@ -18,6 +18,14 @@ namespace IllusionInjector.Utilities return bytes; } + public static string ByteArrayToString(byte[] ba) + { + StringBuilder hex = new StringBuilder(ba.Length * 2); + foreach (byte b in ba) + hex.AppendFormat("{0:x2}", b); + return hex.ToString(); + } + // Copyright (c) 2008-2013 Hafthor Stefansson // Distributed under the MIT/X11 software license // Ref: http://www.opensource.org/licenses/mit-license.php. diff --git a/IllusionInjector/Utilities/SimpleJson.cs b/IllusionInjector/Utilities/SimpleJson.cs deleted file mode 100644 index a31e5fd2..00000000 --- a/IllusionInjector/Utilities/SimpleJson.cs +++ /dev/null @@ -1,1353 +0,0 @@ -/* * * * * - * A simple JSON Parser / builder - * ------------------------------ - * - * It mainly has been written as a simple JSON parser. It can build a JSON string - * from the node-tree, or generate a node tree from any valid JSON string. - * - * If you want to use compression when saving to file / stream / B64 you have to include - * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and - * define "USE_SharpZipLib" at the top of the file - * - * Written by Bunny83 - * 2012-06-09 - * - * [2012-06-09 First Version] - * - provides strongly typed node classes and lists / dictionaries - * - provides easy access to class members / array items / data values - * - the parser now properly identifies types. So generating JSON with this framework should work. - * - only double quotes (") are used for quoting strings. - * - provides "casting" properties to easily convert to / from those types: - * int / float / double / bool - * - provides a common interface for each node so no explicit casting is required. - * - the parser tries to avoid errors, but if malformed JSON is parsed the result is more or less undefined - * - It can serialize/deserialize a node tree into/from an experimental compact binary format. It might - * be handy if you want to store things in a file and don't want it to be easily modifiable - * - * [2012-12-17 Update] - * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree - * Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator - * The class determines the required type by it's further use, creates the type and removes itself. - * - Added binary serialization / deserialization. - * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) - * The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top - * - The serializer uses different types when it comes to store the values. Since my data values - * are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string. - * It's not the most efficient way but for a moderate amount of data it should work on all platforms. - * - * [2017-03-08 Update] - * - Optimised parsing by using a StringBuilder for token. This prevents performance issues when large - * string data fields are contained in the json data. - * - Finally refactored the badly named JSONClass into JSONObject. - * - Replaced the old JSONData class by distict typed classes ( JSONString, JSONNumber, JSONBool, JSONNull ) this - * allows to propertly convert the node tree back to json without type information loss. The actual value - * parsing now happens at parsing time and not when you actually access one of the casting properties. - * - * [2017-04-11 Update] - * - Fixed parsing bug where empty string values have been ignored. - * - Optimised "ToString" by using a StringBuilder internally. This should heavily improve performance for large files - * - Changed the overload of "ToString(string aIndent)" to "ToString(int aIndent)" - * - * [2017-11-29 Update] - * - Removed the IEnumerator implementations on JSONArray & JSONObject and replaced it with a common - * struct Enumerator in JSONNode that should avoid garbage generation. The enumerator always works - * on KeyValuePair, even for JSONArray. - * - Added two wrapper Enumerators that allows for easy key or value enumeration. A JSONNode now has - * a "Keys" and a "Values" enumerable property. Those are also struct enumerators / enumerables - * - A KeyValuePair can now be implicitly converted into a JSONNode. This allows - * a foreach loop over a JSONNode to directly access the values only. Since KeyValuePair as well as - * all the Enumerators are structs, no garbage is allocated. - * - To add Linq support another "LinqEnumerator" is available through the "Linq" property. This - * enumerator does implement the generic IEnumerable interface so most Linq extensions can be used - * on this enumerable object. This one does allocate memory as it's a wrapper class. - * - The Escape method now escapes all control characters (# < 32) in strings as uncode characters - * (\uXXXX) and if the static bool JSONNode.forceASCII is set to true it will also escape all - * characters # > 127. This might be useful if you require an ASCII output. Though keep in mind - * when your strings contain many non-ascii characters the strings become much longer (x6) and are - * no longer human readable. - * - The node types JSONObject and JSONArray now have an "Inline" boolean switch which will default to - * false. It can be used to serialize this element inline even you serialize with an indented format - * This is useful for arrays containing numbers so it doesn't place every number on a new line - * - Extracted the binary serialization code into a seperate extension file. All classes are now declared - * as "partial" so an extension file can even add a new virtual or abstract method / interface to - * JSONNode and override it in the concrete type classes. It's of course a hacky approach which is - * generally not recommended, but i wanted to keep everything tightly packed. - * - Added a static CreateOrGet method to the JSONNull class. Since this class is immutable it could - * be reused without major problems. If you have a lot null fields in your data it will help reduce - * the memory / garbage overhead. I also added a static setting (reuseSameInstance) to JSONNull - * (default is true) which will change the behaviour of "CreateOrGet". If you set this to false - * CreateOrGet will not reuse the cached instance but instead create a new JSONNull instance each time. - * I made the JSONNull constructor private so if you need to create an instance manually use - * JSONNull.CreateOrGet() - * - * [2018-01-09 Update] - * - Changed all double.TryParse and double.ToString uses to use the invariant culture to avoid problems - * on systems with a culture that uses a comma as decimal point. - * - * [2018-01-26 Update] - * - Added AsLong. Note that a JSONNumber is stored as double and can't represent all long values. However - * storing it as string would work. - * - Added static setting "JSONNode.longAsString" which controls the default type that is used by the - * LazyCreator when using AsLong - * - * [2018-04-25 Update] - * - Added support for parsing single values (JSONBool, JSONString, JSONNumber, JSONNull) as top level value. - * - * The MIT License (MIT) - * - * Copyright (c) 2012-2017 Markus Göbel (Bunny83) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - * * * * */ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace SimpleJSON -{ - public enum JSONNodeType - { - Array = 1, - Object = 2, - String = 3, - Number = 4, - NullValue = 5, - Boolean = 6, - None = 7, - Custom = 0xFF, - } - public enum JSONTextMode - { - Compact, - Indent - } - - public abstract partial class JSONNode - { - #region Enumerators - public struct Enumerator - { - private enum Type { None, Array, Object } - private Type type; - private Dictionary.Enumerator m_Object; - private List.Enumerator m_Array; - public bool IsValid { get { return type != Type.None; } } - public Enumerator(List.Enumerator aArrayEnum) - { - type = Type.Array; - m_Object = default(Dictionary.Enumerator); - m_Array = aArrayEnum; - } - public Enumerator(Dictionary.Enumerator aDictEnum) - { - type = Type.Object; - m_Object = aDictEnum; - m_Array = default(List.Enumerator); - } - public KeyValuePair Current - { - get - { - if (type == Type.Array) - return new KeyValuePair(string.Empty, m_Array.Current); - else if (type == Type.Object) - return m_Object.Current; - return new KeyValuePair(string.Empty, null); - } - } - public bool MoveNext() - { - if (type == Type.Array) - return m_Array.MoveNext(); - else if (type == Type.Object) - return m_Object.MoveNext(); - return false; - } - } - public struct ValueEnumerator - { - private Enumerator m_Enumerator; - public ValueEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } - public ValueEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } - public ValueEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } - public JSONNode Current { get { return m_Enumerator.Current.Value; } } - public bool MoveNext() { return m_Enumerator.MoveNext(); } - public ValueEnumerator GetEnumerator() { return this; } - } - public struct KeyEnumerator - { - private Enumerator m_Enumerator; - public KeyEnumerator(List.Enumerator aArrayEnum) : this(new Enumerator(aArrayEnum)) { } - public KeyEnumerator(Dictionary.Enumerator aDictEnum) : this(new Enumerator(aDictEnum)) { } - public KeyEnumerator(Enumerator aEnumerator) { m_Enumerator = aEnumerator; } - public JSONNode Current { get { return m_Enumerator.Current.Key; } } - public bool MoveNext() { return m_Enumerator.MoveNext(); } - public KeyEnumerator GetEnumerator() { return this; } - } - - public class LinqEnumerator : IEnumerator>, IEnumerable> - { - private JSONNode m_Node; - private Enumerator m_Enumerator; - internal LinqEnumerator(JSONNode aNode) - { - m_Node = aNode; - if (m_Node != null) - m_Enumerator = m_Node.GetEnumerator(); - } - public KeyValuePair Current { get { return m_Enumerator.Current; } } - object IEnumerator.Current { get { return m_Enumerator.Current; } } - public bool MoveNext() { return m_Enumerator.MoveNext(); } - - public void Dispose() - { - m_Node = null; - m_Enumerator = new Enumerator(); - } - - public IEnumerator> 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); - } - } - - #endregion Enumerators - - #region common interface - - public static bool forceASCII = false; // Use Unicode by default - public static bool longAsString = false; // lazy creator creates a JSONString instead of JSONNumber - - 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 { get { return 0; } } - - public virtual bool IsNumber { get { return false; } } - public virtual bool IsString { get { return false; } } - public virtual bool IsBoolean { get { return false; } } - public virtual bool IsNull { get { return false; } } - public virtual bool IsArray { get { return false; } } - public virtual bool IsObject { get { return false; } } - - public virtual bool Inline { get { return false; } set { } } - - 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 IEnumerable Children - { - get - { - yield break; - } - } - - public IEnumerable DeepChildren - { - get - { - foreach (var C in Children) - foreach (var D in C.DeepChildren) - yield return D; - } - } - - public override string ToString() - { - StringBuilder sb = new StringBuilder(); - WriteToStringBuilder(sb, 0, 0, JSONTextMode.Compact); - return sb.ToString(); - } - - public virtual string ToString(int aIndent) - { - StringBuilder sb = new StringBuilder(); - WriteToStringBuilder(sb, 0, aIndent, JSONTextMode.Indent); - return sb.ToString(); - } - internal abstract void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode); - - public abstract Enumerator GetEnumerator(); - public IEnumerable> Linq { get { return new LinqEnumerator(this); } } - public KeyEnumerator Keys { get { return new KeyEnumerator(GetEnumerator()); } } - public ValueEnumerator Values { get { return new ValueEnumerator(GetEnumerator()); } } - - #endregion common interface - - #region typecasting properties - - - public virtual double AsDouble - { - get - { - double v = 0.0; - if (double.TryParse(Value, NumberStyles.Float, CultureInfo.InvariantCulture, out v)) - return v; - 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 v = false; - if (bool.TryParse(Value, out v)) - return v; - return !string.IsNullOrEmpty(Value); - } - set - { - Value = (value) ? "true" : "false"; - } - } - - public virtual long AsLong - { - get - { - long val = 0; - if (long.TryParse(Value, out val)) - return val; - return 0L; - } - set - { - Value = value.ToString(); - } - } - - public virtual JSONArray AsArray - { - get - { - return this as JSONArray; - } - } - - public virtual JSONObject AsObject - { - get - { - return this as JSONObject; - } - } - - - #endregion typecasting properties - - #region operators - - public static implicit operator JSONNode(string s) - { - return 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 : d.AsDouble; - } - - public static implicit operator JSONNode(float n) - { - return new JSONNumber(n); - } - public static implicit operator float(JSONNode d) - { - return (d == null) ? 0 : d.AsFloat; - } - - public static implicit operator JSONNode(int n) - { - return new JSONNumber(n); - } - public static implicit operator int(JSONNode d) - { - return (d == null) ? 0 : d.AsInt; - } - - public static implicit operator JSONNode(long n) - { - if (longAsString) - return new JSONString(n.ToString()); - return new JSONNumber(n); - } - public static implicit operator long(JSONNode d) - { - return (d == null) ? 0L : d.AsLong; - } - - public static implicit operator JSONNode(bool b) - { - return new JSONBool(b); - } - public static implicit operator bool(JSONNode d) - { - return (d == null) ? false : d.AsBool; - } - - public static implicit operator JSONNode(KeyValuePair aKeyValue) - { - return aKeyValue.Value; - } - - public static bool operator ==(JSONNode a, object b) - { - if (ReferenceEquals(a, b)) - return true; - bool aIsNull = a is JSONNull || ReferenceEquals(a, null) || a is JSONLazyCreator; - bool bIsNull = b is JSONNull || ReferenceEquals(b, null) || b is JSONLazyCreator; - if (aIsNull && bIsNull) - return true; - return !aIsNull && a.Equals(b); - } - - public static bool operator !=(JSONNode a, object b) - { - return !(a == b); - } - - public override bool Equals(object obj) - { - return ReferenceEquals(this, obj); - } - - public override int GetHashCode() - { - return base.GetHashCode(); - } - - #endregion operators - - [ThreadStatic] - private static StringBuilder m_EscapeBuilder; - internal static StringBuilder EscapeBuilder - { - get - { - if (m_EscapeBuilder == null) - m_EscapeBuilder = new StringBuilder(); - return m_EscapeBuilder; - } - } - internal static string Escape(string aText) - { - var sb = EscapeBuilder; - sb.Length = 0; - if (sb.Capacity < aText.Length + aText.Length / 10) - sb.Capacity = aText.Length + aText.Length / 10; - foreach (char c in aText) - { - switch (c) - { - case '\\': - sb.Append("\\\\"); - break; - case '\"': - sb.Append("\\\""); - break; - case '\n': - sb.Append("\\n"); - break; - case '\r': - sb.Append("\\r"); - break; - case '\t': - sb.Append("\\t"); - break; - case '\b': - sb.Append("\\b"); - break; - case '\f': - sb.Append("\\f"); - break; - default: - if (c < ' ' || (forceASCII && c > 127)) - { - ushort val = c; - sb.Append("\\u").Append(val.ToString("X4")); - } - else - sb.Append(c); - break; - } - } - string result = sb.ToString(); - sb.Length = 0; - return result; - } - - private static JSONNode ParseElement(string token, bool quoted) - { - if (quoted) - return token; - string tmp = token.ToLower(); - if (tmp == "false" || tmp == "true") - return tmp == "true"; - if (tmp == "null") - return JSONNull.CreateOrGet(); - double val; - if (double.TryParse(token, NumberStyles.Float, CultureInfo.InvariantCulture, out val)) - return val; - else - return token; - } - - public static JSONNode Parse(string aJSON) - { - Stack stack = new Stack(); - JSONNode ctx = null; - int i = 0; - StringBuilder Token = new StringBuilder(); - string TokenName = ""; - bool QuoteMode = false; - bool TokenIsQuoted = false; - while (i < aJSON.Length) - { - switch (aJSON[i]) - { - case '{': - if (QuoteMode) - { - Token.Append(aJSON[i]); - break; - } - stack.Push(new JSONObject()); - if (ctx != null) - { - ctx.Add(TokenName, stack.Peek()); - } - TokenName = ""; - Token.Length = 0; - ctx = stack.Peek(); - break; - - case '[': - if (QuoteMode) - { - Token.Append(aJSON[i]); - break; - } - - stack.Push(new JSONArray()); - if (ctx != null) - { - ctx.Add(TokenName, stack.Peek()); - } - TokenName = ""; - Token.Length = 0; - ctx = stack.Peek(); - break; - - case '}': - case ']': - if (QuoteMode) - { - - Token.Append(aJSON[i]); - break; - } - if (stack.Count == 0) - throw new Exception("JSON Parse: Too many closing brackets"); - - stack.Pop(); - if (Token.Length > 0 || TokenIsQuoted) - ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); - TokenIsQuoted = false; - TokenName = ""; - Token.Length = 0; - if (stack.Count > 0) - ctx = stack.Peek(); - break; - - case ':': - if (QuoteMode) - { - Token.Append(aJSON[i]); - break; - } - TokenName = Token.ToString(); - Token.Length = 0; - TokenIsQuoted = false; - break; - - case '"': - QuoteMode ^= true; - TokenIsQuoted |= QuoteMode; - break; - - case ',': - if (QuoteMode) - { - Token.Append(aJSON[i]); - break; - } - if (Token.Length > 0 || TokenIsQuoted) - ctx.Add(TokenName, ParseElement(Token.ToString(), TokenIsQuoted)); - TokenIsQuoted = false; - TokenName = ""; - Token.Length = 0; - TokenIsQuoted = false; - break; - - case '\r': - case '\n': - break; - - case ' ': - case '\t': - if (QuoteMode) - Token.Append(aJSON[i]); - break; - - case '\\': - ++i; - if (QuoteMode) - { - char C = aJSON[i]; - switch (C) - { - case 't': - Token.Append('\t'); - break; - case 'r': - Token.Append('\r'); - break; - case 'n': - Token.Append('\n'); - break; - case 'b': - Token.Append('\b'); - break; - case 'f': - Token.Append('\f'); - break; - case 'u': - { - string s = aJSON.Substring(i + 1, 4); - Token.Append((char)int.Parse( - s, - System.Globalization.NumberStyles.AllowHexSpecifier)); - i += 4; - break; - } - default: - Token.Append(C); - break; - } - } - break; - - default: - Token.Append(aJSON[i]); - break; - } - ++i; - } - if (QuoteMode) - { - throw new Exception("JSON Parse: Quotation marks seems to be messed up."); - } - if (ctx == null) - return ParseElement(Token.ToString(), TokenIsQuoted); - return ctx; - } - - } - // End of JSONNode - - public partial class JSONArray : JSONNode - { - private List m_List = new List(); - private bool inline = false; - public override bool Inline - { - get { return inline; } - set { inline = value; } - } - - public override JSONNodeType Tag { get { return JSONNodeType.Array; } } - public override bool IsArray { get { return true; } } - public override Enumerator GetEnumerator() { return new Enumerator(m_List.GetEnumerator()); } - - 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 - { - get { return m_List.Count; } - } - - 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 tmp = m_List[aIndex]; - m_List.RemoveAt(aIndex); - return tmp; - } - - public override JSONNode Remove(JSONNode aNode) - { - m_List.Remove(aNode); - return aNode; - } - - public override IEnumerable Children - { - get - { - foreach (JSONNode N in m_List) - yield return N; - } - } - - - 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(']'); - } - } - // End of JSONArray - - public partial class JSONObject : JSONNode - { - private Dictionary m_Dict = new Dictionary(); - - private bool inline = false; - public override bool Inline - { - get { return inline; } - set { inline = value; } - } - - public override JSONNodeType Tag { get { return JSONNodeType.Object; } } - public override bool IsObject { get { return true; } } - - public override Enumerator GetEnumerator() { return new Enumerator(m_Dict.GetEnumerator()); } - - - public override JSONNode this[string aKey] - { - get - { - if (m_Dict.ContainsKey(aKey)) - return m_Dict[aKey]; - else - 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) - return; - string key = m_Dict.ElementAt(aIndex).Key; - m_Dict[key] = value; - } - } - - public override int Count - { - get { return m_Dict.Count; } - } - - public override void Add(string aKey, JSONNode aItem) - { - if (aItem == null) - aItem = JSONNull.CreateOrGet(); - - if (!string.IsNullOrEmpty(aKey)) - { - 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 tmp = m_Dict[aKey]; - m_Dict.Remove(aKey); - return tmp; - } - - public override JSONNode Remove(int aIndex) - { - if (aIndex < 0 || aIndex >= m_Dict.Count) - return null; - var item = m_Dict.ElementAt(aIndex); - m_Dict.Remove(item.Key); - return item.Value; - } - - public override JSONNode Remove(JSONNode aNode) - { - try - { - var item = m_Dict.Where(k => k.Value == aNode).First(); - m_Dict.Remove(item.Key); - return aNode; - } - catch - { - return null; - } - } - - public override IEnumerable Children - { - get - { - foreach (KeyValuePair N in m_Dict) - yield return N.Value; - } - } - - internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) - { - aSB.Append('{'); - bool first = true; - if (inline) - aMode = JSONTextMode.Compact; - foreach (var k in m_Dict) - { - if (!first) - aSB.Append(','); - first = false; - if (aMode == JSONTextMode.Indent) - aSB.AppendLine(); - if (aMode == JSONTextMode.Indent) - aSB.Append(' ', aIndent + aIndentInc); - aSB.Append('\"').Append(Escape(k.Key)).Append('\"'); - if (aMode == JSONTextMode.Compact) - aSB.Append(':'); - else - aSB.Append(" : "); - k.Value.WriteToStringBuilder(aSB, aIndent + aIndentInc, aIndentInc, aMode); - } - if (aMode == JSONTextMode.Indent) - aSB.AppendLine().Append(' ', aIndent); - aSB.Append('}'); - } - - } - // End of JSONObject - - public partial class JSONString : JSONNode - { - private string m_Data; - - public override JSONNodeType Tag { get { return JSONNodeType.String; } } - public override bool IsString { get { return true; } } - - public override Enumerator GetEnumerator() { return new Enumerator(); } - - - public override string Value - { - get { return m_Data; } - set - { - m_Data = value; - } - } - - public JSONString(string aData) - { - m_Data = aData; - } - - internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) - { - aSB.Append('\"').Append(Escape(m_Data)).Append('\"'); - } - public override bool Equals(object obj) - { - if (base.Equals(obj)) - return true; - string s = obj as string; - if (s != null) - return m_Data == s; - JSONString s2 = obj as JSONString; - if (s2 != null) - return m_Data == s2.m_Data; - return false; - } - public override int GetHashCode() - { - return m_Data.GetHashCode(); - } - } - // End of JSONString - - public partial class JSONNumber : JSONNode - { - private double m_Data; - - public override JSONNodeType Tag { get { return JSONNodeType.Number; } } - public override bool IsNumber { get { return true; } } - public override Enumerator GetEnumerator() { return new Enumerator(); } - - public override string Value - { - get { return m_Data.ToString(CultureInfo.InvariantCulture); } - set - { - double v; - if (double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out v)) - m_Data = v; - } - } - - 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 JSONNumber(double aData) - { - m_Data = aData; - } - - public JSONNumber(string aData) - { - Value = aData; - } - - internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) - { - aSB.Append(Value); - } - 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 s2 = obj as JSONNumber; - if (s2 != null) - return m_Data == s2.m_Data; - if (IsNumeric(obj)) - return Convert.ToDouble(obj) == m_Data; - return false; - } - public override int GetHashCode() - { - return m_Data.GetHashCode(); - } - } - // End of JSONNumber - - public partial class JSONBool : JSONNode - { - private bool m_Data; - - public override JSONNodeType Tag { get { return JSONNodeType.Boolean; } } - public override bool IsBoolean { get { return true; } } - public override Enumerator GetEnumerator() { return new Enumerator(); } - - public override string Value - { - get { return m_Data.ToString(); } - set - { - bool v; - if (bool.TryParse(value, out v)) - m_Data = v; - } - } - public override bool AsBool - { - get { return m_Data; } - set { m_Data = value; } - } - - public JSONBool(bool aData) - { - m_Data = aData; - } - - public JSONBool(string aData) - { - Value = aData; - } - - 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(); - } - } - // End of JSONBool - - public partial class JSONNull : JSONNode - { - static JSONNull m_StaticInstance = new JSONNull(); - public static bool reuseSameInstance = true; - public static JSONNull CreateOrGet() - { - if (reuseSameInstance) - return m_StaticInstance; - return new JSONNull(); - } - private JSONNull() { } - - public override JSONNodeType Tag { get { return JSONNodeType.NullValue; } } - public override bool IsNull { get { return true; } } - public override Enumerator GetEnumerator() { return new Enumerator(); } - - public override string Value - { - get { return "null"; } - set { } - } - public override bool AsBool - { - get { return false; } - set { } - } - - public override bool Equals(object obj) - { - if (object.ReferenceEquals(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"); - } - } - // End of JSONNull - - internal partial class JSONLazyCreator : JSONNode - { - private JSONNode m_Node = null; - private string m_Key = null; - public override JSONNodeType Tag { get { return JSONNodeType.None; } } - public override Enumerator GetEnumerator() { return new 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 aVal) where T : JSONNode - { - if (m_Key == null) - m_Node.Add(aVal); - else - m_Node.Add(m_Key, aVal); - m_Node = null; // Be GC friendly. - return aVal; - } - - 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 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 System.Object.ReferenceEquals(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 System.Object.ReferenceEquals(this, obj); - } - - public override int GetHashCode() - { - return 0; - } - - public override int AsInt - { - get { Set(new JSONNumber(0)); return 0; } - set { Set(new JSONNumber(value)); } - } - - public override float AsFloat - { - get { Set(new JSONNumber(0.0f)); return 0.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 (longAsString) - Set(new JSONString("0")); - else - Set(new JSONNumber(0.0)); - return 0L; - } - set - { - if (longAsString) - Set(new JSONString(value.ToString())); - else - Set(new JSONNumber(value)); - } - } - - public override bool AsBool - { - get { Set(new JSONBool(false)); return false; } - set { Set(new JSONBool(value)); } - } - - public override JSONArray AsArray - { - get { return Set(new JSONArray()); } - } - - public override JSONObject AsObject - { - get { return Set(new JSONObject()); } - } - internal override void WriteToStringBuilder(StringBuilder aSB, int aIndent, int aIndentInc, JSONTextMode aMode) - { - aSB.Append("null"); - } - } - // End of JSONLazyCreator - - public static class JSON - { - public static JSONNode Parse(string aJSON) - { - return JSONNode.Parse(aJSON); - } - } -} diff --git a/IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache b/IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache index 3de3543e..234d1974 100644 --- a/IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache +++ b/IllusionInjector/obj/Debug/IllusionInjector.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -f6d2b3a83d839d28f9c6280f831d88c7c7de66f4 +71a44b54b01a27b264d5e56666d3bd427569aee5 diff --git a/IllusionInjector/packages.config b/IllusionInjector/packages.config index 5ca7bb21..71c37d6d 100644 --- a/IllusionInjector/packages.config +++ b/IllusionInjector/packages.config @@ -1,4 +1,5 @@  + \ No newline at end of file diff --git a/Libs/System.Runtime.Serialization.dll b/Libs/System.Runtime.Serialization.dll new file mode 100644 index 00000000..48eb92bf Binary files /dev/null and b/Libs/System.Runtime.Serialization.dll differ