2021-07-10 13:15:41 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
#include "Core/Utility.hpp"
|
|
|
|
#include "Library/IO/Buffer.hpp"
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-10-02 20:24:12 +02:00
|
|
|
#include <functional>
|
|
|
|
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
2022-09-15 22:03:38 +02:00
|
|
|
#include <fmt/args.h>
|
|
|
|
#include <fmt/format.h>
|
|
|
|
#include <fmt/xchar.h>
|
|
|
|
|
2021-07-10 13:15:41 +02:00
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
|
|
namespace SqMod {
|
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* ------------------------------------------------------------------------------------------------
|
|
|
|
* JSON serializer. The generated JSON output is always minified for efficiency reasons.
|
|
|
|
*/
|
|
|
|
struct CtxJSON
|
|
|
|
{
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Output string.
|
|
|
|
*/
|
|
|
|
String mOutput{};
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Prefer a table with named members even when a simple array would do the job.
|
|
|
|
* Take a Vector3 for example. Compact array [x, y, z] or named object {x: #.#, y: #.#, z: #.#}
|
|
|
|
*/
|
|
|
|
bool mObjectOverArray{true};
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* How nested are we currently.
|
|
|
|
*/
|
|
|
|
uint32_t mDepth{0};
|
|
|
|
|
2022-10-02 20:24:12 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* The meta-method name to use on objects.
|
|
|
|
*/
|
|
|
|
String mMetaMethod{"_tojson"};
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Last pushed string value. Can be used to heck for key name in the hook.
|
|
|
|
*/
|
|
|
|
String mString{};
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Internal utility used to monitor the existence of certain keys to allow overloading.
|
|
|
|
*/
|
|
|
|
std::function< void(CtxJSON&) > mKeyHook{};
|
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Default constructor.
|
|
|
|
*/
|
2022-10-02 20:47:20 +02:00
|
|
|
CtxJSON() = default;
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit constructor.
|
|
|
|
*/
|
2022-10-02 20:47:20 +02:00
|
|
|
explicit CtxJSON(bool ooa)
|
2022-09-15 22:03:38 +02:00
|
|
|
: CtxJSON()
|
|
|
|
{
|
|
|
|
mObjectOverArray = ooa;
|
|
|
|
}
|
|
|
|
|
2022-10-02 20:24:12 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Explicit constructor.
|
|
|
|
*/
|
2022-10-02 20:47:20 +02:00
|
|
|
CtxJSON(bool ooa, StackStrF & mmname)
|
2022-10-02 20:24:12 +02:00
|
|
|
: CtxJSON()
|
|
|
|
{
|
|
|
|
mObjectOverArray = ooa;
|
|
|
|
// Allow custom metamethod names
|
|
|
|
mMetaMethod.assign(mmname.mPtr, static_cast< size_t >(mmname.mLen));
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Internal constructor.
|
|
|
|
*/
|
2022-10-02 20:47:20 +02:00
|
|
|
explicit CtxJSON(std::function< void(CtxJSON&) > && kh)
|
2022-10-02 20:24:12 +02:00
|
|
|
: CtxJSON()
|
|
|
|
{
|
|
|
|
mKeyHook = std::move(kh);
|
|
|
|
}
|
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy constructor.
|
|
|
|
*/
|
|
|
|
CtxJSON(const CtxJSON &) = default;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Move constructor.
|
|
|
|
*/
|
|
|
|
CtxJSON(CtxJSON &&) noexcept = default;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Destructor.
|
|
|
|
*/
|
|
|
|
~CtxJSON() = default;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Copy assignment operator.
|
|
|
|
*/
|
|
|
|
CtxJSON & operator = (const CtxJSON &) = default;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Move assignment operator.
|
|
|
|
*/
|
|
|
|
CtxJSON & operator = (CtxJSON &&) noexcept = default;
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the current depth.
|
|
|
|
*/
|
|
|
|
SQMOD_NODISCARD const String & GetOutput() const noexcept
|
|
|
|
{
|
|
|
|
return mOutput;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve the current depth.
|
|
|
|
*/
|
|
|
|
SQMOD_NODISCARD SQInteger GetDepth() const noexcept
|
|
|
|
{
|
|
|
|
return mDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve whether objects are preferred over arrays.
|
|
|
|
*/
|
|
|
|
SQMOD_NODISCARD bool GetObjectOverArray() const noexcept
|
|
|
|
{
|
|
|
|
return mObjectOverArray;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Retrieve whether objects are preferred over arrays.
|
|
|
|
*/
|
|
|
|
CtxJSON & SetObjectOverArray(bool toggle) noexcept
|
|
|
|
{
|
|
|
|
mObjectOverArray = toggle;
|
|
|
|
// Allow chaining
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Increase indentation by one level.
|
|
|
|
*/
|
|
|
|
void Advance() noexcept
|
|
|
|
{
|
|
|
|
++mDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Decrease indentation by one level.
|
|
|
|
*/
|
|
|
|
void Retreat() noexcept
|
|
|
|
{
|
|
|
|
assert(mDepth > 0);
|
|
|
|
if (mDepth) --mDepth;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Begin writing an array.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & OpenArray();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Stop writing an array.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & CloseArray();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
2022-10-02 20:24:12 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Resume writing an array.
|
|
|
|
*/
|
|
|
|
CtxJSON & ReopenArray();
|
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Begin writing an object.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & OpenObject();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Stop writing an object.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & CloseObject();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
2022-10-02 20:24:12 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Resume writing an object.
|
|
|
|
*/
|
|
|
|
CtxJSON & ReopenObject();
|
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Begin writing a key value.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & MakeKey();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Check whether the specified weak-ref points to a type of value that must be wrapped.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQMOD_NODISCARD static bool CheckWeakRefWrap(HSQUIRRELVM vm, SQInteger idx) noexcept;
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize given arguments.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeParams(HSQUIRRELVM vm);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize the value a specific position in the stack.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeAt(HSQUIRRELVM vm, SQInteger idx);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize the array a specific position in the stack. Stack index must be absolute!
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeArray(HSQUIRRELVM vm, SQInteger idx);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize the table a specific position in the stack. Stack index must be absolute!
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeTable(HSQUIRRELVM vm, SQInteger idx);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize the instance a specific position in the stack. Stack index must be absolute!
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeInstance(HSQUIRRELVM vm, SQInteger idx);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize the weak-ref a specific position in the stack. Stack index must be absolute!
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT SerializeWeakRef(HSQUIRRELVM vm, SQInteger idx);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize a value to the current container. It assumes an array or object is currently open.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT PushValues(HSQUIRRELVM vm);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Serialize a key/value pair to the current object. It assumes an object is currently open.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
SQRESULT PushElement(HSQUIRRELVM vm);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Push a key in the output. It assumes an object was open and previous element closed properly.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
CtxJSON & PushKey(StackStrF & key);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a null value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushNull();
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write an integer value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushInteger(SQInteger value);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a single precision floating point value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushFloat(float value);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a double precision floating point value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushDouble(double value);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a boolean value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushBool(bool value);
|
2022-09-15 22:03:38 +02:00
|
|
|
|
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a string value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushString(const SQChar * str);
|
2021-07-10 13:15:41 +02:00
|
|
|
|
2022-09-15 22:03:38 +02:00
|
|
|
/* --------------------------------------------------------------------------------------------
|
|
|
|
* Write a string value to the output.
|
|
|
|
*/
|
2022-09-17 22:25:16 +02:00
|
|
|
void PushString(const SQChar * str, size_t length);
|
2022-09-15 22:03:38 +02:00
|
|
|
};
|
2021-07-10 13:15:41 +02:00
|
|
|
|
|
|
|
} // Namespace:: SqMod
|