mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-15 22:57:12 +02:00
Partial implementation of the JSON module.
This commit is contained in:
@ -1,9 +1,257 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
#include "JValue.hpp"
|
||||
#include "JArray.hpp"
|
||||
#include "JObject.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
CSStr JSONTypeToStr(json_type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case JSON_OBJECT: return _SC("object");
|
||||
case JSON_ARRAY: return _SC("array");
|
||||
case JSON_STRING: return _SC("string");
|
||||
case JSON_INTEGER: return _SC("integer");
|
||||
case JSON_REAL: return _SC("real");
|
||||
case JSON_TRUE: return _SC("true");
|
||||
case JSON_FALSE: return _SC("false");
|
||||
case JSON_NULL: return _SC("null");
|
||||
default: return _SC("unknown");
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void SqThrowLast(HSQUIRRELVM vm, CSStr msg)
|
||||
{
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(vm);
|
||||
// Push the last error on the stack
|
||||
sq_getlasterror(vm);
|
||||
// Attempt to obtained the error as a string
|
||||
StackStrF val(vm, -1, false);
|
||||
// Did the retrieval failed?
|
||||
if (SQ_FAILED(val.mRes))
|
||||
{
|
||||
STHROWF("%s [Unknown error]", msg);
|
||||
}
|
||||
// Throw the resulting error message
|
||||
STHROWF("%s [%s]", msg, val.mPtr);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
json_t * SqToJSON(HSQUIRRELVM vm, SQInteger idx)
|
||||
{
|
||||
switch (sq_gettype(vm, idx))
|
||||
{
|
||||
case OT_NULL:
|
||||
{
|
||||
return json_null();
|
||||
} break;
|
||||
case OT_INTEGER:
|
||||
{
|
||||
SQInteger i;
|
||||
// Retrieve the integer value
|
||||
if (SQ_FAILED(sq_getinteger(vm, idx, &i)))
|
||||
{
|
||||
SqThrowLast(vm, "Cannot retrieve integer value");
|
||||
}
|
||||
// Return the JSON value
|
||||
return json_integer(i);
|
||||
} break;
|
||||
case OT_FLOAT:
|
||||
{
|
||||
SQFloat f;
|
||||
// Retrieve the float value
|
||||
if (SQ_FAILED(sq_getfloat(vm, idx, &f)))
|
||||
{
|
||||
SqThrowLast(vm, "Cannot retrieve float value");
|
||||
}
|
||||
// Return the JSON value
|
||||
return json_real(f);
|
||||
} break;
|
||||
case OT_BOOL:
|
||||
{
|
||||
SQBool b;
|
||||
// Retrieve the boolean value
|
||||
if (SQ_FAILED(sq_getbool(vm, idx, &b)))
|
||||
{
|
||||
SqThrowLast(vm, "Cannot retrieve boolean value");
|
||||
}
|
||||
// Return the JSON value
|
||||
return json_boolean(b);
|
||||
} break;
|
||||
case OT_STRING:
|
||||
{
|
||||
CSStr s = nullptr;
|
||||
SQInteger n;
|
||||
// Retrieve the string value
|
||||
if (SQ_FAILED(sq_getstringandsize(vm, idx, &s, &n)))
|
||||
{
|
||||
SqThrowLast(vm, "Cannot retrieve string value");
|
||||
}
|
||||
// Return the JSON value
|
||||
return json_stringn(s, ConvTo< std::size_t >::From(n));
|
||||
} break;
|
||||
case OT_TABLE:
|
||||
{
|
||||
// Create an object wrapper to release automatically in case of failure
|
||||
JObject obj;
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(vm);
|
||||
// Push null to begin table iteration
|
||||
sq_pushnull(vm);
|
||||
// Compute the new table index on the stack if necessary
|
||||
if (idx < 0)
|
||||
{
|
||||
--idx;
|
||||
}
|
||||
// Start iterating table elements
|
||||
while(SQ_SUCCEEDED(sq_next(vm, idx)))
|
||||
{
|
||||
// Attempt to convert the key to a string
|
||||
StackStrF val(vm, -2, false);
|
||||
// Did the conversion failed?
|
||||
if (SQ_FAILED(val.mRes))
|
||||
{
|
||||
SqThrowLast(vm, "Invalid table key");
|
||||
}
|
||||
// Assign the value with further recursive scanning
|
||||
if (json_object_set_new(obj, val.mPtr, SqToJSON(vm, -1)) < 0)
|
||||
{
|
||||
STHROWF("Unable to set table element (&s)", val.mPtr);
|
||||
}
|
||||
// Pop the key and value before the new iteration
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
// Increase the reference count so that we don't destroy the object
|
||||
json_incref(obj);
|
||||
// Return the resulted object
|
||||
return obj;
|
||||
} break;
|
||||
case OT_ARRAY:
|
||||
{
|
||||
// Create an array wrapper to release automatically in case of failure
|
||||
JArray arr;
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(vm);
|
||||
// Obtain the total size of the array
|
||||
const SQInteger size = sq_getsize(vm, idx);
|
||||
// Push null to begin array iteration
|
||||
sq_pushnull(vm);
|
||||
// Compute the new array index on the stack if necessary
|
||||
if (idx < 0)
|
||||
{
|
||||
--idx;
|
||||
}
|
||||
// Currently processed element
|
||||
SQInteger pos;
|
||||
// Start iterating array elements
|
||||
while(SQ_SUCCEEDED(sq_next(vm, idx)))
|
||||
{
|
||||
// Retrieve the currently processed array element index
|
||||
if (SQ_FAILED(sq_getinteger(vm, -2, &pos)))
|
||||
{
|
||||
SqThrowLast(vm, "Unable to retrieve iterator position");
|
||||
}
|
||||
// Are we still within the array bounds?
|
||||
else if (pos >= size)
|
||||
{
|
||||
break; // Stop iterating
|
||||
}
|
||||
// Assign the value with further recursive scanning
|
||||
if (json_array_append_new(arr, SqToJSON(vm, -1)) < 0)
|
||||
{
|
||||
STHROWF("Unable to set array element: " _PRINT_INT_FMT, pos);
|
||||
}
|
||||
// Pop the key and value before the new iteration
|
||||
sq_pop(vm, 2);
|
||||
}
|
||||
// Increase the reference count so that we don't destroy the array
|
||||
json_incref(arr);
|
||||
// Return the resulted array
|
||||
return arr;
|
||||
} break;
|
||||
default: STHROWF("Unknown conversion for type: %s", SqTypeName(vm, idx));
|
||||
}
|
||||
// Should not reach this point
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
JObject SqTableToJSONObject(Table & tbl)
|
||||
{
|
||||
// Make sure that the given table is not null
|
||||
if (tbl.IsNull())
|
||||
{
|
||||
return JObject(); // Nothing to add
|
||||
}
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(tbl.GetVM());
|
||||
// Push our table onto the stack
|
||||
Var< Table & >::push(tbl.GetVM(), tbl);
|
||||
// Attempt to extract the values from the given table
|
||||
return JObject(SqToJSON(tbl.GetVM(), -1), false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
JArray SqArrayToJSONArray(Array & arr)
|
||||
{
|
||||
// Make sure that the given array is not null
|
||||
if (arr.IsNull())
|
||||
{
|
||||
return JArray(); // Nothing to add
|
||||
}
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(arr.GetVM());
|
||||
// Push our array onto the stack
|
||||
Var< Array & >::push(arr.GetVM(), arr);
|
||||
// Attempt to extract the values from the given array
|
||||
return JArray(SqToJSON(arr.GetVM(), -1), false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
JObject SqObjectToJSONObject(Object & obj)
|
||||
{
|
||||
// Make sure that the given object is not null
|
||||
if (obj.IsNull())
|
||||
{
|
||||
return JObject(); // Nothing to add
|
||||
}
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(obj.GetVM());
|
||||
// Push our object onto the stack
|
||||
Var< Object & >::push(obj.GetVM(), obj);
|
||||
// Attempt to extract the values from the given object
|
||||
return JObject(SqToJSON(obj.GetVM(), -1), false);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
JValue SqValueToJSONValue(Object & obj)
|
||||
{
|
||||
// Make sure that the given object is not null
|
||||
if (obj.IsNull())
|
||||
{
|
||||
return JValue(); // Nothing to add
|
||||
}
|
||||
// Remember the current stack size
|
||||
const StackGuard sg(obj.GetVM());
|
||||
// Push our object onto the stack
|
||||
Var< Object & >::push(obj.GetVM(), obj);
|
||||
// Attempt to extract the values from the given object
|
||||
return JValue(SqToJSON(obj.GetVM(), -1), false);
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_Common(Table & jns)
|
||||
{
|
||||
jns.Func(_SC("FromTable"), &SqTableToJSONObject);
|
||||
jns.Func(_SC("FromArray"), &SqArrayToJSONArray);
|
||||
jns.Func(_SC("ToObject"), &SqObjectToJSONObject);
|
||||
jns.Func(_SC("ToValue"), &SqValueToJSONValue);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
@ -4,6 +4,12 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Base/Utility.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <cstdlib>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include <jansson.h>
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
@ -20,6 +26,80 @@ namespace SqMod {
|
||||
#define SQJSON_VERSION_MINOR 0
|
||||
#define SQJSON_VERSION_PATCH 1
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Implements RAII to free the strings obtained from dumps even after exceptions.
|
||||
*/
|
||||
struct CStrGuard
|
||||
{
|
||||
// --------------------------------------------------------------------------------------------
|
||||
CStr mPtr; // The managed pointer
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Base constructor.
|
||||
*/
|
||||
CStrGuard(CStr p)
|
||||
: mPtr(p)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~CStrGuard()
|
||||
{
|
||||
if (mPtr)
|
||||
{
|
||||
std::free(mPtr);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Forward declarations.
|
||||
*/
|
||||
class JValue;
|
||||
class JArray;
|
||||
class JObject;
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the string representation of JSON value type.
|
||||
*/
|
||||
CSStr JSONTypeToStr(json_type type);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Retrieve the string representation of JSON value type.
|
||||
*/
|
||||
inline CSStr JSONTypeStr(json_t * ptr)
|
||||
{
|
||||
return (ptr == nullptr) ? _SC("unknown") : JSONTypeToStr(json_typeof(ptr));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert a script value from the stack to a JSON object.
|
||||
*/
|
||||
json_t * SqToJSON(HSQUIRRELVM vm, SQInteger idx);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert a script table to a JSON object.
|
||||
*/
|
||||
JObject SqTableToJSONObject(Table & obj);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert a script array to a JSON array.
|
||||
*/
|
||||
JArray SqArrayToJSONArray(Array & obj);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert a script object to a JSON object.
|
||||
*/
|
||||
JObject SqObjectToJSONObject(Object & obj);
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Convert a script value to a JSON value.
|
||||
*/
|
||||
JValue SqValueToJSONValue(Object & obj);
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQJSON_COMMON_HPP_
|
||||
|
49
modules/json/JArray.cpp
Normal file
49
modules/json/JArray.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "JArray.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::size_t JArray::s_Flags = JSON_ENCODE_ANY;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger JArray::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqJSONArray");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object JArray::ToString() const
|
||||
{
|
||||
// Dump the values to a string
|
||||
const CStrGuard csg(json_dumps(m_Ptr, s_Flags));
|
||||
// Remember the current stack size
|
||||
const StackGuard sg;
|
||||
// Transform the string into a script object
|
||||
sq_pushstring(_SqVM, csg.mPtr ? csg.mPtr : _SC(""), -1);
|
||||
// Return the created script object
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_JArray(Table & jns)
|
||||
{
|
||||
jns.Bind(_SC("Array"), Class< JArray >(jns.GetVM(), _SC("SqJSONArray"))
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< const JArray & >()
|
||||
// Core Meta-methods
|
||||
.Func(_SC("_cmp"), &JArray::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &JArray::Typename)
|
||||
.Func(_SC("_tostring"), &JArray::ToString)
|
||||
// Properties
|
||||
//.Prop(_SC("Prop"), &JArray::Prop)
|
||||
// Member Methods
|
||||
//.Func(_SC("Func"), &JArray::Func)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
201
modules/json/JArray.hpp
Normal file
201
modules/json/JArray.hpp
Normal file
@ -0,0 +1,201 @@
|
||||
#ifndef _SQJSON_ARRAY_HPP_
|
||||
#define _SQJSON_ARRAY_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Allows management and interaction with a JSON array.
|
||||
*/
|
||||
class JArray
|
||||
{
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef json_t Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer m_Ptr; // Pointer to the managed array instance.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
static std::size_t s_Flags; // Global flags used when dumping to a string.
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor. (empty)
|
||||
*/
|
||||
JArray()
|
||||
: m_Ptr(json_array())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JArray(Pointer ptr)
|
||||
: m_Ptr(ptr)
|
||||
{
|
||||
if (json_is_array(m_Ptr))
|
||||
{
|
||||
json_incref(m_Ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
STHROWF("Expected JSON array got: %s", JSONTypeStr(m_Ptr));
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JArray(Pointer ptr, bool inc)
|
||||
: m_Ptr(ptr)
|
||||
{
|
||||
if (json_is_array(m_Ptr))
|
||||
{
|
||||
if (inc)
|
||||
{
|
||||
json_incref(m_Ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
STHROWF("Expected JSON array got: %s", JSONTypeStr(m_Ptr));
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
JArray(const JArray & o)
|
||||
: m_Ptr(json_incref(o.m_Ptr))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
JArray(JArray && o)
|
||||
: m_Ptr(o.m_Ptr)
|
||||
{
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~JArray()
|
||||
{
|
||||
// Decrease the reference count of the managed object
|
||||
json_decref(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
JArray & operator = (const JArray & o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Grab the reference of the new object
|
||||
m_Ptr = json_incref(o.m_Ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
JArray & operator = (JArray && o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Steal reference
|
||||
m_Ptr = o.m_Ptr;
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const JArray & o) const
|
||||
{
|
||||
if (json_equal(m_Ptr, o.m_Ptr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Ptr > o.m_Ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
Object ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator ConstPtr () const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether the managed value is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (m_Ptr != nullptr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQJSON_ARRAY_HPP_
|
49
modules/json/JObject.cpp
Normal file
49
modules/json/JObject.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "JObject.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::size_t JObject::s_Flags = JSON_ENCODE_ANY;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger JObject::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqJSONObject");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object JObject::ToString() const
|
||||
{
|
||||
// Dump the values to a string
|
||||
const CStrGuard csg(json_dumps(m_Ptr, s_Flags));
|
||||
// Remember the current stack size
|
||||
const StackGuard sg;
|
||||
// Transform the string into a script object
|
||||
sq_pushstring(_SqVM, csg.mPtr ? csg.mPtr : _SC(""), -1);
|
||||
// Return the created script object
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_JObject(Table & jns)
|
||||
{
|
||||
jns.Bind(_SC("Object"), Class< JObject >(jns.GetVM(), _SC("SqJSONObject"))
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< const JObject & >()
|
||||
// Core Meta-methods
|
||||
.Func(_SC("_cmp"), &JObject::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &JObject::Typename)
|
||||
.Func(_SC("_tostring"), &JObject::ToString)
|
||||
// Properties
|
||||
//.Prop(_SC("Prop"), &JObject::Prop)
|
||||
// Member Methods
|
||||
//.Func(_SC("Func"), &JObject::Func)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
201
modules/json/JObject.hpp
Normal file
201
modules/json/JObject.hpp
Normal file
@ -0,0 +1,201 @@
|
||||
#ifndef _SQJSON_JOBJECT_HPP_
|
||||
#define _SQJSON_JOBJECT_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Allows management and interaction with a JSON object.
|
||||
*/
|
||||
class JObject
|
||||
{
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef json_t Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer m_Ptr; // Pointer to the managed object instance.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
static std::size_t s_Flags; // Global flags used when dumping to a string.
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor. (empty)
|
||||
*/
|
||||
JObject()
|
||||
: m_Ptr(json_object())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JObject(Pointer ptr)
|
||||
: m_Ptr(ptr)
|
||||
{
|
||||
if (json_is_object(m_Ptr))
|
||||
{
|
||||
json_incref(m_Ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
STHROWF("Expected JSON object got: %s", JSONTypeStr(m_Ptr));
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JObject(Pointer ptr, bool inc)
|
||||
: m_Ptr(ptr)
|
||||
{
|
||||
if (json_is_object(m_Ptr))
|
||||
{
|
||||
if (inc)
|
||||
{
|
||||
json_incref(m_Ptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
STHROWF("Expected JSON object got: %s", JSONTypeStr(m_Ptr));
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
JObject(const JObject & o)
|
||||
: m_Ptr(json_incref(o.m_Ptr))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
JObject(JObject && o)
|
||||
: m_Ptr(o.m_Ptr)
|
||||
{
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~JObject()
|
||||
{
|
||||
// Release the managed object
|
||||
json_decref(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
JObject & operator = (const JObject & o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Grab the reference of the new object
|
||||
m_Ptr = json_incref(o.m_Ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
JObject & operator = (JObject && o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Steal reference
|
||||
m_Ptr = o.m_Ptr;
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const JObject & o) const
|
||||
{
|
||||
if (json_equal(m_Ptr, o.m_Ptr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Ptr > o.m_Ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
Object ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator ConstPtr () const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether the managed value is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (m_Ptr != nullptr);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQJSON_JOBJECT_HPP_
|
49
modules/json/JValue.cpp
Normal file
49
modules/json/JValue.cpp
Normal file
@ -0,0 +1,49 @@
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "JValue.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
std::size_t JValue::s_Flags = JSON_ENCODE_ANY;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
SQInteger JValue::Typename(HSQUIRRELVM vm)
|
||||
{
|
||||
static const SQChar name[] = _SC("SqJSONValue");
|
||||
sq_pushstring(vm, name, sizeof(name));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
Object JValue::ToString() const
|
||||
{
|
||||
// Dump the values to a string
|
||||
const CStrGuard csg(json_dumps(m_Ptr, s_Flags));
|
||||
// Remember the current stack size
|
||||
const StackGuard sg;
|
||||
// Transform the string into a script object
|
||||
sq_pushstring(_SqVM, csg.mPtr ? csg.mPtr : _SC(""), -1);
|
||||
// Return the created script object
|
||||
return Var< Object >(_SqVM, -1).value;
|
||||
}
|
||||
|
||||
// ================================================================================================
|
||||
void Register_JValue(Table & jns)
|
||||
{
|
||||
jns.Bind(_SC("Value"), Class< JValue >(jns.GetVM(), _SC("SqJSONValue"))
|
||||
// Constructors
|
||||
.Ctor()
|
||||
.Ctor< const JValue & >()
|
||||
// Core Meta-methods
|
||||
.Func(_SC("_cmp"), &JValue::Cmp)
|
||||
.SquirrelFunc(_SC("_typename"), &JValue::Typename)
|
||||
.Func(_SC("_tostring"), &JValue::ToString)
|
||||
// Properties
|
||||
//.Prop(_SC("Prop"), &JValue::Prop)
|
||||
// Member Methods
|
||||
//.Func(_SC("Func"), &JValue::Func)
|
||||
);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
257
modules/json/JValue.hpp
Normal file
257
modules/json/JValue.hpp
Normal file
@ -0,0 +1,257 @@
|
||||
#ifndef _SQJSON_JVALUE_HPP_
|
||||
#define _SQJSON_JVALUE_HPP_
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#include "Common.hpp"
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
namespace SqMod {
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Allows management and interaction with a JSON value.
|
||||
*/
|
||||
class JValue
|
||||
{
|
||||
public:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef json_t Type; // The managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type* Pointer; // Pointer to the managed type.
|
||||
typedef const Type* ConstPtr; // Constant pointer to the managed type.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
typedef Type& Reference; // Reference to the managed type.
|
||||
typedef const Type& ConstRef; // Constant reference to the managed type.
|
||||
|
||||
private:
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
Pointer m_Ptr; // Pointer to the managed value instance.
|
||||
|
||||
// --------------------------------------------------------------------------------------------
|
||||
static std::size_t s_Flags; // Global flags used when dumping to a string.
|
||||
|
||||
public:
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Default constructor. (null)
|
||||
*/
|
||||
JValue()
|
||||
: m_Ptr(json_null())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JValue(Pointer ptr)
|
||||
: m_Ptr(json_incref(ptr))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Pointer constructor.
|
||||
*/
|
||||
JValue(Pointer ptr, bool inc)
|
||||
: m_Ptr(inc ? json_incref(ptr) : ptr)
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Null pointer constructor.
|
||||
*/
|
||||
JValue(std::nullptr_t)
|
||||
: m_Ptr(json_null())
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Boolean constructor.
|
||||
*/
|
||||
JValue(bool val)
|
||||
: m_Ptr(json_boolean(val))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* String constructor.
|
||||
*/
|
||||
JValue(CSStr val, bool check = true)
|
||||
: m_Ptr(check ? json_string(val) : json_string_nocheck(val))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* String constructor.
|
||||
*/
|
||||
JValue(CSStr val, std::size_t len, bool check = true)
|
||||
: m_Ptr(check ? json_stringn(val, len) : json_stringn_nocheck(val,len))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 32 bit signed integer constructor.
|
||||
*/
|
||||
JValue(Int32 val)
|
||||
: m_Ptr(json_integer(ConvTo< json_int_t >::From(val)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 64 bit signed integer constructor.
|
||||
*/
|
||||
JValue(Int64 val)
|
||||
: m_Ptr(json_integer(ConvTo< json_int_t >::From(val)))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 32 bit floating point number constructor.
|
||||
*/
|
||||
JValue(Float32 val)
|
||||
: m_Ptr(json_real(val))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* 64 bit floating point number constructor.
|
||||
*/
|
||||
JValue(Float64 val)
|
||||
: m_Ptr(json_real(val))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy constructor.
|
||||
*/
|
||||
JValue(const JValue & o)
|
||||
: m_Ptr(json_incref(o.m_Ptr))
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move constructor.
|
||||
*/
|
||||
JValue(JValue && o)
|
||||
: m_Ptr(o.m_Ptr)
|
||||
{
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Destructor.
|
||||
*/
|
||||
~JValue()
|
||||
{
|
||||
// Decrease the reference count of the managed value
|
||||
json_decref(m_Ptr);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Copy assignment operator.
|
||||
*/
|
||||
JValue & operator = (const JValue & o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Grab the reference of the new object
|
||||
m_Ptr = json_incref(o.m_Ptr);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Move assignment operator.
|
||||
*/
|
||||
JValue & operator = (JValue && o)
|
||||
{
|
||||
// Avoid self assignment
|
||||
if (m_Ptr != o.m_Ptr)
|
||||
{
|
||||
// Release the current object
|
||||
json_decref(m_Ptr);
|
||||
// Steal reference
|
||||
m_Ptr = o.m_Ptr;
|
||||
// Prevent further interaction
|
||||
o.m_Ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to compare two instances of this type.
|
||||
*/
|
||||
Int32 Cmp(const JValue & o) const
|
||||
{
|
||||
if (json_equal(m_Ptr, o.m_Ptr))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (m_Ptr > o.m_Ptr)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to convert an instance of this type to a string.
|
||||
*/
|
||||
Object ToString() const;
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Used by the script engine to retrieve the name from instances of this type.
|
||||
*/
|
||||
static SQInteger Typename(HSQUIRRELVM vm);
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator Pointer ()
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* Implicit conversion to the managed JSON value.
|
||||
*/
|
||||
operator ConstPtr () const
|
||||
{
|
||||
return m_Ptr;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------------------------------
|
||||
* See whether the managed value is valid.
|
||||
*/
|
||||
bool IsValid() const
|
||||
{
|
||||
return (m_Ptr != nullptr);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
||||
#endif // _SQJSON_JVALUE_HPP_
|
15
modules/json/Library.c
Normal file
15
modules/json/Library.c
Normal file
@ -0,0 +1,15 @@
|
||||
/* ------------------------------------------------------------------------------------------------
|
||||
* Include the entire library into a single C source so it can be compiled at the same time.
|
||||
*/
|
||||
|
||||
#include "dump.c"
|
||||
#include "error.c"
|
||||
#include "hashtable.c"
|
||||
#include "hashtable_seed.c"
|
||||
#include "load.c"
|
||||
#include "memory.c"
|
||||
#include "pack_unpack.c"
|
||||
#include "strbuffer.c"
|
||||
#include "strconv.c"
|
||||
#include "utf.c"
|
||||
#include "value.c"
|
@ -157,10 +157,23 @@ void UnbindCallbacks()
|
||||
_Clbk->OnPluginCommand = nullptr;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
extern void Register_Common(Table & jns);
|
||||
extern void Register_JArray(Table & jns);
|
||||
extern void Register_JObject(Table & jns);
|
||||
extern void Register_JValue(Table & jns);
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
void RegisterAPI(HSQUIRRELVM vm)
|
||||
{
|
||||
Table jns(vm);
|
||||
|
||||
Register_Common(jns);
|
||||
Register_JArray(jns);
|
||||
Register_JObject(jns);
|
||||
Register_JValue(jns);
|
||||
|
||||
RootTable(vm).Bind(_SC("SqJSON"), jns);
|
||||
}
|
||||
|
||||
} // Namespace:: SqMod
|
||||
|
Reference in New Issue
Block a user