From b963eb447bee24a692d4ca718db6252a028f131a Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Mon, 17 Oct 2016 18:30:18 +0800 Subject: [PATCH 1/4] Change SchemaValidator::GetNullHandler() from singleton to instance. --- include/rapidjson/schema.h | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 420db62..bb5607f 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -1368,7 +1368,7 @@ public: } else if (refEntry->schema) *refEntry->schema = SchemaType::GetTypeless(); - + refEntry->~SchemaRefEntry(); } @@ -1579,11 +1579,11 @@ public: : schemaDocument_(&schemaDocument), root_(schemaDocument.GetRoot()), - outputHandler_(GetNullHandler()), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(CreateNullHandler()), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1607,11 +1607,12 @@ public: : schemaDocument_(&schemaDocument), root_(schemaDocument.GetRoot()), - outputHandler_(outputHandler), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(outputHandler), + nullHandler_(0), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(0) @@ -1795,11 +1796,11 @@ private: : schemaDocument_(&schemaDocument), root_(root), - outputHandler_(GetNullHandler()), stateAllocator_(allocator), ownStateAllocator_(0), schemaStack_(allocator, schemaStackCapacity), documentStack_(allocator, documentStackCapacity), + outputHandler_(CreateNullHandler()), valid_(true) #if RAPIDJSON_SCHEMA_VERBOSE , depth_(depth) @@ -1913,20 +1914,20 @@ private: Context& CurrentContext() { return *schemaStack_.template Top(); } const Context& CurrentContext() const { return *schemaStack_.template Top(); } - static OutputHandler& GetNullHandler() { - static OutputHandler nullHandler; - return nullHandler; + OutputHandler& CreateNullHandler() { + return *(nullHandler_ = static_cast(stateAllocator_->Malloc(sizeof(OutputHandler)))); } static const size_t kDefaultSchemaStackCapacity = 1024; static const size_t kDefaultDocumentStackCapacity = 256; const SchemaDocumentType* schemaDocument_; const SchemaType& root_; - OutputHandler& outputHandler_; StateAllocator* stateAllocator_; 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_; bool valid_; #if RAPIDJSON_SCHEMA_VERBOSE unsigned depth_; From ddbd2ef05de8600a297dbbabc6563bd0c65f649b Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 18 Oct 2016 10:14:00 +0800 Subject: [PATCH 2/4] Restore missing deallocation of GenericSchemaValidator::nullHandler_ --- include/rapidjson/schema.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index bb5607f..af3b621 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -1623,6 +1623,10 @@ public: //! Destructor. ~GenericSchemaValidator() { Reset(); + if (nullHandler_) { + nullHandler_->~OutputHandler(); + StateAllocator::Free(nullHandler_); + } RAPIDJSON_DELETE(ownStateAllocator_); } From 7c4e511eb0f00d074237595bc0dc62a3bd266d57 Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 18 Oct 2016 11:37:15 +0800 Subject: [PATCH 3/4] Change Schema::GetTypeless() from singleton to instance Now owned by SchemaDocument::typeless_, and be shared to its Schema::typeless_ --- include/rapidjson/schema.h | 44 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index af3b621..6f1611f 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -349,6 +349,7 @@ public: Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) : allocator_(allocator), + typeless_(schemaDocument->GetTypeless()), enum_(), enumCount_(), not_(), @@ -453,7 +454,7 @@ public: for (SizeType i = 0; i < propertyCount_; i++) { new (&properties_[i]) Property(); properties_[i].name = allProperties[i]; - properties_[i].schema = GetTypeless(); + properties_[i].schema = typeless_; } } } @@ -575,9 +576,7 @@ public: } ~Schema() { - if (allocator_) { - allocator_->Free(enum_); - } + AllocatorType::Free(enum_); if (properties_) { for (SizeType i = 0; i < propertyCount_; i++) properties_[i].~Property(); @@ -592,7 +591,7 @@ public: #if RAPIDJSON_SCHEMA_HAS_REGEX if (pattern_) { pattern_->~RegexType(); - allocator_->Free(pattern_); + AllocatorType::Free(pattern_); } #endif } @@ -610,12 +609,12 @@ public: else if (additionalItemsSchema_) context.valueSchema = additionalItemsSchema_; else if (additionalItems_) - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; else RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString()); } else - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.arrayElementIndex++; } @@ -792,7 +791,7 @@ public: if (FindPropertyIndex(ValueType(str, len).Move(), &index)) { if (context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema; - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.valuePatternValidatorType = Context::kPatternValidatorWithProperty; } else @@ -807,7 +806,7 @@ public: if (additionalPropertiesSchema_) { if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty; } else @@ -815,7 +814,7 @@ public: return true; } else if (additionalProperties_) { - context.valueSchema = GetTypeless(); + context.valueSchema = typeless_; return true; } @@ -949,11 +948,6 @@ private: SizeType count; }; - static const SchemaType* GetTypeless() { - static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); - return &typeless; - } - template void AddUniqueElement(V1& a, const V2& v) { for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr) @@ -1219,6 +1213,7 @@ private: }; AllocatorType* allocator_; + const SchemaType* typeless_; uint64_t* enum_; SizeType enumCount_; SchemaArray allOf_; @@ -1350,6 +1345,9 @@ public: if (!allocator_) ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator()); + typeless_ = static_cast(allocator_->Malloc(sizeof(SchemaType))); + new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0); + // Generate root schema, it will call CreateSchema() to create sub-schemas, // And call AddRefSchema() if there are $ref. CreateSchemaRecursive(&root_, PointerType(), document, document); @@ -1367,7 +1365,7 @@ public: } } else if (refEntry->schema) - *refEntry->schema = SchemaType::GetTypeless(); + *refEntry->schema = typeless_; refEntry->~SchemaRefEntry(); } @@ -1384,12 +1382,14 @@ public: allocator_(rhs.allocator_), ownAllocator_(rhs.ownAllocator_), root_(rhs.root_), + typeless_(rhs.typeless_), schemaMap_(std::move(rhs.schemaMap_)), schemaRef_(std::move(rhs.schemaRef_)) { rhs.remoteProvider_ = 0; rhs.allocator_ = 0; rhs.ownAllocator_ = 0; + rhs.typeless_ = 0; } #endif @@ -1398,6 +1398,9 @@ public: while (!schemaMap_.Empty()) schemaMap_.template Pop(1)->~SchemaEntry(); + typeless_->~SchemaType(); + Allocator::Free(typeless_); + RAPIDJSON_DELETE(ownAllocator_); } @@ -1432,7 +1435,7 @@ private: void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) { if (schema) - *schema = SchemaType::GetTypeless(); + *schema = typeless_; if (v.GetType() == kObjectType) { const SchemaType* s = GetSchema(pointer); @@ -1519,6 +1522,8 @@ private: return PointerType(); } + const SchemaType* GetTypeless() const { return typeless_; } + static const size_t kInitialSchemaMapSize = 64; static const size_t kInitialSchemaRefSize = 64; @@ -1526,6 +1531,7 @@ private: Allocator *allocator_; Allocator *ownAllocator_; const SchemaType* root_; //!< Root schema. + SchemaType* typeless_; internal::Stack schemaMap_; // Stores created Pointer -> Schemas internal::Stack schemaRef_; // Stores Pointer from $ref and schema which holds the $ref }; @@ -1832,8 +1838,8 @@ private: const SchemaType** sa = CurrentContext().patternPropertiesSchemas; typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; bool valueUniqueness = CurrentContext().valueUniqueness; - if (CurrentContext().valueSchema) - PushSchema(*CurrentContext().valueSchema); + RAPIDJSON_ASSERT(CurrentContext().valueSchema); + PushSchema(*CurrentContext().valueSchema); if (count > 0) { CurrentContext().objectPatternValidatorType = patternValidatorType; From bf0cc7bea8f9e8a744098d680bdf521e343dc4db Mon Sep 17 00:00:00 2001 From: Milo Yip Date: Tue, 18 Oct 2016 13:53:00 +0800 Subject: [PATCH 4/4] Fixed a bug for SchemaDocument move constructor --- include/rapidjson/schema.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 6f1611f..178e91c 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -1339,6 +1339,7 @@ public: allocator_(allocator), ownAllocator_(), root_(), + typeless_(), schemaMap_(allocator, kInitialSchemaMapSize), schemaRef_(allocator, kInitialSchemaRefSize) { @@ -1398,8 +1399,10 @@ public: while (!schemaMap_.Empty()) schemaMap_.template Pop(1)->~SchemaEntry(); - typeless_->~SchemaType(); - Allocator::Free(typeless_); + if (typeless_) { + typeless_->~SchemaType(); + Allocator::Free(typeless_); + } RAPIDJSON_DELETE(ownAllocator_); }