diff --git a/sources/Data/JSON/JArray.uc b/sources/Data/JSON/JArray.uc index d160b54..8612fd3 100644 --- a/sources/Data/JSON/JArray.uc +++ b/sources/Data/JSON/JArray.uc @@ -79,6 +79,15 @@ public final function float GetNumber(int index, optional float defaultValue) return data[index].numberValue; } +public final function float GetInteger(int index, optional float defaultValue) +{ + if (index < 0) return defaultValue; + if (index >= data.length) return defaultValue; + if (data[index].type != JSON_Number) return defaultValue; + + return data[index].numberValueAsInt; +} + public final function string GetString(int index, optional string defaultValue) { if (index < 0) return defaultValue; @@ -88,6 +97,21 @@ public final function string GetString(int index, optional string defaultValue) return data[index].stringValue; } +public final function class GetClass( + int index, + optional class defaultValue) +{ + if (index < 0) return defaultValue; + if (index >= data.length) return defaultValue; + if (data[index].type != JSON_String) return defaultValue; + + TryLoadingStringAsClass(data[index]); + if (data[index].stringValueAsClass != none) { + return data[index].stringValueAsClass; + } + return defaultValue; +} + public final function bool GetBoolean(int index, optional bool defaultValue) { if (index < 0) return defaultValue; @@ -132,8 +156,7 @@ public final function JObject GetObject(int index) // `false` (nothing will be done in this case). // They return object itself, allowing user to chain calls like this: // `array.SetNumber("num1", 1).SetNumber("num2", 2);`. -public final function JArray SetNumber -( +public final function JArray SetNumber( int index, float value, optional bool preventExpansion @@ -153,8 +176,36 @@ public final function JArray SetNumber SetLength(index + 1); } } - newStorageValue.type = JSON_Number; - newStorageValue.numberValue = value; + newStorageValue.type = JSON_Number; + newStorageValue.numberValue = value; + newStorageValue.numberValueAsInt = int(value); + data[index] = newStorageValue; + return self; +} + +public final function JArray SetInteger( + int index, + int value, + optional bool preventExpansion +) +{ + local JStorageAtom newStorageValue; + if (index < 0) return self; + + if (index >= data.length) + { + if (preventExpansion) + { + return self; + } + else + { + SetLength(index + 1); + } + } + newStorageValue.type = JSON_Number; + newStorageValue.numberValue = float(value); + newStorageValue.numberValueAsInt = value; data[index] = newStorageValue; return self; } @@ -186,6 +237,33 @@ public final function JArray SetString return self; } +public final function JArray SetClass( + int index, + class value, + optional bool preventExpansion +) +{ + local JStorageAtom newStorageValue; + if (index < 0) return self; + + if (index >= data.length) + { + if (preventExpansion) + { + return self; + } + else + { + SetLength(index + 1); + } + } + newStorageValue.type = JSON_String; + newStorageValue.stringValue = string(value); + newStorageValue.stringValueAsClass = value; + data[index] = newStorageValue; + return self; +} + public final function JArray SetBoolean ( int index, @@ -306,11 +384,21 @@ public final function JArray AddNumber(float value) return SetNumber(data.length, value); } +public final function JArray AddInteger(int value) +{ + return SetInteger(data.length, value); +} + public final function JArray AddString(string value) { return SetString(data.length, value); } +public final function JArray AddClass(class value) +{ + return SetClass(data.length, value); +} + public final function JArray AddBoolean(bool value) { return SetBoolean(data.length, value); diff --git a/sources/Data/JSON/JObject.uc b/sources/Data/JSON/JObject.uc index 4c0a0bb..4f8f48e 100644 --- a/sources/Data/JSON/JObject.uc +++ b/sources/Data/JSON/JObject.uc @@ -272,13 +272,7 @@ public final function class GetClass( if (property.value.type != JSON_String) { return defaultValue; } - if (!property.value.classLoadingWasAttempted) - { - property.value.classLoadingWasAttempted = true; - property.value.stringValueAsClass = - class(DynamicLoadObject( property.value.stringValue, - class'Class', true)); - } + TryLoadingStringAsClass(property.value); if (property.value.stringValueAsClass != none) { return property.value.stringValueAsClass; } diff --git a/sources/Data/JSON/JSON.uc b/sources/Data/JSON/JSON.uc index 2369178..5642057 100644 --- a/sources/Data/JSON/JSON.uc +++ b/sources/Data/JSON/JSON.uc @@ -76,6 +76,14 @@ struct JStorageAtom var protected bool classLoadingWasAttempted; }; +protected final function TryLoadingStringAsClass(out JStorageAtom atom) +{ + if (atom.classLoadingWasAttempted) return; + atom.classLoadingWasAttempted = true; + atom.stringValueAsClass = + class(DynamicLoadObject(atom.stringValue, class'Class', true)); +} + defaultproperties { } \ No newline at end of file diff --git a/sources/Data/JSON/Tests/TEST_JSON.uc b/sources/Data/JSON/Tests/TEST_JSON.uc index de0e791..827a3d3 100644 --- a/sources/Data/JSON/Tests/TEST_JSON.uc +++ b/sources/Data/JSON/Tests/TEST_JSON.uc @@ -50,8 +50,12 @@ protected static function Test_ArrayGetSetRemove() Context("Testing get/set/remove functions for JSON arrays"); SubTest_ArrayUndefined(); SubTest_ArrayStringGetSetRemove(); + SubTest_ArrayClassGetSetRemove(); + SubTest_ArrayStringAsClass(); SubTest_ArrayBooleanGetSetRemove(); SubTest_ArrayNumberGetSetRemove(); + SubTest_ArrayIntegerGetSetRemove(); + SubTest_ArrayFloatAndInteger(); SubTest_ArrayNullGetSetRemove(); SubTest_ArrayMultipleVariablesStorage(); SubTest_ArrayMultipleVariablesRemoval(); @@ -287,7 +291,6 @@ protected static function SubTest_FloatAndInteger() local JObject testJSON; testJSON = _().json.newObject(); testJSON.SetNumber("SetNumber", 6.70087); - testJSON.SetInteger("SetInteger", 62478623874); Context("Testing how `JObject` treats mixed float and" @ "integer setters/getters."); @@ -547,6 +550,68 @@ protected static function SubTest_ArrayStringGetSetRemove() TEST_ExpectTrue(testJSON.GetString(0, "other") == "other"); } +protected static function SubTest_ArrayClassGetSetRemove() +{ + local JArray testJSON; + testJSON = _().json.newArray(); + testJSON.SetClass(0, class'Actor'); + + Context("Testing `JArray`'s get/set/remove functions for" @ + "class variables"); + Issue("Class type isn't properly set by `SetClass`"); + TEST_ExpectTrue(testJSON.GetTypeOf(0) == JSON_String); + + Issue("Value is incorrectly assigned by `SetClass`"); + TEST_ExpectTrue(testJSON.GetClass(0) == class'Actor'); + + Issue( "Providing default variable value makes `GetClass`" @ + "return incorrect value"); + TEST_ExpectTrue(testJSON.GetClass(0, class'GameInfo') == class'Actor'); + + Issue("Variable value isn't correctly reassigned by `SetClass`"); + testJSON.SetClass(0, class'Info'); + TEST_ExpectTrue(testJSON.GetClass(0) == class'Info'); + + Issue( "Getting class variable as a wrong type" @ + "doesn't yield default value"); + TEST_ExpectTrue(testJSON.GetBoolean(0, true) == true); + + Issue("Boolean variable isn't being properly removed"); + testJSON.RemoveValue(0); + TEST_ExpectTrue(testJSON.GetTypeOf(0) == JSON_Undefined); + + Issue( "Getters don't return default value for missing key that" @ + "previously stored string value, but got removed"); + TEST_ExpectTrue(testJSON.GetClass(0, class'Mutator') == class'Mutator'); +} + +protected static function SubTest_ArrayStringAsClass() +{ + local JArray testJSON; + testJSON = _().json.NewArray(); + testJSON.SetString(0, "Engine.Actor"); + testJSON.AddString("blahblahblah"); + testJSON.AddClass(class'Info'); + testJSON.SetClass(3, none); + + Context("Testing how `JArray` treats mixed string and" + @ "class setters/getters."); + Issue("Incorrect result of `SetClass().GetString()` sequence."); + TEST_ExpectTrue(testJSON.GetString(2) == "Engine.Info"); + TEST_ExpectTrue(testJSON.GetString(3) == "None"); + TEST_ExpectTrue(testJSON.GetString(3, "alternative") == "None"); + + Issue("Incorrect result of `SetString().GetClass()` sequence for" + @ "correct value in `SetString()`."); + TEST_ExpectTrue(testJSON.GetClass(0) == class'Actor'); + TEST_ExpectTrue(testJSON.GetClass(0, class'Object') == class'Actor'); + + Issue("Incorrect result of `SetString().GetClass()` sequence for" + @ "incorrect value in `SetString()`."); + TEST_ExpectTrue(testJSON.GetClass(1) == none); + TEST_ExpectTrue(testJSON.GetClass(1, class'Object') == class'Object'); +} + protected static function SubTest_ArrayNumberGetSetRemove() { local JArray testJSON; @@ -582,6 +647,63 @@ protected static function SubTest_ArrayNumberGetSetRemove() TEST_ExpectTrue(testJSON.GetNumber(0, 13) == 13); } +protected static function SubTest_ArrayIntegerGetSetRemove() +{ + local JArray testJSON; + testJSON = _().json.newArray(); + testJSON.SetInteger(0, 19); + + Context("Testing `JArray`'s get/set/remove functions for" @ + "integer variables"); + Issue("Integer type isn't properly set by `SetInteger`"); + TEST_ExpectTrue(testJSON.GetTypeOf(0) == JSON_Number); + + Issue("Value is incorrectly assigned by `SetInteger`"); + TEST_ExpectTrue(testJSON.GetInteger(0) == 19); + + Issue( "Providing default variable value makes `GetInteger`" @ + "return incorrect value"); + TEST_ExpectTrue(testJSON.GetInteger(0, 5) == 19); + + Issue("Variable value isn't correctly reassigned by `SetInteger`"); + testJSON.SetInteger(0, MaxInt); + TEST_ExpectTrue(testJSON.GetInteger(0) == MaxInt); + + Issue( "Getting integer variable as a wrong type" @ + "doesn't yield default value"); + TEST_ExpectTrue(testJSON.GetString(0, "default") == "default"); + + Issue("Integer type isn't being properly removed"); + testJSON.RemoveValue(0); + TEST_ExpectTrue(testJSON.GetTypeOf(0) == JSON_Undefined); + + Issue( "Getters don't return default value for missing key that" @ + "previously stored integer value, but got removed"); + TEST_ExpectTrue(testJSON.GetInteger(0, 13) == 13); +} + +protected static function SubTest_ArrayFloatAndInteger() +{ + local JArray testJSON; + testJSON = _().json.NewArray(); + testJSON.SetNumber(0, 6.70087); + + Context("Testing how `JArray` treats mixed float and" + @ "integer setters/getters."); + Issue("Incorrect result of `SetNumber().GetInteger()` sequence."); + TEST_ExpectTrue(testJSON.GetInteger(0) == 6); + + testJSON.SetInteger(0, 11); + testJSON.SetNumber(1, 0.43); + Issue("SetNumber().SetInteger() for same variable name does not overwrite" + @ "initial number value."); + TEST_ExpectTrue(testJSON.GetNumber(0) == 11); + + Issue("SetInteger().SetNumber() for same variable name does not overwrite" + @ "initial integer value."); + TEST_ExpectTrue(testJSON.GetInteger(1) == 0); +} + protected static function SubTest_ArrayNullGetSetRemove() { local JArray testJSON;