Browse Source

Fix bug with return value of `JSONPointer.Pop(true)`

`JSONPointer`'s `Pop(true)` method returned stored `MutableText` value
instead of expected immutable `Text` copy. This patch fixes that
behavior.
pull/8/head
Anton Tarasenko 3 years ago
parent
commit
f99b3ae466
  1. 12
      sources/Text/JSON/JSONPointer.uc
  2. 27
      sources/Text/Tests/TEST_JSON.uc

12
sources/Text/JSON/JSONPointer.uc

@ -102,7 +102,10 @@ public final function JSONPointer Set(Text pointerAsText)
} }
hasEscapedSequences = (pointerAsText.IndexOf(T(TJSON_ESCAPE)) >= 0); hasEscapedSequences = (pointerAsText.IndexOf(T(TJSON_ESCAPE)) >= 0);
parts = pointerAsText.SplitByCharacter(T(TSLASH).GetCharacter(0)); parts = pointerAsText.SplitByCharacter(T(TSLASH).GetCharacter(0));
// First elements of the array will be empty, so throw it away // First element of the array is expected to be empty, so throw it away;
// If it is not empty - then `pointerAsText` does not start with "/" and
// we will pretend that we have already removed first element, thus
// "fixing" path (e.g. effectively turning "foo/bar" into "/foo/bar").
if (parts[0].IsEmpty()) if (parts[0].IsEmpty())
{ {
_.memory.Free(parts[0]); _.memory.Free(parts[0]);
@ -199,7 +202,7 @@ public final function Text Pop(optional bool doNotRemove)
result = _.text.FromIntM(components[lastIndex].asNumber); result = _.text.FromIntM(components[lastIndex].asNumber);
} }
else { else {
result = components[lastIndex].asText; result = components[lastIndex].asText.Copy();
} }
if (!doNotRemove) { if (!doNotRemove) {
components.length = components.length - 1; components.length = components.length - 1;
@ -229,8 +232,9 @@ public final function int PopNumeric(optional bool doNotRemove)
} }
lastIndex = components.length - 1; lastIndex = components.length - 1;
result = GetNumericComponent(lastIndex); result = GetNumericComponent(lastIndex);
_.memory.Free(components[lastIndex].asText); if (!doNotRemove)
if (!doNotRemove) { {
_.memory.Free(components[lastIndex].asText);
components.length = components.length - 1; components.length = components.length - 1;
} }
return result; return result;

27
sources/Text/Tests/TEST_JSON.uc

@ -36,6 +36,7 @@ protected static function Test_Pointer()
SubTest_PointerToText(); SubTest_PointerToText();
SubTest_PointerPushPop(); SubTest_PointerPushPop();
SubTest_PointerNumeric(); SubTest_PointerNumeric();
SubTest_PopWithoutRemoving();
} }
protected static function SubTest_PointerCreate() protected static function SubTest_PointerCreate()
@ -132,8 +133,8 @@ protected static function SubTest_PointerPushPop()
protected static function SubTest_PointerNumeric() protected static function SubTest_PointerNumeric()
{ {
local JSONPointer pointer; local JSONPointer pointer;
local string correct, incorrect; local string correct, incorrect;
correct = "`GetNumericComponent()`/`PopNumeric()` cannot correctly retrieve" correct = "`GetNumericComponent()`/`PopNumeric()` cannot correctly retrieve"
@ "`JSONPointer`'s numeric components."; @ "`JSONPointer`'s numeric components.";
incorrect = "`GetNumericComponent()`/`PopNumeric()` do not return negative" incorrect = "`GetNumericComponent()`/`PopNumeric()` do not return negative"
@ -164,6 +165,28 @@ protected static function SubTest_PointerNumeric()
TEST_ExpectTrue(pointer.PopNumeric() < 0); TEST_ExpectTrue(pointer.PopNumeric() < 0);
} }
protected static function SubTest_PopWithoutRemoving()
{
local Text component;
local JSONPointer pointer;
Issue("`Pop(true)` removes the value from the pointer.");
pointer = __().json.Pointer(P("/just/a/simple/test"));
TEST_ExpectTrue(pointer.Pop(true).ToPlainString() == "test");
TEST_ExpectTrue(pointer.Pop(true).ToPlainString() == "test");
Issue("`Pop(true)` returns actually stored value instead of a copy.");
pointer.Pop(true).FreeSelf();
TEST_ExpectTrue(pointer.Pop(true).ToPlainString() == "test");
component = pointer.Pop();
TEST_ExpectNotNone(component);
TEST_ExpectTrue(component.ToPlainString() == "test");
TEST_ExpectTrue(component.IsAllocated());
Issue("`Pop(true)` breaks after regular `Pop()` call.");
TEST_ExpectTrue(pointer.Pop(true).ToPlainString() == "simple");
TEST_ExpectTrue(pointer.Pop(true).ToPlainString() == "simple");
}
protected static function Test_Print() protected static function Test_Print()
{ {
Context("Testing printing simple JSON values."); Context("Testing printing simple JSON values.");

Loading…
Cancel
Save