#include "prx/libSceJson2/include/Api.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include "JsonTestAllocator.hpp" #include #include #include #include #include #include using namespace SceJson2; struct Parameter { void* allocator; void* context; std::size_t bufferSize; std::int32_t mode; std::uint32_t reserved[3]; }; static void Require(bool valid, const char* message) { if (!valid) { std::fprintf(stderr, "%s\n", message); std::abort(); } } static const Value& Front(const Value& value) { return *_ZNK3sce4Json5Array5frontEv(_ZNK3sce4Json5Value8getArrayEv(&value)); } static void Tree(const Value& root) { Require(root.type == 6 && !root.parent, "A copied root must own an independent root value"); const auto& child = Front(root); Require(child.parent == &root && child.type == 6, "An array element must refer to its owning value"); const auto& leaf = Front(child); Require(leaf.parent == &child && leaf.type == 2 && leaf.payload == 42, "Nested children must refer to their immediate owner and preserve inline payloads"); } int main() { JsonTest::Allocator allocator; Parameter parameter{&allocator, nullptr, 0, 2, {}}; std::uint8_t initializer = 0; _ZN3sce4Json11InitializerC1Ev(&initializer); Require(_ZN3sce4Json11Initializer10initializeEPKNS0_14InitParameter2E(&initializer, reinterpret_cast(¶meter)) == 0, "Initialize ownership tests"); Value text{}; _ZN3sce4Json5ValueC1EPKc(&text, "keep"); const auto payload = text.payload; const auto* string = _ZNK3sce4Json5Value9getStringEv(&text); Require(reinterpret_cast(string) == payload, "A string payload must hold its String object address"); _ZN3sce4Json5Value3setENS0_9ValueTypeE(&text, static_cast(5)); Require(text.payload == payload && std::strcmp(_ZNK3sce4Json6String5c_strEv(string), "keep") == 0, "Setting an existing type must preserve its contents and identity"); Value leaf{}; _ZN3sce4Json5ValueC1El(&leaf, 42); Array inner{}; _ZN3sce4Json5ArrayC1Ev(&inner); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&inner, &leaf); Require(!_ZNK3sce4Json5Array5frontEv(&inner)->parent, "A standalone array must not invent a value owner"); Value child{}; _ZN3sce4Json5ValueC1ERKNS0_5ArrayE(&child, &inner); Array outer{}; _ZN3sce4Json5ArrayC1Ev(&outer); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(&outer, &child); Value root{}; _ZN3sce4Json5ValueC1ERKNS0_5ArrayE(&root, &outer); Tree(root); Require(reinterpret_cast(_ZNK3sce4Json5Value8getArrayEv(&root)) == root.payload, "An array payload must hold its Array object address"); Value copy{}; _ZN3sce4Json5ValueC1ERKS1_(©, &root); Tree(copy); Require(copy.payload != root.payload && Front(copy).payload != Front(root).payload, "Copies must not share owned containers"); const auto rootPayload = root.payload; _ZN3sce4Json5Value3setENS0_9ValueTypeE(&root, static_cast(6)); Require(root.payload == rootPayload && _ZNK3sce4Json5Array4sizeEv(_ZNK3sce4Json5Value8getArrayEv(&root)) == 1, "Setting the existing array type must retain elements and storage"); auto* ownedArray = const_cast(_ZNK3sce4Json5Value8getArrayEv(©)); _ZN3sce4Json5Array9push_backERKNS0_5ValueE(ownedArray, &child); const auto* appended = _ZNK3sce4Json5Array4backEv(ownedArray); Require(appended->parent == © && Front(*appended).parent == appended, "Appending to an owned array must bind both new and nested children"); _ZN3sce4Json5Value3setERKS1_(©, &Front(copy)); Require(!copy.parent && Front(copy).parent == © && Front(copy).payload == 42, "Assignment from a descendant must finish copying before releasing the old tree"); Value cross{}; _ZN3sce4Json5ValueC1Ev(&cross); const char objectInput[] = "{\"a\":[1,2]}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, objectInput, sizeof(objectInput) - 1) == 0, "Parse cross-type ownership tree"); const auto* arrayMember = _ZNK3sce4Json5ValueixEPKc(&cross, "a"); _ZN3sce4Json5ValueaSERKS1_(&cross, arrayMember); Require(cross.type == 6 && Front(cross).payload == 1 && Front(cross).parent == &cross, "Object-to-array descendant assignment must preserve the source before clearing its owner"); _ZN3sce4Json5Value5clearEv(&cross); const char arrayInput[] = "[\"retained\"]"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, arrayInput, sizeof(arrayInput) - 1) == 0, "Parse string descendant tree"); _ZN3sce4Json5Value3setERKS1_(&cross, &Front(cross)); Require(cross.type == 5 && std::strcmp(_ZNK3sce4Json6String5c_strEv(_ZNK3sce4Json5Value9getStringEv(&cross)), "retained") == 0, "Array-to-string descendant assignment must preserve text before clearing its owner"); _ZN3sce4Json5Value5clearEv(&cross); Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, objectInput, sizeof(objectInput) - 1) == 0, "Parse raw Array descendant source"); _ZN3sce4Json5Value3setERKNS0_5ArrayE(&cross, _ZNK3sce4Json5Value8getArrayEv(_ZNK3sce4Json5ValueixEPKc(&cross, "a"))); Require(cross.type == TypeArray && Front(cross).payload == 1, "Array overload must retain a descendant before changing the destination type"); _ZN3sce4Json5Value5clearEv(&cross); Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, arrayInput, sizeof(arrayInput) - 1) == 0, "Parse raw String descendant source"); _ZN3sce4Json5Value3setERKNS0_6StringE(&cross, _ZNK3sce4Json5Value9getStringEv(&Front(cross))); Require(cross.type == TypeString && std::strcmp(_ZNK3sce4Json6String5c_strEv(_ZNK3sce4Json5Value9getStringEv(&cross)), "retained") == 0, "String overload must retain descendant text before changing the destination type"); _ZN3sce4Json5Value5clearEv(&cross); const char nestedObject[] = "[{\"a\":7}]"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, nestedObject, sizeof(nestedObject) - 1) == 0, "Parse raw Object descendant source"); _ZN3sce4Json5Value3setERKNS0_6ObjectE(&cross, _ZNK3sce4Json5Value9getObjectEv(&Front(cross))); const auto* member = _ZNK3sce4Json5ValueixEPKc(&cross, "a"); Require(cross.type == TypeObject && member->payload == 7 && member->parent == &cross, "Object overload must retain descendant contents and bind their new owner"); for (bool nested : {false, true}) { _ZN3sce4Json5Value5clearEv(&cross); const char* document = nested ? "[{\"retained-key\":7}]" : "{\"retained-key\":7}"; Require(_ZN3sce4Json6Parser5parseERNS0_5ValueEPKcm(&cross, document, std::strlen(document)) == 0, "Parse object-key ownership tree"); const auto* object = _ZNK3sce4Json5Value9getObjectEv(nested ? &Front(cross) : &cross); ObjectIterator iterator{}; _ZNK3sce4Json6Object5beginEv(&iterator, object); const auto* pair = _ZNK3sce4Json6Object8iteratordeEv(&iterator); _ZN3sce4Json5Value3setERKNS0_6StringE(&cross, &pair->key); Require(cross.type == TypeString && std::strcmp(_ZNK3sce4Json6String5c_strEv(_ZNK3sce4Json5Value9getStringEv(&cross)), "retained-key") == 0, "String assignment from an owned object key must copy text before releasing its tree"); _ZN3sce4Json6Object8iteratorD1Ev(&iterator); } _ZN3sce4Json5ValueD1Ev(&cross); _ZN3sce4Json5Value4swapERS1_(&root, &text); Require(root.type == 5 && text.type == 6, "Swap must exchange payloads"); Tree(text); Require(std::strcmp(_ZNK3sce4Json6String5c_strEv(_ZNK3sce4Json5Value9getStringEv(&root)), "keep") == 0, "Swap must preserve string contents"); _ZN3sce4Json5ValueD1Ev(&root); _ZN3sce4Json5ValueD1Ev(©); _ZN3sce4Json5ValueD1Ev(&child); _ZN3sce4Json5ValueD1Ev(&leaf); _ZN3sce4Json5ValueD1Ev(&text); _ZN3sce4Json5ArrayD1Ev(&inner); _ZN3sce4Json5ArrayD1Ev(&outer); Require(_ZN3sce4Json11Initializer9terminateEv(&initializer) == 0, "Terminate ownership tests"); return 0; }