Update nlohmann::json to 3.11.2
Also update json_schema_validator to match new deprecations
This commit is contained in:
parent
9fafd6feff
commit
995a153f27
|
@ -33,6 +33,8 @@
|
|||
#include <boost/uuid/entropy_error.hpp>
|
||||
#endif
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <cctype>
|
||||
#include <mutex>
|
||||
|
||||
|
@ -336,3 +338,15 @@ wxString KIID_PATH::AsString() const
|
|||
|
||||
return path;
|
||||
}
|
||||
|
||||
|
||||
void to_json( nlohmann::json& aJson, const KIID& aKIID )
|
||||
{
|
||||
aJson = aKIID.AsString().ToUTF8();
|
||||
}
|
||||
|
||||
|
||||
void from_json( const nlohmann::json& aJson, KIID& aKIID )
|
||||
{
|
||||
aKIID = KIID( aJson.get<std::string>() );
|
||||
}
|
||||
|
|
|
@ -120,12 +120,6 @@ bool JSON_SETTINGS::Contains( const std::string& aPath ) const
|
|||
}
|
||||
|
||||
|
||||
size_t JSON_SETTINGS::Count( const std::string& aPath ) const
|
||||
{
|
||||
return m_internals->count( JSON_SETTINGS_INTERNALS::PointerFromString( aPath ) );
|
||||
}
|
||||
|
||||
|
||||
JSON_SETTINGS_INTERNALS* JSON_SETTINGS::Internals()
|
||||
{
|
||||
return m_internals.get();
|
||||
|
|
|
@ -77,6 +77,9 @@ principle should be easily implemented by adapting the current STL containers.
|
|||
%ignore operator <<;
|
||||
%ignore operator=;
|
||||
|
||||
%ignore to_json;
|
||||
%ignore from_json;
|
||||
|
||||
// headers/imports that must be included in the _wrapper.cpp at top
|
||||
|
||||
%{
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <macros_swig.h>
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -197,4 +198,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void to_json( nlohmann::json& aJson, const KIID& aKIID );
|
||||
|
||||
void from_json( const nlohmann::json& aJson, KIID& aKIID );
|
||||
|
||||
#endif // KIID_H
|
||||
|
|
|
@ -91,7 +91,6 @@ public:
|
|||
|
||||
nlohmann::json& At( const std::string& aPath );
|
||||
bool Contains( const std::string& aPath ) const;
|
||||
size_t Count( const std::string& aPath ) const;
|
||||
|
||||
JSON_SETTINGS_INTERNALS* Internals();
|
||||
|
||||
|
|
|
@ -963,31 +963,40 @@ bool BOARD_DESIGN_SETTINGS::LoadFromFile( const wxString& aDirectory )
|
|||
return std::string( name.ToUTF8() );
|
||||
};
|
||||
|
||||
std::string bp = "board.design_settings.rule_severities.";
|
||||
std::string rs = "rule_severities.";
|
||||
const std::string rs = "rule_severities.";
|
||||
const std::string no_courtyard_key = "legacy_no_courtyard_defined";
|
||||
const std::string courtyard_overlap_key = "legacy_courtyards_overlap";
|
||||
|
||||
if( std::optional<bool> v = project->Get<bool>( bp + "legacy_no_courtyard_defined" ) )
|
||||
try
|
||||
{
|
||||
if( *v )
|
||||
Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
|
||||
else
|
||||
Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
|
||||
nlohmann::json& severities =
|
||||
project->Internals()->at( "/board/design_settings/rule_severities"_json_pointer );
|
||||
|
||||
project->Internals()->erase( m_internals->PointerFromString( bp + "legacy_no_courtyard_defined" ) );
|
||||
migrated = true;
|
||||
if( severities.contains( no_courtyard_key ) )
|
||||
{
|
||||
if( severities[no_courtyard_key].get<bool>() )
|
||||
Set( rs + drcName( DRCE_MISSING_COURTYARD ), "error" );
|
||||
else
|
||||
Set( rs + drcName( DRCE_MISSING_COURTYARD ), "ignore" );
|
||||
|
||||
severities.erase( no_courtyard_key );
|
||||
migrated = true;
|
||||
}
|
||||
|
||||
if( severities.contains( courtyard_overlap_key ) )
|
||||
{
|
||||
if( severities[courtyard_overlap_key].get<bool>() )
|
||||
Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
|
||||
else
|
||||
Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
|
||||
|
||||
severities.erase( courtyard_overlap_key );
|
||||
migrated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if( std::optional<bool> v = project->Get<bool>( bp + "legacy_courtyards_overlap" ) )
|
||||
catch( ... )
|
||||
{
|
||||
if( *v )
|
||||
Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "error" );
|
||||
else
|
||||
Set( rs + drcName( DRCE_OVERLAPPING_FOOTPRINTS ), "ignore" );
|
||||
|
||||
project->Internals()->erase( JSON_SETTINGS_INTERNALS::PointerFromString( bp + "legacy_courtyards_overlap" ) );
|
||||
migrated = true;
|
||||
}
|
||||
|
||||
if( Contains( "legacy" ) )
|
||||
{
|
||||
// This defaults to false for new boards, but version 5.1.x and prior kept the fillets
|
||||
|
|
|
@ -435,7 +435,7 @@ bool FOOTPRINT_EDITOR_SETTINGS::migrateSchema0to1()
|
|||
|
||||
std::string theme_ptr( "appearance.color_theme" );
|
||||
|
||||
if( !Count( theme_ptr ) )
|
||||
if( !Contains( theme_ptr ) )
|
||||
return true;
|
||||
|
||||
wxString selected = At( theme_ptr ).get<wxString>();
|
||||
|
|
|
@ -85,19 +85,19 @@ json_patch::json_patch(const json &patch)
|
|||
|
||||
json_patch &json_patch::add(const json::json_pointer &ptr, json value)
|
||||
{
|
||||
j_.push_back(json{{"op", "add"}, {"path", ptr}, {"value", std::move(value)}});
|
||||
j_.push_back(json{{"op", "add"}, {"path", ptr.to_string()}, {"value", std::move(value)}});
|
||||
return *this;
|
||||
}
|
||||
|
||||
json_patch &json_patch::replace(const json::json_pointer &ptr, json value)
|
||||
{
|
||||
j_.push_back(json{{"op", "replace"}, {"path", ptr}, {"value", std::move(value)}});
|
||||
j_.push_back(json{{"op", "replace"}, {"path", ptr.to_string()}, {"value", std::move(value)}});
|
||||
return *this;
|
||||
}
|
||||
|
||||
json_patch &json_patch::remove(const json::json_pointer &ptr)
|
||||
{
|
||||
j_.push_back(json{{"op", "remove"}, {"path", ptr}});
|
||||
j_.push_back(json{{"op", "remove"}, {"path", ptr.to_string()}});
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <memory>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
using nlohmann::json;
|
||||
using nlohmann::json_patch;
|
||||
|
@ -34,12 +35,21 @@ using namespace nlohmann::json_schema;
|
|||
namespace
|
||||
{
|
||||
|
||||
static const json EmptyDefault = nullptr;
|
||||
|
||||
class schema
|
||||
{
|
||||
protected:
|
||||
root_schema *root_;
|
||||
json default_value_ = nullptr;
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<schema> make_for_default_(
|
||||
std::shared_ptr<::schema> & /* sch */,
|
||||
root_schema * /* root */,
|
||||
std::vector<nlohmann::json_uri> & /* uris */,
|
||||
nlohmann::json & /* default_value */) const
|
||||
{
|
||||
return nullptr;
|
||||
};
|
||||
|
||||
public:
|
||||
virtual ~schema() = default;
|
||||
|
@ -49,11 +59,13 @@ public:
|
|||
|
||||
virtual void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const = 0;
|
||||
|
||||
virtual const json &defaultValue(const json::json_pointer &, const json &, error_handler &) const
|
||||
virtual const json &default_value(const json::json_pointer &, const json &, error_handler &) const
|
||||
{
|
||||
return EmptyDefault;
|
||||
return default_value_;
|
||||
}
|
||||
|
||||
void set_default_value(const json &v) { default_value_ = v; }
|
||||
|
||||
static std::shared_ptr<schema> make(json &schema,
|
||||
root_schema *root,
|
||||
const std::vector<std::string> &key,
|
||||
|
@ -64,6 +76,8 @@ class schema_ref : public schema
|
|||
{
|
||||
const std::string id_;
|
||||
std::weak_ptr<schema> target_;
|
||||
std::shared_ptr<schema> target_strong_; // for references to references keep also the shared_ptr because
|
||||
// no one else might use it after resolving
|
||||
|
||||
void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const final
|
||||
{
|
||||
|
@ -75,24 +89,47 @@ class schema_ref : public schema
|
|||
e.error(ptr, instance, "unresolved or freed schema-reference " + id_);
|
||||
}
|
||||
|
||||
const json &defaultValue(const json::json_pointer &ptr, const json &instance, error_handler &e) const override
|
||||
const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override final
|
||||
{
|
||||
if (!default_value_.is_null())
|
||||
return default_value_;
|
||||
|
||||
auto target = target_.lock();
|
||||
|
||||
if (target)
|
||||
return target->defaultValue(ptr, instance, e);
|
||||
else
|
||||
e.error(ptr, instance, "unresolved or freed schema-reference " + id_);
|
||||
return target->default_value(ptr, instance, e);
|
||||
|
||||
return EmptyDefault;
|
||||
e.error(ptr, instance, "unresolved or freed schema-reference " + id_);
|
||||
|
||||
return default_value_;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<schema> make_for_default_(
|
||||
std::shared_ptr<::schema> &sch,
|
||||
root_schema *root,
|
||||
std::vector<nlohmann::json_uri> &uris,
|
||||
nlohmann::json &default_value) const override
|
||||
{
|
||||
// create a new reference schema using the original reference (which will be resolved later)
|
||||
// to store this overloaded default value #209
|
||||
auto result = std::make_shared<schema_ref>(uris[0].to_string(), root);
|
||||
result->set_target(sch, true);
|
||||
result->set_default_value(default_value);
|
||||
return result;
|
||||
};
|
||||
|
||||
public:
|
||||
schema_ref(const std::string &id, root_schema *root)
|
||||
: schema(root), id_(id) {}
|
||||
|
||||
const std::string &id() const { return id_; }
|
||||
void set_target(const std::shared_ptr<schema> &target) { target_ = target; }
|
||||
|
||||
void set_target(const std::shared_ptr<schema> &target, bool strong = false)
|
||||
{
|
||||
target_ = target;
|
||||
if (strong)
|
||||
target_strong_ = target;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
@ -168,7 +205,7 @@ public:
|
|||
auto fragment = new_uri.pointer();
|
||||
|
||||
// is there a reference looking for this unknown-keyword, which is thus no longer a unknown keyword but a schema
|
||||
auto unresolved = file.unresolved.find(fragment);
|
||||
auto unresolved = file.unresolved.find(fragment.to_string());
|
||||
if (unresolved != file.unresolved.end())
|
||||
schema::make(value, this, {}, {{new_uri}});
|
||||
else { // no, nothing ref'd it, keep for later
|
||||
|
@ -216,7 +253,7 @@ public:
|
|||
//
|
||||
// an unknown keyword can only be referenced by a json-pointer,
|
||||
// not by a plain name fragment
|
||||
if (uri.pointer() != "") {
|
||||
if (uri.pointer().to_string() != "") {
|
||||
try {
|
||||
auto &subschema = file.unknown_keywords.at(uri.pointer()); // null is returned if not existing
|
||||
auto s = schema::make(subschema, this, {}, {{uri}}); // A JSON Schema MUST be an object or a boolean.
|
||||
|
@ -272,11 +309,31 @@ public:
|
|||
break;
|
||||
} while (1);
|
||||
|
||||
for (const auto &file : files_)
|
||||
if (file.second.unresolved.size() != 0)
|
||||
for (const auto &file : files_) {
|
||||
if (file.second.unresolved.size() != 0) {
|
||||
// Build a representation of the undefined
|
||||
// references as a list of comma-separated strings.
|
||||
auto n_urefs = file.second.unresolved.size();
|
||||
std::string urefs = "[";
|
||||
|
||||
decltype(n_urefs) counter = 0;
|
||||
for (const auto &p : file.second.unresolved) {
|
||||
urefs += p.first;
|
||||
|
||||
if (counter != n_urefs - 1u) {
|
||||
urefs += ", ";
|
||||
}
|
||||
|
||||
++counter;
|
||||
}
|
||||
|
||||
urefs += "]";
|
||||
|
||||
throw std::invalid_argument("after all files have been parsed, '" +
|
||||
(file.first == "" ? "<root>" : file.first) +
|
||||
"' has still undefined references.");
|
||||
"' has still the following undefined references: " + urefs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void validate(const json::json_pointer &ptr,
|
||||
|
@ -347,9 +404,9 @@ class logical_not : public schema
|
|||
e.error(ptr, instance, "the subschema has succeeded, but it is required to not validate");
|
||||
}
|
||||
|
||||
const json &defaultValue(const json::json_pointer &ptr, const json &instance, error_handler &e) const override
|
||||
const json &default_value(const json::json_pointer &ptr, const json &instance, error_handler &e) const override
|
||||
{
|
||||
return subschema_->defaultValue(ptr, instance, e);
|
||||
return subschema_->default_value(ptr, instance, e);
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -443,7 +500,6 @@ bool logical_combination<oneOf>::is_validate_complete(const json &instance, cons
|
|||
|
||||
class type_schema : public schema
|
||||
{
|
||||
json defaultValue_ = EmptyDefault;
|
||||
std::vector<std::shared_ptr<schema>> type_;
|
||||
std::pair<bool, json> enum_, const_;
|
||||
std::vector<std::shared_ptr<schema>> logic_;
|
||||
|
@ -456,15 +512,10 @@ class type_schema : public schema
|
|||
|
||||
std::shared_ptr<schema> if_, then_, else_;
|
||||
|
||||
const json &defaultValue(const json::json_pointer &, const json &, error_handler &) const override
|
||||
{
|
||||
return defaultValue_;
|
||||
}
|
||||
|
||||
void validate(const json::json_pointer &ptr, const json &instance, json_patch &patch, error_handler &e) const override final
|
||||
{
|
||||
// depending on the type of instance run the type specific validator - if present
|
||||
auto type = type_[(uint8_t) instance.type()];
|
||||
auto type = type_[static_cast<uint8_t>(instance.type())];
|
||||
|
||||
if (type)
|
||||
type->validate(ptr, instance, patch, e);
|
||||
|
@ -504,11 +555,23 @@ class type_schema : public schema
|
|||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual std::shared_ptr<schema> make_for_default_(
|
||||
std::shared_ptr<::schema> & /* sch */,
|
||||
root_schema * /* root */,
|
||||
std::vector<nlohmann::json_uri> & /* uris */,
|
||||
nlohmann::json &default_value) const override
|
||||
{
|
||||
auto result = std::make_shared<type_schema>(*this);
|
||||
result->set_default_value(default_value);
|
||||
return result;
|
||||
};
|
||||
|
||||
public:
|
||||
type_schema(json &sch,
|
||||
root_schema *root,
|
||||
const std::vector<nlohmann::json_uri> &uris)
|
||||
: schema(root), type_((uint8_t) json::value_t::discarded + 1)
|
||||
: schema(root), type_(static_cast<uint8_t>(json::value_t::discarded) + 1)
|
||||
{
|
||||
// association between JSON-schema-type and NLohmann-types
|
||||
static const std::vector<std::pair<std::string, json::value_t>> schema_types = {
|
||||
|
@ -526,7 +589,7 @@ public:
|
|||
auto attr = sch.find("type");
|
||||
if (attr == sch.end()) // no type field means all sub-types possible
|
||||
for (auto &t : schema_types)
|
||||
type_[(uint8_t) t.second] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
type_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
else {
|
||||
switch (attr.value().type()) { // "type": "type"
|
||||
|
||||
|
@ -534,14 +597,14 @@ public:
|
|||
auto schema_type = attr.value().get<std::string>();
|
||||
for (auto &t : schema_types)
|
||||
if (t.first == schema_type)
|
||||
type_[(uint8_t) t.second] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
type_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
} break;
|
||||
|
||||
case json::value_t::array: // "type": ["type1", "type2"]
|
||||
for (auto &schema_type : attr.value())
|
||||
for (auto &t : schema_types)
|
||||
if (t.first == schema_type)
|
||||
type_[(uint8_t) t.second] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
type_[static_cast<uint8_t>(t.second)] = type_schema::make(sch, t.second, root, uris, known_keywords);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -551,9 +614,10 @@ public:
|
|||
sch.erase(attr);
|
||||
}
|
||||
|
||||
const auto defaultAttr = sch.find("default");
|
||||
if (defaultAttr != sch.end()) {
|
||||
defaultValue_ = defaultAttr.value();
|
||||
attr = sch.find("default");
|
||||
if (attr != sch.end()) {
|
||||
set_default_value(attr.value());
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
for (auto &key : known_keywords)
|
||||
|
@ -561,16 +625,16 @@ public:
|
|||
|
||||
// with nlohmann::json float instance (but number in schema-definition) can be seen as unsigned or integer -
|
||||
// reuse the number-validator for integer values as well, if they have not been specified explicitly
|
||||
if (type_[(uint8_t) json::value_t::number_float] && !type_[(uint8_t) json::value_t::number_integer])
|
||||
type_[(uint8_t) json::value_t::number_integer] = type_[(uint8_t) json::value_t::number_float];
|
||||
if (type_[static_cast<uint8_t>(json::value_t::number_float)] && !type_[static_cast<uint8_t>(json::value_t::number_integer)])
|
||||
type_[static_cast<uint8_t>(json::value_t::number_integer)] = type_[static_cast<uint8_t>(json::value_t::number_float)];
|
||||
|
||||
// #54: JSON-schema does not differentiate between unsigned and signed integer - nlohmann::json does
|
||||
// we stick with JSON-schema: use the integer-validator if instance-value is unsigned
|
||||
type_[(uint8_t) json::value_t::number_unsigned] = type_[(uint8_t) json::value_t::number_integer];
|
||||
type_[static_cast<uint8_t>(json::value_t::number_unsigned)] = type_[static_cast<uint8_t>(json::value_t::number_integer)];
|
||||
|
||||
// special for binary types
|
||||
if (type_[(uint8_t) json::value_t::string]) {
|
||||
type_[(uint8_t) json::value_t::binary] = type_[(uint8_t) json::value_t::string];
|
||||
if (type_[static_cast<uint8_t>(json::value_t::string)]) {
|
||||
type_[static_cast<uint8_t>(json::value_t::binary)] = type_[static_cast<uint8_t>(json::value_t::string)];
|
||||
}
|
||||
|
||||
attr = sch.find("enum");
|
||||
|
@ -657,7 +721,7 @@ class string : public schema
|
|||
void validate(const json::json_pointer &ptr, const json &instance, json_patch &, error_handler &e) const override
|
||||
{
|
||||
if (minLength_.first) {
|
||||
if (utf8_length(instance) < minLength_.second) {
|
||||
if (utf8_length(instance.get<std::string>()) < minLength_.second) {
|
||||
std::ostringstream s;
|
||||
s << "instance is too short as per minLength:" << minLength_.second;
|
||||
e.error(ptr, instance, s.str());
|
||||
|
@ -665,7 +729,7 @@ class string : public schema
|
|||
}
|
||||
|
||||
if (maxLength_.first) {
|
||||
if (utf8_length(instance) > maxLength_.second) {
|
||||
if (utf8_length(instance.get<std::string>()) > maxLength_.second) {
|
||||
std::ostringstream s;
|
||||
s << "instance is too long as per maxLength: " << maxLength_.second;
|
||||
e.error(ptr, instance, s.str());
|
||||
|
@ -701,7 +765,7 @@ class string : public schema
|
|||
e.error(ptr, instance, std::string("a format checker was not provided but a format keyword for this string is present: ") + format_.second);
|
||||
else {
|
||||
try {
|
||||
root_->format_check()(format_.second, instance);
|
||||
root_->format_check()(format_.second, instance.get<std::string>());
|
||||
} catch (const std::exception &ex) {
|
||||
e.error(ptr, instance, std::string("format-checking failed: ") + ex.what());
|
||||
}
|
||||
|
@ -715,13 +779,13 @@ public:
|
|||
{
|
||||
auto attr = sch.find("maxLength");
|
||||
if (attr != sch.end()) {
|
||||
maxLength_ = {true, attr.value()};
|
||||
maxLength_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("minLength");
|
||||
if (attr != sch.end()) {
|
||||
minLength_ = {true, attr.value()};
|
||||
minLength_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
|
@ -759,7 +823,7 @@ public:
|
|||
#ifndef NO_STD_REGEX
|
||||
attr = sch.find("pattern");
|
||||
if (attr != sch.end()) {
|
||||
patternString_ = attr.value();
|
||||
patternString_ = attr.value().get<std::string>();
|
||||
pattern_ = {true, REGEX_NAMESPACE::regex(attr.value().get<std::string>(),
|
||||
REGEX_NAMESPACE::regex::ECMAScript)};
|
||||
sch.erase(attr);
|
||||
|
@ -771,7 +835,7 @@ public:
|
|||
if (root_->format_check() == nullptr)
|
||||
throw std::invalid_argument{"a format checker was not provided but a format keyword for this string is present: " + format_.second};
|
||||
|
||||
format_ = {true, attr.value()};
|
||||
format_ = {true, attr.value().get<std::string>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
}
|
||||
|
@ -792,7 +856,7 @@ class numeric : public schema
|
|||
bool violates_multiple_of(T x) const
|
||||
{
|
||||
double res = std::remainder(x, multipleOf_.second);
|
||||
double eps = std::nextafter(x, 0) - x;
|
||||
double eps = std::nextafter(x, 0) - static_cast<double>(x);
|
||||
return std::fabs(res) > std::fabs(eps);
|
||||
}
|
||||
|
||||
|
@ -804,15 +868,19 @@ class numeric : public schema
|
|||
if (violates_multiple_of(value))
|
||||
e.error(ptr, instance, "instance is not a multiple of " + std::to_string(multipleOf_.second));
|
||||
|
||||
if (maximum_.first)
|
||||
if ((exclusiveMaximum_ && value >= maximum_.second) ||
|
||||
value > maximum_.second)
|
||||
if (maximum_.first) {
|
||||
if (exclusiveMaximum_ && value >= maximum_.second)
|
||||
e.error(ptr, instance, "instance exceeds or equals maximum of " + std::to_string(maximum_.second));
|
||||
else if (value > maximum_.second)
|
||||
e.error(ptr, instance, "instance exceeds maximum of " + std::to_string(maximum_.second));
|
||||
}
|
||||
|
||||
if (minimum_.first)
|
||||
if ((exclusiveMinimum_ && value <= minimum_.second) ||
|
||||
value < minimum_.second)
|
||||
if (minimum_.first) {
|
||||
if (exclusiveMinimum_ && value <= minimum_.second)
|
||||
e.error(ptr, instance, "instance is below or equals minimum of " + std::to_string(minimum_.second));
|
||||
else if (value < minimum_.second)
|
||||
e.error(ptr, instance, "instance is below minimum of " + std::to_string(minimum_.second));
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -821,33 +889,33 @@ public:
|
|||
{
|
||||
auto attr = sch.find("maximum");
|
||||
if (attr != sch.end()) {
|
||||
maximum_ = {true, attr.value()};
|
||||
maximum_ = {true, attr.value().get<T>()};
|
||||
kw.insert("maximum");
|
||||
}
|
||||
|
||||
attr = sch.find("minimum");
|
||||
if (attr != sch.end()) {
|
||||
minimum_ = {true, attr.value()};
|
||||
minimum_ = {true, attr.value().get<T>()};
|
||||
kw.insert("minimum");
|
||||
}
|
||||
|
||||
attr = sch.find("exclusiveMaximum");
|
||||
if (attr != sch.end()) {
|
||||
exclusiveMaximum_ = true;
|
||||
maximum_ = {true, attr.value()};
|
||||
maximum_ = {true, attr.value().get<T>()};
|
||||
kw.insert("exclusiveMaximum");
|
||||
}
|
||||
|
||||
attr = sch.find("exclusiveMinimum");
|
||||
if (attr != sch.end()) {
|
||||
minimum_ = {true, attr.value()};
|
||||
exclusiveMinimum_ = true;
|
||||
minimum_ = {true, attr.value().get<T>()};
|
||||
kw.insert("exclusiveMinimum");
|
||||
}
|
||||
|
||||
attr = sch.find("multipleOf");
|
||||
if (attr != sch.end()) {
|
||||
multipleOf_ = {true, attr.value()};
|
||||
multipleOf_ = {true, attr.value().get<json::number_float_t>()};
|
||||
kw.insert("multipleOf");
|
||||
}
|
||||
}
|
||||
|
@ -882,8 +950,8 @@ class boolean : public schema
|
|||
{
|
||||
if (!true_) { // false schema
|
||||
// empty array
|
||||
//switch (instance.type()) {
|
||||
//case json::value_t::array:
|
||||
// switch (instance.type()) {
|
||||
// case json::value_t::array:
|
||||
// if (instance.size() != 0) // valid false-schema
|
||||
// e.error(ptr, instance, "false-schema required empty array");
|
||||
// return;
|
||||
|
@ -977,9 +1045,9 @@ class object : public schema
|
|||
for (auto const &prop : properties_) {
|
||||
const auto finding = instance.find(prop.first);
|
||||
if (instance.end() == finding) { // if the prop is not in the instance
|
||||
const auto &defaultValue = prop.second->defaultValue(ptr, instance, e);
|
||||
if (!defaultValue.is_null()) { // if default value is available
|
||||
patch.add((ptr / prop.first), defaultValue);
|
||||
const auto &default_value = prop.second->default_value(ptr, instance, e);
|
||||
if (!default_value.is_null()) { // if default value is available
|
||||
patch.add((ptr / prop.first), default_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -999,13 +1067,13 @@ public:
|
|||
{
|
||||
auto attr = sch.find("maxProperties");
|
||||
if (attr != sch.end()) {
|
||||
maxProperties_ = {true, attr.value()};
|
||||
maxProperties_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("minProperties");
|
||||
if (attr != sch.end()) {
|
||||
minProperties_ = {true, attr.value()};
|
||||
minProperties_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
|
@ -1143,19 +1211,19 @@ public:
|
|||
{
|
||||
auto attr = sch.find("maxItems");
|
||||
if (attr != sch.end()) {
|
||||
maxItems_ = {true, attr.value()};
|
||||
maxItems_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("minItems");
|
||||
if (attr != sch.end()) {
|
||||
minItems_ = {true, attr.value()};
|
||||
minItems_ = {true, attr.value().get<size_t>()};
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
attr = sch.find("uniqueItems");
|
||||
if (attr != sch.end()) {
|
||||
uniqueItems_ = attr.value();
|
||||
uniqueItems_ = attr.value().get<bool>();
|
||||
sch.erase(attr);
|
||||
}
|
||||
|
||||
|
@ -1255,7 +1323,7 @@ std::shared_ptr<schema> schema::make(json &schema,
|
|||
if (std::find(uris.begin(),
|
||||
uris.end(),
|
||||
attr.value().get<std::string>()) == uris.end())
|
||||
uris.push_back(uris.back().derive(attr.value())); // so add it to the list if it is not there already
|
||||
uris.push_back(uris.back().derive(attr.value().get<std::string>())); // so add it to the list if it is not there already
|
||||
schema.erase(attr);
|
||||
}
|
||||
|
||||
|
@ -1270,15 +1338,25 @@ std::shared_ptr<schema> schema::make(json &schema,
|
|||
if (attr != schema.end()) { // this schema is a reference
|
||||
// the last one on the uri-stack is the last id seen before coming here,
|
||||
// so this is the origial URI for this reference, the $ref-value has thus be resolved from it
|
||||
auto id = uris.back().derive(attr.value());
|
||||
auto id = uris.back().derive(attr.value().get<std::string>());
|
||||
sch = root->get_or_create_ref(id);
|
||||
|
||||
schema.erase(attr);
|
||||
|
||||
// special case where we break draft-7 and allow overriding of properties when a $ref is used
|
||||
attr = schema.find("default");
|
||||
if (attr != schema.end()) {
|
||||
// copy the referenced schema depending on the underlying type and modify the default value
|
||||
if (auto new_sch = sch->make_for_default_(sch, root, uris, attr.value())) {
|
||||
sch = new_sch;
|
||||
}
|
||||
schema.erase(attr);
|
||||
}
|
||||
} else {
|
||||
sch = std::make_shared<type_schema>(schema, root, uris);
|
||||
}
|
||||
|
||||
schema.erase("$schema");
|
||||
schema.erase("default");
|
||||
schema.erase("title");
|
||||
schema.erase("description");
|
||||
} else {
|
||||
|
|
|
@ -61,7 +61,7 @@ protected:
|
|||
|
||||
std::tuple<std::string, std::string, std::string, std::string, std::string> as_tuple() const
|
||||
{
|
||||
return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_);
|
||||
return std::make_tuple(urn_, scheme_, authority_, path_, identifier_ != "" ? identifier_ : pointer_.to_string());
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -80,7 +80,7 @@ public:
|
|||
std::string fragment() const
|
||||
{
|
||||
if (identifier_ == "")
|
||||
return pointer_;
|
||||
return pointer_.to_string();
|
||||
else
|
||||
return identifier_;
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ public:
|
|||
/**
|
||||
* Checks validity of JSON schema built-in string format specifiers like 'date-time', 'ipv4', ...
|
||||
*/
|
||||
void default_string_format_check(const std::string &format, const std::string &value);
|
||||
void JSON_SCHEMA_VALIDATOR_API default_string_format_check(const std::string &format, const std::string &value);
|
||||
|
||||
class root_schema;
|
||||
|
||||
|
|
|
@ -61,28 +61,44 @@ void rfc3339_time_check(const std::string &value)
|
|||
throw std::invalid_argument(value + " is not a time string according to RFC 3339.");
|
||||
}
|
||||
|
||||
const auto hour = std::stoi(matches[1].str());
|
||||
const auto minute = std::stoi(matches[2].str());
|
||||
const auto second = std::stoi(matches[3].str());
|
||||
auto hour = std::stoi(matches[1].str());
|
||||
auto minute = std::stoi(matches[2].str());
|
||||
auto second = std::stoi(matches[3].str());
|
||||
// const auto secfrac = std::stof( matches[4].str() );
|
||||
|
||||
range_check(hour, 0, 23);
|
||||
range_check(minute, 0, 59);
|
||||
/**
|
||||
* @todo Could be made more exact by querying a leap second database and choosing the
|
||||
* correct maximum in {58,59,60}. This current solution might match some invalid dates
|
||||
* but it won't lead to false negatives. This only works if we know the full date, however
|
||||
*/
|
||||
range_check(second, 0, 60);
|
||||
|
||||
int offsetHour = 0,
|
||||
offsetMinute = 0;
|
||||
|
||||
/* don't check the numerical offset if time zone is specified as 'Z' */
|
||||
if (!matches[5].str().empty()) {
|
||||
const auto offsetHour = std::stoi(matches[5].str());
|
||||
const auto offsetMinute = std::stoi(matches[6].str());
|
||||
offsetHour = std::stoi(matches[5].str());
|
||||
offsetMinute = std::stoi(matches[6].str());
|
||||
|
||||
range_check(offsetHour, -23, 23);
|
||||
range_check(offsetMinute, 0, 59);
|
||||
if (offsetHour < 0)
|
||||
offsetMinute *= -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Could be made more exact by querying a leap second database and choosing the
|
||||
* correct maximum in {58,59,60}. This current solution might match some invalid dates
|
||||
* but it won't lead to false negatives. This only works if we know the full date, however
|
||||
*/
|
||||
|
||||
auto day_minutes = hour * 60 + minute - (offsetHour * 60 + offsetMinute);
|
||||
if (day_minutes < 0)
|
||||
day_minutes += 60 * 24;
|
||||
hour = day_minutes % 24;
|
||||
minute = day_minutes / 24;
|
||||
|
||||
if (hour == 23 && minute == 59)
|
||||
range_check(second, 0, 60); // possible leap-second
|
||||
else
|
||||
range_check(second, 0, 59);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -110,7 +126,7 @@ void rfc3339_time_check(const std::string &value)
|
|||
* @endverbatim
|
||||
* NOTE: Per [ABNF] and ISO8601, the "T" and "Z" characters in this
|
||||
* syntax may alternatively be lower case "t" or "z" respectively.
|
||||
*/
|
||||
*/
|
||||
void rfc3339_date_time_check(const std::string &value)
|
||||
{
|
||||
const static std::regex dateTimeRegex{R"(^([0-9]{4}\-[0-9]{2}\-[0-9]{2})[Tt]([0-9]{2}\:[0-9]{2}\:[0-9]{2}(?:\.[0-9]+)?(?:[Zz]|(?:\+|\-)[0-9]{2}\:[0-9]{2}))$)"};
|
||||
|
@ -124,7 +140,7 @@ void rfc3339_date_time_check(const std::string &value)
|
|||
rfc3339_time_check(matches[2].str());
|
||||
}
|
||||
|
||||
const std::string decOctet{R"((?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))"}; // matches numbers 0-255
|
||||
const std::string decOctet{R"((?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9]))"}; // matches numbers 0-255
|
||||
const std::string ipv4Address{"(?:" + decOctet + R"(\.){3})" + decOctet};
|
||||
const std::string h16{R"([0-9A-Fa-f]{1,4})"};
|
||||
const std::string h16Left{"(?:" + h16 + ":)"};
|
||||
|
@ -159,6 +175,8 @@ const std::string host{
|
|||
"|" + regName +
|
||||
")"};
|
||||
|
||||
const std::string uuid{R"([0-9a-fA-F]{8}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{4}\-[0-9a-fA-F]{12})"};
|
||||
|
||||
// from http://stackoverflow.com/questions/106179/regular-expression-to-match-dns-hostname-or-ip-address
|
||||
const std::string hostname{R"(^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$)"};
|
||||
|
||||
|
@ -247,6 +265,142 @@ const std::string dotAtom{"(?:" + atext + R"(+(?:\.)" + atext + "+)*)"};
|
|||
const std::string stackoverflowMagicPart{R"((?:[[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?\.)+)"
|
||||
R"([[:alnum:]](?:[[:alnum:]-]*[[:alnum:]])?)"};
|
||||
const std::string email{"(?:" + dotAtom + "|" + quotedString + ")@(?:" + stackoverflowMagicPart + "|" + domainLiteral + ")"};
|
||||
|
||||
/**
|
||||
* @see
|
||||
*
|
||||
* @verbatim
|
||||
* URI = scheme ":" hier-part [ "?" query ] [ "#" fragment ]
|
||||
*
|
||||
* hier-part = "//" authority path-abempty
|
||||
* / path-absolute
|
||||
* / path-rootless
|
||||
* / path-empty
|
||||
*
|
||||
* URI-reference = URI / relative-ref
|
||||
*
|
||||
* absolute-URI = scheme ":" hier-part [ "?" query ]
|
||||
*
|
||||
* relative-ref = relative-part [ "?" query ] [ "#" fragment ]
|
||||
*
|
||||
* relative-part = "//" authority path-abempty
|
||||
* / path-absolute
|
||||
* / path-noscheme
|
||||
* / path-empty
|
||||
*
|
||||
* scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
|
||||
*
|
||||
* authority = [ userinfo "@" ] host [ ":" port ]
|
||||
* userinfo = *( unreserved / pct-encoded / sub-delims / ":" )
|
||||
* host = IP-literal / IPv4address / reg-name
|
||||
* port = *DIGIT
|
||||
*
|
||||
* IP-literal = "[" ( IPv6address / IPvFuture ) "]"
|
||||
*
|
||||
* IPvFuture = "v" 1*HEXDIG "." 1*( unreserved / sub-delims / ":" )
|
||||
*
|
||||
* IPv6address = 6( h16 ":" ) ls32
|
||||
* / "::" 5( h16 ":" ) ls32
|
||||
* / [ h16 ] "::" 4( h16 ":" ) ls32
|
||||
* / [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
|
||||
* / [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
|
||||
* / [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
|
||||
* / [ *4( h16 ":" ) h16 ] "::" ls32
|
||||
* / [ *5( h16 ":" ) h16 ] "::" h16
|
||||
* / [ *6( h16 ":" ) h16 ] "::"
|
||||
*
|
||||
* h16 = 1*4HEXDIG
|
||||
* ls32 = ( h16 ":" h16 ) / IPv4address
|
||||
* IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
|
||||
* dec-octet = DIGIT ; 0-9
|
||||
* / %x31-39 DIGIT ; 10-99
|
||||
* / "1" 2DIGIT ; 100-199
|
||||
* / "2" %x30-34 DIGIT ; 200-249
|
||||
* / "25" %x30-35 ; 250-255
|
||||
*
|
||||
* reg-name = *( unreserved / pct-encoded / sub-delims )
|
||||
*
|
||||
* path = path-abempty ; begins with "/" or is empty
|
||||
* / path-absolute ; begins with "/" but not "//"
|
||||
* / path-noscheme ; begins with a non-colon segment
|
||||
* / path-rootless ; begins with a segment
|
||||
* / path-empty ; zero characters
|
||||
*
|
||||
* path-abempty = *( "/" segment )
|
||||
* path-absolute = "/" [ segment-nz *( "/" segment ) ]
|
||||
* path-noscheme = segment-nz-nc *( "/" segment )
|
||||
* path-rootless = segment-nz *( "/" segment )
|
||||
* path-empty = 0<pchar>
|
||||
*
|
||||
* segment = *pchar
|
||||
* segment-nz = 1*pchar
|
||||
* segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
|
||||
* ; non-zero-length segment without any colon ":"
|
||||
*
|
||||
* pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
|
||||
*
|
||||
* query = *( pchar / "/" / "?" )
|
||||
*
|
||||
* fragment = *( pchar / "/" / "?" )
|
||||
*
|
||||
* pct-encoded = "%" HEXDIG HEXDIG
|
||||
*
|
||||
* unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
|
||||
* reserved = gen-delims / sub-delims
|
||||
* gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@"
|
||||
* sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
|
||||
* / "*" / "+" / "," / ";" / "="
|
||||
*
|
||||
* @endverbatim
|
||||
* @see adapted from: https://github.com/jhermsmeier/uri.regex/blob/master/uri.regex
|
||||
*
|
||||
*/
|
||||
void rfc3986_uri_check(const std::string &value)
|
||||
{
|
||||
const static std::string scheme{R"(([A-Za-z][A-Za-z0-9+\-.]*):)"};
|
||||
const static std::string hierPart{
|
||||
R"((?:(\/\/)(?:((?:[A-Za-z0-9\-._~!$&'()*+,;=:]|)"
|
||||
R"(%[0-9A-Fa-f]{2})*)@)?((?:\[(?:(?:(?:(?:[0-9A-Fa-f]{1,4}:){6}|)"
|
||||
R"(::(?:[0-9A-Fa-f]{1,4}:){5}|)"
|
||||
R"((?:[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){4}|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,1}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){3}|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})?::(?:[0-9A-Fa-f]{1,4}:){2}|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}:|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})?::)(?:[0-9A-Fa-f]{1,4}:[0-9A-Fa-f]{1,4}|)"
|
||||
R"((?:(?:25[0-5]|2[0-4][0-9]|)"
|
||||
R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)"
|
||||
R"(2[0-4][0-9]|)"
|
||||
R"([01]?[0-9][0-9]?))|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})?::[0-9A-Fa-f]{1,4}|)"
|
||||
R"((?:(?:[0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})?::)|)"
|
||||
R"([Vv][0-9A-Fa-f]+\.[A-Za-z0-9\-._~!$&'()*+,;=:]+)\]|)"
|
||||
R"((?:(?:25[0-5]|)"
|
||||
R"(2[0-4][0-9]|)"
|
||||
R"([01]?[0-9][0-9]?)\.){3}(?:25[0-5]|)"
|
||||
R"(2[0-4][0-9]|)"
|
||||
R"([01]?[0-9][0-9]?)|)"
|
||||
R"((?:[A-Za-z0-9\-._~!$&'()*+,;=]|)"
|
||||
R"(%[0-9A-Fa-f]{2})*))(?::([0-9]*))?((?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
|
||||
R"(%[0-9A-Fa-f]{2})*)*)|)"
|
||||
R"(\/((?:(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
|
||||
R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
|
||||
R"(%[0-9A-Fa-f]{2})*)*)?)|)"
|
||||
R"(((?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
|
||||
R"(%[0-9A-Fa-f]{2})+(?:\/(?:[A-Za-z0-9\-._~!$&'()*+,;=:@]|)"
|
||||
R"(%[0-9A-Fa-f]{2})*)*)|))"};
|
||||
|
||||
const static std::string query{R"((?:\?((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"};
|
||||
const static std::string fragment{
|
||||
R"((?:\#((?:[A-Za-z0-9\-._~!$&'()*+,;=:@\/?]|%[0-9A-Fa-f]{2})*))?)"};
|
||||
const static std::string uriFormat{scheme + hierPart + query + fragment};
|
||||
|
||||
const static std::regex uriRegex{uriFormat};
|
||||
|
||||
if (!std::regex_match(value, uriRegex)) {
|
||||
throw std::invalid_argument(value + " is not a URI string according to RFC 3986.");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace nlohmann
|
||||
|
@ -268,6 +422,8 @@ void default_string_format_check(const std::string &format, const std::string &v
|
|||
rfc3339_date_check(value);
|
||||
} else if (format == "time") {
|
||||
rfc3339_time_check(value);
|
||||
} else if (format == "uri") {
|
||||
rfc3986_uri_check(value);
|
||||
} else if (format == "email") {
|
||||
static const std::regex emailRegex{email};
|
||||
if (!std::regex_match(value, emailRegex)) {
|
||||
|
@ -288,6 +444,11 @@ void default_string_format_check(const std::string &format, const std::string &v
|
|||
if (!std::regex_match(value, ipv6Regex)) {
|
||||
throw std::invalid_argument(value + " is not an IPv6 string according to RFC 5954.");
|
||||
}
|
||||
} else if (format == "uuid") {
|
||||
static const std::regex uuidRegex{uuid};
|
||||
if (!std::regex_match(value, uuidRegex)) {
|
||||
throw std::invalid_argument(value + " is not an uuid string according to RFC 4122.");
|
||||
}
|
||||
} else if (format == "regex") {
|
||||
try {
|
||||
std::regex re(value, std::regex::ECMAScript);
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2013-2022 Niels Lohmann
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
|
@ -14,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
SOFTWARE.
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#pragma once
|
||||
|
||||
// This file contains all macro definitions affecting or depending on the ABI
|
||||
|
||||
#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
|
||||
#if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
|
||||
#if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
|
||||
#warning "Already included a different version of the library!"
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
|
||||
#define NLOHMANN_JSON_VERSION_PATCH 2 // NOLINT(modernize-macro-to-enum)
|
||||
|
||||
#ifndef JSON_DIAGNOSTICS
|
||||
#define JSON_DIAGNOSTICS 0
|
||||
#endif
|
||||
|
||||
#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
|
||||
#endif
|
||||
|
||||
#if JSON_DIAGNOSTICS
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
|
||||
#endif
|
||||
|
||||
#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
|
||||
#else
|
||||
#define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
|
||||
#endif
|
||||
|
||||
// Construct the namespace ABI tags component
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
|
||||
#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
|
||||
|
||||
#define NLOHMANN_JSON_ABI_TAGS \
|
||||
NLOHMANN_JSON_ABI_TAGS_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
|
||||
NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
|
||||
|
||||
// Construct the namespace version component
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
|
||||
_v ## major ## _ ## minor ## _ ## patch
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
|
||||
|
||||
#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION
|
||||
#else
|
||||
#define NLOHMANN_JSON_NAMESPACE_VERSION \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
|
||||
NLOHMANN_JSON_VERSION_MINOR, \
|
||||
NLOHMANN_JSON_VERSION_PATCH)
|
||||
#endif
|
||||
|
||||
// Combine namespace components
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
|
||||
#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
|
||||
NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE
|
||||
#define NLOHMANN_JSON_NAMESPACE \
|
||||
nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION)
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
#define NLOHMANN_JSON_NAMESPACE_BEGIN \
|
||||
namespace nlohmann \
|
||||
{ \
|
||||
inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
|
||||
NLOHMANN_JSON_ABI_TAGS, \
|
||||
NLOHMANN_JSON_NAMESPACE_VERSION) \
|
||||
{
|
||||
#endif
|
||||
|
||||
#ifndef NLOHMANN_JSON_NAMESPACE_END
|
||||
#define NLOHMANN_JSON_NAMESPACE_END \
|
||||
} /* namespace (inline namespace) NOLINT(readability/namespace) */ \
|
||||
} // namespace nlohmann
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,3 +1,11 @@
|
|||
// __ _____ _____ _____
|
||||
// __| | __| | | | JSON for Modern C++
|
||||
// | | |__ | | | | | | version 3.11.2
|
||||
// |_____|_____|_____|_|___| https://github.com/nlohmann/json
|
||||
//
|
||||
// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
#define INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
||||
|
@ -7,13 +15,15 @@
|
|||
#include <string> // string
|
||||
#include <vector> // vector
|
||||
|
||||
#include <nlohmann/detail/abi_macros.hpp>
|
||||
|
||||
/*!
|
||||
@brief namespace for Niels Lohmann
|
||||
@see https://github.com/nlohmann
|
||||
@since version 1.0.0
|
||||
*/
|
||||
namespace nlohmann
|
||||
{
|
||||
NLOHMANN_JSON_NAMESPACE_BEGIN
|
||||
|
||||
/*!
|
||||
@brief default JSONSerializer template argument
|
||||
|
||||
|
@ -24,6 +34,8 @@ for serialization.
|
|||
template<typename T = void, typename SFINAE = void>
|
||||
struct adl_serializer;
|
||||
|
||||
/// a class to store JSON values
|
||||
/// @sa https://json.nlohmann.me/api/basic_json/
|
||||
template<template<typename U, typename V, typename... Args> class ObjectType =
|
||||
std::map,
|
||||
template<typename U, typename... Args> class ArrayType = std::vector,
|
||||
|
@ -37,42 +49,26 @@ template<template<typename U, typename V, typename... Args> class ObjectType =
|
|||
class BinaryType = std::vector<std::uint8_t>>
|
||||
class basic_json;
|
||||
|
||||
/*!
|
||||
@brief JSON Pointer
|
||||
|
||||
A JSON pointer defines a string syntax for identifying a specific value
|
||||
within a JSON document. It can be used with functions `at` and
|
||||
`operator[]`. Furthermore, JSON pointers are the base for JSON patches.
|
||||
|
||||
@sa [RFC 6901](https://tools.ietf.org/html/rfc6901)
|
||||
|
||||
@since version 2.0.0
|
||||
*/
|
||||
template<typename BasicJsonType>
|
||||
/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
|
||||
/// @sa https://json.nlohmann.me/api/json_pointer/
|
||||
template<typename RefStringType>
|
||||
class json_pointer;
|
||||
|
||||
/*!
|
||||
@brief default JSON class
|
||||
|
||||
This type is the default specialization of the @ref basic_json class which
|
||||
uses the standard template types.
|
||||
|
||||
@since version 1.0.0
|
||||
@brief default specialization
|
||||
@sa https://json.nlohmann.me/api/json/
|
||||
*/
|
||||
using json = basic_json<>;
|
||||
|
||||
/// @brief a minimal map-like container that preserves insertion order
|
||||
/// @sa https://json.nlohmann.me/api/ordered_map/
|
||||
template<class Key, class T, class IgnoredLess, class Allocator>
|
||||
struct ordered_map;
|
||||
|
||||
/*!
|
||||
@brief ordered JSON class
|
||||
|
||||
This type preserves the insertion order of object keys.
|
||||
|
||||
@since version 3.9.0
|
||||
*/
|
||||
/// @brief specialization that maintains the insertion order of object keys
|
||||
/// @sa https://json.nlohmann.me/api/ordered_json/
|
||||
using ordered_json = basic_json<nlohmann::ordered_map>;
|
||||
|
||||
} // namespace nlohmann
|
||||
NLOHMANN_JSON_NAMESPACE_END
|
||||
|
||||
#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
|
||||
|
|
Loading…
Reference in New Issue