diff --git a/inferno/src/inferno/util/json.h b/inferno/src/inferno/util/json.h index 967d045..5fcc332 100644 --- a/inferno/src/inferno/util/json.h +++ b/inferno/src/inferno/util/json.h @@ -1,7 +1,9 @@ #ifndef JSON_UTIL_H #define JSON_UTIL_H +#include // int32_t, uint32_t #include // std::optional +#include // std::vector #include "nlohmann/json.hpp" @@ -19,8 +21,8 @@ namespace Inferno { return it.value(); } - template - static std::optional getType(const json& json, C check) + template + static std::optional getPropertyValue(const json& json, json::value_t check) { if (json.type() == check) { return json.get(); @@ -29,36 +31,146 @@ namespace Inferno { return {}; } + template + static std::optional getPropertyValue(const json& json, std::vector checks) + { + bool valid = false; + + // Check values with all allowed types + for (auto check : checks) { + if (json.type() == check) { + valid = true; + break; + } + } + + // Get value if valid type + if (valid) { + return json.get(); + } + + return {}; + } + // --------------------------------- - static bool hasProperty(const json& json, json_const_iterator& it, const char* member) + static bool hasProperty(const json& json, const char* property) { - it = json.find(member); + return json.find(property) != json.end(); + } + + static bool hasProperty(const json& json, json_const_iterator& it, const char* property) + { + it = json.find(property); return it != json.end(); } // --------------------------------- - template - static std::optional parseProperty(const json& json, const char* property, bool required, C check) + template + static std::optional parseProperty(const json& json, const char* property, bool required, json::value_t check) + { + return parseProperty(json, property, required, std::vector { check }); + } + + template + static std::optional parseProperty(const json& json, const char* property, bool required, std::vector checks) { - bool result; + bool exists; json_const_iterator it; // Has property - result = hasProperty(json, it, property); - ASSERT(!required || (required && result), "Json could not find property '{}'", property); + exists = hasProperty(json, it, property); + ASSERT(!required || (required && exists), "Json could not find required property '{}'", property); - if (!result) { + if (!exists) { return {}; } // Return data found in iterator, empty if incorrect type - return getType(getValue(it), check); + return getPropertyValue(getValue(it), checks); + } + + template + static std::optional> parseArrayProperty(const json& json, const char* property, bool required, json::value_t check) + { + return parseArrayProperty(json, property, required, std::vector { check }); + } + + template + static std::optional> parseArrayProperty(const json& json, const char* property, bool required, std::vector checks) + { + bool exists; + json_const_iterator it; + + // Has property + exists = hasProperty(json, it, property); + ASSERT(!required || (required && exists), "Json could not find required property '{}'", property); + + if (!exists) { + return {}; + } + + // Check if property is array + ASSERT(getValue(it).is_array(), "Json property is not an array '{}'", property); + + // Fill array with values + std::vector values; + for (auto value : getValue(it)) { + auto typedValue = getPropertyValue(value, checks); + if (typedValue) { + values.emplace_back(typedValue.value()); + } + else { + warnln("Json array property '{}' has type inconsistency", property); + } + } + + return values.size() > 0 ? std::optional { values } : std::nullopt; + } + + static std::optional parseBoolProperty(const json& json, const char* property, bool required) + { + return parseProperty(json, property, required, json::value_t::boolean); + } + + static std::optional parseDoubleProperty(const json& json, const char* property, bool required) + { + return parseProperty(json, property, required, std::vector { json::value_t::number_integer, json::value_t::number_unsigned, json::value_t::number_float }); + } + + static std::optional parseIntegerProperty(const json& json, const char* property, bool required) + { + return parseProperty(json, property, required, json::value_t::number_integer); + } + + static std::optional parseUnsignedProperty(const json& json, const char* property, bool required) + { + return parseProperty(json, property, required, json::value_t::number_unsigned); } + + static std::optional parseStringProperty(const json& json, const char* property, bool required) + { + return parseProperty(json, property, required, json::value_t::string); + } + + static std::optional> parseDoubleArrayProperty(const json& json, const char* property, bool required) + { + return parseArrayProperty(json, property, required, std::vector { json::value_t::number_integer, json::value_t::number_unsigned, json::value_t::number_float }); + } + + static std::optional> parseIntegerArrayProperty(const json& json, const char* property, bool required) + { + return parseArrayProperty(json, property, required, json::value_t::number_integer); + } + + static std::optional> parseUnsignedArrayProperty(const json& json, const char* property, bool required) + { + return parseArrayProperty(json, property, required, json::value_t::number_unsigned); + } + }; } // namespace Inferno - #endif // JSON_UTIL_H