From fcd2e1f60cecc00d414821987b2d3d02dbd593df Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Thu, 13 Jul 2017 16:07:36 +0800 Subject: Fix #1017 allOf keyword fail with Writer handler Gave up using static binding for null handler, because it cannot be used with arbitrary handler type. Change `OutputHandler handler_` to pointer type. --- include/rapidjson/schema.h | 26 ++++++++------------------ test/unittest/schematest.cpp | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 18 deletions(-) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index dd57edbc..abcf1a10 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -1594,7 +1594,7 @@ public: ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), - outputHandler_(CreateNullHandler()), + outputHandler_(0), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1622,8 +1622,7 @@ public: ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), - outputHandler_(outputHandler), - nullHandler_(0), + outputHandler_(&outputHandler), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1634,10 +1633,6 @@ public: //! Destructor. ~GenericSchemaValidator() { Reset(); - if (nullHandler_) { - nullHandler_->~OutputHandler(); - StateAllocator::Free(nullHandler_); - } RAPIDJSON_DELETE(ownStateAllocator_); } @@ -1699,7 +1694,7 @@ RAPIDJSON_MULTILINEMACRO_END } #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ - return valid_ = EndValue() && outputHandler_.method arg2 + return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2) #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ @@ -1721,7 +1716,7 @@ RAPIDJSON_MULTILINEMACRO_END bool StartObject() { RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext())); RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ()); - return valid_ = outputHandler_.StartObject(); + return valid_ = !outputHandler_ || outputHandler_->StartObject(); } bool Key(const Ch* str, SizeType len, bool copy) { @@ -1729,7 +1724,7 @@ RAPIDJSON_MULTILINEMACRO_END AppendToken(str, len); if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false; RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy)); - return valid_ = outputHandler_.Key(str, len, copy); + return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy); } bool EndObject(SizeType memberCount) { @@ -1742,7 +1737,7 @@ RAPIDJSON_MULTILINEMACRO_END bool StartArray() { RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext())); RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ()); - return valid_ = outputHandler_.StartArray(); + return valid_ = !outputHandler_ || outputHandler_->StartArray(); } bool EndArray(SizeType elementCount) { @@ -1815,7 +1810,7 @@ private: ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), - outputHandler_(CreateNullHandler()), + outputHandler_(0), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(depth) @@ -1929,10 +1924,6 @@ private: Context& CurrentContext() { return *schemaStack_.template Top(); } const Context& CurrentContext() const { return *schemaStack_.template Top(); } - OutputHandler& CreateNullHandler() { - return *(nullHandler_ = new (GetStateAllocator().Malloc(sizeof(OutputHandler))) OutputHandler); - } - static const size_t kDefaultSchemaStackCapacity = 1024; static const size_t kDefaultDocumentStackCapacity = 256; const SchemaDocumentType* schemaDocument_; @@ -1941,8 +1932,7 @@ private: StateAllocator* ownStateAllocator_; internal::Stack schemaStack_; //!< stack to store the current path of schema (BaseSchemaType *) internal::Stack documentStack_; //!< stack to store the current path of validating document (Ch) - OutputHandler& outputHandler_; - OutputHandler* nullHandler_; + OutputHandler* outputHandler_; bool valid_; #if RAPIDJSON_SCHEMA_VERBOSE unsigned depth_; diff --git a/test/unittest/schematest.cpp b/test/unittest/schematest.cpp index e79fec28..9b99ba89 100644 --- a/test/unittest/schematest.cpp +++ b/test/unittest/schematest.cpp @@ -1329,6 +1329,25 @@ TEST(SchemaValidator, Issue825) { VALIDATE(s, "{ \"item\": \"hello\" }", true); } +TEST(SchemaValidator, Issue1017_allOfHandler) { + Document sd; + sd.Parse("{\"allOf\": [{\"type\": \"object\",\"properties\": {\"cyanArray2\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}}},{\"type\": \"object\",\"properties\": {\"blackArray\": {\"type\": \"array\",\"items\": { \"type\": \"string\" }}},\"required\": [ \"blackArray\" ]}]}"); + SchemaDocument s(sd); + StringBuffer sb; + Writer writer(sb); + GenericSchemaValidator > validator(s, writer); + EXPECT_TRUE(validator.StartObject()); + EXPECT_TRUE(validator.Key("cyanArray2", 10, false)); + EXPECT_TRUE(validator.StartArray()); + EXPECT_TRUE(validator.EndArray(0)); + EXPECT_TRUE(validator.Key("blackArray", 10, false)); + EXPECT_TRUE(validator.StartArray()); + EXPECT_TRUE(validator.EndArray(0)); + EXPECT_TRUE(validator.EndObject(0)); + EXPECT_TRUE(validator.IsValid()); + EXPECT_STREQ("{\"cyanArray2\":[],\"blackArray\":[]}", sb.GetString()); +} + #ifdef __clang__ RAPIDJSON_DIAG_POP #endif -- cgit v1.2.3