Commit 1062f0a4 authored by Milo Yip's avatar Milo Yip

Add allOf in schema

parent c2649a36
......@@ -56,17 +56,61 @@ enum SchemaType {
template <typename Encoding>
class BaseSchema;
template <typename Encoding, typename ValueType>
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value, const ValueType& type);
template <typename Encoding, typename ValueType>
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value);
template <typename Encoding>
class ISchemaValidator {
public:
typedef typename Encoding::Ch Ch;
virtual ~ISchemaValidator() {};
virtual bool Null() = 0;
virtual bool Bool(bool) = 0;
virtual bool Int(int) = 0;
virtual bool Uint(unsigned) = 0;
virtual bool Int64(int64_t) = 0;
virtual bool Uint64(uint64_t) = 0;
virtual bool Double(double) = 0;
virtual bool String(const Ch*, SizeType, bool) = 0;
virtual bool StartObject() = 0;
virtual bool Key(const Ch*, SizeType, bool) = 0;
virtual bool EndObject(SizeType) = 0;
virtual bool StartArray() = 0;
virtual bool EndArray(SizeType) = 0;
};
template <typename Encoding>
class ISchemaValidatorFactory {
public:
virtual ISchemaValidator<Encoding>* CreateSchemaValidator(const BaseSchema<Encoding>& root) = 0;
};
template <typename Encoding>
struct SchemaValidationContext {
SchemaValidationContext(const BaseSchema<Encoding>* s) : schema(s), valueSchema(), multiTypeSchema(), objectDependencies() {}
SchemaValidationContext(ISchemaValidatorFactory<Encoding>* factory, const BaseSchema<Encoding>* s) :
schemaValidatorFactory(factory), schema(s), valueSchema(), multiTypeSchema(), allOfValidators(), objectDependencies()
{
}
~SchemaValidationContext() {
if (allOfValidators) {
for (SizeType i = 0; i < allOfValidatorCount; i++)
delete allOfValidators[i];
delete[] allOfValidators;
}
delete[] objectDependencies;
}
ISchemaValidatorFactory<Encoding>* schemaValidatorFactory;
const BaseSchema<Encoding>* schema;
const BaseSchema<Encoding>* valueSchema;
const BaseSchema<Encoding>* multiTypeSchema;
ISchemaValidator<Encoding>** allOfValidators;
SizeType allOfValidatorCount;
SizeType objectRequiredCount;
SizeType arrayElementIndex;
bool* objectDependencies;
......@@ -78,10 +122,11 @@ public:
typedef typename Encoding::Ch Ch;
typedef SchemaValidationContext<Encoding> Context;
BaseSchema() {}
BaseSchema() : allOf_(), allOfCount_() {
}
template <typename ValueType>
BaseSchema(const ValueType& value) {
BaseSchema(const ValueType& value) : allOf_(), allOfCount_() {
typename ValueType::ConstMemberIterator enumItr = value.FindMember("enum");
if (enumItr != value.MemberEnd()) {
if (enumItr->value.IsArray() && enumItr->value.Size() > 0)
......@@ -90,28 +135,66 @@ public:
// Error
}
}
typename ValueType::ConstMemberIterator allOfItr = value.FindMember("allOf");
if (allOfItr != value.MemberEnd()) {
const Value& allOf = allOfItr->value;
if (allOf.IsArray() && allOf.Size() > 0) {
allOfCount_ = allOf.Size();
allOf_ = new BaseSchema*[allOfCount_];
memset(allOf_, 0, sizeof(BaseSchema*) * allOfCount_);
for (SizeType i = 0; i < allOfCount_; i++)
allOf_[i] = CreateSchema<Encoding>(allOf[i]);
}
else {
// Error
}
}
}
virtual ~BaseSchema() {}
virtual ~BaseSchema() {
if (allOf_) {
for (SizeType i = 0; i < allOfCount_; i++)
delete allOf_[i];
delete [] allOf_;
}
}
virtual SchemaType GetSchemaType() const = 0;
virtual bool HandleMultiType(Context&, SchemaType) const { return true; }
virtual bool BeginValue(Context&) const { return true; }
virtual bool Null() const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>().Move()); }
virtual bool Bool(bool b) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(b).Move()); }
virtual bool Int(int i) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(i).Move()); }
virtual bool Uint(unsigned u) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(u).Move()); }
virtual bool Int64(int64_t i) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(i).Move()); }
virtual bool Uint64(uint64_t u) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(u).Move()); }
virtual bool Double(double d) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(d).Move()); }
virtual bool String(const Ch* s, SizeType length, bool) const { return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(s, length).Move()); }
virtual bool StartObject(Context&) const { return true; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return true; }
virtual bool EndObject(Context&, SizeType) const { return true; }
virtual bool StartArray(Context&) const { return true; }
virtual bool EndArray(Context&, SizeType) const { return true; }
#define RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, method_call)\
if (allOf_) {\
CreateAllOfSchemaValidators(context);\
for (SizeType i = 0; i < allOfCount_; i++)\
if (!context.allOfValidators[i]->method_call)\
return false;\
}\
return true
#define RAPIDJSON_BASESCHEMA_HANDLER_(context, arg, method_call)\
if (enum_.IsArray() && !CheckEnum(GenericValue<Encoding> arg .Move()))\
return false;\
RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, method_call);
virtual bool Null(Context& context) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (), Null()); }
virtual bool Bool(Context& context, bool b) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (b), Bool(b)); }
virtual bool Int(Context& context, int i) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (i), Int(i)); }
virtual bool Uint(Context& context, unsigned u) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (u), Uint(u)); }
virtual bool Int64(Context& context, int64_t i) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (i), Int64(i)); }
virtual bool Uint64(Context& context, uint64_t u) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (u), Int(i)); }
virtual bool Double(Context& context, double d) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (d), Double(d)); }
virtual bool String(Context& context, const Ch* s, SizeType length, bool copy) const { RAPIDJSON_BASESCHEMA_HANDLER_(context, (s, length), String(s, length, copy)); }
virtual bool StartObject(Context& context) const { RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, StartObject()); }
virtual bool Key(Context& context, const Ch* s, SizeType length, bool copy) const { RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, Key(s, length, copy)); }
virtual bool EndObject(Context& context, SizeType memberCount) const { RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, EndObject(memberCount)); }
virtual bool StartArray(Context& context) const { RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, StartArray()); }
virtual bool EndArray(Context& context, SizeType elementCount) const { RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_(context, EndArray(elementCount)); }
#undef RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_
#undef RAPIDJSON_BASESCHEMA_HANDLER_
protected:
bool CheckEnum(const GenericValue<Encoding>& v) const {
......@@ -121,16 +204,21 @@ protected:
return false;
}
void CreateAllOfSchemaValidators(Context& context) const {
if (!context.allOfValidators) {
context.allOfValidators = new ISchemaValidator<Encoding>*[allOfCount_];
context.allOfValidatorCount = allOfCount_;
for (SizeType i = 0; i < allOfCount_; i++)
context.allOfValidators[i] = context.schemaValidatorFactory->CreateSchemaValidator(*allOf_[i]);
}
}
MemoryPoolAllocator<> allocator_;
GenericValue<Encoding> enum_;
BaseSchema<Encoding>** allOf_;
SizeType allOfCount_;
};
template <typename Encoding, typename ValueType>
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value, const ValueType& type);
template <typename Encoding, typename ValueType>
inline BaseSchema<Encoding>* CreateSchema(const ValueType& value);
template <typename Encoding>
class TypelessSchema : public BaseSchema<Encoding> {
public:
......@@ -207,14 +295,14 @@ public:
virtual SchemaType GetSchemaType() const { return kNullSchemaType; }
virtual bool Null() const { return BaseSchema<Encoding>::Null(); }
virtual bool Bool(bool) const { return false; }
virtual bool Int(int) const { return false; }
virtual bool Uint(unsigned) const { return false; }
virtual bool Int64(int64_t) const { return false; }
virtual bool Uint64(uint64_t) const { return false; }
virtual bool Double(double) const { return false; }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool Null(Context& context) const { return BaseSchema<Encoding>::Null(context); }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(Context&, int) const { return false; }
virtual bool Uint(Context&, unsigned) const { return false; }
virtual bool Int64(Context&, int64_t) const { return false; }
virtual bool Uint64(Context&, uint64_t) const { return false; }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context&) const { return false; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool EndObject(Context&, SizeType) const { return false; }
......@@ -233,14 +321,14 @@ public:
virtual SchemaType GetSchemaType() const { return kBooleanSchemaType; }
virtual bool Null() const { return false; }
virtual bool Bool(bool b) const { return BaseSchema<Encoding>::Bool(b); }
virtual bool Int(int) const { return false; }
virtual bool Uint(unsigned) const { return false; }
virtual bool Int64(int64_t) const { return false; }
virtual bool Uint64(uint64_t) const { return false; }
virtual bool Double(double) const { return false; }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context& context, bool b) const { return BaseSchema<Encoding>::Bool(context, b); }
virtual bool Int(Context&, int) const { return false; }
virtual bool Uint(Context&, unsigned) const { return false; }
virtual bool Int64(Context&, int64_t) const { return false; }
virtual bool Uint64(Context&, uint64_t) const { return false; }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context&) const { return false; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool EndObject(Context&, SizeType) const { return false; }
......@@ -408,16 +496,19 @@ public:
virtual SchemaType GetSchemaType() const { return kObjectSchemaType; }
virtual bool Null() const { return false; }
virtual bool Bool(bool) const { return false; }
virtual bool Int(int) const { return false; }
virtual bool Uint(unsigned) const { return false; }
virtual bool Int64(int64_t) const { return false; }
virtual bool Uint64(uint64_t) const { return false; }
virtual bool Double(double) const { return false; }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(Context&, int) const { return false; }
virtual bool Uint(Context&, unsigned) const { return false; }
virtual bool Int64(Context&, int64_t) const { return false; }
virtual bool Uint64(Context&, uint64_t) const { return false; }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context& context) const {
if (!BaseSchema<Encoding>::StartObject(context))
return false;
context.objectRequiredCount = 0;
if (hasDependencies_) {
context.objectDependencies = new bool[propertyCount_];
......@@ -426,7 +517,10 @@ public:
return true;
}
virtual bool Key(Context& context, const Ch* str, SizeType len, bool) const {
virtual bool Key(Context& context, const Ch* str, SizeType len, bool copy) const {
if (!BaseSchema<Encoding>::Key(context, str, len, copy))
return false;
SizeType index;
if (FindPropertyIndex(str, len, &index)) {
context.valueSchema = properties_[index].schema;
......@@ -469,6 +563,9 @@ public:
}
virtual bool EndObject(Context& context, SizeType memberCount) const {
if (!BaseSchema<Encoding>::EndObject(context, memberCount))
return false;
if (context.objectRequiredCount != requiredCount_ || memberCount < minProperties_ || memberCount > maxProperties_)
return false;
......@@ -643,24 +740,30 @@ public:
return true;
}
virtual bool Null() const { return false; }
virtual bool Bool(bool) const { return false; }
virtual bool Int(int) const { return false; }
virtual bool Uint(unsigned) const { return false; }
virtual bool Int64(int64_t) const { return false; }
virtual bool Uint64(uint64_t) const { return false; }
virtual bool Double(double) const { return false; }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(Context&, int) const { return false; }
virtual bool Uint(Context&, unsigned) const { return false; }
virtual bool Int64(Context&, int64_t) const { return false; }
virtual bool Uint64(Context&, uint64_t) const { return false; }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context&) const { return false; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool EndObject(Context&, SizeType) const { return false; }
virtual bool StartArray(Context& context) const {
if (!BaseSchema<Encoding>::StartArray(context))
return false;
context.arrayElementIndex = 0;
return true;
}
virtual bool EndArray(Context&, SizeType elementCount) const {
virtual bool EndArray(Context& context, SizeType elementCount) const {
if (!BaseSchema<Encoding>::EndArray(context, elementCount))
return false;
return elementCount >= minItems_ && elementCount <= maxItems_;
}
......@@ -738,17 +841,18 @@ public:
virtual SchemaType GetSchemaType() const { return kStringSchemaType; }
virtual bool Null() const { return false; }
virtual bool Bool(bool) const { return false; }
virtual bool Int(int) const { return false; }
virtual bool Uint(unsigned) const { return false; }
virtual bool Int64(int64_t) const { return false; }
virtual bool Uint64(uint64_t) const { return false; }
virtual bool Double(double) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(Context&, int) const { return false; }
virtual bool Uint(Context&, unsigned) const { return false; }
virtual bool Int64(Context&, int64_t) const { return false; }
virtual bool Uint64(Context&, uint64_t) const { return false; }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(const Ch* str, SizeType length, bool copy) const {
if (!BaseSchema<Encoding>::String(str, length, copy))
virtual bool String(Context& context, const Ch* str, SizeType length, bool copy) const {
if (!BaseSchema<Encoding>::String(context, str, length, copy))
return false;
if (length < minLength_ || length > maxLength_)
return false;
......@@ -844,16 +948,14 @@ public:
virtual SchemaType GetSchemaType() const { return kIntegerSchemaType; }
virtual bool Null() const { return false; }
virtual bool Bool(bool) const { return false; }
virtual bool Int(int i) const { return BaseSchema<Encoding>::Int64(i) && Int64(i); }
virtual bool Uint(unsigned u) const { return BaseSchema<Encoding>::Uint64(u) && Uint64(u); }
virtual bool Int64(int64_t i) const { return BaseSchema<Encoding>::Int64(i) && CheckInt64(i); }
virtual bool Uint64(uint64_t u) const { return BaseSchema<Encoding>::Uint64(u) && CheckUint64(u); }
virtual bool Double(double) const { return false; }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(Context& context, int i) const { return BaseSchema<Encoding>::Int64(context, i) && CheckInt64(i); }
virtual bool Uint(Context& context, unsigned u) const { return BaseSchema<Encoding>::Uint64(context, u) && CheckUint64(u); }
virtual bool Int64(Context& context, int64_t i) const { return BaseSchema<Encoding>::Int64(context, i) && CheckInt64(i); }
virtual bool Uint64(Context& context, uint64_t u) const { return BaseSchema<Encoding>::Uint64(context, u) && CheckUint64(u); }
virtual bool Double(Context&, double) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context&) const { return false; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool EndObject(Context&, SizeType) const { return false; }
......@@ -991,16 +1093,16 @@ public:
virtual SchemaType GetSchemaType() const { return kNumberSchemaType; }
virtual bool Null() const { return false; }
virtual bool Bool(bool) const { return false; }
virtual bool Null(Context&) const { return false; }
virtual bool Bool(Context&, bool) const { return false; }
virtual bool Int(int i) const { return BaseSchema<Encoding>::Int(i) && CheckDouble(i); }
virtual bool Uint(unsigned u) const { return BaseSchema<Encoding>::Uint(u) && CheckDouble(u); }
virtual bool Int64(int64_t i) const { return BaseSchema<Encoding>::Int64(i) && CheckDouble(i); }
virtual bool Uint64(uint64_t u) const { return BaseSchema<Encoding>::Uint64(u) && CheckDouble(u); }
virtual bool Double(double d) const { return BaseSchema<Encoding>::Double(d) && CheckDouble(d); }
virtual bool Int(Context& context, int i) const { return BaseSchema<Encoding>::Int(context, i) && CheckDouble(i); }
virtual bool Uint(Context& context, unsigned u) const { return BaseSchema<Encoding>::Uint(context, u) && CheckDouble(u); }
virtual bool Int64(Context& context, int64_t i) const { return BaseSchema<Encoding>::Int64(context, i) && CheckDouble(i); }
virtual bool Uint64(Context& context, uint64_t u) const { return BaseSchema<Encoding>::Uint64(context, u) && CheckDouble(u); }
virtual bool Double(Context& context, double d) const { return BaseSchema<Encoding>::Double(context, d) && CheckDouble(d); }
virtual bool String(const Ch*, SizeType, bool) const { return false; }
virtual bool String(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool StartObject(Context&) const { return false; }
virtual bool Key(Context&, const Ch*, SizeType, bool) const { return false; }
virtual bool EndObject(Context&, SizeType) const { return false; }
......@@ -1071,7 +1173,7 @@ private:
typedef GenericSchema<UTF8<> > Schema;
template <typename Encoding, typename OutputHandler = BaseReaderHandler<Encoding>, typename Allocator = CrtAllocator >
class GenericSchemaValidator {
class GenericSchemaValidator : public ISchemaValidator<Encoding>, public ISchemaValidatorFactory<Encoding> {
public:
typedef typename Encoding::Ch Ch; //!< Character type derived from Encoding.
typedef GenericSchema<Encoding> SchemaT;
......@@ -1079,13 +1181,13 @@ public:
GenericSchemaValidator(
const SchemaT& schema,
Allocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
size_t schemaStackCapacity = kDefaultSchemaStackCapacity/*,
size_t documentStackCapacity = kDefaultDocumentStackCapacity*/)
:
schema_(schema),
root_(*schema.root_),
outputHandler_(nullOutputHandler_),
schemaStack_(allocator, schemaStackCapacity),
documentStack_(allocator, documentStackCapacity)
schemaStack_(allocator, schemaStackCapacity)
// ,documentStack_(allocator, documentStackCapacity)
{
}
......@@ -1093,13 +1195,13 @@ public:
const SchemaT& schema,
OutputHandler& outputHandler,
Allocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
size_t documentStackCapacity = kDefaultDocumentStackCapacity)
size_t schemaStackCapacity = kDefaultSchemaStackCapacity/*,
size_t documentStackCapacity = kDefaultDocumentStackCapacity*/)
:
schema_(schema),
root_(*schema.root_),
outputHandler_(outputHandler),
schemaStack_(allocator, schemaStackCapacity),
documentStack_(allocator, documentStackCapacity)
schemaStack_(allocator, schemaStackCapacity)
// , documentStack_(allocator, documentStackCapacity)
{
}
......@@ -1110,32 +1212,49 @@ public:
void Reset() {
while (!schemaStack_.Empty())
PopSchema();
documentStack_.Clear();
//documentStack_.Clear();
};
bool Null() { return BeginValue(kNullSchemaType) && CurrentSchema().Null() && EndValue() && outputHandler_.Null(); }
bool Bool(bool b) { return BeginValue(kBooleanSchemaType) && CurrentSchema().Bool(b) && EndValue() && outputHandler_.Bool(b); }
bool Int(int i) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int(i) && EndValue() && outputHandler_.Int(i); }
bool Uint(unsigned u) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint(u) && EndValue() && outputHandler_.Uint(u); }
bool Int64(int64_t i64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int64(i64) && EndValue() && outputHandler_.Int64(i64); }
bool Uint64(uint64_t u64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint64(u64) && EndValue() && outputHandler_.Uint64(u64); }
bool Double(double d) { return BeginValue(kNumberSchemaType) && CurrentSchema().Double(d) && EndValue() && outputHandler_.Double(d); }
bool String(const Ch* str, SizeType length, bool copy) { return BeginValue(kStringSchemaType) && CurrentSchema().String(str, length, copy) && EndValue() && outputHandler_.String(str, length, copy); }
bool StartObject() { return BeginValue(kObjectSchemaType) && CurrentSchema().StartObject(CurrentContext()) && outputHandler_.StartObject(); }
bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) && outputHandler_.Key(str, len, copy); }
bool EndObject(SizeType memberCount) { return CurrentSchema().EndObject(CurrentContext(), memberCount) && EndValue() && outputHandler_.EndObject(memberCount); }
bool StartArray() { return BeginValue(kArraySchemaType) && CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray() : false; }
bool EndArray(SizeType elementCount) { return CurrentSchema().EndArray(CurrentContext(), elementCount) && EndValue() && outputHandler_.EndArray(elementCount); }
// Implementation of ISchemaValidator<Encoding>
virtual bool Null() { return BeginValue(kNullSchemaType) && CurrentSchema().Null (CurrentContext() ) && EndValue() && outputHandler_.Null ( ); }
virtual bool Bool(bool b) { return BeginValue(kBooleanSchemaType) && CurrentSchema().Bool (CurrentContext(), b ) && EndValue() && outputHandler_.Bool (b ); }
virtual bool Int(int i) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int (CurrentContext(), i ) && EndValue() && outputHandler_.Int (i ); }
virtual bool Uint(unsigned u) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint (CurrentContext(), u ) && EndValue() && outputHandler_.Uint (u ); }
virtual bool Int64(int64_t i64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Int64 (CurrentContext(), i64) && EndValue() && outputHandler_.Int64 (i64); }
virtual bool Uint64(uint64_t u64) { return BeginValue(kIntegerSchemaType) && CurrentSchema().Uint64(CurrentContext(), u64) && EndValue() && outputHandler_.Uint64(u64); }
virtual bool Double(double d) { return BeginValue(kNumberSchemaType) && CurrentSchema().Double(CurrentContext(), d ) && EndValue() && outputHandler_.Double( d); }
virtual bool String(const Ch* str, SizeType length, bool copy) { return BeginValue(kStringSchemaType) && CurrentSchema().String(CurrentContext(), str, length, copy) && EndValue() && outputHandler_.String(str, length, copy); }
virtual bool StartObject() { return BeginValue(kObjectSchemaType) && CurrentSchema().StartObject(CurrentContext()) && outputHandler_.StartObject(); }
virtual bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) && outputHandler_.Key(str, len, copy); }
virtual bool EndObject(SizeType memberCount) { return CurrentSchema().EndObject(CurrentContext(), memberCount) && EndValue() && outputHandler_.EndObject(memberCount); }
virtual bool StartArray() { return BeginValue(kArraySchemaType) && CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray() : false; }
virtual bool EndArray(SizeType elementCount) { return CurrentSchema().EndArray(CurrentContext(), elementCount) && EndValue() && outputHandler_.EndArray(elementCount); }
// Implementation of ISchemaValidatorFactory<Encoding>
virtual ISchemaValidator<Encoding>* CreateSchemaValidator(const BaseSchema<Encoding>& root) {
return new GenericSchemaValidator(root);
}
private:
typedef BaseSchema<Encoding> BaseSchemaType;
typedef typename BaseSchemaType::Context Context;
GenericSchemaValidator(
const BaseSchemaType& root,
Allocator* allocator = 0,
size_t schemaStackCapacity = kDefaultSchemaStackCapacity/*,
size_t documentStackCapacity = kDefaultDocumentStackCapacity*/)
:
root_(root),
outputHandler_(nullOutputHandler_),
schemaStack_(allocator, schemaStackCapacity)
// , documentStack_(allocator, documentStackCapacity)
{
}
bool BeginValue(SchemaType schemaType) {
if (schemaStack_.Empty())
PushSchema(*schema_.root_);
PushSchema(root_);
else {
if (!CurrentSchema().BeginValue(CurrentContext()))
return false;
......@@ -1160,18 +1279,18 @@ private:
return true;
}
void PushSchema(const BaseSchemaType& schema) { *schemaStack_.template Push<Context>() = Context(&schema); }
void PushSchema(const BaseSchemaType& schema) { *schemaStack_.template Push<Context>() = Context(this, &schema); }
void PopSchema() { schemaStack_.template Pop<Context>(1)->~Context(); }
const BaseSchemaType& CurrentSchema() { return *schemaStack_.template Top<Context>()->schema; }
Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
static const size_t kDefaultSchemaStackCapacity = 256;
static const size_t kDefaultDocumentStackCapacity = 256;
const SchemaT& schema_;
//static const size_t kDefaultDocumentStackCapacity = 256;
const BaseSchemaType& root_;
BaseReaderHandler<Encoding> nullOutputHandler_;
OutputHandler& outputHandler_;
internal::Stack<Allocator> schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *)
internal::Stack<Allocator> documentStack_; //!< stack to store the current path of validating document (Value *)
//internal::Stack<Allocator> documentStack_; //!< stack to store the current path of validating document (Value *)
};
typedef GenericSchemaValidator<UTF8<> > SchemaValidator;
......
......@@ -539,3 +539,34 @@ TEST(SchemaValidator, MultiTypeWithObject) {
VALIDATE(s, "{ \"tel\": \"fail\" }", false);
}
TEST(SchemaValidator, AllOf) {
Document sd;
sd.Parse("{\"allOf\": [{ \"type\": \"string\", \"minLength\": 2 }, { \"type\": \"string\", \"maxLength\": 5 }]}");
Schema s(sd);
VALIDATE(s, "\"ok\"", true);
VALIDATE(s, "\"n\"", false);
VALIDATE(s, "\"too long\"", false);
VALIDATE(s, "123", false);
}
TEST(SchemaValidator, AllOf_Nested) {
Document sd;
sd.Parse(
"{"
" \"allOf\": ["
" { \"type\": \"string\", \"minLength\": 2 },"
" { \"type\": \"string\", \"maxLength\": 5 },"
" { \"allOf\": [ { \"enum\" : [\"ok\", \"okay\", \"OK\", \"o\"] }, { \"enum\" : [\"ok\", \"OK\", \"o\"]} ] }"
" ]"
"}");
Schema s(sd);
VALIDATE(s, "\"ok\"", true);
VALIDATE(s, "\"OK\"", true);
VALIDATE(s, "\"okay\"", false);
VALIDATE(s, "\"o\"", false);
VALIDATE(s, "\"n\"", false);
VALIDATE(s, "\"too long\"", false);
VALIDATE(s, "123", false);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment