mirror of
https://github.com/alliedmodders/sourcemod.git
synced 2025-12-06 18:08:36 +00:00
feat: enhance JSON handling with performance and memory improvements
- Add WriteToStringPtr for optimized serialization without buffer allocations - Implement reference counting with RefCounted/RefPtr for better memory management - Support JSON Patch (RFC 6902) and Merge Patch (RFC 7386) operations - Improve floating-point serialization with adjusted precision limits (1-7) - Enhance iterators with reset capability and better error handling - Update documentation and tests for new features
This commit is contained in:
parent
0ad8d15d1a
commit
f596135996
@ -1,5 +1,5 @@
|
|||||||
#ifndef _INCLUDE_SM_JSON_IJSONMANAGER_H_
|
#ifndef _INCLUDE_IJSONMANAGER_H_
|
||||||
#define _INCLUDE_SM_JSON_IJSONMANAGER_H_
|
#define _INCLUDE_IJSONMANAGER_H_
|
||||||
|
|
||||||
#include <IHandleSys.h>
|
#include <IHandleSys.h>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
@ -15,7 +15,7 @@ class JsonArrIter;
|
|||||||
class JsonObjIter;
|
class JsonObjIter;
|
||||||
|
|
||||||
#define SMINTERFACE_JSONMANAGER_NAME "IJsonManager"
|
#define SMINTERFACE_JSONMANAGER_NAME "IJsonManager"
|
||||||
#define SMINTERFACE_JSONMANAGER_VERSION 1
|
#define SMINTERFACE_JSONMANAGER_VERSION 2
|
||||||
#define JSON_PACK_ERROR_SIZE 256
|
#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
|
||||||
@ -99,10 +99,69 @@ public:
|
|||||||
*
|
*
|
||||||
* @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
|
* @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.
|
||||||
|
* For better performance, use WriteToStringPtr() instead, which avoids intermediate buffers
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
|
* @param handle JSON value
|
||||||
|
* @param write_flg Write flags (YYJSON_WRITE_FLAG values, default: 0)
|
||||||
|
* @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
|
||||||
|
*
|
||||||
|
* @note This is the recommended method for serialization as it avoids intermediate buffer allocations
|
||||||
|
*/
|
||||||
|
virtual char* WriteToStringPtr(JsonValue* handle, uint32_t write_flg = 0, size_t* out_size = nullptr) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply JSON Patch (RFC 6902) and return a new JSON value
|
||||||
|
* @param target Target JSON value
|
||||||
|
* @param patch JSON Patch document
|
||||||
|
* @param result_mutable true to return mutable result, false for immutable
|
||||||
|
* @param error Error buffer (optional)
|
||||||
|
* @param error_size Error buffer size
|
||||||
|
* @return Patched JSON value on success, nullptr on failure
|
||||||
|
*/
|
||||||
|
virtual JsonValue* ApplyJsonPatch(JsonValue* target, JsonValue* patch, bool result_mutable,
|
||||||
|
char* error = nullptr, size_t error_size = 0) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply JSON Patch in place (target must be mutable)
|
||||||
|
* @param target Target JSON value (mutable document)
|
||||||
|
* @param patch JSON Patch document
|
||||||
|
* @param error Error buffer (optional)
|
||||||
|
* @param error_size Error buffer size
|
||||||
|
* @return true on success, false on failure
|
||||||
|
*/
|
||||||
|
virtual bool JsonPatchInPlace(JsonValue* target, JsonValue* patch,
|
||||||
|
char* error = nullptr, size_t error_size = 0) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply JSON Merge Patch (RFC 7396) and return a new JSON value
|
||||||
|
* @param target Target JSON value
|
||||||
|
* @param patch JSON Merge Patch document
|
||||||
|
* @param result_mutable true to return mutable result, false for immutable
|
||||||
|
* @param error Error buffer (optional)
|
||||||
|
* @param error_size Error buffer size
|
||||||
|
* @return Patched JSON value on success, nullptr on failure
|
||||||
|
*/
|
||||||
|
virtual JsonValue* ApplyMergePatch(JsonValue* target, JsonValue* patch, bool result_mutable,
|
||||||
|
char* error = nullptr, size_t error_size = 0) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply JSON Merge Patch in place (target must be mutable)
|
||||||
|
* @param target Target JSON value (mutable document)
|
||||||
|
* @param patch JSON Merge Patch document
|
||||||
|
* @param error Error buffer (optional)
|
||||||
|
* @param error_size Error buffer size
|
||||||
|
* @return true on success, false on failure
|
||||||
|
*/
|
||||||
|
virtual bool MergePatchInPlace(JsonValue* target, JsonValue* patch,
|
||||||
|
char* error = nullptr, size_t error_size = 0) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write JSON to file
|
* Write JSON to file
|
||||||
* @param handle JSON value
|
* @param handle JSON value
|
||||||
@ -316,6 +375,14 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual size_t GetReadSize(JsonValue* handle) = 0;
|
virtual size_t GetReadSize(JsonValue* handle) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the reference count of the document
|
||||||
|
* @param handle JSON value
|
||||||
|
* @return Reference count of the document (number of JsonValue objects sharing this document)
|
||||||
|
* @note Returns 0 if handle is null or has no document
|
||||||
|
*/
|
||||||
|
virtual size_t GetRefCount(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
|
||||||
@ -964,10 +1031,10 @@ public:
|
|||||||
* Remove range of elements (mutable only)
|
* Remove range of elements (mutable only)
|
||||||
* @param handle JSON array
|
* @param handle JSON array
|
||||||
* @param start_index Start index (inclusive)
|
* @param start_index Start index (inclusive)
|
||||||
* @param end_index End index (exclusive)
|
* @param count Number of elements to remove
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
virtual bool ArrayRemoveRange(JsonValue* handle, size_t start_index, size_t end_index) = 0;
|
virtual bool ArrayRemoveRange(JsonValue* handle, size_t start_index, size_t count) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all elements (mutable only)
|
* Remove all elements (mutable only)
|
||||||
@ -1001,20 +1068,12 @@ public:
|
|||||||
virtual int ArrayIndexOfInt(JsonValue* handle, int search_value) = 0;
|
virtual int ArrayIndexOfInt(JsonValue* handle, int search_value) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find index of 64-bit integer value
|
* Find index of 64-bit integer value (auto-detects signed/unsigned)
|
||||||
* @param handle JSON array
|
* @param handle JSON array
|
||||||
* @param search_value 64-bit integer value to search for
|
* @param search_value 64-bit integer value to search for (std::variant<int64_t, uint64_t>)
|
||||||
* @return Index of first match, or -1 if not found
|
* @return Index of first match, or -1 if not found
|
||||||
*/
|
*/
|
||||||
virtual int ArrayIndexOfInt64(JsonValue* handle, int64_t search_value) = 0;
|
virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) = 0;
|
||||||
|
|
||||||
/**
|
|
||||||
* Find index of 64-bit unsigned integer value
|
|
||||||
* @param handle JSON array
|
|
||||||
* @param search_value 64-bit unsigned integer value to search for
|
|
||||||
* @return Index of first match, or -1 if not found
|
|
||||||
*/
|
|
||||||
virtual int ArrayIndexOfUint64(JsonValue* handle, uint64_t search_value) = 0;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find index of float value
|
* Find index of float value
|
||||||
@ -1538,6 +1597,8 @@ public:
|
|||||||
* Initialize an array iterator (same as ArrIterWith but returns pointer)
|
* Initialize an array iterator (same as ArrIterWith but returns pointer)
|
||||||
* @param handle JSON array value
|
* @param handle JSON array value
|
||||||
* @return New array iterator or nullptr on error
|
* @return New array iterator or nullptr on error
|
||||||
|
* @note Caller must release the iterator using ReleaseArrIter() once finished
|
||||||
|
* @note Iterators are single-pass; once ArrIterNext() returns nullptr, create a new iterator or call ArrIterReset() to iterate again
|
||||||
*/
|
*/
|
||||||
virtual JsonArrIter* ArrIterInit(JsonValue* handle) = 0;
|
virtual JsonArrIter* ArrIterInit(JsonValue* handle) = 0;
|
||||||
|
|
||||||
@ -1545,9 +1606,18 @@ public:
|
|||||||
* Create an array iterator with an array
|
* Create an array iterator with an array
|
||||||
* @param handle JSON array value
|
* @param handle JSON array value
|
||||||
* @return New array iterator or nullptr on error
|
* @return New array iterator or nullptr on error
|
||||||
|
* @note Caller must release the iterator using ReleaseArrIter() once finished
|
||||||
|
* @note Iterators are single-pass; once ArrIterNext() returns nullptr, create a new iterator or call ArrIterReset() to iterate again
|
||||||
*/
|
*/
|
||||||
virtual JsonArrIter* ArrIterWith(JsonValue* handle) = 0;
|
virtual JsonArrIter* ArrIterWith(JsonValue* handle) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset an array iterator to the beginning
|
||||||
|
* @param iter Array iterator
|
||||||
|
* @return true on success, false if iterator is invalid or reset failed
|
||||||
|
*/
|
||||||
|
virtual bool ArrIterReset(JsonArrIter* iter) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get next element from array iterator
|
* Get next element from array iterator
|
||||||
* @param iter Array iterator
|
* @param iter Array iterator
|
||||||
@ -1580,6 +1650,8 @@ public:
|
|||||||
* Initialize an object iterator (same as ObjIterWith but returns pointer)
|
* Initialize an object iterator (same as ObjIterWith but returns pointer)
|
||||||
* @param handle JSON object value
|
* @param handle JSON object value
|
||||||
* @return New object iterator or nullptr on error
|
* @return New object iterator or nullptr on error
|
||||||
|
* @note Caller must release the iterator using ReleaseObjIter() once finished
|
||||||
|
* @note Iterators are single-pass; once ObjIterNext() returns nullptr, create a new iterator or call ObjIterReset() to iterate again
|
||||||
*/
|
*/
|
||||||
virtual JsonObjIter* ObjIterInit(JsonValue* handle) = 0;
|
virtual JsonObjIter* ObjIterInit(JsonValue* handle) = 0;
|
||||||
|
|
||||||
@ -1587,9 +1659,18 @@ public:
|
|||||||
* Create an object iterator with an object
|
* Create an object iterator with an object
|
||||||
* @param handle JSON object value
|
* @param handle JSON object value
|
||||||
* @return New object iterator or nullptr on error
|
* @return New object iterator or nullptr on error
|
||||||
|
* @note Caller must release the iterator using ReleaseObjIter() once finished
|
||||||
|
* @note Iterators are single-pass; once ObjIterNext() returns nullptr, create a new iterator or call ObjIterReset() to iterate again
|
||||||
*/
|
*/
|
||||||
virtual JsonObjIter* ObjIterWith(JsonValue* handle) = 0;
|
virtual JsonObjIter* ObjIterWith(JsonValue* handle) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset an object iterator to the beginning
|
||||||
|
* @param iter Object iterator
|
||||||
|
* @return true on success, false if iterator is invalid or reset failed
|
||||||
|
*/
|
||||||
|
virtual bool ObjIterReset(JsonObjIter* iter) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get next key from object iterator
|
* Get next key from object iterator
|
||||||
* @param iter Object iterator
|
* @param iter Object iterator
|
||||||
@ -1707,16 +1788,18 @@ public:
|
|||||||
* @param flt true to use single-precision (float), false to use double-precision (double)
|
* @param flt true to use single-precision (float), false to use double-precision (double)
|
||||||
* @return true on success, false if handle is not a floating-point number
|
* @return true on success, false if handle is not a floating-point number
|
||||||
* @note Only works on floating-point numbers (not integers)
|
* @note Only works on floating-point numbers (not integers)
|
||||||
|
* @note This affects how the number is serialized in all write operations
|
||||||
*/
|
*/
|
||||||
virtual bool SetFpToFloat(JsonValue* handle, bool flt) = 0;
|
virtual bool SetFpToFloat(JsonValue* handle, bool flt) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set floating-point number's output format to fixed-point notation
|
* Set floating-point number's output format to fixed-point notation
|
||||||
* @param handle JSON floating-point number value
|
* @param handle JSON floating-point number value
|
||||||
* @param prec Precision (1-15), similar to ECMAScript Number.prototype.toFixed(prec) but with trailing zeros removed
|
* @param prec Precision (1-15), similar to ECMAScript `Number.prototype.toFixed(prec)` but with trailing zeros removed
|
||||||
* @return true on success, false if handle is not a floating-point number or prec is out of range
|
* @return true on success, false if handle is not a floating-point number or prec is out of range
|
||||||
* @note Only works on floating-point numbers (not integers)
|
* @note Only works on floating-point numbers (not integers)
|
||||||
* @note This will produce shorter output but may lose some precision
|
* @note This will produce shorter output but may lose some precision
|
||||||
|
* @note This affects how the number is serialized in all write operations
|
||||||
*/
|
*/
|
||||||
virtual bool SetFpToFixed(JsonValue* handle, int prec) = 0;
|
virtual bool SetFpToFixed(JsonValue* handle, int prec) = 0;
|
||||||
|
|
||||||
@ -1794,4 +1877,4 @@ public:
|
|||||||
char* error = nullptr, size_t error_size = 0) = 0;
|
char* error = nullptr, size_t error_size = 0) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _INCLUDE_SM_JSON_IJSONMANAGER_H_
|
#endif // _INCLUDE_IJSONMANAGER_H_
|
||||||
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
#ifndef _INCLUDE_SM_JSON_JSONMANAGER_H_
|
#ifndef _INCLUDE_JSONMANAGER_H_
|
||||||
#define _INCLUDE_SM_JSON_JSONMANAGER_H_
|
#define _INCLUDE_JSONMANAGER_H_
|
||||||
|
|
||||||
#include <IJsonManager.h>
|
#include <IJsonManager.h>
|
||||||
#include <yyjson.h>
|
#include <yyjson.h>
|
||||||
@ -7,6 +7,172 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <charconv>
|
#include <charconv>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Base class for intrusive reference counting
|
||||||
|
*
|
||||||
|
* Objects inheriting from this class can be managed by RefPtr.
|
||||||
|
* Reference count starts at 0 and is incremented when RefPtr takes ownership.
|
||||||
|
*/
|
||||||
|
class RefCounted {
|
||||||
|
private:
|
||||||
|
mutable size_t ref_count_ = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual ~RefCounted() = default;
|
||||||
|
RefCounted() = default;
|
||||||
|
|
||||||
|
RefCounted(const RefCounted &) = delete;
|
||||||
|
RefCounted &operator=(const RefCounted &) = delete;
|
||||||
|
|
||||||
|
RefCounted(RefCounted &&) noexcept : ref_count_(0) {}
|
||||||
|
RefCounted &operator=(RefCounted &&) noexcept { return *this; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
void add_ref() const noexcept { ++ref_count_; }
|
||||||
|
|
||||||
|
void release() const noexcept {
|
||||||
|
assert(ref_count_ > 0 && "Reference count underflow");
|
||||||
|
if (--ref_count_ == 0) {
|
||||||
|
delete this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t use_count() const noexcept { return ref_count_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Smart pointer for intrusive reference counting
|
||||||
|
*
|
||||||
|
* Similar to std::shared_ptr but uses intrusive reference counting.
|
||||||
|
* Automatically manages object lifetime through add_ref() and release().
|
||||||
|
* @warning This implementation is not thread-safe. It must only be used
|
||||||
|
* in single-threaded contexts or with external synchronization.
|
||||||
|
*/
|
||||||
|
template <typename T> class RefPtr {
|
||||||
|
private:
|
||||||
|
T *ptr_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
RefPtr() noexcept : ptr_(nullptr) {}
|
||||||
|
|
||||||
|
explicit RefPtr(T *p) noexcept : ptr_(p) {
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr(const RefPtr &other) noexcept : ptr_(other.ptr_) {
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->add_ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr(RefPtr &&other) noexcept : ptr_(other.ptr_) { other.ptr_ = nullptr; }
|
||||||
|
|
||||||
|
~RefPtr() {
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->release();
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr &operator=(const RefPtr &other) noexcept {
|
||||||
|
if (ptr_ != other.ptr_) {
|
||||||
|
if (other.ptr_)
|
||||||
|
other.ptr_->add_ref();
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->release();
|
||||||
|
ptr_ = other.ptr_;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr &operator=(RefPtr &&other) noexcept {
|
||||||
|
if (this != &other) {
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->release();
|
||||||
|
ptr_ = other.ptr_;
|
||||||
|
other.ptr_ = nullptr;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RefPtr &operator=(T *p) noexcept {
|
||||||
|
reset(p);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
T *operator->() const noexcept { return ptr_; }
|
||||||
|
T &operator*() const noexcept { return *ptr_; }
|
||||||
|
T *get() const noexcept { return ptr_; }
|
||||||
|
|
||||||
|
explicit operator bool() const noexcept { return ptr_ != nullptr; }
|
||||||
|
|
||||||
|
size_t use_count() const noexcept { return ptr_ ? ptr_->use_count() : 0; }
|
||||||
|
|
||||||
|
void reset(T *p = nullptr) noexcept {
|
||||||
|
if (ptr_ != p) {
|
||||||
|
if (p)
|
||||||
|
p->add_ref();
|
||||||
|
if (ptr_)
|
||||||
|
ptr_->release();
|
||||||
|
ptr_ = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const RefPtr &other) const noexcept { return ptr_ == other.ptr_; }
|
||||||
|
bool operator!=(const RefPtr &other) const noexcept { return ptr_ != other.ptr_; }
|
||||||
|
bool operator==(std::nullptr_t) const noexcept { return ptr_ == nullptr; }
|
||||||
|
bool operator!=(std::nullptr_t) const noexcept { return ptr_ != nullptr; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Factory function to create RefPtr from new object
|
||||||
|
*/
|
||||||
|
template <typename T, typename... Args> RefPtr<T> make_ref(Args &&...args) {
|
||||||
|
return RefPtr<T>(new T(std::forward<Args>(args)...));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper for yyjson_mut_doc with intrusive reference counting
|
||||||
|
*/
|
||||||
|
class RefCountedMutDoc : public RefCounted {
|
||||||
|
private:
|
||||||
|
yyjson_mut_doc *doc_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RefCountedMutDoc(yyjson_mut_doc *doc) noexcept : doc_(doc) {}
|
||||||
|
|
||||||
|
RefCountedMutDoc(const RefCountedMutDoc &) = delete;
|
||||||
|
RefCountedMutDoc &operator=(const RefCountedMutDoc &) = delete;
|
||||||
|
|
||||||
|
~RefCountedMutDoc() noexcept override {
|
||||||
|
if (doc_) {
|
||||||
|
yyjson_mut_doc_free(doc_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yyjson_mut_doc *get() const noexcept { return doc_; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wrapper for yyjson_doc with intrusive reference counting
|
||||||
|
*/
|
||||||
|
class RefCountedImmutableDoc : public RefCounted {
|
||||||
|
private:
|
||||||
|
yyjson_doc *doc_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RefCountedImmutableDoc(yyjson_doc *doc) noexcept : doc_(doc) {}
|
||||||
|
|
||||||
|
RefCountedImmutableDoc(const RefCountedImmutableDoc &) = delete;
|
||||||
|
RefCountedImmutableDoc &operator=(const RefCountedImmutableDoc &) = delete;
|
||||||
|
|
||||||
|
~RefCountedImmutableDoc() noexcept override {
|
||||||
|
if (doc_) {
|
||||||
|
yyjson_doc_free(doc_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yyjson_doc *get() const noexcept { return doc_; }
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief JSON value wrapper
|
* @brief JSON value wrapper
|
||||||
*
|
*
|
||||||
@ -16,14 +182,7 @@
|
|||||||
class JsonValue {
|
class JsonValue {
|
||||||
public:
|
public:
|
||||||
JsonValue() = default;
|
JsonValue() = default;
|
||||||
~JsonValue() {
|
~JsonValue() = default;
|
||||||
if (m_pDocument_mut.use_count() == 1) {
|
|
||||||
yyjson_mut_doc_free(m_pDocument_mut.get());
|
|
||||||
}
|
|
||||||
if (m_pDocument.use_count() == 1) {
|
|
||||||
yyjson_doc_free(m_pDocument.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonValue(const JsonValue&) = delete;
|
JsonValue(const JsonValue&) = delete;
|
||||||
JsonValue& operator=(const JsonValue&) = delete;
|
JsonValue& operator=(const JsonValue&) = delete;
|
||||||
@ -45,12 +204,21 @@ public:
|
|||||||
return m_pDocument != nullptr;
|
return m_pDocument != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t GetDocumentRefCount() const {
|
||||||
|
if (m_pDocument_mut) {
|
||||||
|
return m_pDocument_mut.use_count();
|
||||||
|
} else if (m_pDocument) {
|
||||||
|
return m_pDocument.use_count();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Mutable document
|
// Mutable document
|
||||||
std::shared_ptr<yyjson_mut_doc> m_pDocument_mut;
|
RefPtr<RefCountedMutDoc> m_pDocument_mut;
|
||||||
yyjson_mut_val* m_pVal_mut{ nullptr };
|
yyjson_mut_val* m_pVal_mut{ nullptr };
|
||||||
|
|
||||||
// Immutable document
|
// Immutable document
|
||||||
std::shared_ptr<yyjson_doc> m_pDocument;
|
RefPtr<RefCountedImmutableDoc> m_pDocument;
|
||||||
yyjson_val* m_pVal{ nullptr };
|
yyjson_val* m_pVal{ nullptr };
|
||||||
|
|
||||||
// Mutable document iterators
|
// Mutable document iterators
|
||||||
@ -84,12 +252,13 @@ public:
|
|||||||
return m_isMutable;
|
return m_isMutable;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<yyjson_mut_doc> m_pDocument_mut;
|
RefPtr<RefCountedMutDoc> m_pDocument_mut;
|
||||||
std::shared_ptr<yyjson_doc> m_pDocument;
|
RefPtr<RefCountedImmutableDoc> m_pDocument;
|
||||||
|
|
||||||
yyjson_mut_arr_iter m_iterMut;
|
yyjson_mut_arr_iter m_iterMut;
|
||||||
|
|
||||||
yyjson_arr_iter m_iterImm;
|
yyjson_arr_iter m_iterImm;
|
||||||
|
yyjson_mut_val* m_rootMut{ nullptr };
|
||||||
|
yyjson_val* m_rootImm{ nullptr };
|
||||||
|
|
||||||
Handle_t m_handle{ BAD_HANDLE };
|
Handle_t m_handle{ BAD_HANDLE };
|
||||||
bool m_isMutable{ false };
|
bool m_isMutable{ false };
|
||||||
@ -113,12 +282,13 @@ public:
|
|||||||
return m_isMutable;
|
return m_isMutable;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<yyjson_mut_doc> m_pDocument_mut;
|
RefPtr<RefCountedMutDoc> m_pDocument_mut;
|
||||||
std::shared_ptr<yyjson_doc> m_pDocument;
|
RefPtr<RefCountedImmutableDoc> m_pDocument;
|
||||||
|
|
||||||
yyjson_mut_obj_iter m_iterMut;
|
yyjson_mut_obj_iter m_iterMut;
|
||||||
|
|
||||||
yyjson_obj_iter m_iterImm;
|
yyjson_obj_iter m_iterImm;
|
||||||
|
yyjson_mut_val* m_rootMut{ nullptr };
|
||||||
|
yyjson_val* m_rootImm{ nullptr };
|
||||||
|
|
||||||
void* m_currentKey{ nullptr };
|
void* m_currentKey{ nullptr };
|
||||||
|
|
||||||
@ -139,6 +309,15 @@ public:
|
|||||||
yyjson_read_flag read_flg, char* error, size_t error_size) override;
|
yyjson_read_flag read_flg, char* error, size_t error_size) override;
|
||||||
virtual bool WriteToString(JsonValue* handle, char* buffer, size_t buffer_size,
|
virtual bool WriteToString(JsonValue* handle, char* buffer, size_t buffer_size,
|
||||||
yyjson_write_flag write_flg, size_t* out_size) override;
|
yyjson_write_flag write_flg, size_t* out_size) override;
|
||||||
|
virtual char* WriteToStringPtr(JsonValue* handle, yyjson_write_flag write_flg, size_t* out_size) override;
|
||||||
|
virtual JsonValue* ApplyJsonPatch(JsonValue* target, JsonValue* patch, bool result_mutable,
|
||||||
|
char* error, size_t error_size) override;
|
||||||
|
virtual bool JsonPatchInPlace(JsonValue* target, JsonValue* patch,
|
||||||
|
char* error, size_t error_size) override;
|
||||||
|
virtual JsonValue* ApplyMergePatch(JsonValue* target, JsonValue* patch, bool result_mutable,
|
||||||
|
char* error, size_t error_size) override;
|
||||||
|
virtual bool MergePatchInPlace(JsonValue* target, JsonValue* patch,
|
||||||
|
char* error, size_t error_size) override;
|
||||||
virtual bool WriteToFile(JsonValue* handle, const char* path, yyjson_write_flag write_flg,
|
virtual bool WriteToFile(JsonValue* handle, const char* path, yyjson_write_flag write_flg,
|
||||||
char* error, size_t error_size) override;
|
char* error, size_t error_size) override;
|
||||||
virtual bool Equals(JsonValue* handle1, JsonValue* handle2) override;
|
virtual bool Equals(JsonValue* handle1, JsonValue* handle2) override;
|
||||||
@ -166,6 +345,7 @@ public:
|
|||||||
virtual bool IsMutable(JsonValue* handle) override;
|
virtual bool IsMutable(JsonValue* handle) override;
|
||||||
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;
|
||||||
|
|
||||||
// ========== Object Operations ==========
|
// ========== Object Operations ==========
|
||||||
virtual JsonValue* ObjectInit() override;
|
virtual JsonValue* ObjectInit() override;
|
||||||
@ -250,13 +430,12 @@ public:
|
|||||||
virtual bool ArrayRemove(JsonValue* handle, size_t index) override;
|
virtual bool ArrayRemove(JsonValue* handle, size_t index) override;
|
||||||
virtual bool ArrayRemoveFirst(JsonValue* handle) override;
|
virtual bool ArrayRemoveFirst(JsonValue* handle) override;
|
||||||
virtual bool ArrayRemoveLast(JsonValue* handle) override;
|
virtual bool ArrayRemoveLast(JsonValue* handle) override;
|
||||||
virtual bool ArrayRemoveRange(JsonValue* handle, size_t start_index, size_t end_index) override;
|
virtual bool ArrayRemoveRange(JsonValue* handle, size_t start_index, size_t count) override;
|
||||||
virtual bool ArrayClear(JsonValue* handle) override;
|
virtual bool ArrayClear(JsonValue* handle) override;
|
||||||
virtual int ArrayIndexOfBool(JsonValue* handle, bool search_value) override;
|
virtual int ArrayIndexOfBool(JsonValue* handle, bool search_value) override;
|
||||||
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, int64_t search_value) override;
|
virtual int ArrayIndexOfInt64(JsonValue* handle, std::variant<int64_t, uint64_t> search_value) override;
|
||||||
virtual int ArrayIndexOfUint64(JsonValue* handle, uint64_t search_value) override;
|
|
||||||
virtual int ArrayIndexOfFloat(JsonValue* handle, double search_value) override;
|
virtual int ArrayIndexOfFloat(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;
|
||||||
|
|
||||||
@ -317,6 +496,7 @@ public:
|
|||||||
// ========== Array Iterator Operations ==========
|
// ========== Array Iterator Operations ==========
|
||||||
virtual JsonArrIter* ArrIterInit(JsonValue* handle) override;
|
virtual JsonArrIter* ArrIterInit(JsonValue* handle) override;
|
||||||
virtual JsonArrIter* ArrIterWith(JsonValue* handle) override;
|
virtual JsonArrIter* ArrIterWith(JsonValue* handle) override;
|
||||||
|
virtual bool ArrIterReset(JsonArrIter* iter) override;
|
||||||
virtual JsonValue* ArrIterNext(JsonArrIter* iter) override;
|
virtual JsonValue* ArrIterNext(JsonArrIter* iter) override;
|
||||||
virtual bool ArrIterHasNext(JsonArrIter* iter) override;
|
virtual bool ArrIterHasNext(JsonArrIter* iter) override;
|
||||||
virtual size_t ArrIterGetIndex(JsonArrIter* iter) override;
|
virtual size_t ArrIterGetIndex(JsonArrIter* iter) override;
|
||||||
@ -325,6 +505,7 @@ public:
|
|||||||
// ========== Object Iterator Operations ==========
|
// ========== Object Iterator Operations ==========
|
||||||
virtual JsonObjIter* ObjIterInit(JsonValue* handle) override;
|
virtual JsonObjIter* ObjIterInit(JsonValue* handle) override;
|
||||||
virtual JsonObjIter* ObjIterWith(JsonValue* handle) override;
|
virtual JsonObjIter* ObjIterWith(JsonValue* handle) override;
|
||||||
|
virtual bool ObjIterReset(JsonObjIter* iter) override;
|
||||||
virtual void* ObjIterNext(JsonObjIter* iter) override;
|
virtual void* ObjIterNext(JsonObjIter* iter) override;
|
||||||
virtual bool ObjIterHasNext(JsonObjIter* iter) override;
|
virtual bool ObjIterHasNext(JsonObjIter* iter) override;
|
||||||
virtual JsonValue* ObjIterGetVal(JsonObjIter* iter, void* key) override;
|
virtual JsonValue* ObjIterGetVal(JsonObjIter* iter, void* key) override;
|
||||||
@ -378,10 +559,11 @@ private:
|
|||||||
|
|
||||||
// Helper methods
|
// Helper methods
|
||||||
static std::unique_ptr<JsonValue> CreateWrapper();
|
static std::unique_ptr<JsonValue> CreateWrapper();
|
||||||
static std::shared_ptr<yyjson_mut_doc> WrapDocument(yyjson_mut_doc* doc);
|
static RefPtr<RefCountedMutDoc> WrapDocument(yyjson_mut_doc* doc);
|
||||||
static std::shared_ptr<yyjson_mut_doc> CopyDocument(yyjson_doc* doc);
|
static RefPtr<RefCountedMutDoc> CopyDocument(yyjson_doc* doc);
|
||||||
static std::shared_ptr<yyjson_mut_doc> CreateDocument();
|
static RefPtr<RefCountedMutDoc> CreateDocument();
|
||||||
static std::shared_ptr<yyjson_doc> WrapImmutableDocument(yyjson_doc* doc);
|
static RefPtr<RefCountedImmutableDoc> WrapImmutableDocument(yyjson_doc* doc);
|
||||||
|
static RefPtr<RefCountedMutDoc> CloneValueToMutable(JsonValue* value);
|
||||||
|
|
||||||
// Pack helper methods
|
// Pack helper methods
|
||||||
static const char* SkipSeparators(const char* ptr);
|
static const char* SkipSeparators(const char* ptr);
|
||||||
@ -398,4 +580,4 @@ private:
|
|||||||
static PtrGetValueResult PtrGetValueInternal(JsonValue* handle, const char* path);
|
static PtrGetValueResult PtrGetValueInternal(JsonValue* handle, const char* path);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _INCLUDE_SM_JSON_JSONMANAGER_H_
|
#endif // _INCLUDE_JSONMANAGER_H_
|
||||||
@ -147,7 +147,14 @@ static cell_t CreateAndReturnObjIterHandle(IPluginContext* pContext, JsonObjIter
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell_t json_pack(IPluginContext* pContext, const cell_t* params) {
|
static cell_t json_pack(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
// SourcePawn has a limit of 32 parameters (defined SP_MAX_EXEC_PARAMS)
|
||||||
|
// including the format string, so we need to check if the number of parameters is less than the limit
|
||||||
|
if (params[0] > SP_MAX_EXEC_PARAMS - 1) {
|
||||||
|
return pContext->ThrowNativeError("Too many parameters (max %d)", SP_MAX_EXEC_PARAMS - 1);
|
||||||
|
}
|
||||||
|
|
||||||
char* fmt;
|
char* fmt;
|
||||||
pContext->LocalToString(params[1], &fmt);
|
pContext->LocalToString(params[1], &fmt);
|
||||||
|
|
||||||
@ -170,7 +177,7 @@ static cell_t json_doc_parse(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
bool is_file = params[2];
|
bool is_file = params[2];
|
||||||
bool is_mutable_doc = params[3];
|
bool is_mutable_doc = params[3];
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[4]);
|
uint32_t read_flg = static_cast<uint32_t>(params[4]);
|
||||||
|
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ParseJSON(str, is_file, is_mutable_doc, read_flg, error, sizeof(error));
|
JsonValue* pJSONValue = g_pJsonManager->ParseJSON(str, is_file, is_mutable_doc, read_flg, error, sizeof(error));
|
||||||
@ -224,7 +231,7 @@ static cell_t json_obj_parse_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
{
|
{
|
||||||
char* str;
|
char* str;
|
||||||
pContext->LocalToString(params[1], &str);
|
pContext->LocalToString(params[1], &str);
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[2]);
|
uint32_t read_flg = static_cast<uint32_t>(params[2]);
|
||||||
|
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ObjectParseString(str, read_flg, error, sizeof(error));
|
JsonValue* pJSONValue = g_pJsonManager->ObjectParseString(str, read_flg, error, sizeof(error));
|
||||||
@ -240,7 +247,7 @@ static cell_t json_obj_parse_file(IPluginContext* pContext, const cell_t* params
|
|||||||
{
|
{
|
||||||
char* path;
|
char* path;
|
||||||
pContext->LocalToString(params[1], &path);
|
pContext->LocalToString(params[1], &path);
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[2]);
|
uint32_t read_flg = static_cast<uint32_t>(params[2]);
|
||||||
|
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ObjectParseFile(path, read_flg, error, sizeof(error));
|
JsonValue* pJSONValue = g_pJsonManager->ObjectParseFile(path, read_flg, error, sizeof(error));
|
||||||
@ -256,7 +263,7 @@ static cell_t json_arr_parse_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
{
|
{
|
||||||
char* str;
|
char* str;
|
||||||
pContext->LocalToString(params[1], &str);
|
pContext->LocalToString(params[1], &str);
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[2]);
|
uint32_t read_flg = static_cast<uint32_t>(params[2]);
|
||||||
|
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ArrayParseString(str, read_flg, error, sizeof(error));
|
JsonValue* pJSONValue = g_pJsonManager->ArrayParseString(str, read_flg, error, sizeof(error));
|
||||||
@ -272,7 +279,7 @@ static cell_t json_arr_parse_file(IPluginContext* pContext, const cell_t* params
|
|||||||
{
|
{
|
||||||
char* path;
|
char* path;
|
||||||
pContext->LocalToString(params[1], &path);
|
pContext->LocalToString(params[1], &path);
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[2]);
|
uint32_t read_flg = static_cast<uint32_t>(params[2]);
|
||||||
|
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ArrayParseFile(path, read_flg, error, sizeof(error));
|
JsonValue* pJSONValue = g_pJsonManager->ArrayParseFile(path, read_flg, error, sizeof(error));
|
||||||
@ -325,35 +332,14 @@ static cell_t json_arr_index_of_integer64(IPluginContext* pContext, const cell_t
|
|||||||
char* searchStr;
|
char* searchStr;
|
||||||
pContext->LocalToString(params[2], &searchStr);
|
pContext->LocalToString(params[2], &searchStr);
|
||||||
|
|
||||||
char* endptr;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
errno = 0;
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
long long searchValue = strtoll(searchStr, &endptr, 10);
|
|
||||||
|
|
||||||
if (errno == ERANGE || *endptr != '\0') {
|
if (!g_pJsonManager->ParseInt64Variant(searchStr, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("Invalid integer64 value: %s", searchStr);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return g_pJsonManager->ArrayIndexOfInt64(handle, searchValue);
|
return g_pJsonManager->ArrayIndexOfInt64(handle, variant_value);
|
||||||
}
|
|
||||||
|
|
||||||
static cell_t json_arr_index_of_uint64(IPluginContext* pContext, const cell_t* params)
|
|
||||||
{
|
|
||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
|
||||||
|
|
||||||
if (!handle) return 0;
|
|
||||||
|
|
||||||
char* searchStr;
|
|
||||||
pContext->LocalToString(params[2], &searchStr);
|
|
||||||
|
|
||||||
char* endptr;
|
|
||||||
errno = 0;
|
|
||||||
unsigned long long searchValue = strtoull(searchStr, &endptr, 10);
|
|
||||||
|
|
||||||
if (errno == ERANGE || *endptr != '\0') {
|
|
||||||
return pContext->ThrowNativeError("Invalid unsigned integer64 value: %s", searchStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return g_pJsonManager->ArrayIndexOfUint64(handle, searchValue);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell_t json_arr_index_of_float(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_arr_index_of_float(IPluginContext* pContext, const cell_t* params)
|
||||||
@ -362,7 +348,7 @@ static cell_t json_arr_index_of_float(IPluginContext* pContext, const cell_t* pa
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
double searchValue = static_cast<double>(sp_ctof(params[2]));
|
float searchValue = sp_ctof(params[2]);
|
||||||
return g_pJsonManager->ArrayIndexOfFloat(handle, searchValue);
|
return g_pJsonManager->ArrayIndexOfFloat(handle, searchValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -597,6 +583,7 @@ static cell_t json_create_integer64(IPluginContext* pContext, const cell_t* para
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -694,8 +681,8 @@ static cell_t json_get_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
const char* str = nullptr;
|
const char* str;
|
||||||
size_t len = 0;
|
size_t len;
|
||||||
|
|
||||||
if (!g_pJsonManager->GetString(handle, &str, &len)) {
|
if (!g_pJsonManager->GetString(handle, &str, &len)) {
|
||||||
return pContext->ThrowNativeError("Type mismatch: expected string value");
|
return pContext->ThrowNativeError("Type mismatch: expected string value");
|
||||||
@ -729,7 +716,7 @@ static cell_t json_get_serialized_size(IPluginContext* pContext, const cell_t* p
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
yyjson_write_flag write_flg = static_cast<yyjson_write_flag>(params[2]);
|
uint32_t write_flg = static_cast<uint32_t>(params[2]);
|
||||||
size_t size = g_pJsonManager->GetSerializedSize(handle, write_flg);
|
size_t size = g_pJsonManager->GetSerializedSize(handle, write_flg);
|
||||||
|
|
||||||
return static_cast<cell_t>(size);
|
return static_cast<cell_t>(size);
|
||||||
@ -747,6 +734,15 @@ static cell_t json_get_read_size(IPluginContext* pContext, const cell_t* params)
|
|||||||
return static_cast<cell_t>(size);
|
return static_cast<cell_t>(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t json_get_ref_count(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
|
|
||||||
|
if (!handle) return 0;
|
||||||
|
|
||||||
|
return g_pJsonManager->GetRefCount(handle);
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t json_create_null(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_create_null(IPluginContext* pContext, const cell_t* params)
|
||||||
{
|
{
|
||||||
JsonValue* pJSONValue = g_pJsonManager->CreateNull();
|
JsonValue* pJSONValue = g_pJsonManager->CreateNull();
|
||||||
@ -890,7 +886,11 @@ static cell_t json_arr_get_val(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ArrayGet(handle, index);
|
JsonValue* pJSONValue = g_pJsonManager->ArrayGet(handle, index);
|
||||||
|
|
||||||
@ -937,7 +937,11 @@ static cell_t json_arr_get_bool(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
bool value;
|
bool value;
|
||||||
if (!g_pJsonManager->ArrayGetBool(handle, index, &value)) {
|
if (!g_pJsonManager->ArrayGetBool(handle, index, &value)) {
|
||||||
@ -953,7 +957,11 @@ static cell_t json_arr_get_float(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
double value;
|
double value;
|
||||||
if (!g_pJsonManager->ArrayGetFloat(handle, index, &value)) {
|
if (!g_pJsonManager->ArrayGetFloat(handle, index, &value)) {
|
||||||
@ -969,7 +977,11 @@ static cell_t json_arr_get_integer(IPluginContext* pContext, const cell_t* param
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
int value;
|
int value;
|
||||||
if (!g_pJsonManager->ArrayGetInt(handle, index, &value)) {
|
if (!g_pJsonManager->ArrayGetInt(handle, index, &value)) {
|
||||||
@ -985,9 +997,13 @@ static cell_t json_arr_get_integer64(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
std::variant<int64_t, uint64_t> value;
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
std::variant<int64_t, uint64_t> value;
|
||||||
if (!g_pJsonManager->ArrayGetInt64(handle, index, &value)) {
|
if (!g_pJsonManager->ArrayGetInt64(handle, index, &value)) {
|
||||||
return pContext->ThrowNativeError("Failed to get integer64 at index %d", index);
|
return pContext->ThrowNativeError("Failed to get integer64 at index %d", index);
|
||||||
}
|
}
|
||||||
@ -1009,10 +1025,14 @@ static cell_t json_arr_get_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
const char* str = nullptr;
|
if (index_param < 0) {
|
||||||
size_t len = 0;
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
const char* str;
|
||||||
|
size_t len;
|
||||||
if (!g_pJsonManager->ArrayGetString(handle, index, &str, &len)) {
|
if (!g_pJsonManager->ArrayGetString(handle, index, &str, &len)) {
|
||||||
return pContext->ThrowNativeError("Failed to get string at index %d", index);
|
return pContext->ThrowNativeError("Failed to get string at index %d", index);
|
||||||
}
|
}
|
||||||
@ -1033,7 +1053,11 @@ static cell_t json_arr_is_null(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayIsNull(handle, index);
|
return g_pJsonManager->ArrayIsNull(handle, index);
|
||||||
}
|
}
|
||||||
@ -1049,7 +1073,12 @@ static cell_t json_arr_replace_val(IPluginContext* pContext, const cell_t* param
|
|||||||
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplace(handle1, index, handle2);
|
return g_pJsonManager->ArrayReplace(handle1, index, handle2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1063,7 +1092,12 @@ static cell_t json_arr_replace_bool(IPluginContext* pContext, const cell_t* para
|
|||||||
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceBool(handle, index, params[3]);
|
return g_pJsonManager->ArrayReplaceBool(handle, index, params[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1077,7 +1111,12 @@ static cell_t json_arr_replace_float(IPluginContext* pContext, const cell_t* par
|
|||||||
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceFloat(handle, index, sp_ctof(params[3]));
|
return g_pJsonManager->ArrayReplaceFloat(handle, index, sp_ctof(params[3]));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1091,7 +1130,12 @@ static cell_t json_arr_replace_integer(IPluginContext* pContext, const cell_t* p
|
|||||||
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceInt(handle, index, params[3]);
|
return g_pJsonManager->ArrayReplaceInt(handle, index, params[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1110,11 +1154,17 @@ static cell_t json_arr_replace_integer64(IPluginContext* pContext, const cell_t*
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceInt64(handle, index, variant_value);
|
return g_pJsonManager->ArrayReplaceInt64(handle, index, variant_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1128,7 +1178,12 @@ static cell_t json_arr_replace_null(IPluginContext* pContext, const cell_t* para
|
|||||||
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot replace value in an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceNull(handle, index);
|
return g_pJsonManager->ArrayReplaceNull(handle, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1145,7 +1200,12 @@ static cell_t json_arr_replace_str(IPluginContext* pContext, const cell_t* param
|
|||||||
char* val;
|
char* val;
|
||||||
pContext->LocalToString(params[3], &val);
|
pContext->LocalToString(params[3], &val);
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayReplaceString(handle, index, val);
|
return g_pJsonManager->ArrayReplaceString(handle, index, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1217,6 +1277,7 @@ static cell_t json_arr_append_integer64(IPluginContext* pContext, const cell_t*
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -1262,7 +1323,17 @@ static cell_t json_arr_insert(IPluginContext* pContext, const cell_t* params)
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
JsonValue* value = g_pJsonManager->GetFromHandle(pContext, params[3]);
|
JsonValue* value = g_pJsonManager->GetFromHandle(pContext, params[3]);
|
||||||
if (!value) return 0;
|
if (!value) return 0;
|
||||||
|
|
||||||
@ -1278,7 +1349,17 @@ static cell_t json_arr_insert_bool(IPluginContext* pContext, const cell_t* param
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
bool value = params[3] != 0;
|
bool value = params[3] != 0;
|
||||||
|
|
||||||
return g_pJsonManager->ArrayInsertBool(handle, index, value);
|
return g_pJsonManager->ArrayInsertBool(handle, index, value);
|
||||||
@ -1293,7 +1374,17 @@ static cell_t json_arr_insert_int(IPluginContext* pContext, const cell_t* params
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
int value = params[3];
|
int value = params[3];
|
||||||
|
|
||||||
return g_pJsonManager->ArrayInsertInt(handle, index, value);
|
return g_pJsonManager->ArrayInsertInt(handle, index, value);
|
||||||
@ -1308,12 +1399,23 @@ static cell_t json_arr_insert_int64(IPluginContext* pContext, const cell_t* para
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
char* value;
|
char* value;
|
||||||
pContext->LocalToString(params[3], &value);
|
pContext->LocalToString(params[3], &value);
|
||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -1330,8 +1432,18 @@ static cell_t json_arr_insert_float(IPluginContext* pContext, const cell_t* para
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
double value = sp_ctof(params[3]);
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
float value = sp_ctof(params[3]);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayInsertFloat(handle, index, value);
|
return g_pJsonManager->ArrayInsertFloat(handle, index, value);
|
||||||
}
|
}
|
||||||
@ -1345,7 +1457,17 @@ static cell_t json_arr_insert_str(IPluginContext* pContext, const cell_t* params
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
char* str;
|
char* str;
|
||||||
pContext->LocalToString(params[3], &str);
|
pContext->LocalToString(params[3], &str);
|
||||||
|
|
||||||
@ -1361,7 +1483,17 @@ static cell_t json_arr_insert_null(IPluginContext* pContext, const cell_t* param
|
|||||||
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot insert value into an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = params[2];
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
|
size_t arr_size = g_pJsonManager->ArrayGetSize(handle);
|
||||||
|
if (index > arr_size) {
|
||||||
|
return pContext->ThrowNativeError("Index is out of bounds (got %d, max %zu)", index, arr_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return g_pJsonManager->ArrayInsertNull(handle, index);
|
return g_pJsonManager->ArrayInsertNull(handle, index);
|
||||||
}
|
}
|
||||||
@ -1423,6 +1555,7 @@ static cell_t json_arr_prepend_int64(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -1439,7 +1572,7 @@ static cell_t json_arr_prepend_float(IPluginContext* pContext, const cell_t* par
|
|||||||
return pContext->ThrowNativeError("Cannot prepend value to an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot prepend value to an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
double value = sp_ctof(params[2]);
|
float value = sp_ctof(params[2]);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayPrependFloat(handle, value);
|
return g_pJsonManager->ArrayPrependFloat(handle, value);
|
||||||
}
|
}
|
||||||
@ -1481,7 +1614,12 @@ static cell_t json_arr_remove(IPluginContext* pContext, const cell_t* params)
|
|||||||
return pContext->ThrowNativeError("Cannot remove value from an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot remove value from an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
return g_pJsonManager->ArrayRemove(handle, index);
|
return g_pJsonManager->ArrayRemove(handle, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1521,10 +1659,18 @@ static cell_t json_arr_remove_range(IPluginContext* pContext, const cell_t* para
|
|||||||
return pContext->ThrowNativeError("Cannot remove value from an immutable JSON array");
|
return pContext->ThrowNativeError("Cannot remove value from an immutable JSON array");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t start_index = static_cast<size_t>(params[2]);
|
cell_t start_index_param = params[2];
|
||||||
size_t end_index = static_cast<size_t>(params[3]);
|
cell_t count_param = params[3];
|
||||||
|
if (start_index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Start index must be >= 0 (got %d)", start_index_param);
|
||||||
|
}
|
||||||
|
if (count_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Count must be >= 0 (got %d)", count_param);
|
||||||
|
}
|
||||||
|
|
||||||
return g_pJsonManager->ArrayRemoveRange(handle, start_index, end_index);
|
size_t start_index = static_cast<size_t>(start_index_param);
|
||||||
|
size_t count = static_cast<size_t>(count_param);
|
||||||
|
return g_pJsonManager->ArrayRemoveRange(handle, start_index, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell_t json_arr_clear(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_arr_clear(IPluginContext* pContext, const cell_t* params)
|
||||||
@ -1547,22 +1693,24 @@ static cell_t json_doc_write_to_str(IPluginContext* pContext, const cell_t* para
|
|||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t buffer_size = static_cast<size_t>(params[3]);
|
size_t buffer_size = static_cast<size_t>(params[3]);
|
||||||
yyjson_write_flag write_flg = static_cast<yyjson_write_flag>(params[4]);
|
uint32_t write_flg = static_cast<uint32_t>(params[4]);
|
||||||
|
|
||||||
char* temp_buffer = (char*)malloc(buffer_size);
|
size_t json_size;
|
||||||
if (!temp_buffer) {
|
char* json_str = g_pJsonManager->WriteToStringPtr(handle, write_flg, &json_size);
|
||||||
return pContext->ThrowNativeError("Failed to allocate buffer");
|
|
||||||
|
if (!json_str) {
|
||||||
|
return pContext->ThrowNativeError("Failed to serialize JSON");
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t output_len = 0;
|
if (json_size > buffer_size) {
|
||||||
if (!g_pJsonManager->WriteToString(handle, temp_buffer, buffer_size, write_flg, &output_len)) {
|
free(json_str);
|
||||||
free(temp_buffer);
|
return pContext->ThrowNativeError("Buffer too small (need %d, have %d)", json_size, buffer_size);
|
||||||
return pContext->ThrowNativeError("Buffer too small or write failed");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pContext->StringToLocalUTF8(params[2], buffer_size, temp_buffer, nullptr);
|
pContext->StringToLocalUTF8(params[2], buffer_size, json_str, nullptr);
|
||||||
free(temp_buffer);
|
free(json_str);
|
||||||
return static_cast<cell_t>(output_len);
|
|
||||||
|
return static_cast<cell_t>(json_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static cell_t json_doc_write_to_file(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_doc_write_to_file(IPluginContext* pContext, const cell_t* params)
|
||||||
@ -1573,7 +1721,7 @@ static cell_t json_doc_write_to_file(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
char* path;
|
char* path;
|
||||||
pContext->LocalToString(params[2], &path);
|
pContext->LocalToString(params[2], &path);
|
||||||
yyjson_write_flag write_flg = static_cast<yyjson_write_flag>(params[3]);
|
uint32_t write_flg = static_cast<uint32_t>(params[3]);
|
||||||
|
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
if (!g_pJsonManager->WriteToFile(handle, path, write_flg, error, sizeof(error))) {
|
if (!g_pJsonManager->WriteToFile(handle, path, write_flg, error, sizeof(error))) {
|
||||||
@ -1599,8 +1747,12 @@ static cell_t json_obj_get_key(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
const char* key = nullptr;
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
const char* key;
|
||||||
|
|
||||||
if (!g_pJsonManager->ObjectGetKey(handle, index, &key)) {
|
if (!g_pJsonManager->ObjectGetKey(handle, index, &key)) {
|
||||||
return pContext->ThrowNativeError("Index %d is out of bounds", index);
|
return pContext->ThrowNativeError("Index %d is out of bounds", index);
|
||||||
@ -1616,7 +1768,11 @@ static cell_t json_obj_get_val_at(IPluginContext* pContext, const cell_t* params
|
|||||||
|
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(params[2]);
|
cell_t index_param = params[2];
|
||||||
|
if (index_param < 0) {
|
||||||
|
return pContext->ThrowNativeError("Index must be >= 0 (got %d)", index_param);
|
||||||
|
}
|
||||||
|
size_t index = static_cast<size_t>(index_param);
|
||||||
|
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ObjectGetValueAt(handle, index);
|
JsonValue* pJSONValue = g_pJsonManager->ObjectGetValueAt(handle, index);
|
||||||
|
|
||||||
@ -1730,8 +1886,8 @@ static cell_t json_obj_get_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
char* key;
|
char* key;
|
||||||
pContext->LocalToString(params[2], &key);
|
pContext->LocalToString(params[2], &key);
|
||||||
|
|
||||||
const char* str = nullptr;
|
const char* str;
|
||||||
size_t len = 0;
|
size_t len;
|
||||||
if (!g_pJsonManager->ObjectGetString(handle, key, &str, &len)) {
|
if (!g_pJsonManager->ObjectGetString(handle, key, &str, &len)) {
|
||||||
return pContext->ThrowNativeError("Failed to get string for key '%s'", key);
|
return pContext->ThrowNativeError("Failed to get string for key '%s'", key);
|
||||||
}
|
}
|
||||||
@ -1768,7 +1924,7 @@ static cell_t json_obj_is_null(IPluginContext* pContext, const cell_t* params)
|
|||||||
char* key;
|
char* key;
|
||||||
pContext->LocalToString(params[2], &key);
|
pContext->LocalToString(params[2], &key);
|
||||||
|
|
||||||
bool is_null = false;
|
bool is_null;
|
||||||
if (!g_pJsonManager->ObjectIsNull(handle, key, &is_null)) {
|
if (!g_pJsonManager->ObjectIsNull(handle, key, &is_null)) {
|
||||||
return pContext->ThrowNativeError("Key not found: %s", key);
|
return pContext->ThrowNativeError("Key not found: %s", key);
|
||||||
}
|
}
|
||||||
@ -1896,6 +2052,7 @@ static cell_t json_obj_set_integer64(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -2060,8 +2217,8 @@ static cell_t json_ptr_get_str(IPluginContext* pContext, const cell_t* params)
|
|||||||
char* path;
|
char* path;
|
||||||
pContext->LocalToString(params[2], &path);
|
pContext->LocalToString(params[2], &path);
|
||||||
|
|
||||||
const char* str = nullptr;
|
const char* str;
|
||||||
size_t len = 0;
|
size_t len;
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
if (!g_pJsonManager->PtrGetString(handle, path, &str, &len, error, sizeof(error))) {
|
if (!g_pJsonManager->PtrGetString(handle, path, &str, &len, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
@ -2214,6 +2371,7 @@ static cell_t json_ptr_set_integer64(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -2369,6 +2527,7 @@ static cell_t json_ptr_add_integer64(IPluginContext* pContext, const cell_t* par
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_PACK_ERROR_SIZE];
|
char error[JSON_PACK_ERROR_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(value, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -2554,8 +2713,8 @@ static cell_t json_ptr_try_get_str(IPluginContext* pContext, const cell_t* param
|
|||||||
char* path;
|
char* path;
|
||||||
pContext->LocalToString(params[2], &path);
|
pContext->LocalToString(params[2], &path);
|
||||||
|
|
||||||
const char* str = nullptr;
|
const char* str;
|
||||||
size_t len = 0;
|
size_t len;
|
||||||
|
|
||||||
if (!g_pJsonManager->PtrTryGetString(handle, path, &str, &len)) {
|
if (!g_pJsonManager->PtrTryGetString(handle, path, &str, &len)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -2576,8 +2735,8 @@ static cell_t json_obj_foreach(IPluginContext* pContext, const cell_t* params)
|
|||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
const char* key = nullptr;
|
const char* key;
|
||||||
JsonValue* pJSONValue = nullptr;
|
JsonValue* pJSONValue;
|
||||||
|
|
||||||
if (!g_pJsonManager->ObjectForeachNext(handle, &key, nullptr, &pJSONValue)) {
|
if (!g_pJsonManager->ObjectForeachNext(handle, &key, nullptr, &pJSONValue)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2593,8 +2752,8 @@ static cell_t json_arr_foreach(IPluginContext* pContext, const cell_t* params)
|
|||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index;
|
||||||
JsonValue* pJSONValue = nullptr;
|
JsonValue* pJSONValue;
|
||||||
|
|
||||||
if (!g_pJsonManager->ArrayForeachNext(handle, &index, &pJSONValue)) {
|
if (!g_pJsonManager->ArrayForeachNext(handle, &index, &pJSONValue)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2612,7 +2771,7 @@ static cell_t json_obj_foreach_key(IPluginContext* pContext, const cell_t* param
|
|||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
const char* key = nullptr;
|
const char* key;
|
||||||
|
|
||||||
if (!g_pJsonManager->ObjectForeachKeyNext(handle, &key, nullptr)) {
|
if (!g_pJsonManager->ObjectForeachKeyNext(handle, &key, nullptr)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2628,7 +2787,7 @@ static cell_t json_arr_foreach_index(IPluginContext* pContext, const cell_t* par
|
|||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t index = 0;
|
size_t index;
|
||||||
|
|
||||||
if (!g_pJsonManager->ArrayForeachIndexNext(handle, &index)) {
|
if (!g_pJsonManager->ArrayForeachIndexNext(handle, &index)) {
|
||||||
return false;
|
return false;
|
||||||
@ -2715,6 +2874,84 @@ static cell_t json_doc_to_immutable(IPluginContext* pContext, const cell_t* para
|
|||||||
return CreateAndReturnHandle(pContext, pJSONValue, "immutable JSON document");
|
return CreateAndReturnHandle(pContext, pJSONValue, "immutable JSON document");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t json_apply_json_patch(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonValue* target = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
|
JsonValue* patch = g_pJsonManager->GetFromHandle(pContext, params[2]);
|
||||||
|
|
||||||
|
if (!target || !patch) return 0;
|
||||||
|
|
||||||
|
bool resultMutable = params[3] != 0;
|
||||||
|
char error[JSON_ERROR_BUFFER_SIZE] = {0};
|
||||||
|
|
||||||
|
JsonValue* result = g_pJsonManager->ApplyJsonPatch(target, patch, resultMutable, error, sizeof(error));
|
||||||
|
if (!result) {
|
||||||
|
if (error[0] != '\0') {
|
||||||
|
return pContext->ThrowNativeError("%s", error);
|
||||||
|
}
|
||||||
|
return pContext->ThrowNativeError("Failed to apply JSON Patch");
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateAndReturnHandle(pContext, result, "JSON patch result");
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t json_json_patch_in_place(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonValue* target = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
|
JsonValue* patch = g_pJsonManager->GetFromHandle(pContext, params[2]);
|
||||||
|
|
||||||
|
if (!target || !patch) return 0;
|
||||||
|
|
||||||
|
char error[JSON_ERROR_BUFFER_SIZE] = {0};
|
||||||
|
if (!g_pJsonManager->JsonPatchInPlace(target, patch, error, sizeof(error))) {
|
||||||
|
if (error[0] != '\0') {
|
||||||
|
return pContext->ThrowNativeError("%s", error);
|
||||||
|
}
|
||||||
|
return pContext->ThrowNativeError("Failed to apply JSON Patch in place");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t json_apply_merge_patch(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonValue* target = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
|
JsonValue* patch = g_pJsonManager->GetFromHandle(pContext, params[2]);
|
||||||
|
|
||||||
|
if (!target || !patch) return 0;
|
||||||
|
|
||||||
|
bool resultMutable = params[3] != 0;
|
||||||
|
char error[JSON_ERROR_BUFFER_SIZE] = {0};
|
||||||
|
|
||||||
|
JsonValue* result = g_pJsonManager->ApplyMergePatch(target, patch, resultMutable, error, sizeof(error));
|
||||||
|
if (!result) {
|
||||||
|
if (error[0] != '\0') {
|
||||||
|
return pContext->ThrowNativeError("%s", error);
|
||||||
|
}
|
||||||
|
return pContext->ThrowNativeError("Failed to apply JSON Merge Patch");
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateAndReturnHandle(pContext, result, "JSON merge patch result");
|
||||||
|
}
|
||||||
|
|
||||||
|
static cell_t json_merge_patch_in_place(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonValue* target = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
|
JsonValue* patch = g_pJsonManager->GetFromHandle(pContext, params[2]);
|
||||||
|
|
||||||
|
if (!target || !patch) return 0;
|
||||||
|
|
||||||
|
char error[JSON_ERROR_BUFFER_SIZE] = {0};
|
||||||
|
if (!g_pJsonManager->MergePatchInPlace(target, patch, error, sizeof(error))) {
|
||||||
|
if (error[0] != '\0') {
|
||||||
|
return pContext->ThrowNativeError("%s", error);
|
||||||
|
}
|
||||||
|
return pContext->ThrowNativeError("Failed to apply JSON Merge Patch in place");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t json_arr_iter_init(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_arr_iter_init(IPluginContext* pContext, const cell_t* params)
|
||||||
{
|
{
|
||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
@ -2769,6 +3006,14 @@ static cell_t json_arr_iter_remove(IPluginContext* pContext, const cell_t* param
|
|||||||
return removed != nullptr;
|
return removed != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t json_arr_iter_reset(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonArrIter* iter = g_pJsonManager->GetArrIterFromHandle(pContext, params[1]);
|
||||||
|
if (!iter) return 0;
|
||||||
|
|
||||||
|
return g_pJsonManager->ArrIterReset(iter);
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t json_obj_iter_init(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_obj_iter_init(IPluginContext* pContext, const cell_t* params)
|
||||||
{
|
{
|
||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
@ -2787,12 +3032,8 @@ static cell_t json_obj_iter_next(IPluginContext* pContext, const cell_t* params)
|
|||||||
if (!key) return 0;
|
if (!key) return 0;
|
||||||
|
|
||||||
const char* key_str;
|
const char* key_str;
|
||||||
if (iter->IsMutable()) {
|
size_t key_len;
|
||||||
key_str = yyjson_mut_get_str(reinterpret_cast<yyjson_mut_val*>(key));
|
g_pJsonManager->GetString(reinterpret_cast<JsonValue*>(key), &key_str, &key_len);
|
||||||
} else {
|
|
||||||
key_str = yyjson_get_str(reinterpret_cast<yyjson_val*>(key));
|
|
||||||
}
|
|
||||||
|
|
||||||
pContext->StringToLocalUTF8(params[2], params[3], key_str, nullptr);
|
pContext->StringToLocalUTF8(params[2], params[3], key_str, nullptr);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -2810,13 +3051,7 @@ static cell_t json_obj_iter_get_val(IPluginContext* pContext, const cell_t* para
|
|||||||
JsonObjIter* iter = g_pJsonManager->GetObjIterFromHandle(pContext, params[1]);
|
JsonObjIter* iter = g_pJsonManager->GetObjIterFromHandle(pContext, params[1]);
|
||||||
if (!iter) return 0;
|
if (!iter) return 0;
|
||||||
|
|
||||||
void* key = nullptr;
|
void* key = iter->m_currentKey;
|
||||||
if (iter->IsMutable()) {
|
|
||||||
key = iter->m_currentKey;
|
|
||||||
} else {
|
|
||||||
key = iter->m_currentKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!key) {
|
if (!key) {
|
||||||
return pContext->ThrowNativeError("Iterator not positioned at a valid key (call Next() first)");
|
return pContext->ThrowNativeError("Iterator not positioned at a valid key (call Next() first)");
|
||||||
}
|
}
|
||||||
@ -2871,14 +3106,22 @@ static cell_t json_obj_iter_remove(IPluginContext* pContext, const cell_t* param
|
|||||||
return removed != nullptr;
|
return removed != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cell_t json_obj_iter_reset(IPluginContext* pContext, const cell_t* params)
|
||||||
|
{
|
||||||
|
JsonObjIter* iter = g_pJsonManager->GetObjIterFromHandle(pContext, params[1]);
|
||||||
|
if (!iter) return 0;
|
||||||
|
|
||||||
|
return g_pJsonManager->ObjIterReset(iter);
|
||||||
|
}
|
||||||
|
|
||||||
static cell_t json_read_number(IPluginContext* pContext, const cell_t* params)
|
static cell_t json_read_number(IPluginContext* pContext, const cell_t* params)
|
||||||
{
|
{
|
||||||
char* dat;
|
char* dat;
|
||||||
pContext->LocalToString(params[1], &dat);
|
pContext->LocalToString(params[1], &dat);
|
||||||
yyjson_read_flag read_flg = static_cast<yyjson_read_flag>(params[2]);
|
uint32_t read_flg = static_cast<uint32_t>(params[2]);
|
||||||
|
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
size_t consumed = 0;
|
size_t consumed;
|
||||||
JsonValue* pJSONValue = g_pJsonManager->ReadNumber(dat, read_flg, error, sizeof(error), &consumed);
|
JsonValue* pJSONValue = g_pJsonManager->ReadNumber(dat, read_flg, error, sizeof(error), &consumed);
|
||||||
|
|
||||||
if (!pJSONValue) {
|
if (!pJSONValue) {
|
||||||
@ -2901,7 +3144,12 @@ static cell_t json_write_number(IPluginContext* pContext, const cell_t* params)
|
|||||||
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
JsonValue* handle = g_pJsonManager->GetFromHandle(pContext, params[1]);
|
||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
size_t buffer_size = static_cast<size_t>(params[3]);
|
cell_t buffer_size_param = params[3];
|
||||||
|
if (buffer_size_param <= 0) {
|
||||||
|
return pContext->ThrowNativeError("Buffer size must be > 0 (got %d)", buffer_size_param);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t buffer_size = static_cast<size_t>(buffer_size_param);
|
||||||
char* temp_buffer = (char*)malloc(buffer_size);
|
char* temp_buffer = (char*)malloc(buffer_size);
|
||||||
if (!temp_buffer) {
|
if (!temp_buffer) {
|
||||||
return pContext->ThrowNativeError("Failed to allocate buffer");
|
return pContext->ThrowNativeError("Failed to allocate buffer");
|
||||||
@ -2946,8 +3194,12 @@ static cell_t json_set_fp_to_fixed(IPluginContext* pContext, const cell_t* param
|
|||||||
if (!handle) return 0;
|
if (!handle) return 0;
|
||||||
|
|
||||||
int prec = params[2];
|
int prec = params[2];
|
||||||
|
if (prec < 1 || prec > 7) {
|
||||||
|
return pContext->ThrowNativeError("Precision out of range (1-7)");
|
||||||
|
}
|
||||||
|
|
||||||
if (!g_pJsonManager->SetFpToFixed(handle, prec)) {
|
if (!g_pJsonManager->SetFpToFixed(handle, prec)) {
|
||||||
return pContext->ThrowNativeError("Failed to set floating-point format to fixed (value is not a floating-point number or precision out of range 1-15)");
|
return pContext->ThrowNativeError("Failed to set floating-point format to fixed (value is not a floating-point number or precision out of range 1-7)");
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -2989,6 +3241,7 @@ static cell_t json_set_int64(IPluginContext* pContext, const cell_t* params)
|
|||||||
|
|
||||||
std::variant<int64_t, uint64_t> variant_value;
|
std::variant<int64_t, uint64_t> variant_value;
|
||||||
char error[JSON_ERROR_BUFFER_SIZE];
|
char error[JSON_ERROR_BUFFER_SIZE];
|
||||||
|
|
||||||
if (!g_pJsonManager->ParseInt64Variant(str, &variant_value, error, sizeof(error))) {
|
if (!g_pJsonManager->ParseInt64Variant(str, &variant_value, error, sizeof(error))) {
|
||||||
return pContext->ThrowNativeError("%s", error);
|
return pContext->ThrowNativeError("%s", error);
|
||||||
}
|
}
|
||||||
@ -3126,7 +3379,6 @@ const sp_nativeinfo_t g_JsonNatives[] =
|
|||||||
{"JSONArray.IndexOfString", json_arr_index_of_str},
|
{"JSONArray.IndexOfString", json_arr_index_of_str},
|
||||||
{"JSONArray.IndexOfInt", json_arr_index_of_int},
|
{"JSONArray.IndexOfInt", json_arr_index_of_int},
|
||||||
{"JSONArray.IndexOfInt64", json_arr_index_of_integer64},
|
{"JSONArray.IndexOfInt64", json_arr_index_of_integer64},
|
||||||
{"JSONArray.IndexOfUint64", json_arr_index_of_uint64},
|
|
||||||
{"JSONArray.IndexOfFloat", json_arr_index_of_float},
|
{"JSONArray.IndexOfFloat", json_arr_index_of_float},
|
||||||
{"JSONArray.Sort", json_arr_sort},
|
{"JSONArray.Sort", json_arr_sort},
|
||||||
|
|
||||||
@ -3140,6 +3392,7 @@ const sp_nativeinfo_t g_JsonNatives[] =
|
|||||||
{"JSON.GetTypeDesc", json_get_type_desc},
|
{"JSON.GetTypeDesc", json_get_type_desc},
|
||||||
{"JSON.GetSerializedSize", json_get_serialized_size},
|
{"JSON.GetSerializedSize", json_get_serialized_size},
|
||||||
{"JSON.ReadSize.get", json_get_read_size},
|
{"JSON.ReadSize.get", json_get_read_size},
|
||||||
|
{"JSON.RefCount.get", json_get_ref_count},
|
||||||
{"JSON.Type.get", json_get_type},
|
{"JSON.Type.get", json_get_type},
|
||||||
{"JSON.SubType.get", json_get_subtype},
|
{"JSON.SubType.get", json_get_subtype},
|
||||||
{"JSON.IsArray.get", json_is_array},
|
{"JSON.IsArray.get", json_is_array},
|
||||||
@ -3163,6 +3416,10 @@ const sp_nativeinfo_t g_JsonNatives[] =
|
|||||||
{"JSON.ForeachIndex", json_arr_foreach_index},
|
{"JSON.ForeachIndex", json_arr_foreach_index},
|
||||||
{"JSON.ToMutable", json_doc_to_mutable},
|
{"JSON.ToMutable", json_doc_to_mutable},
|
||||||
{"JSON.ToImmutable", json_doc_to_immutable},
|
{"JSON.ToImmutable", json_doc_to_immutable},
|
||||||
|
{"JSON.ApplyJsonPatch", json_apply_json_patch},
|
||||||
|
{"JSON.JsonPatchInPlace", json_json_patch_in_place},
|
||||||
|
{"JSON.ApplyMergePatch", json_apply_merge_patch},
|
||||||
|
{"JSON.MergePatchInPlace", json_merge_patch_in_place},
|
||||||
{"JSON.ReadNumber", json_read_number},
|
{"JSON.ReadNumber", json_read_number},
|
||||||
{"JSON.WriteNumber", json_write_number},
|
{"JSON.WriteNumber", json_write_number},
|
||||||
{"JSON.SetFpToFloat", json_set_fp_to_float},
|
{"JSON.SetFpToFloat", json_set_fp_to_float},
|
||||||
@ -3225,6 +3482,7 @@ const sp_nativeinfo_t g_JsonNatives[] =
|
|||||||
{"JSONArrIter.HasNext.get", json_arr_iter_has_next},
|
{"JSONArrIter.HasNext.get", json_arr_iter_has_next},
|
||||||
{"JSONArrIter.Index.get", json_arr_iter_get_index},
|
{"JSONArrIter.Index.get", json_arr_iter_get_index},
|
||||||
{"JSONArrIter.Remove", json_arr_iter_remove},
|
{"JSONArrIter.Remove", json_arr_iter_remove},
|
||||||
|
{"JSONArrIter.Reset", json_arr_iter_reset},
|
||||||
|
|
||||||
// JSONObjIter
|
// JSONObjIter
|
||||||
{"JSONObjIter.JSONObjIter", json_obj_iter_init},
|
{"JSONObjIter.JSONObjIter", json_obj_iter_init},
|
||||||
@ -3234,6 +3492,7 @@ const sp_nativeinfo_t g_JsonNatives[] =
|
|||||||
{"JSONObjIter.Get", json_obj_iter_get},
|
{"JSONObjIter.Get", json_obj_iter_get},
|
||||||
{"JSONObjIter.Index.get", json_obj_iter_get_index},
|
{"JSONObjIter.Index.get", json_obj_iter_get_index},
|
||||||
{"JSONObjIter.Remove", json_obj_iter_remove},
|
{"JSONObjIter.Remove", json_obj_iter_remove},
|
||||||
|
{"JSONObjIter.Reset", json_obj_iter_reset},
|
||||||
|
|
||||||
{nullptr, nullptr}
|
{nullptr, nullptr}
|
||||||
};
|
};
|
||||||
@ -42,7 +42,6 @@ bool JsonExtension::SDK_OnLoad(char* error, size_t maxlen, bool late)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the existing instance if it exists
|
|
||||||
if (g_pJsonManager) {
|
if (g_pJsonManager) {
|
||||||
delete g_pJsonManager;
|
delete g_pJsonManager;
|
||||||
g_pJsonManager = nullptr;
|
g_pJsonManager = nullptr;
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define SMEXT_CONF_NAME "SourceMod JSON Extension"
|
#define SMEXT_CONF_NAME "SourceMod JSON Extension"
|
||||||
#define SMEXT_CONF_DESCRIPTION "Provide JSON Native"
|
#define SMEXT_CONF_DESCRIPTION "Provide JSON Native"
|
||||||
#define SMEXT_CONF_VERSION "1.1.5b"
|
#define SMEXT_CONF_VERSION "1.1.5e"
|
||||||
#define SMEXT_CONF_AUTHOR "ProjectSky"
|
#define SMEXT_CONF_AUTHOR "ProjectSky"
|
||||||
#define SMEXT_CONF_URL "https://github.com/ProjectSky/sm-ext-yyjson"
|
#define SMEXT_CONF_URL "https://github.com/ProjectSky/sm-ext-yyjson"
|
||||||
#define SMEXT_CONF_LOGTAG "json"
|
#define SMEXT_CONF_LOGTAG "json"
|
||||||
|
|||||||
@ -71,12 +71,17 @@ enum JSON_WRITE_FLAG
|
|||||||
JSON_WRITE_FP_TO_FLOAT = 1 << 27 // Write floating-point numbers using single-precision (float)
|
JSON_WRITE_FP_TO_FLOAT = 1 << 27 // Write floating-point numbers using single-precision (float)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Write floating-point number using fixed-point notation
|
/**
|
||||||
- This is similar to ECMAScript Number.prototype.toFixed(prec) but with trailing zeros removed. The prec ranges from 1 to 15
|
* Write floating-point number using fixed-point notation
|
||||||
- This will produce shorter output but may lose some precision
|
* This is similar to ECMAScript Number.prototype.toFixed(prec) but with trailing zeros removed
|
||||||
*/
|
*
|
||||||
|
* @param n Precision digits (1-7)
|
||||||
|
* @return JSON write flag with precision setting
|
||||||
|
* @note This will produce shorter output but may lose some precision
|
||||||
|
*/
|
||||||
stock JSON_WRITE_FLAG JSON_WRITE_FP_TO_FIXED(int n)
|
stock JSON_WRITE_FLAG JSON_WRITE_FP_TO_FIXED(int n)
|
||||||
{
|
{
|
||||||
|
n = (n < 1) ? 1 : (n > 7 ? 7 : n);
|
||||||
return view_as<JSON_WRITE_FLAG>(n << 28);
|
return view_as<JSON_WRITE_FLAG>(n << 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +108,10 @@ methodmap JSON < Handle
|
|||||||
* - [: start array
|
* - [: start array
|
||||||
* - ]: end array
|
* - ]: end array
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
* @note There is a limit of 32 parameters (defined in SourcePawn)
|
||||||
|
* including the format string, so the number of arguments must be less than or equal to 31
|
||||||
|
*
|
||||||
* @param format Format string
|
* @param format Format string
|
||||||
* @param ... Arguments based on format string
|
* @param ... Arguments based on format string
|
||||||
*
|
*
|
||||||
@ -178,6 +187,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Converts an immutable JSON document to a mutable one
|
* Converts an immutable JSON document to a mutable one
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @return Handle to the new mutable JSON document, INVALID_HANDLE on failure
|
* @return Handle to the new mutable JSON document, INVALID_HANDLE on failure
|
||||||
* @error If the document is already mutable
|
* @error If the document is already mutable
|
||||||
*/
|
*/
|
||||||
@ -186,11 +197,59 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Converts a mutable JSON document to an immutable one
|
* Converts a mutable JSON document to an immutable one
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @return Handle to the new immutable JSON document, INVALID_HANDLE on failure
|
* @return Handle to the new immutable JSON document, INVALID_HANDLE on failure
|
||||||
* @error If the document is already immutable
|
* @error If the document is already immutable
|
||||||
*/
|
*/
|
||||||
public native any ToImmutable();
|
public native any ToImmutable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a JSON Patch (RFC 6902) to this value and return a new JSON handle
|
||||||
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
|
* @param patch JSON Patch document
|
||||||
|
* @param resultMutable True to return a mutable result, false for immutable
|
||||||
|
*
|
||||||
|
* @return New JSON handle on success
|
||||||
|
* @error Throws if the patch cannot be applied
|
||||||
|
*/
|
||||||
|
public native any ApplyJsonPatch(const JSON patch, bool resultMutable = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a JSON Patch (RFC 6902) to this value in place
|
||||||
|
*
|
||||||
|
* @param patch JSON Patch document
|
||||||
|
*
|
||||||
|
* @return True on success, false otherwise
|
||||||
|
* @error Throws if this value is immutable or patch failed
|
||||||
|
*/
|
||||||
|
public native bool JsonPatchInPlace(const JSON patch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a JSON Merge Patch (RFC 7396) to this value and return a new JSON handle
|
||||||
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
|
* @param patch JSON Merge Patch document
|
||||||
|
* @param resultMutable True to return a mutable result, false for immutable
|
||||||
|
*
|
||||||
|
* @return New JSON handle on success
|
||||||
|
* @error Throws if the merge patch cannot be applied
|
||||||
|
*/
|
||||||
|
public native any ApplyMergePatch(const JSON patch, bool resultMutable = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply a JSON Merge Patch (RFC 7396) to this value in place
|
||||||
|
*
|
||||||
|
* @param patch JSON Merge Patch document
|
||||||
|
*
|
||||||
|
* @return True on success, false otherwise
|
||||||
|
* @error Throws if this value is immutable or merge patch failed
|
||||||
|
*/
|
||||||
|
public native bool MergePatchInPlace(const JSON patch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write a document to JSON file with options
|
* Write a document to JSON file with options
|
||||||
*
|
*
|
||||||
@ -233,7 +292,7 @@ methodmap JSON < Handle
|
|||||||
* Set floating-point number's output format to single-precision
|
* Set floating-point number's output format to single-precision
|
||||||
*
|
*
|
||||||
* @note Only works on floating-point numbers (not integers)
|
* @note Only works on floating-point numbers (not integers)
|
||||||
* @note This affects how the number is serialized when using ToString()
|
* @note This affects how the number is serialized in all write operations
|
||||||
*
|
*
|
||||||
* @param flt True to use single-precision (float), false to use double-precision (double)
|
* @param flt True to use single-precision (float), false to use double-precision (double)
|
||||||
*
|
*
|
||||||
@ -248,12 +307,12 @@ methodmap JSON < Handle
|
|||||||
* @note Only works on floating-point numbers (not integers)
|
* @note Only works on floating-point numbers (not integers)
|
||||||
* @note This is similar to ECMAScript Number.prototype.toFixed(prec) but with trailing zeros removed
|
* @note This is similar to ECMAScript Number.prototype.toFixed(prec) but with trailing zeros removed
|
||||||
* @note This will produce shorter output but may lose some precision
|
* @note This will produce shorter output but may lose some precision
|
||||||
* @note This affects how the number is serialized when using ToString()
|
* @note This affects how the number is serialized in all write operations
|
||||||
*
|
*
|
||||||
* @param prec Precision (1-15)
|
* @param prec Precision (1-7)
|
||||||
*
|
*
|
||||||
* @return True on success, false if handle is not a floating-point number or prec is out of range
|
* @return True on success, false if handle is not a floating-point number or prec is out of range
|
||||||
* @error Invalid handle, handle is not a floating-point number, or precision out of range (1-15)
|
* @error Invalid handle, handle is not a floating-point number, or precision out of range (1-7)
|
||||||
*/
|
*/
|
||||||
public native bool SetFpToFixed(int prec);
|
public native bool SetFpToFixed(int prec);
|
||||||
|
|
||||||
@ -381,14 +440,13 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Returns the JSON value's type description
|
* Returns the JSON value's type description
|
||||||
*
|
*
|
||||||
* @param value JSON handle
|
|
||||||
* @param buffer String buffer to write to
|
* @param buffer String buffer to write to
|
||||||
* @param maxlength Maximum length of the string buffer
|
* @param maxlength Maximum length of the string buffer
|
||||||
*
|
*
|
||||||
* @return The return value should be one of these strings: "raw", "null", "string",
|
* @return The return value should be one of these strings: "raw", "null", "string",
|
||||||
* "array", "object", "true", "false", "uint", "sint", "real", "unknown"
|
* "array", "object", "true", "false", "uint", "sint", "real", "unknown"
|
||||||
*/
|
*/
|
||||||
public static native void GetTypeDesc(const JSON value, char[] buffer, int maxlength);
|
public native void GetTypeDesc(char[] buffer, int maxlength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether two JSON values are equal (deep compare)
|
* Returns whether two JSON values are equal (deep compare)
|
||||||
@ -396,8 +454,8 @@ methodmap JSON < Handle
|
|||||||
* @note This function is recursive and may cause a stack overflow if the object level is too deep
|
* @note This function is recursive and may cause a stack overflow if the object level is too deep
|
||||||
* @note the result may be inaccurate if object has duplicate keys
|
* @note the result may be inaccurate if object has duplicate keys
|
||||||
*
|
*
|
||||||
* @param value1 JSON handle
|
* @param value1 First JSON value to compare
|
||||||
* @param value2 JSON handle
|
* @param value2 Second JSON value to compare
|
||||||
*
|
*
|
||||||
* @return True if they are the same, false otherwise
|
* @return True if they are the same, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -537,6 +595,7 @@ methodmap JSON < Handle
|
|||||||
* Get value by a JSON Pointer
|
* Get value by a JSON Pointer
|
||||||
*
|
*
|
||||||
* @note Needs to be freed using delete or CloseHandle()
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
*
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
@ -547,6 +606,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Get boolean value by a JSON Pointer
|
* Get boolean value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @return boolean value referenced by the JSON pointer
|
* @return boolean value referenced by the JSON pointer
|
||||||
@ -556,6 +617,8 @@ 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
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @return float value referenced by the JSON pointer
|
* @return float value referenced by the JSON pointer
|
||||||
@ -565,6 +628,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Get integer value by a JSON Pointer
|
* Get integer value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @return integer value referenced by the JSON pointer
|
* @return integer value referenced by the JSON pointer
|
||||||
@ -574,17 +639,21 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Get integer64 value by a JSON Pointer (auto-detects signed/unsigned)
|
* Get integer64 value by a JSON Pointer (auto-detects signed/unsigned)
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param buffer Buffer to copy to
|
* @param buffer Buffer to copy to
|
||||||
* @param maxlength Maximum size of the buffer
|
* @param maxlength Maximum size of the buffer
|
||||||
*
|
*
|
||||||
* @return integer64 value referenced by the JSON pointer
|
* @return True on success, false on failure
|
||||||
*/
|
*/
|
||||||
public native bool PtrGetInt64(const char[] path, char[] buffer, int maxlength);
|
public native bool PtrGetInt64(const char[] path, char[] buffer, int maxlength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get string value by a JSON Pointer
|
* Get string value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param buffer Buffer to copy to
|
* @param buffer Buffer to copy to
|
||||||
* @param maxlength Maximum size of the buffer
|
* @param maxlength Maximum size of the buffer
|
||||||
@ -596,6 +665,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Get value is null by a JSON Pointer
|
* Get value is null by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @return True if the value is null, false otherwise
|
* @return True if the value is null, false otherwise
|
||||||
@ -605,6 +676,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Get JSON content length (string length, array size, object size)
|
* Get JSON content length (string length, array size, object size)
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note For strings: returns string length including null-terminator
|
* @note For strings: returns string length including null-terminator
|
||||||
* @note For arrays/objects: returns number of elements
|
* @note For arrays/objects: returns number of elements
|
||||||
* @note Returns 0 if value is null or type is not string/array/object
|
* @note Returns 0 if value is null or type is not string/array/object
|
||||||
@ -618,6 +690,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set value by a JSON Pointer
|
* Set value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -631,6 +704,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set boolean value by a JSON Pointer
|
* Set boolean value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -644,6 +718,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set float value by a JSON Pointer
|
* Set float value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -657,6 +732,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set integer value by a JSON Pointer
|
* Set integer value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -670,6 +746,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set integer64 value by a JSON Pointer
|
* Set integer64 value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
* @note This function auto-detects whether the value is signed or unsigned
|
* @note This function auto-detects whether the value is signed or unsigned
|
||||||
@ -684,6 +761,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set string value by a JSON Pointer
|
* Set string value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -697,6 +775,7 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Set null value by a JSON Pointer
|
* Set null value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
* @note The parent nodes will be created if they do not exist.
|
* @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
|
* If the target value already exists, it will be replaced by the new value
|
||||||
*
|
*
|
||||||
@ -709,6 +788,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) value by a JSON pointer
|
* Add (insert) value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The value to be added
|
* @param value The value to be added
|
||||||
*
|
*
|
||||||
@ -719,6 +800,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) boolean value by a JSON pointer
|
* Add (insert) boolean value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The boolean value to be added
|
* @param value The boolean value to be added
|
||||||
*
|
*
|
||||||
@ -729,6 +812,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) float value by a JSON pointer
|
* Add (insert) float value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The float value to be added
|
* @param value The float value to be added
|
||||||
*
|
*
|
||||||
@ -739,6 +824,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) integer value by a JSON pointer
|
* Add (insert) integer value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The int value to be added
|
* @param value The int value to be added
|
||||||
*
|
*
|
||||||
@ -749,6 +836,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) integer64 value by a JSON pointer
|
* Add (insert) integer64 value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The integer64 value to be added
|
* @param value The integer64 value to be added
|
||||||
*
|
*
|
||||||
@ -759,6 +848,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) string value by a JSON pointer
|
* Add (insert) string value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value The str value to be added
|
* @param value The str value to be added
|
||||||
*
|
*
|
||||||
@ -769,6 +860,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Add (insert) null value by a JSON pointer
|
* Add (insert) null value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @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
|
||||||
@ -778,6 +871,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Remove value by a JSON pointer
|
* Remove value by a JSON pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
*
|
*
|
||||||
* @return true if removed value, false otherwise
|
* @return true if removed value, false otherwise
|
||||||
@ -787,6 +882,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Try to get value by a JSON Pointer
|
* Try to get value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value Handle to store value
|
* @param value Handle to store value
|
||||||
*
|
*
|
||||||
@ -797,6 +894,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Try to get boolean value by a JSON Pointer
|
* Try to get boolean value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value Store the boolean value
|
* @param value Store the boolean value
|
||||||
*
|
*
|
||||||
@ -807,6 +906,8 @@ 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
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value Store the float value
|
* @param value Store the float value
|
||||||
*
|
*
|
||||||
@ -817,6 +918,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Try to get integer value by a JSON Pointer
|
* Try to get integer value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param value Store the integer value
|
* @param value Store the integer value
|
||||||
*
|
*
|
||||||
@ -827,6 +930,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Try to get integer64 value by a JSON Pointer (automatically detects signed/unsigned)
|
* Try to get integer64 value by a JSON Pointer (automatically detects signed/unsigned)
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param buffer Buffer to store the integer64 value
|
* @param buffer Buffer to store the integer64 value
|
||||||
* @param maxlength Maximum length of the buffer
|
* @param maxlength Maximum length of the buffer
|
||||||
@ -838,6 +943,8 @@ methodmap JSON < Handle
|
|||||||
/**
|
/**
|
||||||
* Try to get string value by a JSON Pointer
|
* Try to get string value by a JSON Pointer
|
||||||
*
|
*
|
||||||
|
* @note JSON Pointer paths are always resolved from the document root, not from the current value
|
||||||
|
*
|
||||||
* @param path The JSON pointer string
|
* @param path The JSON pointer string
|
||||||
* @param buffer Buffer to store the string value
|
* @param buffer Buffer to store the string value
|
||||||
* @param maxlength Maximum length of the buffer
|
* @param maxlength Maximum length of the buffer
|
||||||
@ -978,6 +1085,17 @@ methodmap JSON < Handle
|
|||||||
property int ReadSize {
|
property int ReadSize {
|
||||||
public native get();
|
public native get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the reference count of the document (debugging purpose)
|
||||||
|
*
|
||||||
|
* @return Reference count (number of JSON objects sharing this document)
|
||||||
|
*
|
||||||
|
* @note Returns 0 if the handle is invalid
|
||||||
|
*/
|
||||||
|
property int RefCount {
|
||||||
|
public native get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
methodmap JSONObject < JSON
|
methodmap JSONObject < JSON
|
||||||
@ -995,6 +1113,8 @@ methodmap JSONObject < JSON
|
|||||||
* The array must contain an even number of strings, where even indices are keys
|
* The array must contain an even number of strings, where even indices are keys
|
||||||
* and odd indices are values. Keys cannot be empty strings
|
* and odd indices are values. Keys cannot be empty strings
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param pairs Array of strings containing alternating keys and values
|
* @param pairs Array of strings containing alternating keys and values
|
||||||
* @param size Total size of the array (must be even)
|
* @param size Total size of the array (must be even)
|
||||||
*
|
*
|
||||||
@ -1007,6 +1127,8 @@ methodmap JSONObject < JSON
|
|||||||
/**
|
/**
|
||||||
* Loads a JSON object from a file
|
* Loads a JSON object from a file
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param file File to read from
|
* @param file File to read from
|
||||||
* @param flag The JSON read options
|
* @param flag The JSON read options
|
||||||
*
|
*
|
||||||
@ -1017,6 +1139,8 @@ methodmap JSONObject < JSON
|
|||||||
/**
|
/**
|
||||||
* Loads a JSON object from a string
|
* Loads a JSON object from a string
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param buffer String buffer to load into the JSON object
|
* @param buffer String buffer to load into the JSON object
|
||||||
* @param flag The JSON read options
|
* @param flag The JSON read options
|
||||||
*
|
*
|
||||||
@ -1027,6 +1151,7 @@ methodmap JSONObject < JSON
|
|||||||
/**
|
/**
|
||||||
* Gets a value from the object
|
* Gets a value from the object
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
* @note This function takes a linear search time
|
* @note This function takes a linear search time
|
||||||
*
|
*
|
||||||
* @param key Key name
|
* @param key Key name
|
||||||
@ -1262,6 +1387,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Creates a new JSON array from an array of strings
|
* Creates a new JSON array from an array of strings
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param strings Array of strings to create array from
|
* @param strings Array of strings to create array from
|
||||||
* @param size Size of the array
|
* @param size Size of the array
|
||||||
* @return New JSON array handle, or null if creation failed
|
* @return New JSON array handle, or null if creation failed
|
||||||
@ -1271,6 +1398,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Creates a new JSON array from an array of integer values
|
* Creates a new JSON array from an array of integer values
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param values Array of int values to create array from
|
* @param values Array of int values to create array from
|
||||||
* @param size Size of the array
|
* @param size Size of the array
|
||||||
* @return New JSON array handle, or null if creation failed
|
* @return New JSON array handle, or null if creation failed
|
||||||
@ -1280,6 +1409,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Creates a new JSON array from an array of 64-bit integer strings (auto-detects signed/unsigned)
|
* Creates a new JSON array from an array of 64-bit integer strings (auto-detects signed/unsigned)
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param values Array of int64 string values (can be signed or unsigned)
|
* @param values Array of int64 string values (can be signed or unsigned)
|
||||||
* @param size Size of the array
|
* @param size Size of the array
|
||||||
* @return New JSON array handle, or null if creation failed
|
* @return New JSON array handle, or null if creation failed
|
||||||
@ -1290,6 +1421,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Creates a new JSON array from an array of boolean values
|
* Creates a new JSON array from an array of boolean values
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param values Array of bool values to create array from
|
* @param values Array of bool values to create array from
|
||||||
* @param size Size of the array
|
* @param size Size of the array
|
||||||
* @return New JSON array handle, or null if creation failed
|
* @return New JSON array handle, or null if creation failed
|
||||||
@ -1299,6 +1432,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Creates a new JSON array from an array of float values
|
* Creates a new JSON array from an array of float values
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param values Array of float values to create array from
|
* @param values Array of float values to create array from
|
||||||
* @param size Size of the array
|
* @param size Size of the array
|
||||||
* @return New JSON array handle, or null if creation failed
|
* @return New JSON array handle, or null if creation failed
|
||||||
@ -1308,6 +1443,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Loads a JSON array from a file
|
* Loads a JSON array from a file
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param file File to read from
|
* @param file File to read from
|
||||||
* @param flag Read flag
|
* @param flag Read flag
|
||||||
* @return Array handle, or null on failure
|
* @return Array handle, or null on failure
|
||||||
@ -1317,6 +1454,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Loads a JSON array from a string
|
* Loads a JSON array from a string
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @param buffer String buffer to load into the JSON array
|
* @param buffer String buffer to load into the JSON array
|
||||||
* @param flag Read flag
|
* @param flag Read flag
|
||||||
* @return Array handle, or null on failure
|
* @return Array handle, or null on failure
|
||||||
@ -1326,6 +1465,7 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Gets a value from the array
|
* Gets a value from the array
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
* @note This function takes a linear search time
|
* @note This function takes a linear search time
|
||||||
*
|
*
|
||||||
* @param index Position in the array (starting from 0)
|
* @param index Position in the array (starting from 0)
|
||||||
@ -1368,9 +1508,9 @@ methodmap JSONArray < JSON
|
|||||||
* @param buffer Buffer to copy to
|
* @param buffer Buffer to copy to
|
||||||
* @param maxlength Maximum size of the buffer
|
* @param maxlength Maximum size of the buffer
|
||||||
*
|
*
|
||||||
* @return 64-bit integer
|
* @return True on success, false on failure
|
||||||
*/
|
*/
|
||||||
public native void GetInt64(int index, char[] buffer, int maxlength);
|
public native bool GetInt64(int index, char[] buffer, int maxlength);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets string data from the array
|
* Gets string data from the array
|
||||||
@ -1470,7 +1610,7 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value JSON handle to set
|
* @param value JSON handle to set
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool Push(const JSON value);
|
public native bool Push(const JSON value);
|
||||||
|
|
||||||
@ -1479,7 +1619,7 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value Boolean value to set
|
* @param value Boolean value to set
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushBool(bool value);
|
public native bool PushBool(bool value);
|
||||||
|
|
||||||
@ -1488,7 +1628,7 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value float to set
|
* @param value float to set
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushFloat(float value);
|
public native bool PushFloat(float value);
|
||||||
|
|
||||||
@ -1497,7 +1637,7 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value integer to set
|
* @param value integer to set
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushInt(int value);
|
public native bool PushInt(int value);
|
||||||
|
|
||||||
@ -1506,7 +1646,7 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value integer64 value
|
* @param value integer64 value
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushInt64(const char[] value);
|
public native bool PushInt64(const char[] value);
|
||||||
|
|
||||||
@ -1515,20 +1655,22 @@ methodmap JSONArray < JSON
|
|||||||
*
|
*
|
||||||
* @param value String to copy
|
* @param value String to copy
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushString(const char[] value);
|
public native bool PushString(const char[] value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a null value at the end of the array
|
* Inserts a null value at the end of the array
|
||||||
*
|
*
|
||||||
* @return The value to be inserted. Returns false if it is null
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool PushNull();
|
public native bool PushNull();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inserts a JSON value at specific index
|
* Inserts a JSON value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert (0 to size, size means append)
|
* @param index Position to insert (0 to size, size means append)
|
||||||
* @param value JSON handle to insert
|
* @param value JSON handle to insert
|
||||||
*
|
*
|
||||||
@ -1539,6 +1681,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts a boolean value at specific index
|
* Inserts a boolean value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
* @param value Boolean value
|
* @param value Boolean value
|
||||||
*
|
*
|
||||||
@ -1549,6 +1693,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts an integer value at specific index
|
* Inserts an integer value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
* @param value Integer value
|
* @param value Integer value
|
||||||
*
|
*
|
||||||
@ -1559,6 +1705,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts an integer64 value at specific index
|
* Inserts an integer64 value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
* @param value Integer64 value (as string)
|
* @param value Integer64 value (as string)
|
||||||
*
|
*
|
||||||
@ -1569,6 +1717,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts a float value at specific index
|
* Inserts a float value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
* @param value Float value
|
* @param value Float value
|
||||||
*
|
*
|
||||||
@ -1579,6 +1729,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts a string value at specific index
|
* Inserts a string value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
* @param value String value
|
* @param value String value
|
||||||
*
|
*
|
||||||
@ -1589,6 +1741,8 @@ methodmap JSONArray < JSON
|
|||||||
/**
|
/**
|
||||||
* Inserts a null value at specific index
|
* Inserts a null value at specific index
|
||||||
*
|
*
|
||||||
|
* @note This function takes a linear search time
|
||||||
|
*
|
||||||
* @param index Position to insert
|
* @param index Position to insert
|
||||||
*
|
*
|
||||||
* @return True if succeed, false otherwise
|
* @return True if succeed, false otherwise
|
||||||
@ -1675,7 +1829,7 @@ methodmap JSONArray < JSON
|
|||||||
public native bool RemoveFirst();
|
public native bool RemoveFirst();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes and returns the last value in this array
|
* Removes the last value in this array
|
||||||
*
|
*
|
||||||
* @return True if succeed, false otherwise
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
@ -1687,12 +1841,11 @@ methodmap JSONArray < JSON
|
|||||||
* @note This function takes a linear search time
|
* @note This function takes a linear search time
|
||||||
*
|
*
|
||||||
* @param start_index The start index of the range (0 is the first)
|
* @param start_index The start index of the range (0 is the first)
|
||||||
* @param end_index The number of items in the range (can be 0, but do nothing)
|
* @param count Number of items to remove (can be 0, in which case nothing happens)
|
||||||
*
|
|
||||||
*
|
*
|
||||||
* @return True if succeed, false otherwise
|
* @return True if succeed, false otherwise
|
||||||
*/
|
*/
|
||||||
public native bool RemoveRange(int start_index, int end_index);
|
public native bool RemoveRange(int start_index, int count);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for a boolean value in the array and returns its index
|
* Searches for a boolean value in the array and returns its index
|
||||||
@ -1802,6 +1955,8 @@ methodmap JSONArrIter < Handle
|
|||||||
* Creates an array iterator from a JSON array value
|
* Creates an array iterator from a JSON array value
|
||||||
*
|
*
|
||||||
* @note Needs to be freed using delete or CloseHandle()
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
* @note Iterators are single-pass. Once Next returns null, call Reset() or create
|
||||||
|
* a new iterator to traverse the array again
|
||||||
*
|
*
|
||||||
* @param array JSON array value to iterate
|
* @param array JSON array value to iterate
|
||||||
*
|
*
|
||||||
@ -1810,9 +1965,21 @@ methodmap JSONArrIter < Handle
|
|||||||
*/
|
*/
|
||||||
public native JSONArrIter(JSON array);
|
public native JSONArrIter(JSON array);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the iterator to the beginning of the array
|
||||||
|
*
|
||||||
|
* @note Only resets the iterator, does not free the iterator handle
|
||||||
|
*
|
||||||
|
* @return True on success, false on failure
|
||||||
|
* @error Invalid iterator handle
|
||||||
|
*/
|
||||||
|
public native bool Reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the iterator to the next element
|
* Moves the iterator to the next element
|
||||||
*
|
*
|
||||||
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
*
|
||||||
* @return JSON value handle for the next element, or null if iteration is complete
|
* @return JSON value handle for the next element, or null if iteration is complete
|
||||||
* @error Invalid iterator handle
|
* @error Invalid iterator handle
|
||||||
*/
|
*/
|
||||||
@ -1858,6 +2025,8 @@ methodmap JSONObjIter < Handle
|
|||||||
* Creates an object iterator from a JSON object value
|
* Creates an object iterator from a JSON object value
|
||||||
*
|
*
|
||||||
* @note Needs to be freed using delete or CloseHandle()
|
* @note Needs to be freed using delete or CloseHandle()
|
||||||
|
* @note Iterators are single-pass. Once Next returns null, call Reset() or create
|
||||||
|
* a new iterator to traverse the object again
|
||||||
*
|
*
|
||||||
* @param obj JSON object value to iterate
|
* @param obj JSON object value to iterate
|
||||||
*
|
*
|
||||||
@ -1866,6 +2035,16 @@ methodmap JSONObjIter < Handle
|
|||||||
*/
|
*/
|
||||||
public native JSONObjIter(JSON obj);
|
public native JSONObjIter(JSON obj);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the iterator to the beginning of the object
|
||||||
|
*
|
||||||
|
* @note Only resets the iterator, does not free the iterator handle
|
||||||
|
*
|
||||||
|
* @return True on success, false on failure
|
||||||
|
* @error Invalid iterator handle
|
||||||
|
*/
|
||||||
|
public native bool Reset();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the iterator to the next key
|
* Moves the iterator to the next key
|
||||||
*
|
*
|
||||||
@ -2055,6 +2234,7 @@ public void __pl_json_SetNTVOptional()
|
|||||||
MarkNativeAsOptional("JSON.GetTypeDesc");
|
MarkNativeAsOptional("JSON.GetTypeDesc");
|
||||||
MarkNativeAsOptional("JSON.GetSerializedSize");
|
MarkNativeAsOptional("JSON.GetSerializedSize");
|
||||||
MarkNativeAsOptional("JSON.ReadSize.get");
|
MarkNativeAsOptional("JSON.ReadSize.get");
|
||||||
|
MarkNativeAsOptional("JSON.RefCount.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");
|
||||||
@ -2078,6 +2258,10 @@ public void __pl_json_SetNTVOptional()
|
|||||||
MarkNativeAsOptional("JSON.ForeachIndex");
|
MarkNativeAsOptional("JSON.ForeachIndex");
|
||||||
MarkNativeAsOptional("JSON.ToMutable");
|
MarkNativeAsOptional("JSON.ToMutable");
|
||||||
MarkNativeAsOptional("JSON.ToImmutable");
|
MarkNativeAsOptional("JSON.ToImmutable");
|
||||||
|
MarkNativeAsOptional("JSON.ApplyJsonPatch");
|
||||||
|
MarkNativeAsOptional("JSON.JsonPatchInPlace");
|
||||||
|
MarkNativeAsOptional("JSON.ApplyMergePatch");
|
||||||
|
MarkNativeAsOptional("JSON.MergePatchInPlace");
|
||||||
|
|
||||||
// JSON CREATE & GET
|
// JSON CREATE & GET
|
||||||
MarkNativeAsOptional("JSON.Pack");
|
MarkNativeAsOptional("JSON.Pack");
|
||||||
@ -2140,14 +2324,16 @@ public void __pl_json_SetNTVOptional()
|
|||||||
MarkNativeAsOptional("JSONArrIter.HasNext.get");
|
MarkNativeAsOptional("JSONArrIter.HasNext.get");
|
||||||
MarkNativeAsOptional("JSONArrIter.Index.get");
|
MarkNativeAsOptional("JSONArrIter.Index.get");
|
||||||
MarkNativeAsOptional("JSONArrIter.Remove");
|
MarkNativeAsOptional("JSONArrIter.Remove");
|
||||||
|
MarkNativeAsOptional("JSONArrIter.Reset");
|
||||||
|
|
||||||
// JSONObjIter
|
// JSONObjIter
|
||||||
MarkNativeAsOptional("JSONObjIter.JSONObjIter");
|
MarkNativeAsOptional("JSONObjIter.JSONObjIter");
|
||||||
MarkNativeAsOptional("JSONObjIter.Next");
|
MarkNativeAsOptional("JSONObjIter.Next");
|
||||||
MarkNativeAsOptional("JSONObjIter.HasNext");
|
MarkNativeAsOptional("JSONObjIter.HasNext.get");
|
||||||
MarkNativeAsOptional("JSONObjIter.Value.get");
|
MarkNativeAsOptional("JSONObjIter.Value.get");
|
||||||
MarkNativeAsOptional("JSONObjIter.Get");
|
MarkNativeAsOptional("JSONObjIter.Get");
|
||||||
MarkNativeAsOptional("JSONObjIter.Index.get");
|
MarkNativeAsOptional("JSONObjIter.Index.get");
|
||||||
MarkNativeAsOptional("JSONObjIter.Remove");
|
MarkNativeAsOptional("JSONObjIter.Remove");
|
||||||
|
MarkNativeAsOptional("JSONObjIter.Reset");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -405,19 +405,19 @@ void Test_BasicValues()
|
|||||||
|
|
||||||
char buffer[32];
|
char buffer[32];
|
||||||
|
|
||||||
JSON.GetTypeDesc(boolVal, buffer, sizeof(buffer));
|
boolVal.GetTypeDesc(buffer, sizeof(buffer));
|
||||||
AssertStrEq(buffer, "true");
|
AssertStrEq(buffer, "true");
|
||||||
|
|
||||||
JSON.GetTypeDesc(intVal, buffer, sizeof(buffer));
|
intVal.GetTypeDesc(buffer, sizeof(buffer));
|
||||||
AssertTrue(strcmp(buffer, "uint") == 0 || strcmp(buffer, "sint") == 0);
|
AssertTrue(strcmp(buffer, "uint") == 0 || strcmp(buffer, "sint") == 0);
|
||||||
|
|
||||||
JSON.GetTypeDesc(floatVal, buffer, sizeof(buffer));
|
floatVal.GetTypeDesc(buffer, sizeof(buffer));
|
||||||
AssertStrEq(buffer, "real");
|
AssertStrEq(buffer, "real");
|
||||||
|
|
||||||
JSON.GetTypeDesc(strVal, buffer, sizeof(buffer));
|
strVal.GetTypeDesc(buffer, sizeof(buffer));
|
||||||
AssertStrEq(buffer, "string");
|
AssertStrEq(buffer, "string");
|
||||||
|
|
||||||
JSON.GetTypeDesc(nullVal, buffer, sizeof(buffer));
|
nullVal.GetTypeDesc(buffer, sizeof(buffer));
|
||||||
AssertStrEq(buffer, "null");
|
AssertStrEq(buffer, "null");
|
||||||
|
|
||||||
delete boolVal;
|
delete boolVal;
|
||||||
@ -1547,7 +1547,7 @@ void Test_ParseAndSerialize()
|
|||||||
|
|
||||||
TestStart("Parse_MutableDocument");
|
TestStart("Parse_MutableDocument");
|
||||||
{
|
{
|
||||||
JSON json = JSON.Parse("{\"key\":\"value\"}", false, true);
|
JSON json = JSON.Parse("{\"key\":\"value\"}", .is_mutable_doc = true);
|
||||||
AssertValidHandle(json);
|
AssertValidHandle(json);
|
||||||
AssertTrue(json.IsMutable);
|
AssertTrue(json.IsMutable);
|
||||||
AssertFalse(json.IsImmutable);
|
AssertFalse(json.IsImmutable);
|
||||||
@ -1607,7 +1607,7 @@ void Test_ParseAndSerialize()
|
|||||||
// Test read flags
|
// Test read flags
|
||||||
TestStart("Parse_WithTrailingCommas");
|
TestStart("Parse_WithTrailingCommas");
|
||||||
{
|
{
|
||||||
JSON json = JSON.Parse("[1,2,3,]", false, false, JSON_READ_ALLOW_TRAILING_COMMAS);
|
JSON json = JSON.Parse("[1,2,3,]", .flag = JSON_READ_ALLOW_TRAILING_COMMAS);
|
||||||
AssertValidHandle(json);
|
AssertValidHandle(json);
|
||||||
delete json;
|
delete json;
|
||||||
}
|
}
|
||||||
@ -1615,7 +1615,7 @@ void Test_ParseAndSerialize()
|
|||||||
|
|
||||||
TestStart("Parse_WithComments");
|
TestStart("Parse_WithComments");
|
||||||
{
|
{
|
||||||
JSON json = JSON.Parse("/* comment */ {\"key\":\"value\"}", false, false, JSON_READ_ALLOW_COMMENTS);
|
JSON json = JSON.Parse("/* comment */ {\"key\":\"value\"}", .flag = JSON_READ_ALLOW_COMMENTS);
|
||||||
AssertValidHandle(json);
|
AssertValidHandle(json);
|
||||||
delete json;
|
delete json;
|
||||||
}
|
}
|
||||||
@ -1687,16 +1687,30 @@ void Test_Iterators()
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
char key[32];
|
char key[32];
|
||||||
JSON value;
|
JSONObjIter iter = new JSONObjIter(obj);
|
||||||
|
|
||||||
while (obj.ForeachObject(key, sizeof(key), value))
|
while (iter.Next(key, sizeof(key)))
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
|
JSON value = iter.Value;
|
||||||
AssertValidHandle(value);
|
AssertValidHandle(value);
|
||||||
delete value;
|
delete value;
|
||||||
}
|
}
|
||||||
|
AssertFalse(iter.HasNext);
|
||||||
AssertEq(count, 3);
|
AssertEq(count, 3);
|
||||||
|
|
||||||
|
AssertTrue(iter.Reset());
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
while (iter.Next(key, sizeof(key)))
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
JSON value = iter.Value;
|
||||||
|
AssertValidHandle(value);
|
||||||
|
delete value;
|
||||||
|
}
|
||||||
|
AssertEq(count, 3);
|
||||||
|
delete iter;
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
TestEnd();
|
TestEnd();
|
||||||
@ -1710,18 +1724,32 @@ void Test_Iterators()
|
|||||||
arr.PushInt(30);
|
arr.PushInt(30);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int index;
|
JSONArrIter iter = new JSONArrIter(arr);
|
||||||
JSON value;
|
|
||||||
|
|
||||||
while (arr.ForeachArray(index, value))
|
while (iter.HasNext)
|
||||||
{
|
{
|
||||||
AssertEq(index, count);
|
JSON value = iter.Next;
|
||||||
AssertValidHandle(value);
|
AssertValidHandle(value);
|
||||||
|
AssertEq(iter.Index, count);
|
||||||
delete value;
|
delete value;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
AssertFalse(iter.HasNext);
|
||||||
AssertEq(count, 3);
|
AssertEq(count, 3);
|
||||||
|
|
||||||
|
AssertTrue(iter.Reset());
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
while (iter.HasNext)
|
||||||
|
{
|
||||||
|
JSON value = iter.Next;
|
||||||
|
AssertValidHandle(value);
|
||||||
|
AssertEq(iter.Index, count);
|
||||||
|
delete value;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
AssertEq(count, 3);
|
||||||
|
delete iter;
|
||||||
delete arr;
|
delete arr;
|
||||||
}
|
}
|
||||||
TestEnd();
|
TestEnd();
|
||||||
@ -1736,14 +1764,26 @@ void Test_Iterators()
|
|||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
char key[32];
|
char key[32];
|
||||||
|
JSONObjIter iter = new JSONObjIter(obj);
|
||||||
|
|
||||||
while (obj.ForeachKey(key, sizeof(key)))
|
while (iter.Next(key, sizeof(key)))
|
||||||
{
|
{
|
||||||
AssertTrue(strlen(key) > 0);
|
AssertTrue(strlen(key) > 0);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
AssertFalse(iter.HasNext);
|
||||||
AssertEq(count, 3);
|
AssertEq(count, 3);
|
||||||
|
|
||||||
|
AssertTrue(iter.Reset());
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
while (iter.Next(key, sizeof(key)))
|
||||||
|
{
|
||||||
|
AssertTrue(strlen(key) > 0);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
AssertEq(count, 3);
|
||||||
|
delete iter;
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
TestEnd();
|
TestEnd();
|
||||||
@ -1757,15 +1797,30 @@ void Test_Iterators()
|
|||||||
arr.PushInt(3);
|
arr.PushInt(3);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int index;
|
JSONArrIter iter = new JSONArrIter(arr);
|
||||||
|
|
||||||
while (arr.ForeachIndex(index))
|
while (iter.HasNext)
|
||||||
{
|
{
|
||||||
AssertEq(index, count);
|
JSON value = iter.Next;
|
||||||
|
AssertEq(iter.Index, count);
|
||||||
|
delete value;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
AssertFalse(iter.HasNext);
|
||||||
AssertEq(count, 3);
|
AssertEq(count, 3);
|
||||||
|
|
||||||
|
AssertTrue(iter.Reset());
|
||||||
|
|
||||||
|
count = 0;
|
||||||
|
while (iter.HasNext)
|
||||||
|
{
|
||||||
|
JSON value = iter.Next;
|
||||||
|
AssertEq(iter.Index, count);
|
||||||
|
delete value;
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
AssertEq(count, 3);
|
||||||
|
delete iter;
|
||||||
delete arr;
|
delete arr;
|
||||||
}
|
}
|
||||||
TestEnd();
|
TestEnd();
|
||||||
@ -1774,10 +1829,12 @@ void Test_Iterators()
|
|||||||
TestStart("Iterator_EmptyObject");
|
TestStart("Iterator_EmptyObject");
|
||||||
{
|
{
|
||||||
JSONObject obj = new JSONObject();
|
JSONObject obj = new JSONObject();
|
||||||
|
|
||||||
char key[32];
|
char key[32];
|
||||||
JSON value;
|
JSONObjIter iter = new JSONObjIter(obj);
|
||||||
AssertFalse(obj.ForeachObject(key, sizeof(key), value));
|
AssertFalse(iter.Next(key, sizeof(key)));
|
||||||
|
AssertTrue(iter.Reset());
|
||||||
|
AssertFalse(iter.Next(key, sizeof(key)));
|
||||||
|
delete iter;
|
||||||
|
|
||||||
delete obj;
|
delete obj;
|
||||||
}
|
}
|
||||||
@ -1786,10 +1843,11 @@ void Test_Iterators()
|
|||||||
TestStart("Iterator_EmptyArray");
|
TestStart("Iterator_EmptyArray");
|
||||||
{
|
{
|
||||||
JSONArray arr = new JSONArray();
|
JSONArray arr = new JSONArray();
|
||||||
|
JSONArrIter iter = new JSONArrIter(arr);
|
||||||
int index;
|
AssertFalse(iter.HasNext);
|
||||||
JSON value;
|
AssertTrue(iter.Reset());
|
||||||
AssertFalse(arr.ForeachArray(index, value));
|
AssertFalse(iter.HasNext);
|
||||||
|
delete iter;
|
||||||
|
|
||||||
delete arr;
|
delete arr;
|
||||||
}
|
}
|
||||||
@ -2146,6 +2204,144 @@ void Test_AdvancedFeatures()
|
|||||||
}
|
}
|
||||||
TestEnd();
|
TestEnd();
|
||||||
|
|
||||||
|
// Test ApplyJsonPatch (new value, immutable result)
|
||||||
|
TestStart("Advanced_ApplyJsonPatch");
|
||||||
|
{
|
||||||
|
JSONObject original = new JSONObject();
|
||||||
|
original.SetInt("score", 10);
|
||||||
|
original.SetString("name", "bot");
|
||||||
|
|
||||||
|
JSON patch = JSON.Parse("[{\"op\":\"replace\",\"path\":\"/score\",\"value\":42}]");
|
||||||
|
AssertValidHandle(patch);
|
||||||
|
|
||||||
|
JSON result = original.ApplyJsonPatch(patch);
|
||||||
|
AssertValidHandle(result);
|
||||||
|
AssertTrue(result.IsImmutable);
|
||||||
|
|
||||||
|
AssertEq(result.PtrGetInt("/score"), 42);
|
||||||
|
char buffer[32];
|
||||||
|
result.PtrGetString("/name", buffer, sizeof(buffer));
|
||||||
|
AssertStrEq(buffer, "bot");
|
||||||
|
|
||||||
|
// ensure original unchanged
|
||||||
|
AssertEq(original.GetInt("score"), 10);
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
delete patch;
|
||||||
|
delete original;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
|
// Test ApplyJsonPatch resultMutable = true
|
||||||
|
TestStart("Advanced_ApplyJsonPatch_MutableResult");
|
||||||
|
{
|
||||||
|
JSONObject original = new JSONObject();
|
||||||
|
original.SetInt("count", 1);
|
||||||
|
|
||||||
|
JSON patch = JSON.Parse("[{\"op\":\"add\",\"path\":\"/newField\",\"value\":\"hello\"}]");
|
||||||
|
AssertValidHandle(patch);
|
||||||
|
|
||||||
|
JSON result = original.ApplyJsonPatch(patch, true);
|
||||||
|
AssertValidHandle(result);
|
||||||
|
AssertTrue(result.IsMutable);
|
||||||
|
|
||||||
|
char buffer[16];
|
||||||
|
result.PtrGetString("/newField", buffer, sizeof(buffer));
|
||||||
|
AssertStrEq(buffer, "hello");
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
delete patch;
|
||||||
|
delete original;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
|
// Test JsonPatchInPlace
|
||||||
|
TestStart("Advanced_JsonPatchInPlace");
|
||||||
|
{
|
||||||
|
JSONObject target = new JSONObject();
|
||||||
|
target.SetInt("score", 5);
|
||||||
|
target.SetInt("lives", 3);
|
||||||
|
|
||||||
|
JSON patch = JSON.Parse("[{\"op\":\"remove\",\"path\":\"/lives\"},{\"op\":\"replace\",\"path\":\"/score\",\"value\":9}]");
|
||||||
|
AssertValidHandle(patch);
|
||||||
|
|
||||||
|
AssertTrue(target.JsonPatchInPlace(patch));
|
||||||
|
AssertEq(target.GetInt("score"), 9);
|
||||||
|
AssertFalse(target.HasKey("lives"));
|
||||||
|
|
||||||
|
delete patch;
|
||||||
|
delete target;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
|
// Test ApplyMergePatch (immutable result)
|
||||||
|
TestStart("Advanced_ApplyMergePatch");
|
||||||
|
{
|
||||||
|
JSONObject original = new JSONObject();
|
||||||
|
original.PtrSetString("/settings/mode", "coop");
|
||||||
|
original.PtrSetInt("/settings/difficulty", 1);
|
||||||
|
|
||||||
|
JSON mergePatch = JSON.Parse("{\"settings\":{\"difficulty\":3,\"friendlyFire\":true}}");
|
||||||
|
AssertValidHandle(mergePatch);
|
||||||
|
|
||||||
|
JSON result = original.ApplyMergePatch(mergePatch);
|
||||||
|
AssertValidHandle(result);
|
||||||
|
AssertTrue(result.IsImmutable);
|
||||||
|
|
||||||
|
AssertEq(result.PtrGetInt("/settings/difficulty"), 3);
|
||||||
|
AssertTrue(result.PtrGetBool("/settings/friendlyFire"));
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
delete mergePatch;
|
||||||
|
delete original;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
|
// Test ApplyMergePatch resultMutable = true
|
||||||
|
TestStart("Advanced_ApplyMergePatch_MutableResult");
|
||||||
|
{
|
||||||
|
JSONObject original = new JSONObject();
|
||||||
|
original.PtrSetString("/profile/name", "player");
|
||||||
|
|
||||||
|
JSON mergePatch = JSON.Parse("{\"profile\":{\"rank\":10}}");
|
||||||
|
AssertValidHandle(mergePatch);
|
||||||
|
|
||||||
|
JSON result = original.ApplyMergePatch(mergePatch, true);
|
||||||
|
AssertValidHandle(result);
|
||||||
|
AssertTrue(result.IsMutable);
|
||||||
|
|
||||||
|
AssertEq(result.PtrGetInt("/profile/rank"), 10);
|
||||||
|
char buffer[16];
|
||||||
|
result.PtrGetString("/profile/name", buffer, sizeof(buffer));
|
||||||
|
AssertStrEq(buffer, "player");
|
||||||
|
|
||||||
|
delete result;
|
||||||
|
delete mergePatch;
|
||||||
|
delete original;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
|
// Test MergePatchInPlace
|
||||||
|
TestStart("Advanced_MergePatchInPlace");
|
||||||
|
{
|
||||||
|
JSONObject target = new JSONObject();
|
||||||
|
target.PtrSetString("/config/mode", "coop");
|
||||||
|
target.PtrSetInt("/config/players", 4);
|
||||||
|
|
||||||
|
JSON mergePatch = JSON.Parse("{\"config\":{\"players\":6,\"region\":\"EU\"}}");
|
||||||
|
AssertValidHandle(mergePatch);
|
||||||
|
|
||||||
|
AssertTrue(target.MergePatchInPlace(mergePatch));
|
||||||
|
AssertEq(target.PtrGetInt("/config/players"), 6);
|
||||||
|
char buffer[16];
|
||||||
|
target.PtrGetString("/config/region", buffer, sizeof(buffer));
|
||||||
|
AssertStrEq(buffer, "EU");
|
||||||
|
|
||||||
|
delete mergePatch;
|
||||||
|
delete target;
|
||||||
|
}
|
||||||
|
TestEnd();
|
||||||
|
|
||||||
// Test Pack
|
// Test Pack
|
||||||
TestStart("Advanced_Pack_SimpleObject");
|
TestStart("Advanced_Pack_SimpleObject");
|
||||||
{
|
{
|
||||||
@ -2210,7 +2406,7 @@ void Test_AdvancedFeatures()
|
|||||||
// Test mixed type array sorting
|
// Test mixed type array sorting
|
||||||
TestStart("Advanced_MixedTypeSort");
|
TestStart("Advanced_MixedTypeSort");
|
||||||
{
|
{
|
||||||
JSONArray json = JSON.Parse("[true, 42, \"hello\", 1.5, false]", false, true);
|
JSONArray json = JSON.Parse("[true, 42, \"hello\", 1.5, false]", .is_mutable_doc = true);
|
||||||
JSONArray arr = json;
|
JSONArray arr = json;
|
||||||
|
|
||||||
AssertTrue(arr.Sort(JSON_SORT_ASC));
|
AssertTrue(arr.Sort(JSON_SORT_ASC));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user