mirror of
				https://github.com/Tencent/rapidjson.git
				synced 2025-10-28 11:31:57 +01:00 
			
		
		
		
	Implement additionalItems
This commit is contained in:
		| @@ -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_) { | ||||||
|             context.valueSchema = itemsTuple_[context.arrayElementIndex]; |             if (context.arrayElementIndex < itemsTupleCount_) | ||||||
|  |                 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}"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Milo Yip
					Milo Yip