mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
Tier2: implement new JSON tools
Implemented robust and cheap number parser, which can parse numbers from json string and json numbers. Strings can be hexadecimal, octal and decimal. Converter gets selected at compile time. Also implemented a few inlines that return user provided default if value wasn't found or didn't match specified or classified type.
This commit is contained in:
parent
77851d9ad7
commit
138600a3a6
@ -33,6 +33,23 @@ enum class JSONFieldType_e
|
||||
kArray
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets the object type as string
|
||||
//-----------------------------------------------------------------------------
|
||||
inline const char* JSON_TypeToString(const rapidjson::Type type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case rapidjson::kNullType: return "null";
|
||||
case rapidjson::kFalseType: case rapidjson::kTrueType: return "bool";
|
||||
case rapidjson::kObjectType: return "object";
|
||||
case rapidjson::kArrayType: return "array";
|
||||
case rapidjson::kStringType: return "string";
|
||||
case rapidjson::kNumberType: return "number";
|
||||
default: return "unknown";
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member's value is of type provided
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -74,6 +91,34 @@ inline bool JSON_IsOfType(const T& data, const JSONFieldType_e type)
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: gets json type for data type at compile time
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline JSONFieldType_e JSON_GetTypeForType()
|
||||
{
|
||||
if constexpr (std::is_same<T, bool>::value)
|
||||
return JSONFieldType_e::kBool;
|
||||
else if constexpr (std::is_same<T, int32_t>::value)
|
||||
return JSONFieldType_e::kSint32;
|
||||
else if constexpr (std::is_same<T, int64_t>::value)
|
||||
return JSONFieldType_e::kSint64;
|
||||
else if constexpr (std::is_same<T, uint32_t>::value)
|
||||
return JSONFieldType_e::kUint32;
|
||||
else if constexpr (std::is_same<T, uint64_t>::value)
|
||||
return JSONFieldType_e::kUint64;
|
||||
else if constexpr (std::is_same<T, float>::value)
|
||||
return JSONFieldType_e::kFloat;
|
||||
else if constexpr (std::is_same<T, double>::value)
|
||||
return JSONFieldType_e::kDouble;
|
||||
else if constexpr (std::is_same<T, const char*>::value)
|
||||
return JSONFieldType_e::kString;
|
||||
else if constexpr (std::is_same<T, std::string>::value)
|
||||
return JSONFieldType_e::kString;
|
||||
else
|
||||
static_assert(false, "Cannot classify data type; unsupported.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of type provided
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -91,8 +136,9 @@ inline bool JSON_HasMemberAndIsOfType(const T& data, const char* const member, c
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of type provided,
|
||||
// and sets 'out' to its value if all aforementioned conditions are met
|
||||
// Purpose: checks if the member exists and if its value is of specified type,
|
||||
// and sets 'out' to its value if all aforementioned conditions
|
||||
// are met
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class V>
|
||||
inline bool JSON_GetValue(const T& data, const char* const member, const JSONFieldType_e type, V& out)
|
||||
@ -113,12 +159,36 @@ inline bool JSON_GetValue(const T& data, const char* const member, const JSONFie
|
||||
// Not found or didn't match specified type.
|
||||
return false;
|
||||
}
|
||||
template <class T>
|
||||
inline bool JSON_GetValue(const T& data, const char* const member, const JSONFieldType_e type, std::string& out)
|
||||
{
|
||||
const char* stringVal = nullptr;
|
||||
|
||||
if (JSON_GetValue(data, member, type, stringVal))
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of classified type,
|
||||
// and sets 'out' to its value if all aforementioned conditions are met
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class V>
|
||||
inline bool JSON_GetValue(const T& data, const char* const member, V& out)
|
||||
{
|
||||
const T::ConstMemberIterator it = data.FindMember(member);
|
||||
|
||||
if (it != data.MemberEnd())
|
||||
{
|
||||
const rapidjson::Value& val = it->value;
|
||||
|
||||
if (JSON_IsOfType(val, JSON_GetTypeForType<V>()))
|
||||
{
|
||||
out = val.Get<V>();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Not found or didn't match classified type.
|
||||
return false;
|
||||
}
|
||||
template <class T>
|
||||
inline bool JSON_GetValue(const T& data, const char* const member, std::string& out)
|
||||
{
|
||||
const char* stringVal;
|
||||
|
||||
if (JSON_GetValue(data, member, JSONFieldType_e::kString, stringVal))
|
||||
{
|
||||
out = stringVal;
|
||||
return true;
|
||||
@ -127,9 +197,28 @@ inline bool JSON_GetValue(const T& data, const char* const member, const JSONFie
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of classified type,
|
||||
// and returns the value if all aforementioned conditions are met.
|
||||
// else the provided default gets returned
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class V>
|
||||
inline V JSON_GetValueOrDefault(const T& data, const char* const member, const V def)
|
||||
{
|
||||
V val;
|
||||
|
||||
if (JSON_GetValue(data, member, JSON_GetTypeForType<V>(), val))
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of type provided,
|
||||
// and sets 'out' to its iterator if all aforementioned conditions are met
|
||||
// and sets 'out' to its iterator if all aforementioned conditions
|
||||
// are met
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline bool JSON_GetIterator(const T& data, const char* const member,
|
||||
@ -150,6 +239,93 @@ inline bool JSON_GetIterator(const T& data, const char* const member,
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists, and sets 'out' to its iterator if the
|
||||
// aforementioned condition is met
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T>
|
||||
inline bool JSON_GetIterator(const T& data, const char* const member, typename T::ConstMemberIterator& out)
|
||||
{
|
||||
const T::ConstMemberIterator it = data.FindMember(member);
|
||||
|
||||
if (it != data.MemberEnd())
|
||||
{
|
||||
out = it;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not found.
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: parses json number out of provided integer, float or string. string
|
||||
// can be a hex (0x<num>), octal (0<num>) or decimal (<num>)
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class V>
|
||||
inline bool JSON_ParseNumber(const T& data, V& num)
|
||||
{
|
||||
if (JSON_IsOfType(data, JSONFieldType_e::kNumber))
|
||||
{
|
||||
num = data.Get<V>();
|
||||
return true;
|
||||
}
|
||||
else if (JSON_IsOfType(data, JSONFieldType_e::kString))
|
||||
{
|
||||
const char* const string = data.GetString();
|
||||
char* end = nullptr;
|
||||
|
||||
if constexpr (std::is_same<V, int32_t>::value)
|
||||
num = strtol(string, &end, 0);
|
||||
else if constexpr (std::is_same<V, int64_t>::value)
|
||||
num = strtoll(string, &end, 0);
|
||||
else if constexpr (std::is_same<V, uint32_t>::value)
|
||||
num = strtoul(string, &end, 0);
|
||||
else if constexpr (std::is_same<V, uint64_t>::value)
|
||||
num = strtoull(string, &end, 0);
|
||||
else if constexpr (std::is_same<V, float>::value)
|
||||
num = static_cast<float>(strtod(string, &end));
|
||||
else if constexpr (std::is_same<V, double>::value)
|
||||
num = strtod(string, &end);
|
||||
else
|
||||
static_assert(false, "Cannot classify numeric type; unsupported.");
|
||||
|
||||
return end == &string[data.GetStringLength()];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
template <class T, class V>
|
||||
inline bool JSON_ParseNumber(const T& data, const char* const member, V& num)
|
||||
{
|
||||
rapidjson::Document::ConstMemberIterator it;
|
||||
|
||||
if (JSON_GetIterator(data, member, it))
|
||||
{
|
||||
return JSON_ParseNumber(it->value, num);;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Purpose: checks if the member exists and if its value is of classified type,
|
||||
// and returns the number if all aforementioned conditions are met.
|
||||
// else the provided default gets returned
|
||||
//-----------------------------------------------------------------------------
|
||||
template <class T, class V>
|
||||
inline V JSON_GetNumberOrDefault(const T& data, const char* const member, V def)
|
||||
{
|
||||
V num;
|
||||
|
||||
if (JSON_ParseNumber(data, member, num))
|
||||
{
|
||||
return num;
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
void JSON_DocumentToBufferDeserialize(const rapidjson::Document& document, rapidjson::StringBuffer& buffer, unsigned int indent = 4);
|
||||
|
||||
#endif // TIER2_JSONUTILS_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user