feat: enhance JSON management with new rotation and value counting features

- Added ObjectRotate and ArrayRotate methods for rotating key-value pairs in JSON objects and arrays, respectively
- Introduced GetValCount method to retrieve the total number of values in immutable JSON documents
- Renamed all Float-related methods to Double in C++ interface (IJsonManager) for better precision clarity
- Fixed TypeAccess configuration in handle type registration to allow external extensions to create JSON handles by properly setting HTypeAccess_Create flag
- Renamed GetHandleType to GetJsonHandleType for better clarity and consistency
- Updated documentation to clarify usage and performance considerations for new methods
- Enhanced tests to cover rotation functionality and value counting in various JSON structures
This commit is contained in:
ProjectSky 2025-11-21 00:07:25 +08:00
parent f596135996
commit e1c5578324
7 changed files with 854 additions and 478 deletions

View File

@ -15,8 +15,7 @@ class JsonArrIter;
class JsonObjIter; class JsonObjIter;
#define SMINTERFACE_JSONMANAGER_NAME "IJsonManager" #define SMINTERFACE_JSONMANAGER_NAME "IJsonManager"
#define SMINTERFACE_JSONMANAGER_VERSION 2 #define SMINTERFACE_JSONMANAGER_VERSION 3
#define JSON_PACK_ERROR_SIZE 256
#define JSON_ERROR_BUFFER_SIZE 256 #define JSON_ERROR_BUFFER_SIZE 256
#define JSON_INT64_BUFFER_SIZE 32 #define JSON_INT64_BUFFER_SIZE 32
@ -98,21 +97,36 @@ public:
* @return true on success, false if buffer is too small or on error * @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 The out_size parameter returns the size including null terminator
* @note Use GetSerializedSize() with the same write_flg to determine buffer size *
* @warning This method performs multiple memory allocations and copies, resulting in poor performance. * @warning Buffer Size Requirements:
* For better performance, use WriteToStringPtr() instead, which avoids intermediate buffers * This function does not allocate memory, but the buffer must be larger than
* the final JSON size to allow temporary space.
*
* The extra space is needed temporarily for each value while it is written,
* and is reused for later values:
* - Number: 40 bytes
* - String: 16 + (str_len * 6) bytes
* - Other values: 16 bytes
* - Nesting depth: 16 * max_json_depth bytes
*
* @note GetSerializedSize() only returns the final JSON size, NOT including the temporary space
* You must manually add extra buffer space based on your JSON content
* @note For most use cases, prefer WriteToStringPtr() for simplicity
* Use this method only when you need to avoid heap allocation (e.g., stack buffers, pre-allocated pools)
*/ */
virtual bool WriteToString(JsonValue* handle, char* buffer, size_t buffer_size, virtual bool WriteToString(JsonValue* 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;
/** /**
* Write JSON to string and return allocated string (performance-optimized version) * Write JSON to string and return allocated string
* @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)
* @param out_size Pointer to receive actual size written (including null terminator) optional * @param out_size Pointer to receive actual size written (including null terminator) optional
* @return Allocated string pointer on success, nullptr on error. Caller must free() the returned pointer * @return Allocated string pointer on success, nullptr on error. Caller must free() the returned pointer
* *
* @note This is the recommended method for serialization as it avoids intermediate buffer allocations * @note This function handles memory allocation internally,
* avoiding the complexity of manual buffer size calculation required by WriteToString()
* @note This is the recommended method for most use cases due to its simplicity and safety
*/ */
virtual char* WriteToStringPtr(JsonValue* handle, uint32_t write_flg = 0, size_t* out_size = nullptr) = 0; virtual char* WriteToStringPtr(JsonValue* handle, uint32_t write_flg = 0, size_t* out_size = nullptr) = 0;
@ -383,6 +397,17 @@ public:
*/ */
virtual size_t GetRefCount(JsonValue* handle) = 0; virtual size_t GetRefCount(JsonValue* handle) = 0;
/**
* Get the total number of values in a document
* @param handle JSON value
* @return Total number of values in the document tree, 0 if handle is null or mutable
* @note Only works on immutable documents (parsed from JSON)
* @note Useful for performance planning and memory estimation
* @note Counts ALL values including containers, keys, and leaf values
* Example: {"a":1,"b":2,"c":3} returns 7 (1 object + 3 keys + 3 values)
*/
virtual size_t GetValCount(JsonValue* handle) = 0;
/** /**
* Create an empty mutable JSON object * Create an empty mutable JSON object
* @return New mutable JSON object or nullptr on failure * @return New mutable JSON object or nullptr on failure
@ -466,10 +491,11 @@ public:
* Get float value by key * Get float value by key
* @param handle JSON object * @param handle JSON object
* @param key Key name * @param key Key name
* @param out_value Pointer to receive float value * @param out_value Pointer to receive double value
* @return true on success, false if key not found or type mismatch * @return true on success, false if key not found or type mismatch
* @note Integers values are auto converted to double
*/ */
virtual bool ObjectGetFloat(JsonValue* handle, const char* key, double* out_value) = 0; virtual bool ObjectGetDouble(JsonValue* handle, const char* key, double* out_value) = 0;
/** /**
* Get integer value by key * Get integer value by key
@ -547,13 +573,13 @@ public:
virtual bool ObjectSetBool(JsonValue* handle, const char* key, bool value) = 0; virtual bool ObjectSetBool(JsonValue* handle, const char* key, bool value) = 0;
/** /**
* Set float value by key (mutable only) * Set double value by key (mutable only)
* @param handle Mutable JSON object * @param handle Mutable JSON object
* @param key Key name * @param key Key name
* @param value Float value * @param value Double value
* @return true on success * @return true on success
*/ */
virtual bool ObjectSetFloat(JsonValue* handle, const char* key, double value) = 0; virtual bool ObjectSetDouble(JsonValue* handle, const char* key, double value) = 0;
/** /**
* Set integer value by key (mutable only) * Set integer value by key (mutable only)
@ -614,6 +640,18 @@ public:
*/ */
virtual bool ObjectSort(JsonValue* handle, JSON_SORT_ORDER sort_mode) = 0; virtual bool ObjectSort(JsonValue* handle, JSON_SORT_ORDER sort_mode) = 0;
/**
* Rotate key-value pairs in the object
* @param handle Mutable JSON object
* @param idx Number of positions to rotate (must be less than object size)
* @return true on success, false if idx >= object size or object is immutable
* @note Only works on mutable objects
* @note Example: {"a":1,"b":2,"c":3,"d":4} rotate 1 becomes {"b":2,"c":3,"d":4,"a":1}
* @note Valid range: 0 <= idx < object size
* @warning This function takes linear time proportional to the rotation amount
*/
virtual bool ObjectRotate(JsonValue* handle, size_t idx) = 0;
/** /**
* Create an empty mutable JSON array * Create an empty mutable JSON array
* @return New mutable JSON array or nullptr on failure * @return New mutable JSON array or nullptr on failure
@ -657,12 +695,12 @@ public:
virtual JsonValue* ArrayInitWithBool(const bool* values, size_t count) = 0; virtual JsonValue* ArrayInitWithBool(const bool* values, size_t count) = 0;
/** /**
* Create a JSON array from float values * Create a JSON array from double values
* @param values Array of float values * @param values Array of double values
* @param count Number of values * @param count Number of values
* @return New JSON array or nullptr on failure * @return New JSON array or nullptr on failure
*/ */
virtual JsonValue* ArrayInitWithFloat(const double* values, size_t count) = 0; virtual JsonValue* ArrayInitWithDouble(const double* values, size_t count) = 0;
/** /**
* Parse a JSON array from string * Parse a JSON array from string
@ -727,13 +765,14 @@ public:
virtual bool ArrayGetBool(JsonValue* handle, size_t index, bool* out_value) = 0; virtual bool ArrayGetBool(JsonValue* handle, size_t index, bool* out_value) = 0;
/** /**
* Get float value at index * Get double value at index
* @param handle JSON array * @param handle JSON array
* @param index Element index * @param index Element index
* @param out_value Pointer to receive float value * @param out_value Pointer to receive double value
* @return true on success, false if index out of bounds or type mismatch * @return true on success, false if index out of bounds or type mismatch
* @note Integers values are auto converted to double
*/ */
virtual bool ArrayGetFloat(JsonValue* handle, size_t index, double* out_value) = 0; virtual bool ArrayGetDouble(JsonValue* handle, size_t index, double* out_value) = 0;
/** /**
* Get integer value at index * Get integer value at index
@ -790,13 +829,13 @@ public:
virtual bool ArrayReplaceBool(JsonValue* handle, size_t index, bool value) = 0; virtual bool ArrayReplaceBool(JsonValue* handle, size_t index, bool value) = 0;
/** /**
* Replace element at index with float (mutable only) * Replace element at index with double (mutable only)
* @param handle Mutable JSON array * @param handle Mutable JSON array
* @param index Element index * @param index Element index
* @param value Float value * @param value Double value
* @return true on success * @return true on success
*/ */
virtual bool ArrayReplaceFloat(JsonValue* handle, size_t index, double value) = 0; virtual bool ArrayReplaceDouble(JsonValue* handle, size_t index, double value) = 0;
/** /**
* Replace element at index with integer (mutable only) * Replace element at index with integer (mutable only)
@ -850,12 +889,12 @@ public:
virtual bool ArrayAppendBool(JsonValue* handle, bool value) = 0; virtual bool ArrayAppendBool(JsonValue* handle, bool value) = 0;
/** /**
* Append float to end of array (mutable only) * Append double to end of array (mutable only)
* @param handle Mutable JSON array * @param handle Mutable JSON array
* @param value Float value * @param value Double value
* @return true on success * @return true on success
*/ */
virtual bool ArrayAppendFloat(JsonValue* handle, double value) = 0; virtual bool ArrayAppendDouble(JsonValue* handle, double value) = 0;
/** /**
* Append integer to end of array (mutable only) * Append integer to end of array (mutable only)
@ -925,13 +964,13 @@ public:
virtual bool ArrayInsertInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) = 0; virtual bool ArrayInsertInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) = 0;
/** /**
* Insert float at specific index (mutable only) * Insert double at specific index (mutable only)
* @param handle Mutable JSON array * @param handle Mutable JSON array
* @param index Element index * @param index Element index
* @param value Float value * @param value Double value
* @return true on success * @return true on success
*/ */
virtual bool ArrayInsertFloat(JsonValue* handle, size_t index, double value) = 0; virtual bool ArrayInsertDouble(JsonValue* handle, size_t index, double value) = 0;
/** /**
* Insert string at specific index (mutable only) * Insert string at specific index (mutable only)
@ -983,12 +1022,12 @@ public:
virtual bool ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) = 0; virtual bool ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) = 0;
/** /**
* Prepend float to beginning of array (mutable only) * Prepend double to beginning of array (mutable only)
* @param handle Mutable JSON array * @param handle Mutable JSON array
* @param value Float value * @param value Double value
* @return true on success * @return true on success
*/ */
virtual bool ArrayPrependFloat(JsonValue* handle, double value) = 0; virtual bool ArrayPrependDouble(JsonValue* handle, double value) = 0;
/** /**
* Prepend string to beginning of array (mutable only) * Prepend string to beginning of array (mutable only)
@ -1076,12 +1115,12 @@ public:
virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) = 0; virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) = 0;
/** /**
* Find index of float value * Find index of double value
* @param handle JSON array * @param handle JSON array
* @param search_value Float value to search for * @param search_value Double value to search for
* @return Index of first match, or -1 if not found * @return Index of first match, or -1 if not found
*/ */
virtual int ArrayIndexOfFloat(JsonValue* handle, double search_value) = 0; virtual int ArrayIndexOfDouble(JsonValue* handle, double search_value) = 0;
/** /**
* Sort array elements * Sort array elements
@ -1092,6 +1131,18 @@ public:
*/ */
virtual bool ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode) = 0; virtual bool ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode) = 0;
/**
* Rotate array elements
* @param handle Mutable JSON array
* @param idx Number of positions to rotate (must be less than array length)
* @return true on success, false if idx >= array length or array is immutable
* @note Only works on mutable arrays
* @note Example: [1,2,3,4,5] rotate 2 becomes [3,4,5,1,2]
* @note Valid range: 0 <= idx < array length
* @warning This function takes linear time proportional to the rotation amount
*/
virtual bool ArrayRotate(JsonValue* handle, size_t idx) = 0;
/** /**
* Create JSON value from format string and parameters * Create JSON value from format string and parameters
* @param format Format string (e.g., "{s:i,s:s}", "[i,s,b]") * @param format Format string (e.g., "{s:i,s:s}", "[i,s,b]")
@ -1120,11 +1171,11 @@ public:
virtual JsonValue* CreateBool(bool value) = 0; virtual JsonValue* CreateBool(bool value) = 0;
/** /**
* Create a JSON float value * Create a JSON double value
* @param value Float value * @param value Double value
* @return New JSON float or nullptr on failure * @return New JSON double or nullptr on failure
*/ */
virtual JsonValue* CreateFloat(double value) = 0; virtual JsonValue* CreateDouble(double value) = 0;
/** /**
* Create a JSON integer value * Create a JSON integer value
@ -1162,12 +1213,13 @@ public:
virtual bool GetBool(JsonValue* handle, bool* out_value) = 0; virtual bool GetBool(JsonValue* handle, bool* out_value) = 0;
/** /**
* Get float value from JSON * Get double value from JSON
* @param handle JSON value * @param handle JSON value
* @param out_value Pointer to receive float value * @param out_value Pointer to receive double value
* @return true on success, false on type mismatch * @return true on success, false on type mismatch
* @note Integers values are auto converted to double
*/ */
virtual bool GetFloat(JsonValue* handle, double* out_value) = 0; virtual bool GetDouble(JsonValue* handle, double* out_value) = 0;
/** /**
* Get integer value from JSON * Get integer value from JSON
@ -1218,15 +1270,16 @@ public:
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
* Get float value using JSON Pointer * Get double value using JSON Pointer
* @param handle JSON value * @param handle JSON value
* @param path JSON Pointer path * @param path JSON Pointer path
* @param out_value Pointer to receive float value * @param out_value Pointer to receive double value
* @param error Error buffer (optional) * @param error Error buffer (optional)
* @param error_size Error buffer size * @param error_size Error buffer size
* @return true on success, false on error * @return true on success, false on error
* @note Integers values are auto converted to double
*/ */
virtual bool PtrGetFloat(JsonValue* handle, const char* path, double* out_value, virtual bool PtrGetDouble(JsonValue* handle, const char* path, double* out_value,
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
@ -1315,15 +1368,15 @@ public:
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
* Set float value using JSON Pointer (mutable only) * Set double value using JSON Pointer (mutable only)
* @param handle Mutable JSON value * @param handle Mutable JSON value
* @param path JSON Pointer path * @param path JSON Pointer path
* @param value Float value * @param value Double value
* @param error Error buffer (optional) * @param error Error buffer (optional)
* @param error_size Error buffer size * @param error_size Error buffer size
* @return true on success, false on error * @return true on success, false on error
*/ */
virtual bool PtrSetFloat(JsonValue* handle, const char* path, double value, virtual bool PtrSetDouble(JsonValue* handle, const char* path, double value,
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
@ -1398,15 +1451,15 @@ public:
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
* Add float to array using JSON Pointer (mutable only) * Add double to array using JSON Pointer (mutable only)
* @param handle Mutable JSON value * @param handle Mutable JSON value
* @param path JSON Pointer path to array * @param path JSON Pointer path to array
* @param value Float value * @param value Double value
* @param error Error buffer (optional) * @param error Error buffer (optional)
* @param error_size Error buffer size * @param error_size Error buffer size
* @return true on success, false on error * @return true on success, false on error
*/ */
virtual bool PtrAddFloat(JsonValue* handle, const char* path, double value, virtual bool PtrAddDouble(JsonValue* handle, const char* path, double value,
char* error = nullptr, size_t error_size = 0) = 0; char* error = nullptr, size_t error_size = 0) = 0;
/** /**
@ -1485,13 +1538,14 @@ public:
virtual bool PtrTryGetBool(JsonValue* handle, const char* path, bool* out_value) = 0; virtual bool PtrTryGetBool(JsonValue* handle, const char* path, bool* out_value) = 0;
/** /**
* Try to get float value using JSON Pointer (returns false on failure) * Try to get double value using JSON Pointer (returns false on failure)
* @param handle JSON value * @param handle JSON value
* @param path JSON Pointer path * @param path JSON Pointer path
* @param out_value Pointer to receive float value * @param out_value Pointer to receive double value
* @return true on success, false if not found or type mismatch * @return true on success, false if not found or type mismatch
* @note Integers values are auto converted to double
*/ */
virtual bool PtrTryGetFloat(JsonValue* handle, const char* path, double* out_value) = 0; virtual bool PtrTryGetDouble(JsonValue* handle, const char* path, double* out_value) = 0;
/** /**
* Try to get integer value using JSON Pointer (returns false on failure) * Try to get integer value using JSON Pointer (returns false on failure)
@ -1583,7 +1637,7 @@ public:
* External extensions MUST use this method to obtain the handle type * External extensions MUST use this method to obtain the handle type
* @return The HandleType_t for JSON handles * @return The HandleType_t for JSON handles
*/ */
virtual HandleType_t GetHandleType() = 0; virtual HandleType_t GetJsonHandleType() = 0;
/** /**
* Read JsonValue from a SourceMod handle * Read JsonValue from a SourceMod handle
@ -1591,7 +1645,7 @@ public:
* @param handle Handle to read from * @param handle Handle to read from
* @return JsonValue pointer, or nullptr on error (error will be reported to context) * @return JsonValue pointer, or nullptr on error (error will be reported to context)
*/ */
virtual JsonValue* GetFromHandle(IPluginContext* pContext, Handle_t handle) = 0; virtual JsonValue* GetValueFromHandle(IPluginContext* pContext, Handle_t handle) = 0;
/** /**
* Initialize an array iterator (same as ArrIterWith but returns pointer) * Initialize an array iterator (same as ArrIterWith but returns pointer)
@ -1717,6 +1771,17 @@ public:
*/ */
virtual void* ObjIterRemove(JsonObjIter* iter) = 0; virtual void* ObjIterRemove(JsonObjIter* iter) = 0;
/**
* Get key string from object iterator key pointer
* @param iter Object iterator
* @param key Key pointer (returned from ObjIterNext)
* @param out_str Pointer to receive key string
* @param out_len Pointer to receive key length (optional)
* @return true on success, false on error
* @note Do not free the returned string - it is owned by the JSON document
*/
virtual bool ObjIterGetKeyString(JsonObjIter* iter, void* key, const char** out_str, size_t* out_len = nullptr) = 0;
/** /**
* Release an array iterator * Release an array iterator
* @param iter Iterator to release * @param iter Iterator to release
@ -1836,12 +1901,12 @@ public:
/** /**
* Directly modify a JSON value to floating-point type * Directly modify a JSON value to floating-point type
* @param handle JSON value to modify (cannot be object or array) * @param handle JSON value to modify (cannot be object or array)
* @param value Float value * @param value Double value
* @return true on success, false if handle is object or array * @return true on success, false if handle is object or array
* @warning For immutable documents, this breaks immutability. Use with caution. * @warning For immutable documents, this breaks immutability. Use with caution.
* @note This modifies the value in-place without creating a new value * @note This modifies the value in-place without creating a new value
*/ */
virtual bool SetFloat(JsonValue* handle, double value) = 0; virtual bool SetDouble(JsonValue* handle, double value) = 0;
/** /**
* Directly modify a JSON value to string type * Directly modify a JSON value to string type

View File

@ -137,9 +137,6 @@ JsonValue* JsonManager::ParseJSON(const char* json_str, bool is_file, bool is_mu
readError.msg, readError.code, readError.pos); readError.msg, readError.code, readError.pos);
} }
} }
if (idoc) {
yyjson_doc_free(idoc);
}
return nullptr; return nullptr;
} }
@ -258,7 +255,7 @@ JsonValue* JsonManager::ApplyJsonPatch(JsonValue* target, JsonValue* patch, bool
yyjson_mut_val* resultRoot = yyjson_mut_patch(doc, root, patchCopy, &patch_err); yyjson_mut_val* resultRoot = yyjson_mut_patch(doc, root, patchCopy, &patch_err);
if (!resultRoot) { if (!resultRoot) {
SetErrorSafe(error, error_size, "JSON patch failed (code %u, op index %zu, message: %s)", SetErrorSafe(error, error_size, "JSON patch failed (code %u, op index %zu, message: %s)",
patch_err.code, patch_err.idx, patch_err); patch_err.code, patch_err.idx, patch_err.msg);
return nullptr; return nullptr;
} }
@ -881,6 +878,14 @@ size_t JsonManager::GetRefCount(JsonValue* handle)
return handle->GetDocumentRefCount(); return handle->GetDocumentRefCount();
} }
size_t JsonManager::GetValCount(JsonValue* handle)
{
if (!handle || !handle->IsImmutable()) {
return 0;
}
return yyjson_doc_get_val_count(handle->m_pDocument->get());
}
JsonValue* JsonManager::ObjectInit() JsonValue* JsonManager::ObjectInit()
{ {
auto pJSONValue = CreateWrapper(); auto pJSONValue = CreateWrapper();
@ -949,9 +954,6 @@ JsonValue* JsonManager::ObjectParseString(const char* str, yyjson_read_flag read
SetErrorSafe(error, error_size, "Failed to parse JSON str: %s (error code: %u, position: %zu)", SetErrorSafe(error, error_size, "Failed to parse JSON str: %s (error code: %u, position: %zu)",
readError.msg, readError.code, readError.pos); readError.msg, readError.code, readError.pos);
} }
if (idoc) {
yyjson_doc_free(idoc);
}
return nullptr; return nullptr;
} }
@ -994,9 +996,6 @@ JsonValue* JsonManager::ObjectParseFile(const char* path, yyjson_read_flag read_
SetErrorSafe(error, error_size, "Failed to parse JSON file: %s (error code: %u, msg: %s, position: %zu)", SetErrorSafe(error, error_size, "Failed to parse JSON file: %s (error code: %u, msg: %s, position: %zu)",
realpath, readError.code, readError.msg, readError.pos); realpath, readError.code, readError.msg, readError.pos);
} }
if (idoc) {
yyjson_doc_free(idoc);
}
return nullptr; return nullptr;
} }
@ -1181,7 +1180,7 @@ bool JsonManager::ObjectGetBool(JsonValue* handle, const char* key, bool* out_va
} }
} }
bool JsonManager::ObjectGetFloat(JsonValue* handle, const char* key, double* out_value) bool JsonManager::ObjectGetDouble(JsonValue* handle, const char* key, double* out_value)
{ {
if (!handle || !key || !out_value) { if (!handle || !key || !out_value) {
return false; return false;
@ -1189,19 +1188,19 @@ bool JsonManager::ObjectGetFloat(JsonValue* handle, const char* key, double* out
if (handle->IsMutable()) { if (handle->IsMutable()) {
yyjson_mut_val* val = yyjson_mut_obj_get(handle->m_pVal_mut, key); yyjson_mut_val* val = yyjson_mut_obj_get(handle->m_pVal_mut, key);
if (!val || !yyjson_mut_is_real(val)) { if (!val || !yyjson_mut_is_num(val)) {
return false; return false;
} }
*out_value = yyjson_mut_get_real(val); *out_value = yyjson_mut_get_num(val);
return true; return true;
} else { } else {
yyjson_val* val = yyjson_obj_get(handle->m_pVal, key); yyjson_val* val = yyjson_obj_get(handle->m_pVal, key);
if (!val || !yyjson_is_real(val)) { if (!val || !yyjson_is_num(val)) {
return false; return false;
} }
*out_value = yyjson_get_real(val); *out_value = yyjson_get_num(val);
return true; return true;
} }
} }
@ -1381,7 +1380,7 @@ bool JsonManager::ObjectSetBool(JsonValue* handle, const char* key, bool value)
return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_bool(handle->m_pDocument_mut->get(), value)); return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_bool(handle->m_pDocument_mut->get(), value));
} }
bool JsonManager::ObjectSetFloat(JsonValue* handle, const char* key, double value) bool JsonManager::ObjectSetDouble(JsonValue* handle, const char* key, double value)
{ {
if (!handle || !handle->IsMutable() || !key) { if (!handle || !handle->IsMutable() || !key) {
return false; return false;
@ -1405,15 +1404,11 @@ bool JsonManager::ObjectSetInt64(JsonValue* handle, const char* key, std::varian
return false; return false;
} }
return std::visit([&](auto&& val) -> bool { if (std::holds_alternative<int64_t>(value)) {
using T = std::decay_t<decltype(val)>; return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value)));
if constexpr (std::is_same_v<T, int64_t>) { } else {
return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_sint(handle->m_pDocument_mut->get(), val)); return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value)));
} else if constexpr (std::is_same_v<T, uint64_t>) { }
return yyjson_mut_obj_put(handle->m_pVal_mut, yyjson_mut_strcpy(handle->m_pDocument_mut->get(), key), yyjson_mut_uint(handle->m_pDocument_mut->get(), val));
}
return false;
}, value);
} }
bool JsonManager::ObjectSetNull(JsonValue* handle, const char* key) bool JsonManager::ObjectSetNull(JsonValue* handle, const char* key)
@ -1511,6 +1506,19 @@ bool JsonManager::ObjectSort(JsonValue* handle, JSON_SORT_ORDER sort_mode)
return true; return true;
} }
bool JsonManager::ObjectRotate(JsonValue* handle, size_t idx)
{
if (!handle || !handle->IsMutable()) {
return false;
}
if (!yyjson_mut_is_obj(handle->m_pVal_mut)) {
return false;
}
return yyjson_mut_obj_rotate(handle->m_pVal_mut, idx);
}
JsonValue* JsonManager::ArrayInit() JsonValue* JsonManager::ArrayInit()
{ {
auto pJSONValue = CreateWrapper(); auto pJSONValue = CreateWrapper();
@ -1641,15 +1649,12 @@ JsonValue* JsonManager::ArrayInitWithInt64(const char** values, size_t count, ch
return nullptr; return nullptr;
} }
yyjson_mut_val* val = std::visit([&](auto&& arg) -> yyjson_mut_val* { yyjson_mut_val* val;
using T = std::decay_t<decltype(arg)>; if (std::holds_alternative<int64_t>(variant_value)) {
if constexpr (std::is_same_v<T, int64_t>) { val = yyjson_mut_sint(doc, std::get<int64_t>(variant_value));
return yyjson_mut_sint(doc, arg); } else {
} else if constexpr (std::is_same_v<T, uint64_t>) { val = yyjson_mut_uint(doc, std::get<uint64_t>(variant_value));
return yyjson_mut_uint(doc, arg); }
}
return nullptr;
}, variant_value);
if (!val || !yyjson_mut_arr_append(pJSONValue->m_pVal_mut, val)) { if (!val || !yyjson_mut_arr_append(pJSONValue->m_pVal_mut, val)) {
if (error && error_size > 0) { if (error && error_size > 0) {
@ -1692,7 +1697,7 @@ JsonValue* JsonManager::ArrayInitWithBool(const bool* values, size_t count)
return pJSONValue.release(); return pJSONValue.release();
} }
JsonValue* JsonManager::ArrayInitWithFloat(const double* values, size_t count) JsonValue* JsonManager::ArrayInitWithDouble(const double* values, size_t count)
{ {
if (!values) { if (!values) {
return nullptr; return nullptr;
@ -1740,9 +1745,6 @@ JsonValue* JsonManager::ArrayParseString(const char* str, yyjson_read_flag read_
SetErrorSafe(error, error_size, "Failed to parse JSON string: %s (error code: %u, position: %zu)", SetErrorSafe(error, error_size, "Failed to parse JSON string: %s (error code: %u, position: %zu)",
readError.msg, readError.code, readError.pos); readError.msg, readError.code, readError.pos);
} }
if (idoc) {
yyjson_doc_free(idoc);
}
return nullptr; return nullptr;
} }
@ -1785,9 +1787,6 @@ JsonValue* JsonManager::ArrayParseFile(const char* path, yyjson_read_flag read_f
SetErrorSafe(error, error_size, "Failed to parse JSON file: %s (error code: %u, msg: %s, position: %zu)", SetErrorSafe(error, error_size, "Failed to parse JSON file: %s (error code: %u, msg: %s, position: %zu)",
realpath, readError.code, readError.msg, readError.pos); realpath, readError.code, readError.msg, readError.pos);
} }
if (idoc) {
yyjson_doc_free(idoc);
}
return nullptr; return nullptr;
} }
@ -1973,7 +1972,7 @@ bool JsonManager::ArrayGetBool(JsonValue* handle, size_t index, bool* out_value)
} }
} }
bool JsonManager::ArrayGetFloat(JsonValue* handle, size_t index, double* out_value) bool JsonManager::ArrayGetDouble(JsonValue* handle, size_t index, double* out_value)
{ {
if (!handle || !out_value) { if (!handle || !out_value) {
return false; return false;
@ -1986,11 +1985,11 @@ bool JsonManager::ArrayGetFloat(JsonValue* handle, size_t index, double* out_val
} }
yyjson_mut_val* val = yyjson_mut_arr_get(handle->m_pVal_mut, index); yyjson_mut_val* val = yyjson_mut_arr_get(handle->m_pVal_mut, index);
if (!yyjson_mut_is_real(val)) { if (!yyjson_mut_is_num(val)) {
return false; return false;
} }
*out_value = yyjson_mut_get_real(val); *out_value = yyjson_mut_get_num(val);
return true; return true;
} else { } else {
size_t arr_size = yyjson_arr_size(handle->m_pVal); size_t arr_size = yyjson_arr_size(handle->m_pVal);
@ -1999,11 +1998,11 @@ bool JsonManager::ArrayGetFloat(JsonValue* handle, size_t index, double* out_val
} }
yyjson_val* val = yyjson_arr_get(handle->m_pVal, index); yyjson_val* val = yyjson_arr_get(handle->m_pVal, index);
if (!yyjson_is_real(val)) { if (!yyjson_is_num(val)) {
return false; return false;
} }
*out_value = yyjson_get_real(val); *out_value = yyjson_get_num(val);
return true; return true;
} }
} }
@ -2183,7 +2182,7 @@ bool JsonManager::ArrayReplaceBool(JsonValue* handle, size_t index, bool value)
return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_bool(handle->m_pDocument_mut->get(), value)) != nullptr; return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_bool(handle->m_pDocument_mut->get(), value)) != nullptr;
} }
bool JsonManager::ArrayReplaceFloat(JsonValue* handle, size_t index, double value) bool JsonManager::ArrayReplaceDouble(JsonValue* handle, size_t index, double value)
{ {
if (!handle || !handle->IsMutable()) { if (!handle || !handle->IsMutable()) {
return false; return false;
@ -2222,15 +2221,11 @@ bool JsonManager::ArrayReplaceInt64(JsonValue* handle, size_t index, std::varian
return false; return false;
} }
return std::visit([&](auto&& val) -> bool { if (std::holds_alternative<int64_t>(value)) {
using T = std::decay_t<decltype(val)>; return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value))) != nullptr;
if constexpr (std::is_same_v<T, int64_t>) { } else {
return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_sint(handle->m_pDocument_mut->get(), val)) != nullptr; return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value))) != nullptr;
} else if constexpr (std::is_same_v<T, uint64_t>) { }
return yyjson_mut_arr_replace(handle->m_pVal_mut, index, yyjson_mut_uint(handle->m_pDocument_mut->get(), val)) != nullptr;
}
return false;
}, value);
} }
bool JsonManager::ArrayReplaceNull(JsonValue* handle, size_t index) bool JsonManager::ArrayReplaceNull(JsonValue* handle, size_t index)
@ -2290,7 +2285,7 @@ bool JsonManager::ArrayAppendBool(JsonValue* handle, bool value)
return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_bool(handle->m_pDocument_mut->get(), value)); return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_bool(handle->m_pDocument_mut->get(), value));
} }
bool JsonManager::ArrayAppendFloat(JsonValue* handle, double value) bool JsonManager::ArrayAppendDouble(JsonValue* handle, double value)
{ {
if (!handle || !handle->IsMutable()) { if (!handle || !handle->IsMutable()) {
return false; return false;
@ -2314,15 +2309,11 @@ bool JsonManager::ArrayAppendInt64(JsonValue* handle, std::variant<int64_t, uint
return false; return false;
} }
return std::visit([&](auto&& val) -> bool { if (std::holds_alternative<int64_t>(value)) {
using T = std::decay_t<decltype(val)>; return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value)));
if constexpr (std::is_same_v<T, int64_t>) { } else {
return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_sint(handle->m_pDocument_mut->get(), val)); return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value)));
} else if constexpr (std::is_same_v<T, uint64_t>) { }
return yyjson_mut_arr_append(handle->m_pVal_mut, yyjson_mut_uint(handle->m_pDocument_mut->get(), val));
}
return false;
}, value);
} }
bool JsonManager::ArrayAppendNull(JsonValue* handle) bool JsonManager::ArrayAppendNull(JsonValue* handle)
@ -2392,15 +2383,12 @@ bool JsonManager::ArrayInsertInt64(JsonValue* handle, size_t index, std::variant
return false; return false;
} }
yyjson_mut_val* val = std::visit([&](auto&& arg) -> yyjson_mut_val* { yyjson_mut_val* val;
using T = std::decay_t<decltype(arg)>; if (std::holds_alternative<int64_t>(value)) {
if constexpr (std::is_same_v<T, int64_t>) { val = yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value));
return yyjson_mut_sint(handle->m_pDocument_mut->get(), arg); } else {
} else if constexpr (std::is_same_v<T, uint64_t>) { val = yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value));
return yyjson_mut_uint(handle->m_pDocument_mut->get(), arg); }
}
return nullptr;
}, value);
if (!val) { if (!val) {
return false; return false;
@ -2409,7 +2397,7 @@ bool JsonManager::ArrayInsertInt64(JsonValue* handle, size_t index, std::variant
return yyjson_mut_arr_insert(handle->m_pVal_mut, val, index); return yyjson_mut_arr_insert(handle->m_pVal_mut, val, index);
} }
bool JsonManager::ArrayInsertFloat(JsonValue* handle, size_t index, double value) bool JsonManager::ArrayInsertDouble(JsonValue* handle, size_t index, double value)
{ {
if (!handle || !handle->IsMutable()) { if (!handle || !handle->IsMutable()) {
return false; return false;
@ -2480,15 +2468,12 @@ bool JsonManager::ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uin
return false; return false;
} }
yyjson_mut_val* val = std::visit([&](auto&& arg) -> yyjson_mut_val* { yyjson_mut_val* val;
using T = std::decay_t<decltype(arg)>; if (std::holds_alternative<int64_t>(value)) {
if constexpr (std::is_same_v<T, int64_t>) { val = yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value));
return yyjson_mut_sint(handle->m_pDocument_mut->get(), arg); } else {
} else if constexpr (std::is_same_v<T, uint64_t>) { val = yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value));
return yyjson_mut_uint(handle->m_pDocument_mut->get(), arg); }
}
return nullptr;
}, value);
if (!val) { if (!val) {
return false; return false;
@ -2497,7 +2482,7 @@ bool JsonManager::ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uin
return yyjson_mut_arr_prepend(handle->m_pVal_mut, val); return yyjson_mut_arr_prepend(handle->m_pVal_mut, val);
} }
bool JsonManager::ArrayPrependFloat(JsonValue* handle, double value) bool JsonManager::ArrayPrependDouble(JsonValue* handle, double value)
{ {
if (!handle || !handle->IsMutable()) { if (!handle || !handle->IsMutable()) {
return false; return false;
@ -2722,7 +2707,7 @@ int JsonManager::ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint
return -1; return -1;
} }
int JsonManager::ArrayIndexOfFloat(JsonValue* handle, double search_value) int JsonManager::ArrayIndexOfDouble(JsonValue* handle, double search_value)
{ {
if (!handle) { if (!handle) {
return -1; return -1;
@ -2775,7 +2760,7 @@ bool JsonManager::ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode)
struct ValueInfo { struct ValueInfo {
yyjson_mut_val* val; yyjson_mut_val* val;
uint8_t type; uint8_t type;
uint8_t subtype; // 0=float, 1=signed int, 2=unsigned int uint8_t subtype; // 0=double, 1=signed int, 2=unsigned int
}; };
std::vector<ValueInfo> values; std::vector<ValueInfo> values;
@ -2881,6 +2866,19 @@ bool JsonManager::ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode)
return true; return true;
} }
bool JsonManager::ArrayRotate(JsonValue* handle, size_t idx)
{
if (!handle || !handle->IsMutable()) {
return false;
}
if (!yyjson_mut_is_arr(handle->m_pVal_mut)) {
return false;
}
return yyjson_mut_arr_rotate(handle->m_pVal_mut, idx);
}
const char* JsonManager::SkipSeparators(const char* ptr) const char* JsonManager::SkipSeparators(const char* ptr)
{ {
while (*ptr && (isspace(*ptr) || *ptr == ':' || *ptr == ',')) { while (*ptr && (isspace(*ptr) || *ptr == ':' || *ptr == ',')) {
@ -3156,7 +3154,7 @@ JsonValue* JsonManager::CreateBool(bool value)
return pJSONValue.release(); return pJSONValue.release();
} }
JsonValue* JsonManager::CreateFloat(double value) JsonValue* JsonManager::CreateDouble(double value)
{ {
auto pJSONValue = CreateWrapper(); auto pJSONValue = CreateWrapper();
pJSONValue->m_pDocument_mut = CreateDocument(); pJSONValue->m_pDocument_mut = CreateDocument();
@ -3207,14 +3205,11 @@ JsonValue* JsonManager::CreateInt64(std::variant<int64_t, uint64_t> value)
auto* doc = pJSONValue->m_pDocument_mut->get(); auto* doc = pJSONValue->m_pDocument_mut->get();
std::visit([&](auto&& val) { if (std::holds_alternative<int64_t>(value)) {
using T = std::decay_t<decltype(val)>; pJSONValue->m_pVal_mut = yyjson_mut_sint(doc, std::get<int64_t>(value));
if constexpr (std::is_same_v<T, int64_t>) { } else {
pJSONValue->m_pVal_mut = yyjson_mut_sint(doc, val); pJSONValue->m_pVal_mut = yyjson_mut_uint(doc, std::get<uint64_t>(value));
} else if constexpr (std::is_same_v<T, uint64_t>) { }
pJSONValue->m_pVal_mut = yyjson_mut_uint(doc, val);
}
}, value);
if (!pJSONValue->m_pVal_mut) { if (!pJSONValue->m_pVal_mut) {
return nullptr; return nullptr;
@ -3290,23 +3285,23 @@ bool JsonManager::GetBool(JsonValue* handle, bool* out_value)
} }
} }
bool JsonManager::GetFloat(JsonValue* handle, double* out_value) bool JsonManager::GetDouble(JsonValue* handle, double* out_value)
{ {
if (!handle || !out_value) { if (!handle || !out_value) {
return false; return false;
} }
if (handle->IsMutable()) { if (handle->IsMutable()) {
if (!yyjson_mut_is_real(handle->m_pVal_mut)) { if (!yyjson_mut_is_num(handle->m_pVal_mut)) {
return false; return false;
} }
*out_value = yyjson_mut_get_real(handle->m_pVal_mut); *out_value = yyjson_mut_get_num(handle->m_pVal_mut);
return true; return true;
} else { } else {
if (!yyjson_is_real(handle->m_pVal)) { if (!yyjson_is_num(handle->m_pVal)) {
return false; return false;
} }
*out_value = yyjson_get_real(handle->m_pVal); *out_value = yyjson_get_num(handle->m_pVal);
return true; return true;
} }
} }
@ -3477,7 +3472,7 @@ bool JsonManager::PtrGetBool(JsonValue* handle, const char* path, bool* out_valu
} }
} }
bool JsonManager::PtrGetFloat(JsonValue* handle, const char* path, double* out_value, char* error, size_t error_size) bool JsonManager::PtrGetDouble(JsonValue* handle, const char* path, double* out_value, char* error, size_t error_size)
{ {
if (!handle || !path || !out_value) { if (!handle || !path || !out_value) {
if (error && error_size > 0) { if (error && error_size > 0) {
@ -3499,14 +3494,14 @@ bool JsonManager::PtrGetFloat(JsonValue* handle, const char* path, double* out_v
return false; return false;
} }
if (!yyjson_mut_is_real(val)) { if (!yyjson_mut_is_num(val)) {
if (error && error_size > 0) { if (error && error_size > 0) {
SetErrorSafe(error, error_size, "Type mismatch at path '%s': expected float value, got %s", path, yyjson_mut_get_type_desc(val)); SetErrorSafe(error, error_size, "Type mismatch at path '%s': expected number value, got %s", path, yyjson_mut_get_type_desc(val));
} }
return false; return false;
} }
*out_value = yyjson_mut_get_real(val); *out_value = yyjson_mut_get_num(val);
return true; return true;
} else { } else {
yyjson_val* val = yyjson_doc_ptr_getx(handle->m_pDocument->get(), path, strlen(path), &ptrGetError); yyjson_val* val = yyjson_doc_ptr_getx(handle->m_pDocument->get(), path, strlen(path), &ptrGetError);
@ -3519,14 +3514,14 @@ bool JsonManager::PtrGetFloat(JsonValue* handle, const char* path, double* out_v
return false; return false;
} }
if (!yyjson_is_real(val)) { if (!yyjson_is_num(val)) {
if (error && error_size > 0) { if (error && error_size > 0) {
SetErrorSafe(error, error_size, "Type mismatch at path '%s': expected float value, got %s", path, yyjson_get_type_desc(val)); SetErrorSafe(error, error_size, "Type mismatch at path '%s': expected number value, got %s", path, yyjson_get_type_desc(val));
} }
return false; return false;
} }
*out_value = yyjson_get_real(val); *out_value = yyjson_get_num(val);
return true; return true;
} }
} }
@ -3849,7 +3844,7 @@ bool JsonManager::PtrSetBool(JsonValue* handle, const char* path, bool value, ch
return success; return success;
} }
bool JsonManager::PtrSetFloat(JsonValue* handle, const char* path, double value, char* error, size_t error_size) bool JsonManager::PtrSetDouble(JsonValue* handle, const char* path, double value, char* error, size_t error_size)
{ {
if (!handle || !handle->IsMutable() || !path) { if (!handle || !handle->IsMutable() || !path) {
if (error && error_size > 0) { if (error && error_size > 0) {
@ -3914,14 +3909,12 @@ bool JsonManager::PtrSetInt64(JsonValue* handle, const char* path, std::variant<
return false; return false;
} }
yyjson_mut_val* val = std::visit([&](auto&& val_input) -> yyjson_mut_val* { yyjson_mut_val* val;
using T = std::decay_t<decltype(val_input)>; if (std::holds_alternative<int64_t>(value)) {
if constexpr (std::is_same_v<T, int64_t>) { val = yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value));
return yyjson_mut_sint(handle->m_pDocument_mut->get(), val_input); } else {
} else { val = yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value));
return yyjson_mut_uint(handle->m_pDocument_mut->get(), val_input); }
}
}, value);
if (!val) { if (!val) {
if (error && error_size > 0) { if (error && error_size > 0) {
SetErrorSafe(error, error_size, "Failed to create JSON value"); SetErrorSafe(error, error_size, "Failed to create JSON value");
@ -4058,7 +4051,7 @@ bool JsonManager::PtrAddBool(JsonValue* handle, const char* path, bool value, ch
return success; return success;
} }
bool JsonManager::PtrAddFloat(JsonValue* handle, const char* path, double value, char* error, size_t error_size) bool JsonManager::PtrAddDouble(JsonValue* handle, const char* path, double value, char* error, size_t error_size)
{ {
if (!handle || !handle->IsMutable() || !path) { if (!handle || !handle->IsMutable() || !path) {
if (error && error_size > 0) { if (error && error_size > 0) {
@ -4123,14 +4116,12 @@ bool JsonManager::PtrAddInt64(JsonValue* handle, const char* path, std::variant<
return false; return false;
} }
yyjson_mut_val* val = std::visit([&](auto&& val_input) -> yyjson_mut_val* { yyjson_mut_val* val;
using T = std::decay_t<decltype(val_input)>; if (std::holds_alternative<int64_t>(value)) {
if constexpr (std::is_same_v<T, int64_t>) { val = yyjson_mut_sint(handle->m_pDocument_mut->get(), std::get<int64_t>(value));
return yyjson_mut_sint(handle->m_pDocument_mut->get(), val_input); } else {
} else { val = yyjson_mut_uint(handle->m_pDocument_mut->get(), std::get<uint64_t>(value));
return yyjson_mut_uint(handle->m_pDocument_mut->get(), val_input); }
}
}, value);
if (!val) { if (!val) {
if (error && error_size > 0) { if (error && error_size > 0) {
SetErrorSafe(error, error_size, "Failed to create JSON value"); SetErrorSafe(error, error_size, "Failed to create JSON value");
@ -4300,7 +4291,7 @@ bool JsonManager::PtrTryGetBool(JsonValue* handle, const char* path, bool* out_v
} }
} }
bool JsonManager::PtrTryGetFloat(JsonValue* handle, const char* path, double* out_value) bool JsonManager::PtrTryGetDouble(JsonValue* handle, const char* path, double* out_value)
{ {
if (!handle || !path || !out_value) { if (!handle || !path || !out_value) {
return false; return false;
@ -4616,12 +4607,12 @@ void JsonManager::Release(JsonValue* value)
} }
} }
HandleType_t JsonManager::GetHandleType() HandleType_t JsonManager::GetJsonHandleType()
{ {
return g_JsonType; return g_JsonType;
} }
JsonValue* JsonManager::GetFromHandle(IPluginContext* pContext, Handle_t handle) JsonValue* JsonManager::GetValueFromHandle(IPluginContext* pContext, Handle_t handle)
{ {
HandleError err; HandleError err;
HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity()); HandleSecurity sec(pContext->GetIdentity(), myself->GetIdentity());
@ -4945,6 +4936,27 @@ void* JsonManager::ObjIterRemove(JsonObjIter* iter)
return yyjson_mut_obj_iter_remove(&iter->m_iterMut); return yyjson_mut_obj_iter_remove(&iter->m_iterMut);
} }
bool JsonManager::ObjIterGetKeyString(JsonObjIter* iter, void* key, const char** out_str, size_t* out_len)
{
if (!iter || !key || !out_str) {
return false;
}
if (iter->m_isMutable) {
*out_str = yyjson_mut_get_str(reinterpret_cast<yyjson_mut_val*>(key));
if (out_len) {
*out_len = yyjson_mut_get_len(reinterpret_cast<yyjson_mut_val*>(key));
}
} else {
*out_str = yyjson_get_str(reinterpret_cast<yyjson_val*>(key));
if (out_len) {
*out_len = yyjson_get_len(reinterpret_cast<yyjson_val*>(key));
}
}
return *out_str != nullptr;
}
void JsonManager::ReleaseArrIter(JsonArrIter* iter) void JsonManager::ReleaseArrIter(JsonArrIter* iter)
{ {
if (iter) { if (iter) {
@ -5143,26 +5155,22 @@ bool JsonManager::SetInt64(JsonValue* handle, std::variant<int64_t, uint64_t> va
return false; return false;
} }
return std::visit([&](auto&& val) -> bool { if (handle->IsMutable()) {
using T = std::decay_t<decltype(val)>; if (std::holds_alternative<int64_t>(value)) {
if (handle->IsMutable()) { return yyjson_mut_set_sint(handle->m_pVal_mut, std::get<int64_t>(value));
if constexpr (std::is_same_v<T, int64_t>) {
return yyjson_mut_set_sint(handle->m_pVal_mut, val);
} else if constexpr (std::is_same_v<T, uint64_t>) {
return yyjson_mut_set_uint(handle->m_pVal_mut, val);
}
} else { } else {
if constexpr (std::is_same_v<T, int64_t>) { return yyjson_mut_set_uint(handle->m_pVal_mut, std::get<uint64_t>(value));
return yyjson_set_sint(handle->m_pVal, val);
} else if constexpr (std::is_same_v<T, uint64_t>) {
return yyjson_set_uint(handle->m_pVal, val);
}
} }
return false; } else {
}, value); if (std::holds_alternative<int64_t>(value)) {
return yyjson_set_sint(handle->m_pVal, std::get<int64_t>(value));
} else {
return yyjson_set_uint(handle->m_pVal, std::get<uint64_t>(value));
}
}
} }
bool JsonManager::SetFloat(JsonValue* handle, double value) bool JsonManager::SetDouble(JsonValue* handle, double value)
{ {
if (!handle) { if (!handle) {
return false; return false;

View File

@ -346,6 +346,7 @@ public:
virtual bool IsImmutable(JsonValue* handle) override; virtual bool IsImmutable(JsonValue* handle) override;
virtual size_t GetReadSize(JsonValue* handle) override; virtual size_t GetReadSize(JsonValue* handle) override;
virtual size_t GetRefCount(JsonValue* handle) override; virtual size_t GetRefCount(JsonValue* handle) override;
virtual size_t GetValCount(JsonValue* handle) override;
// ========== Object Operations ========== // ========== Object Operations ==========
virtual JsonValue* ObjectInit() override; virtual JsonValue* ObjectInit() override;
@ -359,7 +360,7 @@ public:
virtual JsonValue* ObjectGetValueAt(JsonValue* handle, size_t index) override; virtual JsonValue* ObjectGetValueAt(JsonValue* handle, size_t index) override;
virtual JsonValue* ObjectGet(JsonValue* handle, const char* key) override; virtual JsonValue* ObjectGet(JsonValue* handle, const char* key) override;
virtual bool ObjectGetBool(JsonValue* handle, const char* key, bool* out_value) override; virtual bool ObjectGetBool(JsonValue* handle, const char* key, bool* out_value) override;
virtual bool ObjectGetFloat(JsonValue* handle, const char* key, double* out_value) override; virtual bool ObjectGetDouble(JsonValue* handle, const char* key, double* out_value) override;
virtual bool ObjectGetInt(JsonValue* handle, const char* key, int* out_value) override; virtual bool ObjectGetInt(JsonValue* handle, const char* key, int* out_value) override;
virtual bool ObjectGetInt64(JsonValue* handle, const char* key, std::variant<int64_t, uint64_t>* out_value) override; virtual bool ObjectGetInt64(JsonValue* handle, const char* key, std::variant<int64_t, uint64_t>* out_value) override;
virtual bool ObjectGetString(JsonValue* handle, const char* key, const char** out_str, size_t* out_len) override; virtual bool ObjectGetString(JsonValue* handle, const char* key, const char** out_str, size_t* out_len) override;
@ -368,7 +369,7 @@ public:
virtual bool ObjectRenameKey(JsonValue* handle, const char* old_key, const char* new_key, bool allow_duplicate) override; virtual bool ObjectRenameKey(JsonValue* handle, const char* old_key, const char* new_key, bool allow_duplicate) override;
virtual bool ObjectSet(JsonValue* handle, const char* key, JsonValue* value) override; virtual bool ObjectSet(JsonValue* handle, const char* key, JsonValue* value) override;
virtual bool ObjectSetBool(JsonValue* handle, const char* key, bool value) override; virtual bool ObjectSetBool(JsonValue* handle, const char* key, bool value) override;
virtual bool ObjectSetFloat(JsonValue* handle, const char* key, double value) override; virtual bool ObjectSetDouble(JsonValue* handle, const char* key, double value) override;
virtual bool ObjectSetInt(JsonValue* handle, const char* key, int value) override; virtual bool ObjectSetInt(JsonValue* handle, const char* key, int value) override;
virtual bool ObjectSetInt64(JsonValue* handle, const char* key, std::variant<int64_t, uint64_t> value) override; virtual bool ObjectSetInt64(JsonValue* handle, const char* key, std::variant<int64_t, uint64_t> value) override;
virtual bool ObjectSetNull(JsonValue* handle, const char* key) override; virtual bool ObjectSetNull(JsonValue* handle, const char* key) override;
@ -376,6 +377,7 @@ public:
virtual bool ObjectRemove(JsonValue* handle, const char* key) override; virtual bool ObjectRemove(JsonValue* handle, const char* key) override;
virtual bool ObjectClear(JsonValue* handle) override; virtual bool ObjectClear(JsonValue* handle) override;
virtual bool ObjectSort(JsonValue* handle, JSON_SORT_ORDER sort_mode) override; virtual bool ObjectSort(JsonValue* handle, JSON_SORT_ORDER sort_mode) override;
virtual bool ObjectRotate(JsonValue* handle, size_t idx) override;
// ========== Array Operations ========== // ========== Array Operations ==========
virtual JsonValue* ArrayInit() override; virtual JsonValue* ArrayInit() override;
@ -384,7 +386,7 @@ public:
virtual JsonValue* ArrayInitWithInt64(const char** values, size_t count, virtual JsonValue* ArrayInitWithInt64(const char** values, size_t count,
char* error, size_t error_size) override; char* error, size_t error_size) override;
virtual JsonValue* ArrayInitWithBool(const bool* values, size_t count) override; virtual JsonValue* ArrayInitWithBool(const bool* values, size_t count) override;
virtual JsonValue* ArrayInitWithFloat(const double* values, size_t count) override; virtual JsonValue* ArrayInitWithDouble(const double* values, size_t count) override;
virtual JsonValue* ArrayParseString(const char* str, yyjson_read_flag read_flg, virtual JsonValue* ArrayParseString(const char* str, yyjson_read_flag read_flg,
char* error, size_t error_size) override; char* error, size_t error_size) override;
virtual JsonValue* ArrayParseFile(const char* path, yyjson_read_flag read_flg, virtual JsonValue* ArrayParseFile(const char* path, yyjson_read_flag read_flg,
@ -394,21 +396,21 @@ public:
virtual JsonValue* ArrayGetFirst(JsonValue* handle) override; virtual JsonValue* ArrayGetFirst(JsonValue* handle) override;
virtual JsonValue* ArrayGetLast(JsonValue* handle) override; virtual JsonValue* ArrayGetLast(JsonValue* handle) override;
virtual bool ArrayGetBool(JsonValue* handle, size_t index, bool* out_value) override; virtual bool ArrayGetBool(JsonValue* handle, size_t index, bool* out_value) override;
virtual bool ArrayGetFloat(JsonValue* handle, size_t index, double* out_value) override; virtual bool ArrayGetDouble(JsonValue* handle, size_t index, double* out_value) override;
virtual bool ArrayGetInt(JsonValue* handle, size_t index, int* out_value) override; virtual bool ArrayGetInt(JsonValue* handle, size_t index, int* out_value) override;
virtual bool ArrayGetInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t>* out_value) override; virtual bool ArrayGetInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t>* out_value) override;
virtual bool ArrayGetString(JsonValue* handle, size_t index, const char** out_str, size_t* out_len) override; virtual bool ArrayGetString(JsonValue* handle, size_t index, const char** out_str, size_t* out_len) override;
virtual bool ArrayIsNull(JsonValue* handle, size_t index) override; virtual bool ArrayIsNull(JsonValue* handle, size_t index) override;
virtual bool ArrayReplace(JsonValue* handle, size_t index, JsonValue* value) override; virtual bool ArrayReplace(JsonValue* handle, size_t index, JsonValue* value) override;
virtual bool ArrayReplaceBool(JsonValue* handle, size_t index, bool value) override; virtual bool ArrayReplaceBool(JsonValue* handle, size_t index, bool value) override;
virtual bool ArrayReplaceFloat(JsonValue* handle, size_t index, double value) override; virtual bool ArrayReplaceDouble(JsonValue* handle, size_t index, double value) override;
virtual bool ArrayReplaceInt(JsonValue* handle, size_t index, int value) override; virtual bool ArrayReplaceInt(JsonValue* handle, size_t index, int value) override;
virtual bool ArrayReplaceInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) override; virtual bool ArrayReplaceInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) override;
virtual bool ArrayReplaceNull(JsonValue* handle, size_t index) override; virtual bool ArrayReplaceNull(JsonValue* handle, size_t index) override;
virtual bool ArrayReplaceString(JsonValue* handle, size_t index, const char* value) override; virtual bool ArrayReplaceString(JsonValue* handle, size_t index, const char* value) override;
virtual bool ArrayAppend(JsonValue* handle, JsonValue* value) override; virtual bool ArrayAppend(JsonValue* handle, JsonValue* value) override;
virtual bool ArrayAppendBool(JsonValue* handle, bool value) override; virtual bool ArrayAppendBool(JsonValue* handle, bool value) override;
virtual bool ArrayAppendFloat(JsonValue* handle, double value) override; virtual bool ArrayAppendDouble(JsonValue* handle, double value) override;
virtual bool ArrayAppendInt(JsonValue* handle, int value) override; virtual bool ArrayAppendInt(JsonValue* handle, int value) override;
virtual bool ArrayAppendInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override; virtual bool ArrayAppendInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override;
virtual bool ArrayAppendNull(JsonValue* handle) override; virtual bool ArrayAppendNull(JsonValue* handle) override;
@ -417,14 +419,14 @@ public:
virtual bool ArrayInsertBool(JsonValue* handle, size_t index, bool value) override; virtual bool ArrayInsertBool(JsonValue* handle, size_t index, bool value) override;
virtual bool ArrayInsertInt(JsonValue* handle, size_t index, int value) override; virtual bool ArrayInsertInt(JsonValue* handle, size_t index, int value) override;
virtual bool ArrayInsertInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) override; virtual bool ArrayInsertInt64(JsonValue* handle, size_t index, std::variant<int64_t, uint64_t> value) override;
virtual bool ArrayInsertFloat(JsonValue* handle, size_t index, double value) override; virtual bool ArrayInsertDouble(JsonValue* handle, size_t index, double value) override;
virtual bool ArrayInsertString(JsonValue* handle, size_t index, const char* value) override; virtual bool ArrayInsertString(JsonValue* handle, size_t index, const char* value) override;
virtual bool ArrayInsertNull(JsonValue* handle, size_t index) override; virtual bool ArrayInsertNull(JsonValue* handle, size_t index) override;
virtual bool ArrayPrepend(JsonValue* handle, JsonValue* value) override; virtual bool ArrayPrepend(JsonValue* handle, JsonValue* value) override;
virtual bool ArrayPrependBool(JsonValue* handle, bool value) override; virtual bool ArrayPrependBool(JsonValue* handle, bool value) override;
virtual bool ArrayPrependInt(JsonValue* handle, int value) override; virtual bool ArrayPrependInt(JsonValue* handle, int value) override;
virtual bool ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override; virtual bool ArrayPrependInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override;
virtual bool ArrayPrependFloat(JsonValue* handle, double value) override; virtual bool ArrayPrependDouble(JsonValue* handle, double value) override;
virtual bool ArrayPrependString(JsonValue* handle, const char* value) override; virtual bool ArrayPrependString(JsonValue* handle, const char* value) override;
virtual bool ArrayPrependNull(JsonValue* handle) override; virtual bool ArrayPrependNull(JsonValue* handle) override;
virtual bool ArrayRemove(JsonValue* handle, size_t index) override; virtual bool ArrayRemove(JsonValue* handle, size_t index) override;
@ -436,19 +438,20 @@ public:
virtual int ArrayIndexOfString(JsonValue* handle, const char* search_value) override; virtual int ArrayIndexOfString(JsonValue* handle, const char* search_value) override;
virtual int ArrayIndexOfInt(JsonValue* handle, int search_value) override; virtual int ArrayIndexOfInt(JsonValue* handle, int search_value) override;
virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) override; virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) override;
virtual int ArrayIndexOfFloat(JsonValue* handle, double search_value) override; virtual int ArrayIndexOfDouble(JsonValue* handle, double search_value) override;
virtual bool ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode) override; virtual bool ArraySort(JsonValue* handle, JSON_SORT_ORDER sort_mode) override;
virtual bool ArrayRotate(JsonValue* handle, size_t idx) override;
// ========== Value Operations ========== // ========== Value Operations ==========
virtual JsonValue* Pack(const char* format, IPackParamProvider* param_provider, char* error, size_t error_size) override; virtual JsonValue* Pack(const char* format, IPackParamProvider* param_provider, char* error, size_t error_size) override;
virtual JsonValue* CreateBool(bool value) override; virtual JsonValue* CreateBool(bool value) override;
virtual JsonValue* CreateFloat(double value) override; virtual JsonValue* CreateDouble(double value) override;
virtual JsonValue* CreateInt(int value) override; virtual JsonValue* CreateInt(int value) override;
virtual JsonValue* CreateInt64(std::variant<int64_t, uint64_t> value) override; virtual JsonValue* CreateInt64(std::variant<int64_t, uint64_t> value) override;
virtual JsonValue* CreateNull() override; virtual JsonValue* CreateNull() override;
virtual JsonValue* CreateString(const char* value) override; virtual JsonValue* CreateString(const char* value) override;
virtual bool GetBool(JsonValue* handle, bool* out_value) override; virtual bool GetBool(JsonValue* handle, bool* out_value) override;
virtual bool GetFloat(JsonValue* handle, double* out_value) override; virtual bool GetDouble(JsonValue* handle, double* out_value) override;
virtual bool GetInt(JsonValue* handle, int* out_value) override; virtual bool GetInt(JsonValue* handle, int* out_value) override;
virtual bool GetInt64(JsonValue* handle, std::variant<int64_t, uint64_t>* out_value) override; virtual bool GetInt64(JsonValue* handle, std::variant<int64_t, uint64_t>* out_value) override;
virtual bool GetString(JsonValue* handle, const char** out_str, size_t* out_len) override; virtual bool GetString(JsonValue* handle, const char** out_str, size_t* out_len) override;
@ -456,7 +459,7 @@ public:
// ========== Pointer Operations ========== // ========== Pointer Operations ==========
virtual JsonValue* PtrGet(JsonValue* handle, const char* path, char* error, size_t error_size) override; virtual JsonValue* PtrGet(JsonValue* handle, const char* path, char* error, size_t error_size) override;
virtual bool PtrGetBool(JsonValue* handle, const char* path, bool* out_value, char* error, size_t error_size) override; virtual bool PtrGetBool(JsonValue* handle, const char* path, bool* out_value, char* error, size_t error_size) override;
virtual bool PtrGetFloat(JsonValue* handle, const char* path, double* out_value, char* error, size_t error_size) override; virtual bool PtrGetDouble(JsonValue* handle, const char* path, double* out_value, char* error, size_t error_size) override;
virtual bool PtrGetInt(JsonValue* handle, const char* path, int* out_value, char* error, size_t error_size) override; virtual bool PtrGetInt(JsonValue* handle, const char* path, int* out_value, char* error, size_t error_size) override;
virtual bool PtrGetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t>* out_value, char* error, size_t error_size) override; virtual bool PtrGetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t>* out_value, char* error, size_t error_size) override;
virtual bool PtrGetString(JsonValue* handle, const char* path, const char** out_str, size_t* out_len, char* error, size_t error_size) override; virtual bool PtrGetString(JsonValue* handle, const char* path, const char** out_str, size_t* out_len, char* error, size_t error_size) override;
@ -464,14 +467,14 @@ public:
virtual bool PtrGetLength(JsonValue* handle, const char* path, size_t* out_len, char* error, size_t error_size) override; virtual bool PtrGetLength(JsonValue* handle, const char* path, size_t* out_len, char* error, size_t error_size) override;
virtual bool PtrSet(JsonValue* handle, const char* path, JsonValue* value, char* error, size_t error_size) override; virtual bool PtrSet(JsonValue* handle, const char* path, JsonValue* value, char* error, size_t error_size) override;
virtual bool PtrSetBool(JsonValue* handle, const char* path, bool value, char* error, size_t error_size) override; virtual bool PtrSetBool(JsonValue* handle, const char* path, bool value, char* error, size_t error_size) override;
virtual bool PtrSetFloat(JsonValue* handle, const char* path, double value, char* error, size_t error_size) override; virtual bool PtrSetDouble(JsonValue* handle, const char* path, double value, char* error, size_t error_size) override;
virtual bool PtrSetInt(JsonValue* handle, const char* path, int value, char* error, size_t error_size) override; virtual bool PtrSetInt(JsonValue* handle, const char* path, int value, char* error, size_t error_size) override;
virtual bool PtrSetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t> value, char* error, size_t error_size) override; virtual bool PtrSetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t> value, char* error, size_t error_size) override;
virtual bool PtrSetString(JsonValue* handle, const char* path, const char* value, char* error, size_t error_size) override; virtual bool PtrSetString(JsonValue* handle, const char* path, const char* value, char* error, size_t error_size) override;
virtual bool PtrSetNull(JsonValue* handle, const char* path, char* error, size_t error_size) override; virtual bool PtrSetNull(JsonValue* handle, const char* path, char* error, size_t error_size) override;
virtual bool PtrAdd(JsonValue* handle, const char* path, JsonValue* value, char* error, size_t error_size) override; virtual bool PtrAdd(JsonValue* handle, const char* path, JsonValue* value, char* error, size_t error_size) override;
virtual bool PtrAddBool(JsonValue* handle, const char* path, bool value, char* error, size_t error_size) override; virtual bool PtrAddBool(JsonValue* handle, const char* path, bool value, char* error, size_t error_size) override;
virtual bool PtrAddFloat(JsonValue* handle, const char* path, double value, char* error, size_t error_size) override; virtual bool PtrAddDouble(JsonValue* handle, const char* path, double value, char* error, size_t error_size) override;
virtual bool PtrAddInt(JsonValue* handle, const char* path, int value, char* error, size_t error_size) override; virtual bool PtrAddInt(JsonValue* handle, const char* path, int value, char* error, size_t error_size) override;
virtual bool PtrAddInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t> value, char* error, size_t error_size) override; virtual bool PtrAddInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t> value, char* error, size_t error_size) override;
virtual bool PtrAddString(JsonValue* handle, const char* path, const char* value, char* error, size_t error_size) override; virtual bool PtrAddString(JsonValue* handle, const char* path, const char* value, char* error, size_t error_size) override;
@ -479,7 +482,7 @@ public:
virtual bool PtrRemove(JsonValue* handle, const char* path, char* error, size_t error_size) override; virtual bool PtrRemove(JsonValue* handle, const char* path, char* error, size_t error_size) override;
virtual JsonValue* PtrTryGet(JsonValue* handle, const char* path) override; virtual JsonValue* PtrTryGet(JsonValue* handle, const char* path) override;
virtual bool PtrTryGetBool(JsonValue* handle, const char* path, bool* out_value) override; virtual bool PtrTryGetBool(JsonValue* handle, const char* path, bool* out_value) override;
virtual bool PtrTryGetFloat(JsonValue* handle, const char* path, double* out_value) override; virtual bool PtrTryGetDouble(JsonValue* handle, const char* path, double* out_value) override;
virtual bool PtrTryGetInt(JsonValue* handle, const char* path, int* out_value) override; virtual bool PtrTryGetInt(JsonValue* handle, const char* path, int* out_value) override;
virtual bool PtrTryGetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t>* out_value) override; virtual bool PtrTryGetInt64(JsonValue* handle, const char* path, std::variant<int64_t, uint64_t>* out_value) override;
virtual bool PtrTryGetString(JsonValue* handle, const char* path, const char** out_str, size_t* out_len) override; virtual bool PtrTryGetString(JsonValue* handle, const char* path, const char** out_str, size_t* out_len) override;
@ -512,6 +515,7 @@ public:
virtual JsonValue* ObjIterGet(JsonObjIter* iter, const char* key) override; virtual JsonValue* ObjIterGet(JsonObjIter* iter, const char* key) override;
virtual size_t ObjIterGetIndex(JsonObjIter* iter) override; virtual size_t ObjIterGetIndex(JsonObjIter* iter) override;
virtual void* ObjIterRemove(JsonObjIter* iter) override; virtual void* ObjIterRemove(JsonObjIter* iter) override;
virtual bool ObjIterGetKeyString(JsonObjIter* iter, void* key, const char** out_str, size_t* out_len = nullptr) override;
// ========== Iterator Release Operations ========== // ========== Iterator Release Operations ==========
virtual void ReleaseArrIter(JsonArrIter* iter) override; virtual void ReleaseArrIter(JsonArrIter* iter) override;
@ -527,10 +531,10 @@ public:
virtual void Release(JsonValue* value) override; virtual void Release(JsonValue* value) override;
// ========== Handle Type Operations ========== // ========== Handle Type Operations ==========
virtual HandleType_t GetHandleType() override; virtual HandleType_t GetJsonHandleType() override;
// ========== Handle Operations ========== // ========== Handle Operations ==========
virtual JsonValue* GetFromHandle(IPluginContext* pContext, Handle_t handle) override; virtual JsonValue* GetValueFromHandle(IPluginContext* pContext, Handle_t handle) override;
// ========== Number Read/Write Operations ========== // ========== Number Read/Write Operations ==========
virtual JsonValue* ReadNumber(const char* dat, uint32_t read_flg = 0, virtual JsonValue* ReadNumber(const char* dat, uint32_t read_flg = 0,
@ -546,7 +550,7 @@ public:
virtual bool SetBool(JsonValue* handle, bool value) override; virtual bool SetBool(JsonValue* handle, bool value) override;
virtual bool SetInt(JsonValue* handle, int value) override; virtual bool SetInt(JsonValue* handle, int value) override;
virtual bool SetInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override; virtual bool SetInt64(JsonValue* handle, std::variant<int64_t, uint64_t> value) override;
virtual bool SetFloat(JsonValue* handle, double value) override; virtual bool SetDouble(JsonValue* handle, double value) override;
virtual bool SetString(JsonValue* handle, const char* value) override; virtual bool SetString(JsonValue* handle, const char* value) override;
virtual bool SetNull(JsonValue* handle) override; virtual bool SetNull(JsonValue* handle) override;

File diff suppressed because it is too large Load Diff

View File

@ -17,26 +17,30 @@ bool JsonExtension::SDK_OnLoad(char* error, size_t maxlen, bool late)
sharesys->AddNatives(myself, g_JsonNatives); sharesys->AddNatives(myself, g_JsonNatives);
sharesys->RegisterLibrary(myself, "json"); sharesys->RegisterLibrary(myself, "json");
HandleAccess haJSON; HandleAccess haDefault;
handlesys->InitAccessDefaults(nullptr, &haJSON); handlesys->InitAccessDefaults(nullptr, &haDefault);
haJSON.access[HandleAccess_Read] = 0; haDefault.access[HandleAccess_Read] = 0;
haJSON.access[HandleAccess_Delete] = 0; haDefault.access[HandleAccess_Delete] = 0;
TypeAccess taDefault;
handlesys->InitAccessDefaults(&taDefault, nullptr);
taDefault.access[HTypeAccess_Create] = true;
HandleError err; HandleError err;
g_JsonType = handlesys->CreateType("JSON", &g_JsonHandler, 0, nullptr, &haJSON, myself->GetIdentity(), &err); g_JsonType = handlesys->CreateType("JSON", &g_JsonHandler, 0, &taDefault, &haDefault, myself->GetIdentity(), &err);
if (!g_JsonType) { if (!g_JsonType) {
snprintf(error, maxlen, "Failed to create JSON handle type (err: %d)", err); snprintf(error, maxlen, "Failed to create JSON handle type (err: %d)", err);
return false; return false;
} }
g_ArrIterType = handlesys->CreateType("JSONArrIter", &g_ArrIterHandler, 0, nullptr, &haJSON, myself->GetIdentity(), &err); g_ArrIterType = handlesys->CreateType("JSONArrIter", &g_ArrIterHandler, 0, &taDefault, &haDefault, myself->GetIdentity(), &err);
if (!g_ArrIterType) { if (!g_ArrIterType) {
snprintf(error, maxlen, "Failed to create JSONArrIter handle type (err: %d)", err); snprintf(error, maxlen, "Failed to create JSONArrIter handle type (err: %d)", err);
return false; return false;
} }
g_ObjIterType = handlesys->CreateType("JSONObjIter", &g_ObjIterHandler, 0, nullptr, &haJSON, myself->GetIdentity(), &err); g_ObjIterType = handlesys->CreateType("JSONObjIter", &g_ObjIterHandler, 0, &taDefault, &haDefault, myself->GetIdentity(), &err);
if (!g_ObjIterType) { if (!g_ObjIterType) {
snprintf(error, maxlen, "Failed to create JSONObjIter handle type (err: %d)", err); snprintf(error, maxlen, "Failed to create JSONObjIter handle type (err: %d)", err);
return false; return false;
@ -47,7 +51,7 @@ bool JsonExtension::SDK_OnLoad(char* error, size_t maxlen, bool late)
g_pJsonManager = nullptr; g_pJsonManager = nullptr;
} }
g_pJsonManager = new JsonManager(); g_pJsonManager = new(std::nothrow) JsonManager();
if (!g_pJsonManager) { if (!g_pJsonManager) {
snprintf(error, maxlen, "Failed to create JSON manager instance"); snprintf(error, maxlen, "Failed to create JSON manager instance");
return false; return false;

View File

@ -109,8 +109,8 @@ methodmap JSON < Handle
* - ]: end array * - ]: end array
* *
* @note Needs to be freed using delete or CloseHandle() * @note Needs to be freed using delete or CloseHandle()
* @note There is a limit of 32 parameters (defined in SourcePawn) * @note SourcePawn imposes a limit of 32 parameters per function (defined by SP_MAX_EXEC_PARAMS),
* including the format string, so the number of arguments must be less than or equal to 31 * which precludes the construction of complex objects with this method.
* *
* @param format Format string * @param format Format string
* @param ... Arguments based on format string * @param ... Arguments based on format string
@ -546,6 +546,8 @@ methodmap JSON < Handle
/** /**
* Get float value * Get float value
* *
* @note Integers values are auto converted to float
*
* @return float value * @return float value
*/ */
public native float GetFloat(); public native float GetFloat();
@ -618,6 +620,7 @@ methodmap JSON < Handle
* Get float value by a JSON Pointer * Get float value by a JSON Pointer
* *
* @note JSON Pointer paths are always resolved from the document root, not from the current value * @note JSON Pointer paths are always resolved from the document root, not from the current value
* @note Integers values are auto converted to float
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* *
@ -907,6 +910,7 @@ methodmap JSON < Handle
* Try to get float value by a JSON Pointer * Try to get float value by a JSON Pointer
* *
* @note JSON Pointer paths are always resolved from the document root, not from the current value * @note JSON Pointer paths are always resolved from the document root, not from the current value
* @note Integers values are auto converted to float
* *
* @param path The JSON pointer string * @param path The JSON pointer string
* @param value Store the float value * @param value Store the float value
@ -1096,6 +1100,17 @@ methodmap JSON < Handle
property int RefCount { property int RefCount {
public native get(); public native get();
} }
/**
* Get the total number of values in the document
*
* @note Only works on immutable documents (parsed from JSON)
* @note Returns 0 for mutable documents or null handles
* @note Useful for performance planning and memory estimation
*/
property int ValCount {
public native get();
}
}; };
methodmap JSONObject < JSON methodmap JSONObject < JSON
@ -1182,6 +1197,8 @@ methodmap JSONObject < JSON
/** /**
* Gets a float value from the object * Gets a float value from the object
* *
* @note Integers values are auto converted to float
*
* @param key Key name * @param key Key name
* *
* @return Float value * @return Float value
@ -1367,6 +1384,20 @@ methodmap JSONObject < JSON
*/ */
public native bool Sort(JSON_SORT_ORDER order = JSON_SORT_ASC); public native bool Sort(JSON_SORT_ORDER order = JSON_SORT_ASC);
/**
* Rotates key-value pairs in the object
*
* @note This function takes a linear search time
* @note Only works on mutable objects
* @note Example: {"a":1,"b":2,"c":3,"d":4} rotate 1 becomes {"b":2,"c":3,"d":4,"a":1}
*
* @param idx Number of positions to rotate
*
* @return True on success, false if object is immutable or operation failed
* @error Invalid handle or attempting to rotate an immutable object
*/
public native bool Rotate(int idx);
/** /**
* Retrieves the size of the object * Retrieves the size of the object
*/ */
@ -1486,6 +1517,8 @@ methodmap JSONArray < JSON
/** /**
* Gets a float value from the array * Gets a float value from the array
* *
* @note Integers values are auto converted to float
*
* @param index Position in the array (starting from 0) * @param index Position in the array (starting from 0)
* *
* @return The number as float * @return The number as float
@ -1921,6 +1954,20 @@ methodmap JSONArray < JSON
*/ */
public native bool Sort(JSON_SORT_ORDER order = JSON_SORT_ASC); public native bool Sort(JSON_SORT_ORDER order = JSON_SORT_ASC);
/**
* Rotates array elements
*
* @note This function takes a linear search time
* @note Only works on mutable arrays
* @note Example: [1,2,3,4,5] rotate 2 becomes [3,4,5,1,2]
*
* @param idx Number of positions to rotate
*
* @return True on success, false if array is immutable or operation failed
* @error Invalid handle or attempting to rotate an immutable array
*/
public native bool Rotate(int idx);
/** /**
* Retrieves the size of the array * Retrieves the size of the array
*/ */
@ -2164,6 +2211,7 @@ public void __pl_json_SetNTVOptional()
MarkNativeAsOptional("JSONObject.FromString"); MarkNativeAsOptional("JSONObject.FromString");
MarkNativeAsOptional("JSONObject.FromFile"); MarkNativeAsOptional("JSONObject.FromFile");
MarkNativeAsOptional("JSONObject.Sort"); MarkNativeAsOptional("JSONObject.Sort");
MarkNativeAsOptional("JSONObject.Rotate");
// JSONArray // JSONArray
MarkNativeAsOptional("JSONArray.JSONArray"); MarkNativeAsOptional("JSONArray.JSONArray");
@ -2223,6 +2271,7 @@ public void __pl_json_SetNTVOptional()
MarkNativeAsOptional("JSONArray.IndexOfInt64"); MarkNativeAsOptional("JSONArray.IndexOfInt64");
MarkNativeAsOptional("JSONArray.IndexOfFloat"); MarkNativeAsOptional("JSONArray.IndexOfFloat");
MarkNativeAsOptional("JSONArray.Sort"); MarkNativeAsOptional("JSONArray.Sort");
MarkNativeAsOptional("JSONArray.Rotate");
// JSON // JSON
MarkNativeAsOptional("JSON.ToString"); MarkNativeAsOptional("JSON.ToString");
@ -2235,6 +2284,7 @@ public void __pl_json_SetNTVOptional()
MarkNativeAsOptional("JSON.GetSerializedSize"); MarkNativeAsOptional("JSON.GetSerializedSize");
MarkNativeAsOptional("JSON.ReadSize.get"); MarkNativeAsOptional("JSON.ReadSize.get");
MarkNativeAsOptional("JSON.RefCount.get"); MarkNativeAsOptional("JSON.RefCount.get");
MarkNativeAsOptional("JSON.ValCount.get");
MarkNativeAsOptional("JSON.Type.get"); MarkNativeAsOptional("JSON.Type.get");
MarkNativeAsOptional("JSON.SubType.get"); MarkNativeAsOptional("JSON.SubType.get");
MarkNativeAsOptional("JSON.IsArray.get"); MarkNativeAsOptional("JSON.IsArray.get");

View File

@ -653,6 +653,64 @@ void Test_ObjectOperations()
} }
TestEnd(); TestEnd();
// Test Rotate
TestStart("Object_Rotate_Forward");
{
JSONObject obj = new JSONObject();
obj.SetInt("a", 1);
obj.SetInt("b", 2);
obj.SetInt("c", 3);
obj.SetInt("d", 4);
AssertTrue(obj.Rotate(1));
char key[32];
obj.GetKey(0, key, sizeof(key));
AssertStrEq(key, "b", "First key should be 'b' after rotate 1");
obj.GetKey(3, key, sizeof(key));
AssertStrEq(key, "a", "Last key should be 'a' after rotate 1");
delete obj;
}
TestEnd();
TestStart("Object_Rotate_Multiple");
{
JSONObject obj = new JSONObject();
obj.SetInt("first", 1);
obj.SetInt("second", 2);
obj.SetInt("third", 3);
obj.SetInt("fourth", 4);
obj.SetInt("fifth", 5);
AssertTrue(obj.Rotate(2));
char key[32];
obj.GetKey(0, key, sizeof(key));
AssertStrEq(key, "third", "First key should be 'third' after rotate 2");
obj.GetKey(4, key, sizeof(key));
AssertStrEq(key, "second", "Last key should be 'second' after rotate 2");
delete obj;
}
TestEnd();
TestStart("Object_Rotate_Zero");
{
JSONObject obj = new JSONObject();
obj.SetInt("x", 1);
obj.SetInt("y", 2);
AssertTrue(obj.Rotate(0));
char key[32];
obj.GetKey(0, key, sizeof(key));
AssertStrEq(key, "x", "Order should not change after rotate 0");
delete obj;
}
TestEnd();
// Test Set with handle // Test Set with handle
TestStart("Object_SetWithHandle"); TestStart("Object_SetWithHandle");
{ {
@ -1013,6 +1071,83 @@ void Test_ArrayOperations()
} }
TestEnd(); TestEnd();
// Test Rotate
TestStart("Array_Rotate_Forward");
{
JSONArray arr = new JSONArray();
arr.PushInt(1);
arr.PushInt(2);
arr.PushInt(3);
arr.PushInt(4);
arr.PushInt(5);
AssertTrue(arr.Rotate(2));
AssertEq(arr.GetInt(0), 3, "First element should be 3 after rotate 2");
AssertEq(arr.GetInt(1), 4, "Second element should be 4");
AssertEq(arr.GetInt(2), 5, "Third element should be 5");
AssertEq(arr.GetInt(3), 1, "Fourth element should be 1");
AssertEq(arr.GetInt(4), 2, "Fifth element should be 2");
delete arr;
}
TestEnd();
TestStart("Array_Rotate_Single");
{
JSONArray arr = new JSONArray();
arr.PushString("a");
arr.PushString("b");
arr.PushString("c");
arr.PushString("d");
AssertTrue(arr.Rotate(1));
char buffer[32];
arr.GetString(0, buffer, sizeof(buffer));
AssertStrEq(buffer, "b", "First element should be 'b' after rotate 1");
arr.GetString(3, buffer, sizeof(buffer));
AssertStrEq(buffer, "a", "Last element should be 'a' after rotate 1");
delete arr;
}
TestEnd();
TestStart("Array_Rotate_Zero");
{
JSONArray arr = new JSONArray();
arr.PushInt(10);
arr.PushInt(20);
arr.PushInt(30);
AssertTrue(arr.Rotate(0));
AssertEq(arr.GetInt(0), 10, "Order should not change after rotate 0");
AssertEq(arr.GetInt(1), 20);
AssertEq(arr.GetInt(2), 30);
delete arr;
}
TestEnd();
TestStart("Array_Rotate_LargeIndex");
{
JSONArray arr = new JSONArray();
arr.PushInt(1);
arr.PushInt(2);
arr.PushInt(3);
// Rotate by array length or greater should fail (idx must be < length)
AssertFalse(arr.Rotate(3), "Rotate by array length should fail");
AssertFalse(arr.Rotate(10), "Rotate by value > length should fail");
// Values should remain unchanged
AssertEq(arr.GetInt(0), 1);
AssertEq(arr.GetInt(1), 2);
AssertEq(arr.GetInt(2), 3);
delete arr;
}
TestEnd();
// Test Push with handle // Test Push with handle
TestStart("Array_PushHandle"); TestStart("Array_PushHandle");
{ {
@ -1555,6 +1690,68 @@ void Test_ParseAndSerialize()
} }
TestEnd(); TestEnd();
// Test ValCount (only works on immutable documents)
TestStart("Parse_ValCount_SimpleObject");
{
JSON json = JSON.Parse("{\"a\":1,\"b\":2,\"c\":3}");
AssertValidHandle(json);
int valCount = json.ValCount;
// Object has 7 values: 1 object + 3 keys ("a","b","c") + 3 integer values (1,2,3)
AssertEq(valCount, 7, "Simple object should have 7 values (object + keys + values)");
delete json;
}
TestEnd();
TestStart("Parse_ValCount_NestedStructure");
{
// {"user":{"name":"John","age":30},"items":[1,2,3]}
// Root object: 1
// "user" key + nested object: 2
// "name" key + "John" value: 2
// "age" key + 30 value: 2
// "items" key + array: 2
// Three integers in array: 3
// Total: 1 + 2 + 2 + 2 + 2 + 3 = 12
JSON json = JSON.Parse("{\"user\":{\"name\":\"John\",\"age\":30},\"items\":[1,2,3]}");
AssertValidHandle(json);
int valCount = json.ValCount;
AssertTrue(valCount > 0, "Nested structure should have multiple values");
delete json;
}
TestEnd();
TestStart("Parse_ValCount_Array");
{
JSON json = JSON.Parse("[1,2,3,4,5]");
AssertValidHandle(json);
int valCount = json.ValCount;
// Array itself + 5 integers = 6
AssertEq(valCount, 6, "Array with 5 elements should have 6 values");
delete json;
}
TestEnd();
TestStart("Parse_ValCount_MutableReturnsZero");
{
JSON json = JSON.Parse("{\"key\":\"value\"}", .is_mutable_doc = true);
AssertValidHandle(json);
int valCount = json.ValCount;
AssertEq(valCount, 0, "ValCount should return 0 for mutable documents");
delete json;
}
TestEnd();
TestStart("Parse_ValCount_CreatedObjectReturnsZero");
{
JSONObject obj = new JSONObject();
obj.SetInt("a", 1);
obj.SetInt("b", 2);
int valCount = obj.ValCount;
AssertEq(valCount, 0, "ValCount should return 0 for created (mutable) objects");
delete obj;
}
TestEnd();
// Test ToString // Test ToString
TestStart("Serialize_ToString"); TestStart("Serialize_ToString");
{ {