Implement additionalItems
This commit is contained in:
parent
33b5c59e5d
commit
05ae593583
@ -64,7 +64,7 @@ public:
|
|||||||
|
|
||||||
virtual ~BaseSchema() {}
|
virtual ~BaseSchema() {}
|
||||||
|
|
||||||
virtual void BeginValue(Context&) const {}
|
virtual bool BeginValue(Context&) const { return true; }
|
||||||
|
|
||||||
virtual bool Null() const { return enum_.IsArray() ? CheckEnum(GenericValue<Encoding>().Move()) : true; }
|
virtual bool Null() const { return enum_.IsArray() ? CheckEnum(GenericValue<Encoding>().Move()) : true; }
|
||||||
virtual bool Bool(bool b) const { return enum_.IsArray() ? CheckEnum(GenericValue<Encoding>(b).Move()) : true; }
|
virtual bool Bool(bool b) const { return enum_.IsArray() ? CheckEnum(GenericValue<Encoding>(b).Move()) : true; }
|
||||||
@ -105,7 +105,7 @@ public:
|
|||||||
template <typename ValueType>
|
template <typename ValueType>
|
||||||
TypelessSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
TypelessSchema(const ValueType& value) : BaseSchema<Encoding>(value) {}
|
||||||
|
|
||||||
virtual void BeginValue(Context& context) const { context.valueSchema = this; }
|
virtual bool BeginValue(Context& context) const { context.valueSchema = this; return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
@ -347,7 +347,8 @@ public:
|
|||||||
itemsTuple_(),
|
itemsTuple_(),
|
||||||
itemsTupleCount_(),
|
itemsTupleCount_(),
|
||||||
minItems_(),
|
minItems_(),
|
||||||
maxItems_(SizeType(~0))
|
maxItems_(SizeType(~0)),
|
||||||
|
additionalItems_(true)
|
||||||
{
|
{
|
||||||
typename ValueType::ConstMemberIterator itemsItr = value.FindMember(Value("items").Move());
|
typename ValueType::ConstMemberIterator itemsItr = value.FindMember(Value("items").Move());
|
||||||
if (itemsItr != value.MemberEnd()) {
|
if (itemsItr != value.MemberEnd()) {
|
||||||
@ -383,6 +384,15 @@ public:
|
|||||||
// Error
|
// Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typename ValueType::ConstMemberIterator additionalItemsItr = value.FindMember(Value("additionalItems").Move());
|
||||||
|
if (additionalItemsItr != value.MemberEnd()) {
|
||||||
|
if (additionalItemsItr->value.IsBool())
|
||||||
|
additionalItems_ = maxItemsItr->value.GetBool();
|
||||||
|
else {
|
||||||
|
// Error
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~ArraySchema() {
|
~ArraySchema() {
|
||||||
@ -392,15 +402,22 @@ public:
|
|||||||
delete [] itemsTuple_;
|
delete [] itemsTuple_;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void BeginValue(Context& context) const {
|
virtual bool BeginValue(Context& context) const {
|
||||||
if (itemsList_)
|
if (itemsList_)
|
||||||
context.valueSchema = itemsList_;
|
context.valueSchema = itemsList_;
|
||||||
else if (itemsTuple_ && context.arrayElementIndex < itemsTupleCount_)
|
else if (itemsTuple_) {
|
||||||
|
if (context.arrayElementIndex < itemsTupleCount_)
|
||||||
context.valueSchema = itemsTuple_[context.arrayElementIndex];
|
context.valueSchema = itemsTuple_[context.arrayElementIndex];
|
||||||
|
else if (additionalItems_)
|
||||||
|
context.valueSchema = &typeless_;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
context.valueSchema = &typeless_;
|
context.valueSchema = &typeless_;
|
||||||
|
|
||||||
context.arrayElementIndex++;
|
context.arrayElementIndex++;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool Null() const { return false; }
|
virtual bool Null() const { return false; }
|
||||||
@ -431,6 +448,7 @@ private:
|
|||||||
SizeType itemsTupleCount_;
|
SizeType itemsTupleCount_;
|
||||||
SizeType minItems_;
|
SizeType minItems_;
|
||||||
SizeType maxItems_;
|
SizeType maxItems_;
|
||||||
|
bool additionalItems_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Encoding>
|
template <typename Encoding>
|
||||||
@ -804,15 +822,17 @@ public:
|
|||||||
documentStack_.Clear();
|
documentStack_.Clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool Null() { BeginValue(); return PopSchema().Null() ? outputHandler_.Null() : false; }
|
bool Null() { return BeginValue() && PopSchema().Null() ? outputHandler_.Null() : false; }
|
||||||
bool Bool(bool b) { BeginValue(); return PopSchema().Bool(b) ? outputHandler_.Bool(b) : false; }
|
bool Bool(bool b) { return BeginValue() && PopSchema().Bool(b) ? outputHandler_.Bool(b) : false; }
|
||||||
bool Int(int i) { BeginValue(); return PopSchema().Int(i) ? outputHandler_.Int(i) : false; }
|
bool Int(int i) { return BeginValue() && PopSchema().Int(i) ? outputHandler_.Int(i) : false; }
|
||||||
bool Uint(unsigned u) { BeginValue(); return PopSchema().Uint(u) ? outputHandler_.Uint(u) : false; }
|
bool Uint(unsigned u) { return BeginValue() && PopSchema().Uint(u) ? outputHandler_.Uint(u) : false; }
|
||||||
bool Int64(int64_t i64) { BeginValue(); return PopSchema().Int64(i64) ? outputHandler_.Int64(i64) : false; }
|
bool Int64(int64_t i64) { return BeginValue() && PopSchema().Int64(i64) ? outputHandler_.Int64(i64) : false; }
|
||||||
bool Uint64(uint64_t u64) { BeginValue(); return PopSchema().Uint64(u64) ? outputHandler_.Uint64(u64) : false; }
|
bool Uint64(uint64_t u64) { return BeginValue() && PopSchema().Uint64(u64) ? outputHandler_.Uint64(u64) : false; }
|
||||||
bool Double(double d) { BeginValue(); return PopSchema().Double(d) ? outputHandler_.Double(d) : false; }
|
bool Double(double d) { return BeginValue() && PopSchema().Double(d) ? outputHandler_.Double(d) : false; }
|
||||||
bool String(const Ch* str, SizeType length, bool copy) { BeginValue(); return PopSchema().String(str, length, copy) ? outputHandler_.String(str, length, copy) : false; }
|
bool String(const Ch* str, SizeType length, bool copy) { return BeginValue() && PopSchema().String(str, length, copy) ? outputHandler_.String(str, length, copy) : false; }
|
||||||
bool StartObject() { BeginValue(); return CurrentSchema().StartObject(CurrentContext()) ? outputHandler_.StartObject() : false; }
|
|
||||||
|
bool StartObject() { return BeginValue() && CurrentSchema().StartObject(CurrentContext()) ? outputHandler_.StartObject() : false; }
|
||||||
|
|
||||||
bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) ? outputHandler_.Key(str, len, copy) : false; }
|
bool Key(const Ch* str, SizeType len, bool copy) { return CurrentSchema().Key(CurrentContext(), str, len, copy) ? outputHandler_.Key(str, len, copy) : false; }
|
||||||
|
|
||||||
bool EndObject(SizeType memberCount) {
|
bool EndObject(SizeType memberCount) {
|
||||||
@ -824,7 +844,7 @@ public:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StartArray() { BeginValue(); return CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray(): false; }
|
bool StartArray() { return BeginValue() && CurrentSchema().StartArray(CurrentContext()) ? outputHandler_.StartArray() : false; }
|
||||||
|
|
||||||
bool EndArray(SizeType elementCount) {
|
bool EndArray(SizeType elementCount) {
|
||||||
if (CurrentSchema().EndArray(CurrentContext(), elementCount)) {
|
if (CurrentSchema().EndArray(CurrentContext(), elementCount)) {
|
||||||
@ -839,12 +859,15 @@ private:
|
|||||||
typedef BaseSchema<Encoding> BaseSchemaType;
|
typedef BaseSchema<Encoding> BaseSchemaType;
|
||||||
typedef typename BaseSchemaType::Context Context;
|
typedef typename BaseSchemaType::Context Context;
|
||||||
|
|
||||||
void BeginValue() {
|
bool BeginValue() {
|
||||||
if (schemaStack_.Empty()) {
|
if (schemaStack_.Empty()) {
|
||||||
PushSchema(*schema_.root_);
|
PushSchema(*schema_.root_);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CurrentSchema().BeginValue(CurrentContext());
|
if (!CurrentSchema().BeginValue(CurrentContext()))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (CurrentContext().valueSchema)
|
if (CurrentContext().valueSchema)
|
||||||
PushSchema(*CurrentContext().valueSchema);
|
PushSchema(*CurrentContext().valueSchema);
|
||||||
}
|
}
|
||||||
|
@ -350,6 +350,36 @@ TEST(SchemaValidator, Array_ItemsTuple) {
|
|||||||
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true);
|
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SchemaValidator, Array_AdditionalItmes) {
|
||||||
|
Document sd;
|
||||||
|
sd.Parse(
|
||||||
|
"{"
|
||||||
|
" \"type\": \"array\","
|
||||||
|
" \"items\": ["
|
||||||
|
" {"
|
||||||
|
" \"type\": \"number\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"type\": \"string\""
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"type\": \"string\","
|
||||||
|
" \"enum\": [\"Street\", \"Avenue\", \"Boulevard\"]"
|
||||||
|
" },"
|
||||||
|
" {"
|
||||||
|
" \"type\": \"string\","
|
||||||
|
" \"enum\": [\"NW\", \"NE\", \"SW\", \"SE\"]"
|
||||||
|
" }"
|
||||||
|
" ],"
|
||||||
|
" \"additionalItems\": false"
|
||||||
|
"}");
|
||||||
|
Schema s(sd);
|
||||||
|
|
||||||
|
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\"]", true);
|
||||||
|
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\"]", true);
|
||||||
|
VALIDATE(s, "[1600, \"Pennsylvania\", \"Avenue\", \"NW\", \"Washington\"]", false);
|
||||||
|
}
|
||||||
|
|
||||||
TEST(SchemaValidator, Array_ItemsRange) {
|
TEST(SchemaValidator, Array_ItemsRange) {
|
||||||
Document sd;
|
Document sd;
|
||||||
sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}");
|
sd.Parse("{\"type\": \"array\",\"minItems\": 2,\"maxItems\" : 3}");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user