Commit 05ae5935 authored by Milo Yip's avatar Milo Yip

Implement additionalItems

parent 33b5c59e
...@@ -64,7 +64,7 @@ public: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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) { ...@@ -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}");
......
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