Insanely huge initial commit

This commit is contained in:
2026-02-21 17:04:05 -08:00
parent 9cdd36191a
commit 613d75914a
22525 changed files with 4035207 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 97069a453ee85044eb569c9e2537607f
folderAsset: yes
timeCreated: 1590931574
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
// ExcludeFromJSONSerialize
using System;
namespace Leguar.TotalJSON {
/// <summary>
/// Attribute that can be used to exclude single field from JSON serialization. With default serialization settings, this does same as System.NonSerialized attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
public sealed class ExcludeFromJSONSerializeAttribute : Attribute {
/// <summary>
/// Constructor for new ExcludeFromJSONSerialize attribute.
/// </summary>
public ExcludeFromJSONSerializeAttribute() {
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 034c500d71cd9534495808dd214850aa
timeCreated: 1590931574
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
// IncludeToJSONSerialize
using System;
namespace Leguar.TotalJSON {
/// <summary>
/// Attribute that can be used to include single field to JSON serialization. With default serialization settings, this does same as UnityEngine.SerializeField attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
public sealed class IncludeToJSONSerializeAttribute : Attribute {
/// <summary>
/// Constructor for new IncludeToJSONSerialize attribute.
/// </summary>
public IncludeToJSONSerializeAttribute() {
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8ba9598d27e19bb4390b76212069d33d
timeCreated: 1590931574
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 16c2aac88e0f4124097642e0c257e5d0
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
// DeserializeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if something goes wrong when deserializing JSON to objects.
/// </summary>
public class DeserializeException : ArgumentException {
private DeserializeException(string message) : base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
internal static DeserializeException forDictionaryKeyTypeNotString(Type type, string toFieldName) {
string fullMessage = "Can not deserialize to dictionary where key type is '"+type.GetType()+"'"+getToFieldNameString(toFieldName)+". Key type need to be string, or allow more loose options using DeserializeSettings";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forDictionaryKeyTypeNotKnown(Type type, string toFieldName) {
string fullMessage = "Can not deserialize to dictionary where key type is '"+type.GetType()+"'"+getToFieldNameString(toFieldName)+". Key type is none of the supported";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNonMatchingType(JValue jValue, Type type, string toFieldName) {
string fullMessage = "Can not deserialize '"+jValue.GetType()+"' to object which type is '"+type+"'"+getToFieldNameString(toFieldName);
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNoMatchingField(string fieldName, Type type) {
string fullMessage = "Can't find field named '"+fieldName+"' needed for object type '"+type+"'. Values for all fields need to exist, or allow more loose options using DeserializeSettings";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNoMatchingValue(Type type) {
string fullMessage = "Not all JSON values were used when populating object type '"+type+"'. Used DeserializeSettings requires that all fields are used";
return (new DeserializeException(fullMessage));
}
private static string getToFieldNameString(string toFieldName) {
return (string.IsNullOrEmpty(toFieldName) ? "" : " (field \""+toFieldName+"\")");
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d739cecfd5833dc42bd95ea1ee004e93
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JSON, JArray or JNumber parameter is invalid.
/// </summary>
public class JArgumentException : ArgumentException {
internal JArgumentException(string message, string paramName)
: base(message,paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4da601bc20dfdc642ad5c19464fb980a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JSON, JArray or JString parameter is null when it is not allowed to be null.
/// </summary>
public class JArgumentNullException : ArgumentNullException {
internal JArgumentNullException(string paramName, string message)
: base(paramName,message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c292f493140d1f6409bd3f0d25242435
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArrayIndexOutOfRangeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JArray method parameter is out of range.
/// </summary>
public class JArrayIndexOutOfRangeException : ArgumentOutOfRangeException {
internal JArrayIndexOutOfRangeException(string paramName, int actualValue, string message)
: base(paramName,actualValue,message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3c678893eebfa4b4f955712f5da64aa8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// JNumberFormatException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if trying to read JNumber value in wrong format, for example float as int.
/// </summary>
public class JNumberFormatException : FormatException {
internal JNumberFormatException(string valueAsString, string wantedType)
: base("JNumber value ("+valueAsString+") is floating point number and can't be returned as "+wantedType) {
}
internal JNumberFormatException(string valueAsString)
: base("JNumber value ("+valueAsString+") is not valid decimal number") { // (contains E/e notation, consider reading this value as double or float)
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 969a97261570e1e4697cb1fa851fe6ec
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JNumberOverflowException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if trying to read JNumber value in format where it doesn't fit. For example trying to read number 2147483648 as int.
/// </summary>
public class JNumberOverflowException : OverflowException {
internal JNumberOverflowException(string valueAsString, string wantedType, string minValue, string maxValue)
: base("JNumber value ("+valueAsString+") is outside "+wantedType+" range ["+minValue+".."+maxValue+"]") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f205c82ee9338384c8f040c98dabc3de
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JSONKeyAlreadyExistsException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if JSON already contains certain key and trying to add it again.
/// </summary>
public class JSONKeyAlreadyExistsException : ArgumentException {
internal JSONKeyAlreadyExistsException(string message)
: base(message,"key") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 77652c275db7f6047830bf596953706c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JSONKeyNotFoundException
using System.Collections.Generic;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if given parameter key doesn't exist in JSON.
/// </summary>
public class JSONKeyNotFoundException : KeyNotFoundException {
internal JSONKeyNotFoundException(string message)
: base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e47b0f3992e0232419eac53940948159
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// JValueNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to read value which is null while that is not allowed.
/// </summary>
public class JValueNullException : JValueTypeException {
internal JValueNullException(string key, string triedType, string exceptionMessageTail)
: base("Can not read value mapped to key \""+key+"\" as "+triedType+", value is null"+exceptionMessageTail) {
}
internal JValueNullException(int index, string triedType)
: base("Can not read value at index "+index+" as "+triedType+", value is null") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 43ec8a0036358ec41b40c1a534330183
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// JValueTypeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to read value which is different type than requested. For example trying to read bool (JBoolean) as string (JString).
/// </summary>
public class JValueTypeException : InvalidCastException {
internal JValueTypeException(string key, JValue realValue, string triedType, string exceptionMessageTail)
: base("Can not cast value mapped to key \""+key+"\" to "+triedType+", value type is "+realValue.GetType()+exceptionMessageTail) {
}
internal JValueTypeException(int arrayIndex, JValue realValue, string triedType)
: base("Can not cast array element at index "+arrayIndex+" to "+triedType+", element type is "+realValue.GetType()) {
}
protected JValueTypeException(string message)
: base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dd4e8553edfa51747a9f603037136b60
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
// ParseException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if parsing string to JSON or JArray fails.
/// </summary>
public class ParseException : ArgumentException {
private ParseException(string message) : base(message) {
}
internal static ParseException forEmpty(String message, ParseStringSettings parseStrignSettings) {
string fullMessage=message+getExceptionMessageTail(parseStrignSettings);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidStart(String message, ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage=message+" - "+sp.getLineAndColumnForException()+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidCharacter(String message, ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage=message+" - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(32)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidEnd(ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage="Unexpected end of input - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(16)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forCharactersAfterEnd(ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage="Unexpected non-white character after end of object - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(32)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
private static string getExceptionMessageTail(ParseStringRunner parseStringRunner) {
if (parseStringRunner!=null) {
return getExceptionMessageTailForID(parseStringRunner.getParseDebugIDForExceptions());
}
return getExceptionMessageTailForID(null);
}
internal static string getExceptionMessageTail(ParseStringSettings parseStringSettings) {
if (parseStringSettings!=null) {
return getExceptionMessageTailForID(parseStringSettings.DebugIDForExceptions);
}
return getExceptionMessageTailForID(null);
}
internal static string getExceptionMessageTailForID(string debugIDForExceptions) {
return InternalTools.getExceptionMessageTailForID(debugIDForExceptions,"Parse");
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9e4ae93c61b48af488cbf680e3f56180
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
// ProtectedException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to change anything in protected JSON or JArray objects.
/// </summary>
public class ProtectedException : Exception {
internal ProtectedException(string message) : base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 336cc7907a0696743b7748f5af9b05bc
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// SerializeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if something goes wrong when serializing system objects to JSON.
/// </summary>
public class SerializeException : ArgumentException {
internal SerializeException(string message)
: base(message) {
}
internal SerializeException(string message, object problemObject)
: base(message+", object type = "+problemObject.GetType()) {
}
internal SerializeException(string message, object problemObject, string paramName)
: base(message+", object type = "+problemObject.GetType(),paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d56315144217402429d47a7e5eeceb95
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if object added to JSON or JArray is type that can't be converted to any JValue.
/// </summary>
public class UnknownObjectTypeException : JArgumentException {
internal UnknownObjectTypeException(object unknownValue, string paramName)
: base("Parameter object is unknown type '"+unknownValue.GetType().ToString()+"'",paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 951941f4547f23840810348b4969ba00
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: aeff757c46539624ea433dfad5d5d062
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
// JValue - JBoolean
using System;
using System.Text;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store boolean value in JSON format. Once JBoolean instance is created, its value can't be changed.
/// </summary>
public class JBoolean : JValue {
private const string TRUE="true";
private const string FALSE="false";
private bool boolValue;
/// <summary>
/// Creates new instance of JBoolean class.
/// </summary>
/// <param name="value">
/// Boolean value stored to this object.
/// </param>
public JBoolean(bool boolValue) : base() {
this.boolValue = boolValue;
}
public override string ToString() {
return ("[JBoolean: "+(boolValue?TRUE:FALSE)+"]");
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JBoolean.
/// Two JBoolean objects are equal if both contains same boolean value.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JBoolean)) {
return false;
}
JBoolean anotherJBoolean=(JBoolean)(anotherObject);
return (boolValue==anotherJBoolean.AsBool());
}
public override int GetHashCode() {
return (boolValue?1:0);
}
/// <summary>
/// Get value of this JSON boolean as c# system bool.
/// </summary>
/// <returns>
/// System bool value.
/// </returns>
public bool AsBool() {
return boolValue;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(boolValue?TRUE:FALSE);
}
internal static JBoolean zParse(ParseStringRunner parseStringRunner, bool expectingTrue) {
StringPointer sp = parseStringRunner.getStringPointer();
if (expectingTrue) {
if (sp.isNextChars(TRUE.Substring(1))) {
return (new JBoolean(true));
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+TRUE+"'",parseStringRunner);
}
} else {
if (sp.isNextChars(FALSE.Substring(1))) {
return (new JBoolean(false));
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+FALSE+"'",parseStringRunner);
}
}
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// In case type is nullable type "bool?"
Type nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null) {
return this.zDeserialize(nullableType, toFieldName, deserializeSettings);
}
if (type==typeof(bool)) {
return this.AsBool();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsBool();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 1e8c311d10eb1fd469a766c3c9debde0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
// JValue - JNull
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store null value in JSON format.
/// </summary>
public class JNull : JValue {
private const string NULL="null";
/// <summary>
/// Creates new JNull object.
/// </summary>
public JNull() : base() {
}
public override string ToString() {
return ("[JNull]");
}
/// <summary>
/// Test if another object equals to this object. This method always returns true if parameter object is instance of JNull, but false if parameter is system null.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JNull)) {
return false;
}
return true;
}
public override int GetHashCode() {
return 101;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(NULL);
}
internal static JNull zParse(ParseStringRunner parseStringRunner) {
StringPointer sp = parseStringRunner.getStringPointer();
if (sp.isNextChars(NULL.Substring(1))) {
return (new JNull());
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+NULL+"'",parseStringRunner);
}
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// Do at least some basic checking that not trying to add null to number or boolean field, as trying to set null to these objects using FieldInfo doesn't cause exception.
// If field type is nullable like "bool?" or "int?", type is also System.Nullable so this check doesn't prevent adding null value to those fields.
if (type==typeof(float) || type==typeof(double) || type==typeof(decimal)
|| type==typeof(int) || type==typeof(long) || type==typeof(short) || type==typeof(byte)
|| type==typeof(uint) || type==typeof(ulong) || type==typeof(ushort) || type==typeof(sbyte)
|| type==typeof(bool)) {
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
// bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != null);
return null;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a6590f14a3524344684bb0378328c57a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,751 @@
// JValue - JNumber
using System;
using System.Text;
using System.Globalization;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store number value in JSON format. Once JNumber instance is created, its value can't be changed.
///
/// There is no limit how long or big numbers can be, but trying to read too big number for example as long will cause exception.
/// Oversized numbers can be still read out and handled as strings.
/// </summary>
public class JNumber : JValue {
private readonly string valueAsString;
/// <summary>
/// Creates new JSON number value from string. There is no limits in number size as long as it follows json number format.
/// </summary>
/// <param name="numberAsString">
/// Value for this JNumber object in string format.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter string is not valid number.
/// </exception>
public JNumber(string numberAsString) : base() {
string errorMessage=numberFormatCheck(numberAsString);
if (errorMessage!=null) {
throw (new JArgumentException("Parameter \""+numberAsString+"\" is not valid JSON format number: "+errorMessage,"numberAsString"));
}
valueAsString = numberAsString;
}
/// <summary>
/// Creates new JSON number value from c# int value.
/// </summary>
/// <param name="numberAsInt">
/// Value for this JNumber object.
/// </param>
public JNumber(int numberAsInt) : base() {
valueAsString=safeLongAsString(numberAsInt);
}
/// <summary>
/// Creates new JSON number value from c# long value.
/// </summary>
/// <param name="numberAsLong">
/// Value for this JNumber object.
/// </param>
public JNumber(long numberAsLong) : base() {
valueAsString=safeLongAsString(numberAsLong);
}
/// <summary>
/// Creates new JSON number value from c# float value.
/// </summary>
/// <param name="numberAsFloat">
/// Value for this JNumber object.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter is NaN or Infinity.
/// </exception>
public JNumber(float numberAsFloat) : base() {
if (float.IsNaN(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is NaN","numberAsFloat"));
}
if (float.IsPositiveInfinity(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is infinity","numberAsFloat"));
}
if (float.IsNegativeInfinity(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is negative infinity","numberAsFloat"));
}
valueAsString=safeFloatAsString(numberAsFloat);
}
/// <summary>
/// Creates new JSON number value from c# double value.
/// </summary>
/// <param name="numberAsDouble">
/// Value for this JNumber object.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter is NaN or Infinity.
/// </exception>
public JNumber(double numberAsDouble) : base() {
if (double.IsNaN(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is NaN","numberAsDouble"));
}
if (double.IsPositiveInfinity(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is infinity","numberAsDouble"));
}
if (double.IsNegativeInfinity(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is negative infinity","numberAsDouble"));
}
valueAsString=safeDoubleAsString(numberAsDouble);
}
/// <summary>
/// Creates new JSON number value from c# decimal value.
/// </summary>
/// <param name="numberAsDecimal">
/// Value for this JNumber object.
/// </param>
public JNumber(decimal numberAsDecimal) : base() {
valueAsString=addDecimalPoint(numberAsDecimal.ToString(CultureInfo.InvariantCulture));
}
private JNumber(string safeValueAsString, ParseStringRunner parseStringRunner) : base() {
valueAsString=parseStringRunner.getPossiblyFixedNumber(safeValueAsString);
}
public override string ToString() {
return ("[JNumber: "+valueAsString+"]");
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JNumber.
/// Two JNumber objects are equal if both contains value which string representation is exactly equal.
/// For example JNumber that contains "1" is not equal to JNumber that contains "1.0"
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JNumber)) {
return false;
}
JNumber anotherJNumber=(JNumber)(anotherObject);
return (valueAsString.Equals(anotherJNumber.AsString()));
}
public override int GetHashCode() {
return valueAsString.GetHashCode();
}
/// <summary>
/// Gets value of this number object as long. This will throw exception if number is floating point number or outside long range.
/// </summary>
/// <returns>
/// Value as long.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in long.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public long AsLong() {
try {
return long.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"long",""+long.MinValue,""+long.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"long"));
}
}
/// <summary>
/// Gets value of this number object as unsigned long. This will throw exception if number is floating point number or outside ulong range.
/// </summary>
/// <returns>
/// Value as ulong.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in ulong.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public ulong AsULong() {
try {
return ulong.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"ulong",""+ulong.MinValue,""+ulong.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"ulong"));
}
}
/// <summary>
/// Gets value of this number object as int. This will throw exception if number is floating point number or outside int range.
/// </summary>
/// <returns>
/// Value as int.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in int.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public int AsInt() {
try {
return int.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"int",""+int.MinValue,""+int.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"int"));
}
}
/// <summary>
/// Gets value of this number object as unsigned int. This will throw exception if number is floating point number or outside uint range.
/// </summary>
/// <returns>
/// Value as uint.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in uint.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public uint AsUInt() {
try {
return uint.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"uint",""+uint.MinValue,""+uint.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"uint"));
}
}
/// <summary>
/// Gets value of this number object as short. This will throw exception if number is floating point number or outside short range.
/// </summary>
/// <returns>
/// Value as short.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in short.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public short AsShort() {
try {
return short.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"short",""+short.MinValue,""+short.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"short"));
}
}
/// <summary>
/// Gets value of this number object as unsigned short. This will throw exception if number is floating point number or outside ushort range.
/// </summary>
/// <returns>
/// Value as ushort.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in ushort.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public ushort AsUShort() {
try {
return ushort.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"ushort",""+ushort.MinValue,""+ushort.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"ushort"));
}
}
/// <summary>
/// Gets value of this number object as byte. This will throw exception if number is floating point number or outside byte range.
/// </summary>
/// <returns>
/// Value as byte.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in byte.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public byte AsByte() {
try {
return byte.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"byte",""+byte.MinValue,""+byte.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"byte"));
}
}
/// <summary>
/// Gets value of this number object as signed byte. This will throw exception if number is floating point number or outside sbyte range.
/// </summary>
/// <returns>
/// Value as sbyte.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in sbyte.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public sbyte AsSByte() {
try {
return sbyte.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"sbyte",""+sbyte.MinValue,""+sbyte.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"sbyte"));
}
}
/// <summary>
/// Gets value of this number object as double. This will throw exception if number is outside double range.
/// </summary>
/// <returns>
/// Value as double.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in double.
/// </exception>
public double AsDouble() {
try {
double value=double.Parse(valueAsString,CultureInfo.InvariantCulture);
if (double.IsInfinity(value)) {
throw (new OverflowException());
}
return value;
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"double",""+double.MinValue,""+double.MaxValue));
}
}
/// <summary>
/// Gets value of this number object as float. This will throw exception if number is outside float range.
/// </summary>
/// <returns>
/// Value as float.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in float.
/// </exception>
public float AsFloat() {
try {
float value=float.Parse(valueAsString,CultureInfo.InvariantCulture);
if (float.IsInfinity(value)) {
throw (new OverflowException());
}
return value;
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"float",""+float.MinValue,""+float.MaxValue));
}
}
/// <summary>
/// Gets value of this number object as decimal. This will throw exception if number is outside decimal range or number contains E/e notation.
/// </summary>
/// <returns>
/// Value as decimal.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in decimal.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber uses E/e notation (like 1.234567e89)
/// </exception>
public decimal AsDecimal() {
try {
return decimal.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"decimal",""+decimal.MinValue,""+decimal.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString));
}
}
/// <summary>
/// Gets value of this number as string.
/// </summary>
/// <returns>
/// Value as string.
/// </returns>
public string AsString() {
return valueAsString;
}
/// <summary>
/// Gets value of this number as object. First fitting value of these are returned: int, long, float, double
/// </summary>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in double.
/// </exception>
/// <returns>
/// Value as object, that may be one of the 4 basic number objects.
/// </returns>
public object AsObject() {
int iValue;
if (int.TryParse(valueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out iValue)) {
return iValue;
}
long lValue;
if (long.TryParse(valueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out lValue)) {
return lValue;
}
float fValue;
if (float.TryParse(valueAsString, NumberStyles.Float, CultureInfo.InvariantCulture, out fValue)) {
if (!float.IsInfinity(fValue)) {
return fValue;
}
}
// This could fail too in extreme cases, but custom exception is thrown
return this.AsDouble();
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(this.AsString());
}
internal static JNumber zParse(ParseStringRunner parseStringRunner, char firstChr) {
StringPointer sp = parseStringRunner.getStringPointer();
int start=sp.getCurrentIndex()-1; // -1 since first character is already read
bool valid=parseCheck(sp,firstChr);
if (!valid) {
throw ParseException.forInvalidCharacter("Invalid number value \""+sp.getSubStringStartingFrom(start)+"\"",parseStringRunner);
} else {
sp.stepBack();
string validNumber=sp.getSubStringStartingFrom(start);
return (new JNumber(validNumber,parseStringRunner));
}
}
private static bool parseCheck(StringPointer sp, char chr) {
int state;
if (chr=='-') {
chr=sp.getNextChar();
}
if (chr=='0') {
chr=sp.getNextChar();
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)0
}
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return false;
}
do {
chr=sp.getNextChar();
if (state==4) {
if (chr>='0' && chr<='9') {
state=4;
} else if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)##
}
} else if (state==5) {
if (chr>='0' && chr<='9') {
state=6;
} else {
return false;
}
} else if (state==6) {
if (chr>='0' && chr<='9') {
state=6;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)(##).##
}
} else if (state==7) {
if (chr=='+' || chr=='-') {
chr=sp.getNextChar();
if (chr>='0' && chr<='9') {
state=9;
} else {
return false;
}
} else if (chr>='0' && chr<='9') {
state=9;
} else {
return false;
}
} else if (state==9) {
if (chr>='0' && chr<='9') {
state=9;
} else {
return true; // (-)(##).##[e/E](+/-)##
}
}
} while (true);
}
private static string numberFormatCheck(string str) {
int count=str.Length,
state=1;
for (int index=0; index<count; index++) {
char chr=str[index];
if (state==1) { // Minus or first digit
if (chr=='-') {
state=2;
} else if (chr=='0') {
state=3;
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return ("Invalid first character '"+chr+"', should be digit or minus sign");
}
} else if (state==2) { // First digit after minus
if (chr=='0') {
state=3;
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return ("Expecting at least one digit after minus sign, got '"+chr+"' instead");
}
} else if (state==3) { // Number started with (minus) zero, only decimal point or E can follow
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return ("Only decimal point or E/e can follow number starting with 0 or -0, got '"+chr+"' instead");
}
} else if (state==4) { // Digits before decimal point or E
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' (before possible decimal point or E/e)");
}
} else if (state==5) { // Need at least one digit after decimal point
if (chr>='0' && chr<='9') {
state=6;
} else {
return ("Need at least one digit after decimal point, got '"+chr+"' instead");
}
} else if (state==6) { // Following digits after decimal point
if (chr=='e' || chr=='E') {
state=7;
} else if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' after decimal point");
}
} else if (state==7) { // Plus, minus or digit after E
if (chr=='+' || chr=='-') {
state=8;
} else if (chr>='0' && chr<='9') {
state=9;
} else {
return ("Expecting digit or plus/minus sign after E/e, got '"+chr+"' instead");
}
} else if (state==8) { // Need at least one digit after E plus/minus,
if (chr>='0' && chr<='9') {
state=9;
} else {
return ("Expecting digit after plus/minus sign after E/e, got '"+chr+"' instead");
}
} else if (state==9) { // Following digits after E
if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' in digits after E/e");
}
}
}
if (state==1) {
return "String is empty";
}
if (state==2) {
return "String contains only minus sign";
}
if (state==5) {
return "No digits after decimal point";
}
if (state==7) {
return "Need at least one digit after E/e";
}
if (state==8) {
return "Need at least one digit after plus/minus sign after E/e";
}
return null;
}
private string safeFloatAsString(float value) {
// Basic change that doesn't add too many decimals
string basicStr=value.ToString(CultureInfo.InvariantCulture);
basicStr=addDecimalPoint(basicStr);
try {
float reverse=float.Parse(basicStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) { // May not be true because rounding
return basicStr;
}
}
catch (OverflowException) {
// This happens because rounding if value is close min/max
}
// Try out with more decimals
string rStr=value.ToString("R",CultureInfo.InvariantCulture);
rStr=addDecimalPoint(rStr);
try {
float reverse=float.Parse(rStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return rStr;
}
}
catch (Exception) {
}
// If neither works, fall back to simplest
return basicStr;
}
private string safeDoubleAsString(double value) {
// Basic change that doesn't add too many decimals
string basicStr=value.ToString(CultureInfo.InvariantCulture);
basicStr=addDecimalPoint(basicStr);
try {
double reverse=double.Parse(basicStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return basicStr;
}
}
catch (OverflowException) {
// This happens because rounding if value is close min/max
}
// Try out with more decimals
string rStr=value.ToString("R",CultureInfo.InvariantCulture);
rStr=addDecimalPoint(rStr);
try {
double reverse=double.Parse(rStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return rStr;
}
}
catch (Exception) {
}
// If neither works, fall back to simplest
return basicStr;
}
private static string addDecimalPoint(string str) {
if (str.IndexOf('E')==-1 && str.IndexOf('e')==-1 && str.IndexOf('.')==-1) {
str+=".0";
}
return str;
}
private static string safeLongAsString(long value) {
return value.ToString(CultureInfo.InvariantCulture);
}
private static string safeULongAsString(ulong value) {
return value.ToString(CultureInfo.InvariantCulture);
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// In case type is nullable type, for example "int?"
Type nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null) {
return this.zDeserialize(nullableType, toFieldName, deserializeSettings);
}
if (type==typeof(float)) {
return this.AsFloat();
}
if (type==typeof(double)) {
return this.AsDouble();
}
if (type==typeof(decimal)) {
return this.AsDecimal();
}
if (type==typeof(int)) {
return this.AsInt();
}
if (type==typeof(long)) {
return this.AsLong();
}
if (type==typeof(short)) {
return this.AsShort();
}
if (type==typeof(byte)) {
return this.AsByte();
}
if (type==typeof(uint)) {
return this.AsUInt();
}
if (type==typeof(ulong)) {
return this.AsULong();
}
if (type==typeof(ushort)) {
return this.AsUShort();
}
if (type==typeof(sbyte)) {
return this.AsSByte();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsObject();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 23275ca83e39b864188eecf9c5fa19ee
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2ac3101645eb62d46b49e8887468095c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,211 @@
// JValue - JString
using System;
using System.Text;
using System.Collections.Generic;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store string value in JSON format. Once JString instance is created, its value can't be changed.
/// </summary>
public class JString : JValue { // , IEquatable<JString> {
private const string HEX="0123456789ABCDEF";
private string stringValue;
/// <summary>
/// Creates new instance of JString object.
///
/// Parameter can't be null. If you wish to add null to JSON or JArray object, create <code>new JNull()</code> and add that one.
/// </summary>
/// <param name="stringValue">
/// C# string value to be stored in this object.
/// </param>
/// <exception cref="JArgumentNullException">
/// If parameter is null.
/// </exception>
public JString(string stringValue) : base() {
if (stringValue==null) {
throw (new JArgumentNullException("stringValue","Parameter can not be null in constructor JString.<init>(string)"));
}
this.stringValue=stringValue;
}
public override string ToString() {
int length = stringValue.Length;
if (length==0) {
return ("[JString: Empty string]");
} else {
return ("[JString: \""+stringValue+"\" ("+length+" character"+(length>1?"s":"")+")]");
}
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JString.
/// Two JString objects are equal if both contains exactly same string.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JString)) {
return false;
}
JString anotherJString=(JString)(anotherObject);
return (stringValue.Equals(anotherJString.AsString()));
}
public override int GetHashCode() {
return stringValue.GetHashCode();
}
/// <summary>
/// Get value of this JSON string as c# system string.
/// </summary>
/// <returns>
/// c# string value, can not be null.
/// </returns>
public string AsString() {
return stringValue;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
encode(createStringRunner,stringValue);
}
internal static void encode(CreateStringRunner createStringRunner, string str) {
createStringRunner.append('"');
foreach (char chr in str) {
if (chr=='"') {
createStringRunner.append("\\\"");
} else if (chr=='\\') {
createStringRunner.append("\\\\");
} else if (chr=='/' && createStringRunner.isEscapeForwardSlashes()) {
createStringRunner.append("\\/");
} else if (chr=='\b') {
createStringRunner.append("\\b");
} else if (chr=='\f') {
createStringRunner.append("\\f");
} else if (chr=='\n') {
createStringRunner.append("\\n");
} else if (chr=='\r') {
createStringRunner.append("\\r");
} else if (chr=='\t') {
createStringRunner.append("\\t");
} else if (chr<32 || chr>126) { // } else if (chr<32 || (chr>126 && createStringRunner.isEncodeNon7bitCharacters())) {
if (chr<16) {
createStringRunner.append("\\u000");
createStringRunner.append(HEX[chr]);
} else if (chr<256) {
createStringRunner.append("\\u00");
createStringRunner.append(HEX[chr/16]);
createStringRunner.append(HEX[chr%16]);
} else if (chr<4096) {
createStringRunner.append("\\u0");
createStringRunner.append(HEX[chr/256]);
createStringRunner.append(HEX[(chr%256)/16]);
createStringRunner.append(HEX[chr%16]);
} else {
createStringRunner.append("\\u");
createStringRunner.append(HEX[chr/4096]);
createStringRunner.append(HEX[(chr%4096)/256]);
createStringRunner.append(HEX[(chr%256)/16]);
createStringRunner.append(HEX[chr%16]);
}
} else {
createStringRunner.append(chr);
}
}
createStringRunner.append('"');
}
internal static JString zParse(ParseStringRunner parseStringRunner, bool expectStartOfString) {
StringPointer sp = parseStringRunner.getStringPointer();
if (expectStartOfString) {
char chr;
if (!sp.tryGetNextNonWhiteChar(out chr)) {
throw ParseException.forInvalidStart("Parameter string didn't contain any non-white characters",parseStringRunner);
}
if (chr!='"') {
throw ParseException.forInvalidStart("Invalid character '"+chr+"' when expecting start of string '\"'",parseStringRunner);
}
}
return (new JString(decode(parseStringRunner)));
}
internal static string decode(ParseStringRunner parseStringRunner) {
// At this point, StringPointer has passed starting "
StringPointer sp = parseStringRunner.getStringPointer();
StringBuilder sb=new StringBuilder();
do {
char chr=sp.getNextChar();
if (chr=='"') {
return sb.ToString();
}
if (chr=='\\') {
chr=sp.getNextChar();
if (chr=='"' || chr=='\\' || chr=='/') {
// 'chr' works as is
} else if (chr=='b') {
chr='\b';
} else if (chr=='f') {
chr='\f';
} else if (chr=='n') {
chr='\n';
} else if (chr=='r') {
chr='\r';
} else if (chr=='t') {
chr='\t';
} else if (chr=='u') {
int ucode=0;
for (int n=0; n<4; n++) {
chr=sp.getNextChar();
int uvalue=HEX.IndexOf(char.ToUpperInvariant(chr));
if (uvalue<0) {
throw ParseException.forInvalidCharacter("Invalid hexadecimal character '"+chr+"' after '\\u' in string value",parseStringRunner);
}
ucode=ucode*16+uvalue;
}
chr=(char)(ucode);
} else {
throw ParseException.forInvalidCharacter("Invalid character '"+chr+"' after '\\' in string value",parseStringRunner);
}
}
sb.Append(chr);
} while (true);
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
if (type==typeof(string)) {
return this.AsString();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsString();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 0ac0f6ca9838f034faae8634da415da2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
// JValue
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Abstract base class for all JSON objects: JSON, JArray, JNumber, JBoolean, JString and JNull.
/// </summary>
public abstract class JValue {
protected JValue() {
}
/// <summary>
/// Turns this object to JSON formatted string.
/// </summary>
/// <returns>
/// This object as JSON formatted string, containing only basic ascii characters between [32..126] without line feeds.
/// </returns>
public virtual string CreateString() {
return CreateString(new CreateStringSettings());
}
/// <summary>
/// Turns this object to JSON formatted string using specified settings.
/// </summary>
/// <returns>
/// This object as JSON formatted string.
/// </returns>
public virtual string CreateString(CreateStringSettings settings) {
CreateStringRunner createStringRunner = new CreateStringRunner(settings);
zCreate(createStringRunner);
return createStringRunner.getFinalString();
}
internal abstract void zCreate(CreateStringRunner createStringRunner);
internal abstract object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings);
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: bee442bd1b37b0443b732f66c02dbdd1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 127024a622546da49addc03939a56ba7
folderAsset: yes
timeCreated: 1539193114
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
// CreateStringSettings
using System;
using UnityEngine;
namespace Leguar.TotalJSON {
/// <summary>
/// Settings that can be used to make output of creating JSON-formatted string different.
/// </summary>
public class CreateStringSettings {
private bool escapeForwardSlashes = false;
/// <summary>
/// Sets forward slashes to escaped or not. TotalJSON default is false since escaped forward slashes could cause problems if included to C# code.
/// However, if resulting JSON string is included to for example HTML or JavaScript, it is better to set forward slash escaping on.
/// </summary>
/// <value>
/// True to escape forward slashes ("\/"), false to not ("/").
/// </value>
public bool EscapeForwardSlashes {
set {
escapeForwardSlashes = value;
}
get {
return escapeForwardSlashes;
}
}
private bool humanReadable = false;
/// <summary>
/// Sets output to be more human readable. Linefeeds and indentations are added to output to make it easier for humans to read and edit.
/// Output is still completely valid JSON that can be parsed back to JSON or JArray object.
/// </summary>
/// <value>
/// True to make output human readable. Default is false.
/// </value>
public bool HumanReadable {
set {
humanReadable = value;
}
get {
return humanReadable;
}
}
private bool indentUsingTab = true;
/// <summary>
/// Sets whatever indent of human readable output should use tabs. If false, spaces are used instead of tab.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true.
/// </remarks>
/// <value>
/// True to use tabs for indent. Default is true.
/// </value>
public bool IndentUsingTab {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.IndentUsingTab setting have no effect when CreateStringSettings.HumanReadable is false");
}
indentUsingTab = value;
}
get {
return indentUsingTab;
}
}
private int indentSpaceCount = 4;
/// <summary>
/// Sets how many spaces are used for indent. Can be 0 or any positive integer.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true and 'IndentUsingTab' is false.
/// </remarks>
/// <value>
/// Amount of spaces to use for indent. Default is 4.
/// </value>
public int IndentSpaceCount {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.IndentSpaceCount setting have no effect when CreateStringSettings.HumanReadable is false");
} else if (indentUsingTab) {
Debug.LogWarning("CreateStringSettings.IndentSpaceCount setting have no effect when CreateStringSettings.IndentUsingTab is true");
}
indentSpaceCount = value;
}
get {
return indentSpaceCount;
}
}
public enum NewLineTypes {
EnvironmentDefault,
LF,
CR_LF
}
private NewLineTypes newLine = NewLineTypes.EnvironmentDefault;
/// <summary>
/// Sets type of linefeeds in human readable output.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true.
/// </remarks>
/// <value>
/// Type of linefeeds, one of values from NewLineTypes. Default is EnvironmentDefault.
/// </value>
public NewLineTypes NewLine {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.NewLine setting have no effect when CreateStringSettings.HumanReadable is false");
}
newLine = value;
}
get {
return newLine;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e51ce8bcbc9ee4c4db94a03f8c456c64
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
// DeserializeSettings
namespace Leguar.TotalJSON {
/// <summary>
/// Settings for deserialization.
/// </summary>
public class DeserializeSettings {
private bool allowFieldsToBeObjects = false;
/// <summary>
/// By default this is false. Meaning that any fields where values are deserialized need to be exactly same type as JSON object. For example JBoolean goes only to
/// bool, JString goes only to string, JSON goes only to Dictionary etc.
///
/// If this is set true, deserialization allows target fields also to be just objects (System.Object). Note however that in some cases deserialization may need to
/// "guess" the correct type, for example if deserializing JNumber to object field ("10" can be either int, long, float or double).
/// </summary>
/// <value>
/// False by default, set true to allow more loose deserialization.
/// </value>
public bool AllowFieldsToBeObjects {
set {
allowFieldsToBeObjects = value;
}
get {
return allowFieldsToBeObjects;
}
}
private bool allowNonStringDictionaryKeys = false;
/// <summary>
/// By default this is false. Meaning that if any JSON object is deserialized to dictionary, target dictionary must be using string keys, like JSON itself is using.
///
/// If this is set true, dictionaries key type may also be integer or long. In this case deserialization try to change JSON keys to required dictionary key type.
/// Note however that this may cause several problems when deserializing. For example, JSON object may contain keys "1" and "01". Deserializing this to Dictionary
/// with string keys can be done without issues. But deserializing that JSON to Dictionary with integer keys causes error due duplicate key, even original JSON is
/// completely valid.
/// </summary>
/// <value>
/// False by default, set true to allow more loose and flexible deserialization to dictionaries.
/// </value>
public bool AllowNonStringDictionaryKeys {
set {
allowNonStringDictionaryKeys = value;
}
get {
return allowNonStringDictionaryKeys;
}
}
private bool ignoreSystemAndUnitySerializeAttributes = false;
/// <summary>
/// By default this is false. Meaning that deserialization will check fields for UnityEngine.SerializeField and System.NonSerialized attributes and follow those.
///
/// In case these attributes are required for other uses but JSON deserialization should not follow these attributes, you can set this setting to true and those
/// attributes will be ignored during JSON deserialization. You can still include/exclude single fields during deserialization using TotalJSON's own
/// IncludeToJSONSerialize and ExcludeFromJSONSerialize attributes which are always followed regardless of this setting.
/// </summary>
/// <value>
/// False by default, set true to ignore non-json specific serialization attributes.
/// </value>
public bool IgnoreSystemAndUnitySerializeAttributes {
set {
ignoreSystemAndUnitySerializeAttributes = value;
}
get {
return ignoreSystemAndUnitySerializeAttributes;
}
}
private bool requireAllFieldsArePopulated = true;
/// <summary>
/// Default is true, meaning all the public fields in class/struct where JSON is deserialized must get their value set. So source JSON must contain matching values
/// for all the fields.
///
/// If set to false, fields that have no matching data in JSON are just left in their default values.
///
/// For example, with default setting, deserializing JSON {"a":1,"b":2} to class { public int a; public int b; public int c; } will cause exception since there's
/// no value for field 'c'.
/// </summary>
/// <value>
/// True by default, set false to allow classes/structs not to get fully populated.
/// </value>
public bool RequireAllFieldsArePopulated {
set {
requireAllFieldsArePopulated = value;
}
get {
return requireAllFieldsArePopulated;
}
}
private bool requireAllJSONValuesAreUsed = false;
/// <summary>
/// Default is false, meaning that any possible extra values in source JSON are ignored. If set to true, it is strictly required that all the values from JSON must
/// get used to populate some field in target class/struct.
///
/// For example, with default setting, deserializing JSON {"a":1,"b":2,"c":3} to class { public int a; public int b; } is acceptable and JSON value for 'c' is just
/// not used.
/// </summary>
/// <value>
/// False by default, set true to require that everything in source JSON is used.
/// </value>
public bool RequireAllJSONValuesAreUsed {
set {
requireAllJSONValuesAreUsed = value;
}
get {
return requireAllJSONValuesAreUsed;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 75df3196b7ff7f146a45b3bea4f17153
timeCreated: 1575388796
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
// ParseStringSettings
using System;
using UnityEngine;
namespace Leguar.TotalJSON {
/// <summary>
/// Settings that can be used to make changes how string is parsed to JSON or JArray.
/// </summary>
public class ParseStringSettings {
private bool fixRoundedFloatingPointMinMaxValues = true;
/// <summary>
/// If set true, numeric values that seem to be just rounded float.MinValue, float.MaxValue, double.MinValue or double.MaxValue are set to those exact values.
///
/// C# floating point numbers rounding sometimes causes unwanted effects. In some systems, for example double.Parse(double.MaxValue.ToString()) will cause number overflow exception.
/// TotalJSON will use exact values when creating JSON formatted string using CreateString() method. But if JSON is created using other methods and it is possible JSON may contain
/// rounded floating point min/max values, it is better to set this setting true so that parsed values are what they are expected to be.
/// </summary>
/// <value>
/// True to fix rounded floating point values to float/double min/max values. False to parse numbers exactly as they are. Default is true.
/// </value>
public bool FixRoundedFloatingPointMinMaxValues {
set {
fixRoundedFloatingPointMinMaxValues = value;
}
get {
return fixRoundedFloatingPointMinMaxValues;
}
}
private int parseStartIndex = 0;
/// <summary>
/// Sets index of input string where parsing JSON or JArray object is started.
/// </summary>
/// <value>
/// The index of the parse start. Default is 0.
/// </value>
public int ParseStartIndex {
set {
parseStartIndex = value;
}
get {
return parseStartIndex;
}
}
private bool allowNonWhiteCharactersAfterObject = false;
/// <summary>
/// Sets whatever it is acceptable for input string to have other than non-white characters after end of JSON or JArray object.
/// </summary>
/// <value>
/// If set to true, non-white characters are accepted at end of object. Default is false, so expecting that input string ends at the end of JSON or JArray object.
/// </value>
public bool AllowNonWhiteCharactersAfterObject {
set {
allowNonWhiteCharactersAfterObject = value;
}
get {
return allowNonWhiteCharactersAfterObject;
}
}
private string debugIDForExceptions = null;
/// <summary>
/// Sets debug ID for this string parse and resulting JSON object. If any exception occurres during parsing or JSON handling after
/// succesful parse, this debug ID will be added to exception message.
///
/// This is typically useful in production builds where only exception message is logged but full stacktrace may not be available.
/// Typical parse error could be that source string is null or empty for some reason. Without adding this debug id to the parse,
/// exception is just "ParseException: Source string is empty" which isn't very helpful if project is parsing lots of incoming JSON
/// and so it is not clear which one causes this error. When adding this debug id to the parse, above exception would be for example
/// "ParseException: Source string is empty - Parse Debug ID: Backend own currency settings", which pinpoints the problem instantly.
/// </summary>
/// <value>
/// Debug ID. Default is null.
/// </value>
public string DebugIDForExceptions {
set {
debugIDForExceptions = value;
}
get {
return debugIDForExceptions;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: cef3164b1a677324f831ad8b0c509a49
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
// SerializeSettings
namespace Leguar.TotalJSON {
/// <summary>
/// Settings for serialization.
/// </summary>
public class SerializeSettings {
private bool allowNonStringDictionaryKeys = false;
/// <summary>
/// By default this is false. Meaning that if any dictionary is serialized to JSON object, source dictionary must be using string keys, like JSON itself is using.
///
/// If this is set false, dictionaries key type may be anything and serialization is just using ToString() to create key. In this case, make sure each dictionary
/// key string representation is unique.
/// </summary>
/// <value>
/// False by default, set true to allow any dictionary keys.
/// </value>
public bool AllowNonStringDictionaryKeys {
set {
allowNonStringDictionaryKeys = value;
}
get {
return allowNonStringDictionaryKeys;
}
}
private bool ignoreSystemAndUnitySerializeAttributes = false;
/// <summary>
/// By default this is false. Meaning that serialization will check fields for UnityEngine.SerializeField and System.NonSerialized attributes and follow those.
///
/// In case these attributes are required for other uses but JSON serialization should not follow these attributes, you can set this setting to true and those
/// attributes will be ignored during JSON serialization. You can still include/exclude single fields from serialization using TotalJSON's own
/// IncludeToJSONSerialize and ExcludeFromJSONSerialize attributes which are always followed regardless of this setting.
/// </summary>
/// <value>
/// False by default, set true to ignore non-json specific serialization attributes.
/// </value>
public bool IgnoreSystemAndUnitySerializeAttributes {
set {
ignoreSystemAndUnitySerializeAttributes = value;
}
get {
return ignoreSystemAndUnitySerializeAttributes;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a0a1c7d8f21e2f24bbf40192a47ff82a
timeCreated: 1575455464
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: