docs: fix documentation errors, typos and improve API clarity

This commit is contained in:
ProjectSky 2025-10-20 20:39:17 +08:00
parent 3200a6ba1a
commit 2212b5f900
9 changed files with 2121 additions and 618 deletions

View File

@ -5,6 +5,7 @@
using SourceMod::Handle_t; using SourceMod::Handle_t;
using SourceMod::HandleType_t; using SourceMod::HandleType_t;
using SourceMod::SMInterface;
using SourcePawn::IPluginContext; using SourcePawn::IPluginContext;
// Forward declaration // Forward declaration
@ -27,7 +28,7 @@ enum YYJSON_SORT_ORDER
/** /**
* @brief Parameter provider interface for Pack operation * @brief Parameter provider interface for Pack operation
* *
* Allows Pack to retrieve parameters in a platform-independent way. * Allows Pack to retrieve parameters in a platform-independent way.
*/ */
class IPackParamProvider class IPackParamProvider
@ -56,7 +57,7 @@ public:
* SM_GET_LATE_IFACE(YYJSONMANAGER, g_pYYJSONManager); * SM_GET_LATE_IFACE(YYJSONMANAGER, g_pYYJSONManager);
* } * }
*/ */
class IYYJSONManager : public SourceMod::SMInterface class IYYJSONManager : public SMInterface
{ {
public: public:
virtual const char *GetInterfaceName() override { virtual const char *GetInterfaceName() override {
@ -87,8 +88,11 @@ public:
* @param buffer Output buffer * @param buffer Output buffer
* @param buffer_size Buffer size * @param buffer_size Buffer size
* @param write_flg Write flags (YYJSON_WRITE_FLAG values, default: 0) * @param write_flg Write flags (YYJSON_WRITE_FLAG values, default: 0)
* @param out_size Pointer to receive actual size (optional, default: nullptr) * @param out_size Pointer to receive actual size written (including null terminator), optional
* @return true on success * @return true on success, false if buffer is too small or on error
*
* @note The out_size parameter returns the size including null terminator
* @note Use GetSerializedSize() with the same write_flg to determine buffer size
*/ */
virtual bool WriteToString(YYJSONValue* handle, char* buffer, size_t buffer_size, virtual bool WriteToString(YYJSONValue* handle, char* buffer, size_t buffer_size,
uint32_t write_flg = 0, size_t* out_size = nullptr) = 0; uint32_t write_flg = 0, size_t* out_size = nullptr) = 0;
@ -126,15 +130,28 @@ public:
/** /**
* Get human-readable type description string * Get human-readable type description string
* @param handle JSON value * @param handle JSON value
* @return Type description string (e.g., "object", "array", "string", "number", "true", "false", "null") * @return Type description string (e.g., "object", "array", "string", "number", "true", "false", "unknown")
*/ */
virtual const char* GetTypeDesc(YYJSONValue* handle) = 0; virtual const char* GetTypeDesc(YYJSONValue* handle) = 0;
/** /**
* Get the size needed to serialize this JSON value * Get the size needed to serialize this JSON value
*
* @param handle JSON value * @param handle JSON value
* @param write_flg Write flags (YYJSON_WRITE_FLAG values, default: 0) * @param write_flg Write flags (YYJSON_WRITE_FLAG values, default: 0)
* @return Size in bytes (including null terminator) * @return Size in bytes (including null terminator)
*
* @note The returned size depends on the write_flg parameter.
* You MUST use the same flags when calling both GetSerializedSize()
* and WriteToString(). Using different flags will return
* different sizes and may cause buffer overflow.
*
* @example
* // Correct usage:
* auto flags = YYJSON_WRITE_PRETTY;
* size_t size = g_pYYJSONManager->GetSerializedSize(handle, flags);
* char* buffer = new char[size];
* g_pYYJSONManager->WriteToString(handle, buffer, size, flags); // Use same flags
*/ */
virtual size_t GetSerializedSize(YYJSONValue* handle, uint32_t write_flg = 0) = 0; virtual size_t GetSerializedSize(YYJSONValue* handle, uint32_t write_flg = 0) = 0;
@ -278,7 +295,11 @@ public:
/** /**
* Get the number of bytes read when parsing this document * Get the number of bytes read when parsing this document
* @param handle JSON value * @param handle JSON value
* @return Number of bytes read during parsing, 0 if not from parsing * @return Number of bytes read during parsing (excluding null terminator), 0 if not from parsing
*
* @note This value only applies to documents created from parsing
* @note Manually created documents (ObjectInit, CreateBool, etc.) will return 0
* @note The returned size does not include the null terminator
*/ */
virtual size_t GetReadSize(YYJSONValue* handle) = 0; virtual size_t GetReadSize(YYJSONValue* handle) = 0;

View File

@ -527,7 +527,12 @@ size_t YYJSONManager::GetReadSize(YYJSONValue* handle)
return 0; return 0;
} }
return handle->m_readSize; // this not happen in normal case, but it's possible if the document is not from parsing.
if (handle->m_readSize == 0) {
return 0;
}
return handle->m_readSize + 1;
} }
YYJSONValue* YYJSONManager::ObjectInit() YYJSONValue* YYJSONManager::ObjectInit()

View File

@ -61,7 +61,7 @@ public:
yyjson_obj_iter m_iterObjImm; yyjson_obj_iter m_iterObjImm;
yyjson_arr_iter m_iterArrImm; yyjson_arr_iter m_iterArrImm;
SourceMod::Handle_t m_handle{ BAD_HANDLE }; Handle_t m_handle{ BAD_HANDLE };
size_t m_arrayIndex{ 0 }; size_t m_arrayIndex{ 0 };
size_t m_readSize{ 0 }; size_t m_readSize{ 0 };
bool m_iterInitialized{ false }; bool m_iterInitialized{ false };

View File

@ -54,9 +54,4 @@ void JsonExtension::SDK_OnUnload()
void JSONHandler::OnHandleDestroy(HandleType_t type, void* object) void JSONHandler::OnHandleDestroy(HandleType_t type, void* object)
{ {
delete (YYJSONValue*)object; delete (YYJSONValue*)object;
}
IYYJSONManager* JsonExtension::GetYYJSONManager()
{
return g_pYYJSONManager;
} }

View File

@ -11,7 +11,6 @@ class JsonExtension : public SDKExtension
public: public:
virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late); virtual bool SDK_OnLoad(char *error, size_t maxlength, bool late);
virtual void SDK_OnUnload(); virtual void SDK_OnUnload();
IYYJSONManager* GetYYJSONManager();
}; };
class JSONHandler : public IHandleTypeDispatch class JSONHandler : public IHandleTypeDispatch

View File

@ -669,7 +669,7 @@ static cell_t json_val_get_read_size(IPluginContext* pContext, const cell_t* par
size_t size = g_pYYJSONManager->GetReadSize(handle); size_t size = g_pYYJSONManager->GetReadSize(handle);
if (size == 0) return 0; if (size == 0) return 0;
return static_cast<cell_t>(size + 1); return static_cast<cell_t>(size);
} }
static cell_t json_val_create_null(IPluginContext* pContext, const cell_t* params) static cell_t json_val_create_null(IPluginContext* pContext, const cell_t* params)

View File

@ -198,7 +198,7 @@ methodmap YYJSON < Handle
* @param maxlength Maximum length of the string buffer * @param maxlength Maximum length of the string buffer
* @param flag The JSON write options * @param flag The JSON write options
* *
* @return Number of characters written to the buffer, including the null terminator. 0 on failure * @return Number of characters written to the buffer (including null terminator) or 0 on failure
*/ */
public native int ToString(char[] buffer, int maxlength, YYJSON_WRITE_FLAG flag = YYJSON_WRITE_NOFLAG); public native int ToString(char[] buffer, int maxlength, YYJSON_WRITE_FLAG flag = YYJSON_WRITE_NOFLAG);
@ -278,7 +278,7 @@ methodmap YYJSON < Handle
public static native YYJSON CreateFloat(float value); public static native YYJSON CreateFloat(float value);
/** /**
* Creates and returns a int value * Creates and returns an int value
* *
* @note Needs to be freed using delete or CloseHandle() * @note Needs to be freed using delete or CloseHandle()
* *
@ -289,11 +289,11 @@ methodmap YYJSON < Handle
public static native YYJSON CreateInt(int value); public static native YYJSON CreateInt(int value);
/** /**
* Creates and returns a intger64 value * Creates and returns an integer64 value
* *
* @note Needs to be freed using delete or CloseHandle() * @note Needs to be freed using delete or CloseHandle()
* *
* @param value The intger64 value to be set * @param value The integer64 value to be set
* *
* @return JSON handle, NULL on error * @return JSON handle, NULL on error
*/ */
@ -347,7 +347,7 @@ methodmap YYJSON < Handle
public static native int GetInt(const YYJSON value); public static native int GetInt(const YYJSON value);
/** /**
* Get intger64 value by a JSON Handle * Get integer64 value by a JSON Handle
* *
* @param value JSON handle * @param value JSON handle
* @param buffer Buffer to copy to * @param buffer Buffer to copy to
@ -369,12 +369,17 @@ methodmap YYJSON < Handle
public static native bool GetString(const YYJSON value, char[] buffer, int maxlength); public static native bool GetString(const YYJSON value, char[] buffer, int maxlength);
/** /**
* Get JSON Handle serialized size in bytes (including null-terminator) * Get JSON Handle serialized size in bytes (including null-terminator)
* *
* @param flag The JSON write options * @param flag The JSON write options
* *
* @return serialized size * @return Size in bytes (including null terminator)
*/ *
* @note The returned size depends on the flag parameter.
* You MUST use the same flags when calling both GetSerializedSize()
* and ToString(). Using different flags will return different sizes
* and may cause buffer overflow.
*/
public native int GetSerializedSize(YYJSON_WRITE_FLAG flag = YYJSON_WRITE_NOFLAG); public native int GetSerializedSize(YYJSON_WRITE_FLAG flag = YYJSON_WRITE_NOFLAG);
/** /**
@ -435,7 +440,7 @@ methodmap YYJSON < Handle
* *
* @return True on success, false on failure * @return True on success, false on failure
*/ */
public native bool PtrGetString(const char[] path, char[] buffer, int maxlength) public native bool PtrGetString(const char[] path, char[] buffer, int maxlength);
/** /**
* Get value is null by a JSON Pointer * Get value is null by a JSON Pointer
@ -444,18 +449,20 @@ methodmap YYJSON < Handle
* *
* @return True if the value is null, false otherwise * @return True if the value is null, false otherwise
*/ */
public native bool PtrGetIsNull(const char[] path) public native bool PtrGetIsNull(const char[] path);
/** /**
* Get JSON content length (string length, array size, object size) * Get JSON content length (string length, array size, object size)
* Returns 0 if val is NULL or type is not string/array/object *
* if str including null-terminator * @note For strings: returns string length including null-terminator
* @note For arrays/objects: returns number of elements
* @note Returns 0 if value is NULL or type is not string/array/object
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* *
* @return JSON content length * @return JSON content length
*/ */
public native int PtrGetLength(const char[] path) public native int PtrGetLength(const char[] path);
/** /**
* Set value by a JSON Pointer * Set value by a JSON Pointer
@ -463,7 +470,7 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The value to be set, pass NULL to remove * @param value The value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -475,7 +482,7 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The boolean value to be set, pass NULL to remove * @param value The boolean value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -487,7 +494,7 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The float value to be set, pass NULL to remove * @param value The float value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -499,19 +506,19 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The integer value to be set, pass NULL to remove * @param value The integer value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
public native bool PtrSetInt(const char[] path, int value); public native bool PtrSetInt(const char[] path, int value);
/** /**
* Set intger64 value by a JSON Pointer * Set integer64 value by a JSON Pointer
* *
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The intger64 value to be set, pass NULL to remove * @param value The integer64 value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -523,7 +530,7 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The string value to be set, pass NULL to remove * @param value The string value to be set
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -535,7 +542,6 @@ methodmap YYJSON < Handle
* @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value * @note The parent nodes will be created if they do not exist. If the target value already exists, it will be replaced by the new value
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The null value to be set, pass NULL to remove
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -585,7 +591,7 @@ methodmap YYJSON < Handle
* Add (insert) integer64 value by a JSON pointer * Add (insert) integer64 value by a JSON pointer
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value The intger64 value to be added * @param value The integer64 value to be added
* *
* @return true if JSON pointer is valid and new value is set, false otherwise * @return true if JSON pointer is valid and new value is set, false otherwise
*/ */
@ -617,7 +623,7 @@ methodmap YYJSON < Handle
* *
* @return true if removed value, false otherwise * @return true if removed value, false otherwise
*/ */
public native bool PtrRemove(const char[] path) public native bool PtrRemove(const char[] path);
/** /**
* Try to get value by a JSON Pointer * Try to get value by a JSON Pointer
@ -801,14 +807,16 @@ methodmap YYJSON < Handle
} }
/** /**
* Retrieves read size of the JSON data * Retrieves the size of the JSON data as it was originally read from parsing
* *
* @note This value reflects the size of the JSON data as read from the document * @return Size in bytes (including null terminator) or 0 if not from parsing
* - It does not auto update if the document is modified
* - For modified document, use GetSerializedSize to obtain the current size
* *
* @note This value only applies to documents created from parsing (Parse, FromString, FromFile)
* @note Manually created documents (new YYJSONObject(), YYJSON.CreateBool(), etc.) will return 0
* @note This value does not auto-update if the document is modified
* @note For modified documents, use GetSerializedSize() to obtain the current size
*/ */
property bool ReadSize { property int ReadSize {
public native get(); public native get();
} }
}; };
@ -1219,7 +1227,7 @@ methodmap YYJSONArray < YYJSON
public native bool SetFloat(int index, float value); public native bool SetFloat(int index, float value);
/** /**
* Replaces a integer value at index * Replaces an integer value at index
* *
* @param index The index to which to replace the value * @param index The index to which to replace the value
* @param value The new int value to replace * @param value The new int value to replace
@ -1229,10 +1237,10 @@ methodmap YYJSONArray < YYJSON
public native bool SetInt(int index, int value); public native bool SetInt(int index, int value);
/** /**
* Replaces a intger64 value at index * Replaces an integer64 value at index
* *
* @param index The index to which to replace the value * @param index The index to which to replace the value
* @param value The new intger64 value to replace * @param value The new integer64 value to replace
* *
* @return True if succeed, false otherwise * @return True if succeed, false otherwise
*/ */
@ -1285,7 +1293,7 @@ methodmap YYJSONArray < YYJSON
public native bool PushFloat(float value); public native bool PushFloat(float value);
/** /**
* Inserts a integer value at the end of the array * Inserts an integer value at the end of the array
* *
* @param value integer to set * @param value integer to set
* *
@ -1294,9 +1302,9 @@ methodmap YYJSONArray < YYJSON
public native bool PushInt(int value); public native bool PushInt(int value);
/** /**
* Inserts a intger64 value at the end of the array * Inserts an integer64 value at the end of the array
* *
* @param value intger64 value * @param value integer64 value
* *
* @return The value to be inserted. Returns false if it is NULL * @return The value to be inserted. Returns false if it is NULL
*/ */

2041
plugins/testsuite/test_yyjson.sp Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,566 +0,0 @@
#include <sourcemod>
#include <yyjson>
public Plugin myinfo =
{
name = "YYJSON Test Suite",
author = "ProjectSky",
description = "Test suite for YYJSON extension",
version = "1.0.2",
url = "https://github.com/ProjectSky/sm-ext-yyjson"
};
public void OnPluginStart()
{
RegServerCmd("sm_yyjson_test", Command_RunTests, "Run YYJSON test suite");
}
Action Command_RunTests(int args)
{
// Run all test cases
TestBasicOperations();
TestArrayOperations();
TestObjectOperations();
TestSortOperations();
TestSearchOperations();
TestPointerOperations();
TestIterationOperations();
TestTypeOperations();
TestFileOperations();
TestImmutabilityOperations();
TestPackOperations();
TestFromStringsOperations();
PrintToServer("[YYJSON] All tests completed!");
return Plugin_Handled;
}
void TestBasicOperations()
{
PrintToServer("[YYJSON] Testing basic operations...");
// Test creation and parsing
YYJSONObject obj = new YYJSONObject();
obj.SetInt("int", 42);
obj.SetFloat("float", 3.14);
obj.SetBool("bool", true);
obj.SetString("string", "hello");
obj.SetNull("null");
// Test serialization
char buffer[1024];
obj.ToString(buffer, sizeof(buffer));
PrintToServer("Serialized: %s", buffer);
// Test type checking
PrintToServer("Type of 'int': %d", obj.Type);
PrintToServer("SubType of 'int': %d", obj.SubType);
PrintToServer("Is object: %d", obj.IsObject);
// Test value existence
PrintToServer("Has 'int': %d", obj.HasKey("int"));
PrintToServer("Has 'nonexistent': %d", obj.HasKey("nonexistent"));
// Test value retrieval
PrintToServer("Int value: %d", obj.GetInt("int"));
PrintToServer("Float value: %f", obj.GetFloat("float"));
PrintToServer("Bool value: %d", obj.GetBool("bool"));
char strBuffer[64];
obj.GetString("string", strBuffer, sizeof(strBuffer));
PrintToServer("String value: %s", strBuffer);
PrintToServer("Is 'null' null: %d", obj.IsNull("null"));
// Test parsing
YYJSONObject parsed = YYJSON.Parse(buffer);
// Test equality
PrintToServer("Objects are equal: %d", YYJSON.Equals(obj, parsed));
// Test deep copy
YYJSONObject copy = new YYJSONObject();
YYJSONObject copyResult = YYJSON.DeepCopy(copy, obj);
PrintToServer("Copy equals original: %d", YYJSON.Equals(copyResult, obj));
// Test size and read size
PrintToServer("Object size: %d", obj.Size);
PrintToServer("Read size: %d", obj.ReadSize);
// Test type description
char typeDesc[64];
YYJSON.GetTypeDesc(obj, typeDesc, sizeof(typeDesc));
PrintToServer("Type description: %s", typeDesc);
delete obj;
delete parsed;
delete copy;
delete copyResult;
}
void TestArrayOperations()
{
PrintToServer("[YYJSON] Testing array operations...");
YYJSONArray arr = new YYJSONArray();
// Test push operations
arr.PushInt(1);
arr.PushFloat(2.5);
arr.PushBool(true);
arr.PushString("test");
arr.PushNull();
PrintToServer("Array after push operations:");
PrintJson(arr);
// Test get operations
PrintToServer("First element: %d", arr.GetInt(0));
PrintToServer("Second element: %f", arr.GetFloat(1));
PrintToServer("Third element: %d", arr.GetBool(2));
char strBuffer[64];
arr.GetString(3, strBuffer, sizeof(strBuffer));
PrintToServer("Fourth element: %s", strBuffer);
PrintToServer("Fifth element is null: %d", arr.IsNull(4));
YYJSON first = arr.First;
YYJSON last = arr.Last;
// Test array properties
PrintToServer("Array length: %d", arr.Length);
PrintToServer("First value: %x", first);
PrintToServer("Last value: %x", last);
// Test set operations
arr.SetInt(0, 100);
arr.SetFloat(1, 3.14);
arr.SetBool(2, false);
arr.SetString(3, "modified");
arr.SetNull(4);
PrintToServer("Array after set operations:");
PrintJson(arr);
// Test remove operations
arr.RemoveFirst();
PrintToServer("After RemoveFirst:");
PrintJson(arr);
arr.RemoveLast();
PrintToServer("After RemoveLast:");
PrintJson(arr);
arr.Remove(1);
PrintToServer("After Remove(1):");
PrintJson(arr);
arr.RemoveRange(0, 1);
PrintToServer("After RemoveRange(0, 1):");
PrintJson(arr);
arr.Clear();
PrintToServer("Array length after Clear: %d", arr.Length);
delete arr;
delete first;
delete last;
}
void TestObjectOperations()
{
PrintToServer("[YYJSON] Testing object operations...");
YYJSONObject obj = new YYJSONObject();
// Test set operations
obj.SetInt("int", 123);
obj.SetFloat("float", 3.14);
obj.SetBool("bool", true);
obj.SetString("string", "test");
obj.SetNull("null");
PrintToServer("Object after set operations:");
PrintJson(obj);
// Test get operations
PrintToServer("Int value: %d", obj.GetInt("int"));
PrintToServer("Float value: %f", obj.GetFloat("float"));
PrintToServer("Bool value: %d", obj.GetBool("bool"));
char strBuffer[64];
obj.GetString("string", strBuffer, sizeof(strBuffer));
PrintToServer("String value: %s", strBuffer);
PrintToServer("Is null value null: %d", obj.IsNull("null"));
// Test key operations
char key[64];
for (int i = 0; i < obj.Size; i++)
{
obj.GetKey(i, key, sizeof(key));
PrintToServer("Key at %d: %s", i, key);
YYJSON value = obj.GetValueAt(i);
PrintToServer("Value type at %d: %d", i, value.Type);
delete value;
}
// Test rename key
obj.RenameKey("int", "number");
PrintToServer("After renaming 'int' to 'number':");
PrintJson(obj);
// Test remove operations
obj.Remove("number");
PrintToServer("After removing 'number':");
PrintJson(obj);
obj.Clear();
PrintToServer("Object size after Clear: %d", obj.Size);
delete obj;
}
void TestSortOperations()
{
PrintToServer("[YYJSON] Testing sort operations...");
// Test array sorting
YYJSONArray arr = YYJSON.Parse("[3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5]", .is_mutable_doc = true);
PrintToServer("Original array:");
PrintJson(arr);
arr.Sort();
PrintToServer("After ascending sort:");
PrintJson(arr);
arr.Sort(YYJSON_SORT_DESC);
PrintToServer("After descending sort:");
PrintJson(arr);
arr.Sort(YYJSON_SORT_RANDOM);
PrintToServer("After random sort:");
PrintJson(arr);
// Test mixed type array sorting
YYJSONArray mixed = YYJSON.Parse("[true, 42, \"hello\", 1.23, false, \"world\"]", .is_mutable_doc = true);
PrintToServer("Original mixed array:");
PrintJson(mixed);
mixed.Sort();
PrintToServer("After sorting mixed array:");
PrintJson(mixed);
// Test object sorting
YYJSONObject obj = YYJSON.Parse("{\"zebra\": 1, \"alpha\": 2, \"beta\": 3}", .is_mutable_doc = true);
PrintToServer("Original object:");
PrintJson(obj);
obj.Sort();
PrintToServer("After ascending sort:");
PrintJson(obj);
obj.Sort(YYJSON_SORT_DESC);
PrintToServer("After descending sort:");
PrintJson(obj);
obj.Sort(YYJSON_SORT_RANDOM);
PrintToServer("After random sort:");
PrintJson(obj);
delete arr;
delete mixed;
delete obj;
}
void TestSearchOperations()
{
PrintToServer("[YYJSON] Testing search operations...");
YYJSONArray arr = YYJSON.Parse("[42, true, \"hello\", 3.14, \"world\", false, 42]");
PrintToServer("Test array:");
PrintJson(arr);
// Test all search methods
PrintToServer("Search results:");
PrintToServer("IndexOfInt(42): %d", arr.IndexOfInt(42));
PrintToServer("IndexOfInt(999): %d", arr.IndexOfInt(999));
PrintToServer("IndexOfBool(true): %d", arr.IndexOfBool(true));
PrintToServer("IndexOfBool(false): %d", arr.IndexOfBool(false));
PrintToServer("IndexOfString(\"hello\"): %d", arr.IndexOfString("hello"));
PrintToServer("IndexOfString(\"missing\"): %d", arr.IndexOfString("missing"));
PrintToServer("IndexOfFloat(3.14): %d", arr.IndexOfFloat(3.14));
PrintToServer("IndexOfFloat(2.718): %d", arr.IndexOfFloat(2.718));
delete arr;
}
void TestPointerOperations()
{
PrintToServer("[YYJSON] Testing JSON pointer operations...");
YYJSONObject obj = new YYJSONObject();
// Test setting nested values
obj.PtrSetInt("/a/b/c", 1);
obj.PtrSetString("/a/b/name", "test");
obj.PtrSetBool("/a/flag", true);
obj.PtrSetFloat("/a/b/pi", 3.14);
obj.PtrSetNull("/a/b/empty");
PrintToServer("After setting values:");
PrintJson(obj);
// Test getting values
PrintToServer("Pointer get operations:");
PrintToServer("/a/b/c: %d", obj.PtrGetInt("/a/b/c"));
char strBuffer[64];
obj.PtrGetString("/a/b/name", strBuffer, sizeof(strBuffer));
PrintToServer("/a/b/name: %s", strBuffer);
PrintToServer("/a/flag: %d", obj.PtrGetBool("/a/flag"));
PrintToServer("/a/b/pi: %f", obj.PtrGetFloat("/a/b/pi"));
PrintToServer("/a/b/empty is null: %d", obj.PtrGetIsNull("/a/b/empty"));
// Test adding values
obj.PtrAddInt("/a/b/numbers/0", 1);
obj.PtrAddInt("/a/b/numbers/1", 2);
obj.PtrAddString("/a/b/strings", "append");
PrintToServer("After adding values:");
PrintJson(obj);
// Test length
PrintToServer("Length of /a/b/numbers: %d", obj.PtrGetLength("/a/b/numbers"));
// Test removing values
obj.PtrRemove("/a/b/c");
PrintToServer("After removing /a/b/c:");
PrintJson(obj);
delete obj;
}
void TestIterationOperations()
{
PrintToServer("[YYJSON] Testing iteration operations...");
// Test object iteration
YYJSONObject obj = YYJSON.Parse("{\"a\": 1, \"b\": 2, \"c\": 3}");
char key[64];
YYJSON value;
while (obj.ForeachObject(key, sizeof(key), value))
{
PrintToServer("Key: %s", key);
delete value;
}
// Test array iteration
YYJSONArray arr = YYJSON.Parse("[1, 2, 3, 4, 5]");
int index;
while (arr.ForeachArray(index, value))
{
PrintToServer("Index: %d", index);
delete value;
}
delete obj;
delete arr;
}
void TestTypeOperations()
{
PrintToServer("[YYJSON] Testing type operations...");
// Test value creation
YYJSON boolVal = YYJSON.CreateBool(true);
YYJSON intVal = YYJSON.CreateInt(42);
YYJSON floatVal = YYJSON.CreateFloat(3.14);
YYJSON strVal = YYJSON.CreateString("test");
YYJSON nullVal = YYJSON.CreateNull();
// Test value types
PrintToServer("Value types:");
PrintToServer("Bool type: %d", boolVal.Type);
PrintToServer("Int type: %d", intVal.Type);
PrintToServer("Float type: %d", floatVal.Type);
PrintToServer("String type: %d", strVal.Type);
PrintToServer("Null type: %d", nullVal.Type);
// Test value retrieval
PrintToServer("Value contents:");
PrintToServer("Bool value: %d", YYJSON.GetBool(boolVal));
PrintToServer("Int value: %d", YYJSON.GetInt(intVal));
PrintToServer("Float value: %f", YYJSON.GetFloat(floatVal));
char strBuffer[64];
YYJSON.GetString(strVal, strBuffer, sizeof(strBuffer));
PrintToServer("String value: %s", strBuffer);
delete boolVal;
delete intVal;
delete floatVal;
delete strVal;
delete nullVal;
}
void TestFileOperations()
{
PrintToServer("[YYJSON] Testing file operations...");
// Create test data
YYJSONObject obj = new YYJSONObject();
obj.SetInt("id", 1);
obj.SetString("name", "test");
obj.SetBool("active", true);
// Test file writing
PrintToServer("Writing to file...");
obj.ToFile("test.json", YYJSON_WRITE_PRETTY_TWO_SPACES);
// Test file reading
PrintToServer("Reading from file...");
YYJSONObject loaded = YYJSON.Parse("test.json", true);
PrintToServer("File content:");
PrintJson(loaded);
delete loaded;
delete obj;
}
void TestImmutabilityOperations()
{
PrintToServer("[YYJSON] Testing immutability operations...");
// Test immutable document creation
YYJSONObject immutable = YYJSON.Parse("{\"key\": 123, \"str\": \"test\"}");
PrintToServer("Created immutable document:");
PrintJson(immutable);
// Test property checks
PrintToServer("Is mutable: %d", immutable.IsMutable);
PrintToServer("Is immutable: %d", immutable.IsImmutable);
// Test read operations (should succeed)
PrintToServer("Read operations on immutable document:");
PrintToServer("Int value: %d", immutable.GetInt("key"));
char buffer[64];
immutable.GetString("str", buffer, sizeof(buffer));
PrintToServer("String value: %s", buffer);
// Test conversion to mutable
YYJSONObject mutable = immutable.ToMutable();
PrintToServer("\nConverted to mutable document:");
PrintToServer("Is mutable: %d", mutable.IsMutable);
PrintToServer("Is immutable: %d", mutable.IsImmutable);
// Now modifications should work
mutable.SetInt("key", 456)
PrintToServer("Successfully modified mutable document:");
PrintJson(mutable);
// Test conversion back to immutable
YYJSONObject backToImmutable = mutable.ToImmutable();
PrintToServer("\nConverted back to immutable:");
PrintToServer("Is mutable: %d", backToImmutable.IsMutable);
PrintToServer("Is immutable: %d", backToImmutable.IsImmutable);
delete backToImmutable;
delete mutable;
delete immutable;
// Test file operations with immutability
PrintToServer("\nTesting file operations with immutability...");
// Create and write a mutable document
YYJSONObject writeObj = new YYJSONObject();
writeObj.SetInt("test", 123);
writeObj.ToFile("test_immutable.json");
delete writeObj;
// Read as immutable
YYJSONObject readImmutable = YYJSON.Parse("test_immutable.json", true);
PrintToServer("Read as immutable document:");
PrintJson(readImmutable);
PrintToServer("Is mutable: %d", readImmutable.IsMutable);
PrintToServer("Is immutable: %d", readImmutable.IsImmutable);
delete readImmutable;
}
void TestPackOperations()
{
PrintToServer("[YYJSON] Testing pack operations...");
// Test basic pack operation with different types
YYJSON packed = YYJSON.Pack("{s:s,s:i,s:f,s:b,s:n}",
"name", "test",
"age", 25,
"height", 1.75,
"active", true,
"extra"
);
PrintToServer("Packed JSON:");
PrintJson(packed);
// Test nested object packing
YYJSON nested = YYJSON.Pack("{s:{s:s,s:[i,i,i]}}",
"user",
"name", "test",
"scores", 85, 90, 95
);
PrintToServer("Nested packed JSON:");
PrintJson(nested);
// Test array packing with mixed types
YYJSON array = YYJSON.Pack("[s,i,f,b,n]",
"test", 42, 3.14, true
);
PrintToServer("Array packed JSON:");
PrintJson(array);
delete packed;
delete nested;
delete array;
}
void TestFromStringsOperations()
{
PrintToServer("[YYJSON] Testing FromStrings operations...");
// Test object creation from key-value string arrays
char pairs[][] = {"name", "test", "type", "demo", "version", "1.0.0"};
YYJSONObject obj = YYJSONObject.FromStrings(pairs, sizeof(pairs));
PrintToServer("Object from strings:");
PrintJson(obj);
// Test array creation from string array
char items[][] = {"apple", "banana", "orange", "grape"};
YYJSONArray arr = YYJSONArray.FromStrings(items, sizeof(items));
PrintToServer("Array from strings:");
PrintJson(arr);
delete obj;
delete arr;
}
// Helper function to print json contents
void PrintJson(YYJSON data)
{
int len = data.GetSerializedSize(YYJSON_WRITE_PRETTY_TWO_SPACES);
char[] buffer = new char[len];
data.ToString(buffer, len, YYJSON_WRITE_PRETTY_TWO_SPACES);
PrintToServer("%s", buffer);
}