mirror of
https://github.com/geode-sdk/geode.git
synced 2024-11-22 23:48:08 -05:00
Merge pull request #60 from geode-sdk/altalk
add json validation to source
This commit is contained in:
commit
a1c9063767
3 changed files with 401 additions and 149 deletions
|
@ -1,8 +1,5 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define GEODE_API extern "C"
|
|
||||||
#define GEODE_DLL
|
|
||||||
|
|
||||||
namespace geode {
|
namespace geode {
|
||||||
using dylib_t = void*;
|
using dylib_t = void*;
|
||||||
struct PlatformInfo {
|
struct PlatformInfo {
|
||||||
|
|
|
@ -104,47 +104,38 @@ namespace geode {
|
||||||
friend struct JsonMaybeObject<Json>;
|
friend struct JsonMaybeObject<Json>;
|
||||||
friend struct JsonMaybeValue<Json>;
|
friend struct JsonMaybeValue<Json>;
|
||||||
|
|
||||||
void setError(std::string const& error);
|
GEODE_DLL void setError(std::string const& error);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Json& json() {
|
GEODE_DLL Json& json();
|
||||||
return m_json;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonMaybeSomething(
|
GEODE_DLL JsonMaybeSomething(
|
||||||
JsonChecker<Json>& checker,
|
JsonChecker<Json>& checker,
|
||||||
Json& json,
|
Json& json,
|
||||||
std::string const& hierarchy,
|
std::string const& hierarchy,
|
||||||
bool hasValue
|
bool hasValue
|
||||||
) : m_checker(checker),
|
);
|
||||||
m_json(json),
|
|
||||||
m_hierarchy(hierarchy),
|
|
||||||
m_hasValue(hasValue) {}
|
|
||||||
|
|
||||||
bool isError() const;
|
GEODE_DLL bool isError() const;
|
||||||
|
|
||||||
operator bool() const {
|
GEODE_DLL operator bool() const;
|
||||||
return !isError();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Json>
|
template<class Json>
|
||||||
struct JsonMaybeValue : public JsonMaybeSomething<Json> {
|
struct JsonMaybeValue : public JsonMaybeSomething<Json> {
|
||||||
bool m_inferType = true;
|
bool m_inferType = true;
|
||||||
|
|
||||||
JsonMaybeValue(
|
GEODE_DLL JsonMaybeValue(
|
||||||
JsonChecker<Json>& checker,
|
JsonChecker<Json>& checker,
|
||||||
Json& json,
|
Json& json,
|
||||||
std::string const& hierarchy,
|
std::string const& hierarchy,
|
||||||
bool hasValue
|
bool hasValue
|
||||||
) : JsonMaybeSomething<Json>(checker, json, hierarchy, hasValue) {}
|
);
|
||||||
|
|
||||||
JsonMaybeSomething<Json>& self() {
|
GEODE_DLL JsonMaybeSomething<Json>& self();
|
||||||
return *static_cast<JsonMaybeSomething<Json>*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<nlohmann::detail::value_t T>
|
template<nlohmann::detail::value_t T>
|
||||||
JsonMaybeValue<Json> as() {
|
JsonMaybeValue<Json>& as() {
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
if (!jsonConvertibleTo(self().m_json.type(), T)) {
|
if (!jsonConvertibleTo(self().m_json.type(), T)) {
|
||||||
this->setError(
|
this->setError(
|
||||||
|
@ -157,13 +148,10 @@ namespace geode {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonMaybeValue<Json> array() {
|
GEODE_DLL JsonMaybeValue<Json>& array();
|
||||||
this->as<value_t::array>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<nlohmann::detail::value_t... T>
|
template<nlohmann::detail::value_t... T>
|
||||||
JsonMaybeValue<Json> asOneOf() {
|
JsonMaybeValue<Json>& asOneOf() {
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
bool isOneOf = (... || jsonConvertibleTo(self().m_json.type(), T));
|
bool isOneOf = (... || jsonConvertibleTo(self().m_json.type(), T));
|
||||||
if (!isOneOf) {
|
if (!isOneOf) {
|
||||||
|
@ -178,7 +166,7 @@ namespace geode {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<nlohmann::detail::value_t T>
|
template<nlohmann::detail::value_t T>
|
||||||
JsonMaybeValue<Json> is() {
|
JsonMaybeValue<Json>& is() {
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
self().m_hasValue = jsonConvertibleTo(self().m_json.type(), T);
|
self().m_hasValue = jsonConvertibleTo(self().m_json.type(), T);
|
||||||
m_inferType = false;
|
m_inferType = false;
|
||||||
|
@ -186,7 +174,7 @@ namespace geode {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
JsonMaybeValue<Json> validate(JsonValueValidator<T> validator) {
|
JsonMaybeValue<Json>& validate(JsonValueValidator<T> validator) {
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
try {
|
try {
|
||||||
if (!validator(self().m_json.template get<T>())) {
|
if (!validator(self().m_json.template get<T>())) {
|
||||||
|
@ -202,30 +190,30 @@ namespace geode {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
JsonMaybeValue<Json> inferType() {
|
JsonMaybeValue<Json>& inferType() {
|
||||||
if (this->isError() || !m_inferType) return *this;
|
if (this->isError() || !m_inferType) return *this;
|
||||||
return this->as<getJsonType<T>()>();
|
return this->as<getJsonType<T>()>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
JsonMaybeValue<Json> intoRaw(T& target) {
|
JsonMaybeValue<Json>& intoRaw(T& target) {
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
target = self().m_json;
|
target = self().m_json;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
JsonMaybeValue<Json> into(T& target) {
|
JsonMaybeValue<Json>& into(T& target) {
|
||||||
return this->intoAs<T, T>(target);
|
return this->intoAs<T, T>(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
JsonMaybeValue<Json> into(std::optional<T>& target) {
|
JsonMaybeValue<Json>& into(std::optional<T>& target) {
|
||||||
return this->intoAs<T, std::optional<T>>(target);
|
return this->intoAs<T, std::optional<T>>(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class A, class T>
|
template<class A, class T>
|
||||||
JsonMaybeValue<Json> intoAs(T& target) {
|
JsonMaybeValue<Json>& intoAs(T& target) {
|
||||||
this->inferType<A>();
|
this->inferType<A>();
|
||||||
if (this->isError()) return *this;
|
if (this->isError()) return *this;
|
||||||
try {
|
try {
|
||||||
|
@ -278,112 +266,37 @@ namespace geode {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
JsonMaybeValue<Json> at(size_t i) {
|
GEODE_DLL JsonMaybeValue<Json> at(size_t i);
|
||||||
this->as<value_t::array>();
|
|
||||||
if (this->isError()) return *this;
|
|
||||||
if (self().m_json.size() <= i) {
|
|
||||||
this->setError(
|
|
||||||
self().m_hierarchy + ": has " +
|
|
||||||
std::to_string(self().m_json.size()) + "items "
|
|
||||||
", expected to have at least " + std::to_string(i + 1)
|
|
||||||
);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
return JsonMaybeValue<Json>(
|
|
||||||
self().m_checker, self().m_json.at(i),
|
|
||||||
self().m_hierarchy + "." + std::to_string(i),
|
|
||||||
self().m_hasValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<JsonMaybeValue<Json>> iterate() {
|
GEODE_DLL Iterator<JsonMaybeValue<Json>> iterate();
|
||||||
this->as<value_t::array>();
|
|
||||||
Iterator<JsonMaybeValue<Json>> iter;
|
|
||||||
if (this->isError()) return iter;
|
|
||||||
size_t i = 0;
|
|
||||||
for (auto& obj : self().m_json) {
|
|
||||||
iter.m_values.emplace_back(
|
|
||||||
self().m_checker, obj,
|
|
||||||
self().m_hierarchy + "." + std::to_string(i++),
|
|
||||||
self().m_hasValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
Iterator<std::pair<std::string, JsonMaybeValue<Json>>> items() {
|
GEODE_DLL Iterator<std::pair<std::string, JsonMaybeValue<Json>>> items();
|
||||||
this->as<value_t::object>();
|
|
||||||
Iterator<std::pair<std::string, JsonMaybeValue<Json>>> iter;
|
|
||||||
if (this->isError()) return iter;
|
|
||||||
|
|
||||||
for (auto& [k, v] : self().m_json.items()) {
|
|
||||||
iter.m_values.emplace_back(k, JsonMaybeValue<Json>(
|
|
||||||
self().m_checker, v,
|
|
||||||
self().m_hierarchy + "." + k,
|
|
||||||
self().m_hasValue
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return iter;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Json>
|
template<class Json>
|
||||||
struct JsonMaybeObject : JsonMaybeSomething<Json> {
|
struct JsonMaybeObject : JsonMaybeSomething<Json> {
|
||||||
std::set<std::string> m_knownKeys;
|
std::set<std::string> m_knownKeys;
|
||||||
|
|
||||||
JsonMaybeObject(
|
GEODE_DLL JsonMaybeObject(
|
||||||
JsonChecker<Json>& checker,
|
JsonChecker<Json>& checker,
|
||||||
Json& json,
|
Json& json,
|
||||||
std::string const& hierarchy,
|
std::string const& hierarchy,
|
||||||
bool hasValue
|
bool hasValue
|
||||||
) : JsonMaybeSomething<Json>(checker, json, hierarchy, hasValue) {}
|
);
|
||||||
|
|
||||||
JsonMaybeSomething<Json>& self() {
|
GEODE_DLL JsonMaybeSomething<Json>& self();
|
||||||
return *static_cast<JsonMaybeSomething<Json>*>(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addKnownKey(std::string const& key) {
|
GEODE_DLL void addKnownKey(std::string const& key);
|
||||||
m_knownKeys.insert(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
Json& json() {
|
GEODE_DLL Json& json();
|
||||||
return self().m_json;
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonMaybeValue<Json> emptyValue() {
|
GEODE_DLL JsonMaybeValue<Json> emptyValue();
|
||||||
return JsonMaybeValue(self().m_checker, self().m_json, "", false);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonMaybeValue<Json> has(std::string const& key) {
|
GEODE_DLL JsonMaybeValue<Json> has(std::string const& key);
|
||||||
this->addKnownKey(key);
|
|
||||||
if (this->isError()) return emptyValue();
|
|
||||||
if (!self().m_json.contains(key) || self().m_json[key].is_null()) {
|
|
||||||
return emptyValue();
|
|
||||||
}
|
|
||||||
return JsonMaybeValue<Json>(self().m_checker, self().m_json[key], key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonMaybeValue<Json> needs(std::string const& key) {
|
GEODE_DLL JsonMaybeValue<Json> needs(std::string const& key);
|
||||||
this->addKnownKey(key);
|
|
||||||
if (this->isError()) return emptyValue();
|
|
||||||
if (!self().m_json.contains(key)) {
|
|
||||||
this->setError(
|
|
||||||
self().m_hierarchy + " is missing required key \"" + key + "\""
|
|
||||||
);
|
|
||||||
return emptyValue();
|
|
||||||
}
|
|
||||||
return JsonMaybeValue<Json>(self().m_checker, self().m_json[key], key, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void checkUnknownKeys() {
|
GEODE_DLL void checkUnknownKeys();
|
||||||
for (auto& [key, _] : self().m_json.items()) {
|
|
||||||
if (!m_knownKeys.count(key)) {
|
|
||||||
// log::debug(self().m_hierarchy + " contains unknown key \"" + key + "\"");
|
|
||||||
log::debug("{} contains unknown key \"{}\"", self().m_hierarchy, key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Json = nlohmann::json>
|
template<class Json = nlohmann::json>
|
||||||
|
@ -391,37 +304,13 @@ namespace geode {
|
||||||
std::variant<std::monostate, std::string> m_result;
|
std::variant<std::monostate, std::string> m_result;
|
||||||
Json& m_json;
|
Json& m_json;
|
||||||
|
|
||||||
JsonChecker(Json& json) : m_json(json), m_result(std::monostate()) {}
|
GEODE_DLL JsonChecker(Json& json);
|
||||||
|
|
||||||
bool isError() const {
|
GEODE_DLL bool isError() const;
|
||||||
return std::holds_alternative<std::string>(m_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string getError() const {
|
GEODE_DLL std::string getError() const;
|
||||||
return std::get<std::string>(m_result);
|
|
||||||
}
|
|
||||||
|
|
||||||
JsonMaybeValue<Json> root(std::string const& hierarchy) {
|
GEODE_DLL JsonMaybeValue<Json> root(std::string const& hierarchy);
|
||||||
return JsonMaybeValue(*this, m_json, hierarchy, true);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Json>
|
|
||||||
void JsonMaybeSomething<Json>::setError(std::string const& error) {
|
|
||||||
m_checker.m_result = error;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Json>
|
|
||||||
bool JsonMaybeSomething<Json>::isError() const {
|
|
||||||
return m_checker.isError() || !m_hasValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Json>
|
|
||||||
JsonMaybeObject<Json> JsonMaybeValue<Json>::obj() {
|
|
||||||
this->as<value_t::object>();
|
|
||||||
return JsonMaybeObject(
|
|
||||||
self().m_checker, self().m_json,
|
|
||||||
self().m_hierarchy, self().m_hasValue
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
366
loader/src/utils/JsonValidation.cpp
Normal file
366
loader/src/utils/JsonValidation.cpp
Normal file
|
@ -0,0 +1,366 @@
|
||||||
|
#include <Geode/utils/JsonValidation.hpp>
|
||||||
|
|
||||||
|
USE_GEODE_NAMESPACE();
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
Json& JsonMaybeSomething<Json>::json() {
|
||||||
|
return m_json;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeSomething<Json>::JsonMaybeSomething(
|
||||||
|
JsonChecker<Json>& checker,
|
||||||
|
Json& json,
|
||||||
|
std::string const& hierarchy,
|
||||||
|
bool hasValue
|
||||||
|
) : m_checker(checker),
|
||||||
|
m_json(json),
|
||||||
|
m_hierarchy(hierarchy),
|
||||||
|
m_hasValue(hasValue) {}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
bool JsonMaybeSomething<Json>::isError() const {
|
||||||
|
return m_checker.isError() || !m_hasValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeSomething<Json>::operator bool() const {
|
||||||
|
return !isError();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
void JsonMaybeSomething<Json>::setError(std::string const& error) {
|
||||||
|
m_checker.m_result = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeValue<Json>::JsonMaybeValue(
|
||||||
|
JsonChecker<Json>& checker,
|
||||||
|
Json& json,
|
||||||
|
std::string const& hierarchy,
|
||||||
|
bool hasValue
|
||||||
|
) : JsonMaybeSomething<Json>(checker, json, hierarchy, hasValue) {}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeSomething<Json>& JsonMaybeValue<Json>::self() {
|
||||||
|
return *static_cast<JsonMaybeSomething<Json>*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<nlohmann::detail::value_t T>
|
||||||
|
// JsonMaybeValue<Json>& JsonMaybeValue<Json>::as() {
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// if (!jsonConvertibleTo(self().m_json.type(), T)) {
|
||||||
|
// this->setError(
|
||||||
|
// self().m_hierarchy + ": Invalid type \"" +
|
||||||
|
// self().m_json.type_name() + "\", expected \"" +
|
||||||
|
// jsonValueTypeToString(T) + "\""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// m_inferType = false;
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeValue<Json>& JsonMaybeValue<Json>::array() {
|
||||||
|
this->as<value_t::array>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<nlohmann::detail::value_t... T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::asOneOf() {
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// bool isOneOf = (... || jsonConvertibleTo(self().m_json.type(), T));
|
||||||
|
// if (!isOneOf) {
|
||||||
|
// this->setError(
|
||||||
|
// self().m_hierarchy + ": Invalid type \"" +
|
||||||
|
// self().m_json.type_name() + "\", expected one of \"" +
|
||||||
|
// (jsonValueTypeToString(T), ...) + "\""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// m_inferType = false;
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<nlohmann::detail::value_t T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::is() {
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// self().m_hasValue = jsonConvertibleTo(self().m_json.type(), T);
|
||||||
|
// m_inferType = false;
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::validate(JsonValueValidator<T> validator) {
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// try {
|
||||||
|
// if (!validator(self().m_json.template get<T>())) {
|
||||||
|
// this->setError(self().m_hierarchy + ": Invalid value format");
|
||||||
|
// }
|
||||||
|
// } catch(...) {
|
||||||
|
// this->setError(
|
||||||
|
// self().m_hierarchy + ": Invalid type \"" +
|
||||||
|
// std::string(self().m_json.type_name()) + "\""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::inferType() {
|
||||||
|
// if (this->isError() || !m_inferType) return *this;
|
||||||
|
// return this->as<getJsonType<T>()>();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::intoRaw(T& target) {
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// target = self().m_json;
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::into(T& target) {
|
||||||
|
// return this->intoAs<T, T>(target);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::into(std::optional<T>& target) {
|
||||||
|
// return this->intoAs<T, std::optional<T>>(target);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class A, class T>
|
||||||
|
// JsonMaybeValue<Json> JsonMaybeValue<Json>::intoAs(T& target) {
|
||||||
|
// this->inferType<A>();
|
||||||
|
// if (this->isError()) return *this;
|
||||||
|
// try {
|
||||||
|
// target = self().m_json.template get<A>();
|
||||||
|
// } catch(...) {
|
||||||
|
// this->setError(
|
||||||
|
// self().m_hierarchy + ": Invalid type \"" +
|
||||||
|
// std::string(self().m_json.type_name()) + "\""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return *this;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// T JsonMaybeValue<Json>::get() {
|
||||||
|
// this->inferType<T>();
|
||||||
|
// if (this->isError()) return T();
|
||||||
|
// try {
|
||||||
|
// return self().m_json.template get<T>();
|
||||||
|
// } catch(...) {
|
||||||
|
// this->setError(
|
||||||
|
// self().m_hierarchy + ": Invalid type to get \"" +
|
||||||
|
// std::string(self().m_json.type_name()) + "\""
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return T();
|
||||||
|
// }
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeObject<Json> JsonMaybeValue<Json>::obj() {
|
||||||
|
this->as<value_t::object>();
|
||||||
|
return JsonMaybeObject(
|
||||||
|
self().m_checker, self().m_json,
|
||||||
|
self().m_hierarchy, self().m_hasValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// template<class Json>
|
||||||
|
// template<class T>
|
||||||
|
// struct JsonMaybeValue<Json>::Iterator {
|
||||||
|
// std::vector<T> m_values;
|
||||||
|
|
||||||
|
// using iterator = typename std::vector<T>::iterator;
|
||||||
|
// using const_iterator = typename std::vector<T>::const_iterator;
|
||||||
|
|
||||||
|
// iterator begin() {
|
||||||
|
// return m_values.begin();
|
||||||
|
// }
|
||||||
|
// iterator end() {
|
||||||
|
// return m_values.end();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const_iterator begin() const {
|
||||||
|
// return m_values.begin();
|
||||||
|
// }
|
||||||
|
// const_iterator end() const {
|
||||||
|
// return m_values.end();
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
JsonMaybeValue<Json> JsonMaybeValue<Json>::at(size_t i) {
|
||||||
|
this->as<value_t::array>();
|
||||||
|
if (this->isError()) return *this;
|
||||||
|
if (self().m_json.size() <= i) {
|
||||||
|
this->setError(
|
||||||
|
self().m_hierarchy + ": has " +
|
||||||
|
std::to_string(self().m_json.size()) + "items "
|
||||||
|
", expected to have at least " + std::to_string(i + 1)
|
||||||
|
);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
return JsonMaybeValue<Json>(
|
||||||
|
self().m_checker, self().m_json.at(i),
|
||||||
|
self().m_hierarchy + "." + std::to_string(i),
|
||||||
|
self().m_hasValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
typename JsonMaybeValue<Json>::template Iterator<JsonMaybeValue<Json>> JsonMaybeValue<Json>::iterate() {
|
||||||
|
this->as<value_t::array>();
|
||||||
|
Iterator<JsonMaybeValue<Json>> iter;
|
||||||
|
if (this->isError()) return iter;
|
||||||
|
size_t i = 0;
|
||||||
|
for (auto& obj : self().m_json) {
|
||||||
|
iter.m_values.emplace_back(
|
||||||
|
self().m_checker, obj,
|
||||||
|
self().m_hierarchy + "." + std::to_string(i++),
|
||||||
|
self().m_hasValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Json>
|
||||||
|
typename JsonMaybeValue<Json>::template Iterator<std::pair<std::string, JsonMaybeValue<Json>>> JsonMaybeValue<Json>::items() {
|
||||||
|
this->as<value_t::object>();
|
||||||
|
Iterator<std::pair<std::string, JsonMaybeValue<Json>>> iter;
|
||||||
|
if (this->isError()) return iter;
|
||||||
|
|
||||||
|
for (auto& [k, v] : self().m_json.items()) {
|
||||||
|
iter.m_values.emplace_back(k, JsonMaybeValue<Json>(
|
||||||
|
self().m_checker, v,
|
||||||
|
self().m_hierarchy + "." + k,
|
||||||
|
self().m_hasValue
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeObject<Json>::JsonMaybeObject(
|
||||||
|
JsonChecker<Json>& checker,
|
||||||
|
Json& json,
|
||||||
|
std::string const& hierarchy,
|
||||||
|
bool hasValue
|
||||||
|
) : JsonMaybeSomething<Json>(checker, json, hierarchy, hasValue) {}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeSomething<Json>& JsonMaybeObject<Json>::self() {
|
||||||
|
return *static_cast<JsonMaybeSomething<Json>*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
void JsonMaybeObject<Json>::addKnownKey(std::string const& key) {
|
||||||
|
m_knownKeys.insert(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
Json& JsonMaybeObject<Json>::json() {
|
||||||
|
return self().m_json;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeValue<Json> JsonMaybeObject<Json>::emptyValue() {
|
||||||
|
return JsonMaybeValue(self().m_checker, self().m_json, "", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeValue<Json> JsonMaybeObject<Json>::has(std::string const& key) {
|
||||||
|
this->addKnownKey(key);
|
||||||
|
if (this->isError()) return emptyValue();
|
||||||
|
if (!self().m_json.contains(key) || self().m_json[key].is_null()) {
|
||||||
|
return emptyValue();
|
||||||
|
}
|
||||||
|
return JsonMaybeValue<Json>(self().m_checker, self().m_json[key], key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeValue<Json> JsonMaybeObject<Json>::needs(std::string const& key) {
|
||||||
|
this->addKnownKey(key);
|
||||||
|
if (this->isError()) return emptyValue();
|
||||||
|
if (!self().m_json.contains(key)) {
|
||||||
|
this->setError(
|
||||||
|
self().m_hierarchy + " is missing required key \"" + key + "\""
|
||||||
|
);
|
||||||
|
return emptyValue();
|
||||||
|
}
|
||||||
|
return JsonMaybeValue<Json>(self().m_checker, self().m_json[key], key, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
void JsonMaybeObject<Json>::checkUnknownKeys() {
|
||||||
|
for (auto& [key, _] : self().m_json.items()) {
|
||||||
|
if (!m_knownKeys.count(key)) {
|
||||||
|
// log::debug(self().m_hierarchy + " contains unknown key \"" + key + "\"");
|
||||||
|
log::debug("{} contains unknown key \"{}\"", self().m_hierarchy, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonChecker<Json>::JsonChecker(Json& json) : m_json(json), m_result(std::monostate()) {}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
bool JsonChecker<Json>::isError() const {
|
||||||
|
return std::holds_alternative<std::string>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
std::string JsonChecker<Json>::getError() const {
|
||||||
|
return std::get<std::string>(m_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class Json>
|
||||||
|
JsonMaybeValue<Json> JsonChecker<Json>::root(std::string const& hierarchy) {
|
||||||
|
return JsonMaybeValue(*this, m_json, hierarchy, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
namespace geode {
|
||||||
|
|
||||||
|
template struct JsonMaybeSomething<nlohmann::json>;
|
||||||
|
template struct JsonMaybeSomething<nlohmann::json const>;
|
||||||
|
template struct JsonMaybeSomething<ModJson>;
|
||||||
|
|
||||||
|
|
||||||
|
template struct JsonMaybeValue<nlohmann::json>;
|
||||||
|
template struct JsonMaybeValue<nlohmann::json const>;
|
||||||
|
template struct JsonMaybeValue<ModJson>;
|
||||||
|
|
||||||
|
|
||||||
|
template struct JsonMaybeObject<nlohmann::json>;
|
||||||
|
template struct JsonMaybeObject<nlohmann::json const>;
|
||||||
|
template struct JsonMaybeObject<ModJson>;
|
||||||
|
|
||||||
|
|
||||||
|
template struct JsonChecker<nlohmann::json>;
|
||||||
|
template struct JsonChecker<nlohmann::json const>;
|
||||||
|
template struct JsonChecker<ModJson>;
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in a new issue