diff --git a/module/Library/IO/Buffer.cpp b/module/Library/IO/Buffer.cpp index 5a9a5444..d6acf198 100644 --- a/module/Library/IO/Buffer.cpp +++ b/module/Library/IO/Buffer.cpp @@ -351,6 +351,33 @@ Vector4 SqBuffer::ReadVector4() const return {value}; } +// ------------------------------------------------------------------------------------------------ +extern SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size); + +// ------------------------------------------------------------------------------------------------ +SQInteger SqBuffer::GetJSON(HSQUIRRELVM vm) const +{ + // Remember the current stack size + const SQInteger top = sq_gettop(vm); + // Was the JSON string size specified? + if (top < 2) + { + return sq_throwerror(vm, _SC("Please specify the size of the JSON string to parse")); + } + // Do we even point to a valid buffer? + if (!m_Buffer) + { + return sq_throwerror(vm, _SC("Invalid memory buffer reference")); + } + // Validate the buffer itself + else if (!(*m_Buffer)) + { + return sq_throwerror(vm, _SC("Invalid memory buffer")); + } + // Attempt to create the JSON object and push it on the stack + return SqFromNativeJSON(vm, &m_Buffer->Cursor< char >(), static_cast< size_t >(Var< SQInteger >{vm, 2}.value)); +} + // ------------------------------------------------------------------------------------------------ SQInteger SqBuffer::GetCRC32(SQInteger n) const { @@ -500,6 +527,7 @@ void Register_Buffer(HSQUIRRELVM vm) .Func(_SC("ADLER32"), &SqBuffer::GetADLER32) .Func(_SC("Base32"), &SqBuffer::GetBase32) .Func(_SC("Base64"), &SqBuffer::GetBase64) + .SquirrelMethod< SqBuffer, &SqBuffer::GetJSON >(_SC("GetJSON")) ); } diff --git a/module/Library/IO/Buffer.hpp b/module/Library/IO/Buffer.hpp index bee88590..c7a4e0a6 100644 --- a/module/Library/IO/Buffer.hpp +++ b/module/Library/IO/Buffer.hpp @@ -782,6 +782,12 @@ public: */ SQMOD_NODISCARD Vector4 ReadVector4() const; + /* -------------------------------------------------------------------------------------------- + * Transform a portion of the data in the buffer to a JSON object. + * This has the benefit that a temporary string doesn't have to be created. + */ + SQMOD_NODISCARD SQInteger GetJSON(HSQUIRRELVM vm) const; + /* -------------------------------------------------------------------------------------------- * Compute the CRC-32 checksums on the data in the buffer. */ diff --git a/module/Library/JSON.cpp b/module/Library/JSON.cpp index aaeedfea..5d4f98ff 100644 --- a/module/Library/JSON.cpp +++ b/module/Library/JSON.cpp @@ -149,6 +149,22 @@ static SQInteger SqFromJSON(HSQUIRRELVM vm) noexcept return SQ_SUCCEEDED(r) ? 1 : r; } +// ------------------------------------------------------------------------------------------------ +SQInteger SqFromNativeJSON(HSQUIRRELVM vm, const char * data, size_t size) +{ + // Attempt to parse the specified JSON string + const sajson::document & document = sajson::parse(sajson::dynamic_allocation(), sajson::string(data, size)); + // See if there was an error + if (!document.is_valid()) + { + return sq_throwerror(vm, document.get_error_message_as_cstring()); + } + // Process the nodes that were parsed from the string + SQInteger r = SqFromJson_Push(vm, document.get_root()); + // We either have a value to return or we propagate some error + return SQ_SUCCEEDED(r) ? 1 : r; +} + // ------------------------------------------------------------------------------------------------ CtxJSON & CtxJSON::OpenArray() {