/*
- * Copyright 2015 Facebook, Inc.
+ * Copyright 2017 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include <folly/Conv.h>
#include <folly/Memory.h>
#include <folly/Optional.h>
-#include <folly/String.h>
#include <folly/Singleton.h>
+#include <folly/String.h>
#include <folly/json.h>
namespace folly {
struct ValidationContext;
struct IValidator {
- virtual ~IValidator() {}
+ virtual ~IValidator() = default;
private:
friend struct ValidationContext;
explicit SchemaValidatorContext(const dynamic& s) : schema(s) {}
const dynamic& schema;
- std::unordered_map<fbstring, IValidator*> refs;
+ std::unordered_map<std::string, IValidator*> refs;
};
/**
* Root validator for a schema.
*/
struct SchemaValidator final : IValidator, public Validator {
- SchemaValidator() {}
+ SchemaValidator() = default;
void loadSchema(SchemaValidatorContext& context, const dynamic& schema);
Optional<SchemaError> validate(ValidationContext&,
// We break apart the constructor and actually loading the schema so that
// we can handle the case where a schema refers to itself, e.g. via
// "$ref": "#".
- auto v = make_unique<SchemaValidator>();
+ auto v = std::make_unique<SchemaValidator>();
v->loadSchema(context, schema);
return v;
}
if (type_ == Type::MIN) {
if (exclusive_) {
if (v <= s) {
- return makeError("greater than", schema_, value);
+ return makeError("greater than ", schema_, value);
}
} else {
if (v < s) {
- return makeError("greater than or equal to", schema_, value);
+ return makeError("greater than or equal to ", schema_, value);
}
}
} else if (type_ == Type::MAX) {
if (exclusive_) {
if (v >= s) {
- return makeError("less than", schema_, value);
+ return makeError("less than ", schema_, value);
}
} else {
if (v > s) {
- return makeError("less than or equal to", schema_, value);
+ return makeError("less than or equal to ", schema_, value);
}
}
}
if (value.type() != type_) {
return none;
}
- if (!Comparison()(length_, value.size())) {
+ if (!Comparison()(length_, int64_t(value.size()))) {
return makeError("different length string/array/object", value);
}
return none;
struct StringPatternValidator final : IValidator {
explicit StringPatternValidator(const dynamic& schema) {
if (schema.isString()) {
- regex_ = boost::regex(schema.getString().toStdString());
+ regex_ = boost::regex(schema.getString());
}
}
if (!value.isString() || regex_.empty()) {
return none;
}
- if (!boost::regex_search(value.getString().toStdString(), regex_)) {
+ if (!boost::regex_search(value.getString(), regex_)) {
return makeError("string matching regex", value);
}
return none;
if (value.isObject()) {
for (const auto& prop : properties_) {
if (!value.get_ptr(prop)) {
- return makeError("to have property", prop, value);
+ return makeError("property ", prop, value);
}
}
}
}
private:
- std::vector<fbstring> properties_;
+ std::vector<std::string> properties_;
};
struct PropertiesValidator final : IValidator {
for (const auto& pair : patternProperties->items()) {
if (pair.first.isString()) {
patternPropertyValidators_.emplace_back(
- boost::regex(pair.first.getString().toStdString()),
+ boost::regex(pair.first.getString()),
SchemaValidator::make(context, pair.second));
}
}
if (!pair.first.isString()) {
continue;
}
- const fbstring& key = pair.first.getString();
+ const std::string& key = pair.first.getString();
auto it = propertyValidators_.find(key);
bool matched = false;
if (it != propertyValidators_.end()) {
matched = true;
}
- const std::string& strkey = key.toStdString();
+ const std::string& strkey = key;
for (const auto& ppv : patternPropertyValidators_) {
if (boost::regex_search(strkey, ppv.first)) {
if (auto se = vc.validate(ppv.second.get(), pair.second)) {
return none;
}
- std::unordered_map<fbstring, std::unique_ptr<IValidator>> propertyValidators_;
+ std::unordered_map<std::string, std::unique_ptr<IValidator>>
+ propertyValidators_;
std::vector<std::pair<boost::regex, std::unique_ptr<IValidator>>>
patternPropertyValidators_;
std::unique_ptr<IValidator> additionalPropertyValidator_;
continue;
}
if (pair.second.isArray()) {
- auto p = make_pair(pair.first.getString(), std::vector<fbstring>());
+ auto p = make_pair(pair.first.getString(), std::vector<std::string>());
for (const auto& item : pair.second) {
if (item.isString()) {
p.second.push_back(item.getString());
if (value.count(pair.first)) {
for (const auto& prop : pair.second) {
if (!value.count(prop)) {
- return makeError("property", prop, value);
+ return makeError("property ", prop, value);
}
}
}
return none;
}
- std::vector<std::pair<fbstring, std::vector<fbstring>>> propertyDep_;
- std::vector<std::pair<fbstring, std::unique_ptr<IValidator>>> schemaDep_;
+ std::vector<std::pair<std::string, std::vector<std::string>>> propertyDep_;
+ std::vector<std::pair<std::string, std::unique_ptr<IValidator>>> schemaDep_;
};
struct EnumValidator final : IValidator {
errors.emplace_back(*se);
}
}
- const int success = validators_.size() - errors.size();
+ const auto success = validators_.size() - errors.size();
if (success == 0) {
return makeError("at least one valid schema", value);
} else if (success > 1 && type_ == Type::EXACTLY_ONE) {
if (p->isString() && p->stringPiece()[0] == '#') {
auto it = context.refs.find(p->getString());
if (it != context.refs.end()) {
- validators_.emplace_back(make_unique<RefValidator>(it->second));
+ validators_.emplace_back(std::make_unique<RefValidator>(it->second));
return;
}
s = s->get_ptr(pos);
continue;
}
- } catch (const std::range_error& e) {
+ } catch (const std::range_error&) {
// ignore
}
}
// future references to it will just see that pointer and won't try to
// keep parsing further.
if (s) {
- auto v = make_unique<SchemaValidator>();
+ auto v = std::make_unique<SchemaValidator>();
context.refs[p->getString()] = v.get();
v->loadSchema(context, *s);
validators_.emplace_back(std::move(v));
// Numeric validators
if (const auto* p = schema.get_ptr("multipleOf")) {
- validators_.emplace_back(make_unique<MultipleOfValidator>(*p));
+ validators_.emplace_back(std::make_unique<MultipleOfValidator>(*p));
}
if (const auto* p = schema.get_ptr("maximum")) {
- validators_.emplace_back(
- make_unique<ComparisonValidator>(*p,
- schema.get_ptr("exclusiveMaximum"),
- ComparisonValidator::Type::MAX));
+ validators_.emplace_back(std::make_unique<ComparisonValidator>(
+ *p,
+ schema.get_ptr("exclusiveMaximum"),
+ ComparisonValidator::Type::MAX));
}
if (const auto* p = schema.get_ptr("minimum")) {
- validators_.emplace_back(
- make_unique<ComparisonValidator>(*p,
- schema.get_ptr("exclusiveMinimum"),
- ComparisonValidator::Type::MIN));
+ validators_.emplace_back(std::make_unique<ComparisonValidator>(
+ *p,
+ schema.get_ptr("exclusiveMinimum"),
+ ComparisonValidator::Type::MIN));
}
// String validators
if (const auto* p = schema.get_ptr("maxLength")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::greater_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::greater_equal<int64_t>>>(
*p, dynamic::Type::STRING));
}
if (const auto* p = schema.get_ptr("minLength")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::less_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::less_equal<int64_t>>>(
*p, dynamic::Type::STRING));
}
if (const auto* p = schema.get_ptr("pattern")) {
- validators_.emplace_back(make_unique<StringPatternValidator>(*p));
+ validators_.emplace_back(std::make_unique<StringPatternValidator>(*p));
}
// Array validators
const auto* additionalItems = schema.get_ptr("additionalItems");
if (items || additionalItems) {
validators_.emplace_back(
- make_unique<ArrayItemsValidator>(context, items, additionalItems));
+ std::make_unique<ArrayItemsValidator>(context, items, additionalItems));
}
if (const auto* p = schema.get_ptr("maxItems")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::greater_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::greater_equal<int64_t>>>(
*p, dynamic::Type::ARRAY));
}
if (const auto* p = schema.get_ptr("minItems")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::less_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::less_equal<int64_t>>>(
*p, dynamic::Type::ARRAY));
}
if (const auto* p = schema.get_ptr("uniqueItems")) {
- validators_.emplace_back(make_unique<ArrayUniqueValidator>(*p));
+ validators_.emplace_back(std::make_unique<ArrayUniqueValidator>(*p));
}
// Object validators
const auto* patternProperties = schema.get_ptr("patternProperties");
const auto* additionalProperties = schema.get_ptr("additionalProperties");
if (properties || patternProperties || additionalProperties) {
- validators_.emplace_back(make_unique<PropertiesValidator>(
+ validators_.emplace_back(std::make_unique<PropertiesValidator>(
context, properties, patternProperties, additionalProperties));
}
if (const auto* p = schema.get_ptr("maxProperties")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::greater_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::greater_equal<int64_t>>>(
*p, dynamic::Type::OBJECT));
}
if (const auto* p = schema.get_ptr("minProperties")) {
validators_.emplace_back(
- make_unique<SizeValidator<std::less_equal<int64_t>>>(
+ std::make_unique<SizeValidator<std::less_equal<int64_t>>>(
*p, dynamic::Type::OBJECT));
}
if (const auto* p = schema.get_ptr("required")) {
- validators_.emplace_back(make_unique<RequiredValidator>(*p));
+ validators_.emplace_back(std::make_unique<RequiredValidator>(*p));
}
// Misc validators
if (const auto* p = schema.get_ptr("dependencies")) {
- validators_.emplace_back(make_unique<DependencyValidator>(context, *p));
+ validators_.emplace_back(
+ std::make_unique<DependencyValidator>(context, *p));
}
if (const auto* p = schema.get_ptr("enum")) {
- validators_.emplace_back(make_unique<EnumValidator>(*p));
+ validators_.emplace_back(std::make_unique<EnumValidator>(*p));
}
if (const auto* p = schema.get_ptr("type")) {
- validators_.emplace_back(make_unique<TypeValidator>(*p));
+ validators_.emplace_back(std::make_unique<TypeValidator>(*p));
}
if (const auto* p = schema.get_ptr("allOf")) {
- validators_.emplace_back(make_unique<AllOfValidator>(context, *p));
+ validators_.emplace_back(std::make_unique<AllOfValidator>(context, *p));
}
if (const auto* p = schema.get_ptr("anyOf")) {
- validators_.emplace_back(make_unique<AnyOfValidator>(
+ validators_.emplace_back(std::make_unique<AnyOfValidator>(
context, *p, AnyOfValidator::Type::ONE_OR_MORE));
}
if (const auto* p = schema.get_ptr("oneOf")) {
- validators_.emplace_back(make_unique<AnyOfValidator>(
+ validators_.emplace_back(std::make_unique<AnyOfValidator>(
context, *p, AnyOfValidator::Type::EXACTLY_ONE));
}
if (const auto* p = schema.get_ptr("not")) {
- validators_.emplace_back(make_unique<NotValidator>(context, *p));
+ validators_.emplace_back(std::make_unique<NotValidator>(context, *p));
}
}
folly::Singleton<Validator> schemaValidator([]() {
return makeValidator(parseJson(metaschemaJson)).release();
});
-}
+} // namespace
-Validator::~Validator() {}
+Validator::~Validator() = default;
std::unique_ptr<Validator> makeValidator(const dynamic& schema) {
- auto v = make_unique<SchemaValidator>();
+ auto v = std::make_unique<SchemaValidator>();
SchemaValidatorContext context(schema);
context.refs["#"] = v.get();
v->loadSchema(context, schema);
return std::move(v);
}
-Validator* makeSchemaValidator() { return schemaValidator.get(); }
-}
+std::shared_ptr<Validator> makeSchemaValidator() {
+ return schemaValidator.try_get();
}
+} // namespace jsonschema
+} // namespace folly