diff --git a/include/rapidjson/schema.h b/include/rapidjson/schema.h index 0e86d4f2..db2207e2 100644 --- a/include/rapidjson/schema.h +++ b/include/rapidjson/schema.h @@ -130,16 +130,19 @@ public: virtual ~ISchemaStateFactory() {} virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0; virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0; + virtual void* MallocState(size_t size) = 0; + virtual void* ReallocState(void* originalPtr, size_t originalSize, size_t newSize) = 0; + virtual void FreeState(void* p) = 0; }; /////////////////////////////////////////////////////////////////////////////// // Hasher // For comparison of compound value -template +template class Hasher { public: - typedef typename ValueType::Ch Ch; + typedef typename Encoding::Ch Ch; Hasher(Allocator* allocator = 0) : stack_(allocator, kDefaultSize) {} @@ -231,10 +234,8 @@ template struct SchemaValidationContext { typedef Schema SchemaType; typedef ISchemaStateFactory SchemaValidatorFactoryType; - typedef GenericValue, CrtAllocator> HashCodeArray; typedef typename SchemaType::ValueType ValueType; typedef typename ValueType::Ch Ch; - typedef Hasher HasherType; enum PatternValidatorType { kPatternValidatorOnly, @@ -242,7 +243,7 @@ struct SchemaValidationContext { kPatternValidatorWithAdditionalProperty }; - SchemaValidationContext(SchemaValidatorFactoryType* f, const SchemaType* s) : + SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) : factory(f), schema(s), valueSchema(), @@ -255,6 +256,7 @@ struct SchemaValidationContext { patternPropertiesSchemas(), patternPropertiesSchemaCount(), valuePatternValidatorType(kPatternValidatorOnly), + arrayElementHashCodes(), objectDependencies(), inArray(false), valueUniqueness(false), @@ -263,26 +265,25 @@ struct SchemaValidationContext { } ~SchemaValidationContext() { - delete hasher; if (validators) { for (SizeType i = 0; i < validatorCount; i++) - factory->DestroySchemaValidator(validators[i]); - delete [] validators; + factory.DestroySchemaValidator(validators[i]); + factory.FreeState(validators); } if (patternPropertiesValidators) { for (SizeType i = 0; i < patternPropertiesValidatorCount; i++) - factory->DestroySchemaValidator(patternPropertiesValidators[i]); - delete [] patternPropertiesValidators; + factory.DestroySchemaValidator(patternPropertiesValidators[i]); + factory.FreeState(patternPropertiesValidators); } - delete[] patternPropertiesSchemas; - delete[] objectDependencies; + factory.FreeState(patternPropertiesSchemas); + factory.FreeState(objectDependencies); } - SchemaValidatorFactoryType* factory; + SchemaValidatorFactoryType& factory; const SchemaType* schema; const SchemaType* valueSchema; const Ch* invalidKeyword; - HasherType* hasher; + void* hasher; // Only calidator access ISchemaValidator** validators; SizeType validatorCount; ISchemaValidator** patternPropertiesValidators; @@ -291,7 +292,7 @@ struct SchemaValidationContext { SizeType patternPropertiesSchemaCount; PatternValidatorType valuePatternValidatorType; PatternValidatorType objectPatternValidatorType; - HashCodeArray arrayElementHashCodes; // array of uint64_t + void* arrayElementHashCodes; // Only validator access this SizeType objectRequiredCount; SizeType arrayElementIndex; bool* objectDependencies; @@ -313,7 +314,7 @@ public: typedef typename EncodingType::Ch Ch; typedef SchemaValidationContext Context; typedef Schema SchemaType; - typedef Hasher HasherType; + typedef Hasher HasherType; typedef GenericValue SValue; friend class GenericSchemaDocument; @@ -612,7 +613,7 @@ public: } if (enum_) { - const uint64_t h = context.hasher->GetHashCode(); + const uint64_t h = static_cast(context.hasher)->GetHashCode(); for (SizeType i = 0; i < enumCount_; i++) if (enum_[i] == h) goto foundEnum; @@ -730,13 +731,13 @@ public: context.objectRequiredCount = 0; if (hasDependencies_) { - context.objectDependencies = new bool[propertyCount_]; + context.objectDependencies = static_cast(context.factory.MallocState(sizeof(bool) * propertyCount_)); std::memset(context.objectDependencies, 0, sizeof(bool) * propertyCount_); } if (patternProperties_) { // pre-allocate schema array SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType - context.patternPropertiesSchemas = new const SchemaType*[count]; + context.patternPropertiesSchemas = static_cast(context.factory.MallocState(sizeof(const SchemaType*) * count)); context.patternPropertiesSchemaCount = 0; std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count); } @@ -823,9 +824,6 @@ public: if (!(type_ & (1 << kArraySchemaType))) RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString()); - if (uniqueItems_) - context.arrayElementHashCodes.SetArray(); - context.arrayElementIndex = 0; context.inArray = true; @@ -999,12 +997,13 @@ private: bool CreateParallelValidator(Context& context) const { if (enum_ || context.arrayUniqueness) - context.hasher = new HasherType; + context.hasher = new (context.factory.MallocState(sizeof(HasherType))) HasherType; if (validatorCount_) { RAPIDJSON_ASSERT(context.validators == 0); - context.validators = new ISchemaValidator*[validatorCount_]; + context.validators = static_cast(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_)); context.validatorCount = validatorCount_; + if (allOf_.schemas) CreateSchemaValidators(context, allOf_); @@ -1015,12 +1014,12 @@ private: CreateSchemaValidators(context, oneOf_); if (not_) - context.validators[notValidatorIndex_] = context.factory->CreateSchemaValidator(*not_); + context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_); if (hasSchemaDependencies_) { for (SizeType i = 0; i < propertyCount_; i++) if (properties_[i].dependenciesSchema) - context.validators[properties_[i].dependenciesValidatorIndex] = context.factory->CreateSchemaValidator(*properties_[i].dependenciesSchema); + context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema); } } @@ -1029,7 +1028,7 @@ private: void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const { for (SizeType i = 0; i < schemas.count; i++) - context.validators[schemas.begin + i] = context.factory->CreateSchemaValidator(*schemas.schemas[i]); + context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]); } // O(n) @@ -1484,7 +1483,7 @@ RAPIDJSON_MULTILINEMACRO_END #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ for (Context* context = schemaStack_.template Bottom(); context != schemaStack_.template End(); context++) {\ if (context->hasher)\ - context->hasher->method arg2;\ + static_cast(context->hasher)->method arg2;\ if (context->validators)\ for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ static_cast(context->validators[i_])->method arg2;\ @@ -1565,8 +1564,22 @@ RAPIDJSON_MULTILINEMACRO_END StateAllocator::Free(v); } + virtual void* MallocState(size_t size) { + return GetStateAllocator().Malloc(size); + } + + virtual void* ReallocState(void* originalPtr, size_t originalSize, size_t newSize) { + return GetStateAllocator().Realloc(originalPtr, originalSize, newSize); + } + + virtual void FreeState(void* p) { + return StateAllocator::Free(p); + } + private: typedef typename SchemaType::Context Context; + typedef GenericValue, StateAllocator> HashCodeArray; + typedef internal::Hasher HasherType; GenericSchemaValidator( const SchemaDocumentType& schemaDocument, @@ -1611,7 +1624,7 @@ private: CurrentContext().objectPatternValidatorType = patternValidatorType; ISchemaValidator**& va = CurrentContext().patternPropertiesValidators; SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount; - va = new ISchemaValidator*[count]; + va = static_cast(MallocState(sizeof(ISchemaValidator*) * count)); for (SizeType i = 0; i < count; i++) va[validatorCount++] = CreateSchemaValidator(*sa[i]); } @@ -1634,17 +1647,20 @@ private: internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom()); #endif - uint64_t h = CurrentContext().arrayUniqueness ? CurrentContext().hasher->GetHashCode() : 0; + uint64_t h = CurrentContext().arrayUniqueness ? static_cast(CurrentContext().hasher)->GetHashCode() : 0; PopSchema(); if (!schemaStack_.Empty()) { Context& context = CurrentContext(); if (context.valueUniqueness) { - for (typename Context::HashCodeArray::ConstValueIterator itr = context.arrayElementHashCodes.Begin(); itr != context.arrayElementHashCodes.End(); ++itr) + HashCodeArray* a = static_cast(context.arrayElementHashCodes); + if (!a) + CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType); + for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr) if (itr->GetUint64() == h) RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString()); - context.arrayElementHashCodes.PushBack(h, GetStateAllocator()); + a->PushBack(h, GetStateAllocator()); } } @@ -1679,8 +1695,21 @@ private: *documentStack_.template Push() = buffer[i]; } - void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(this, &schema); } - void PopSchema() { schemaStack_.template Pop(1)->~Context(); } + void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push()) Context(*this, &schema); } + + void PopSchema() { + Context* c = schemaStack_.template Pop(1); + if (HashCodeArray* a = static_cast(c->arrayElementHashCodes)) { + a->~HashCodeArray(); + StateAllocator::Free(a); + } + if (HasherType* h = static_cast(c->hasher)) { + h->~HasherType(); + StateAllocator::Free(h); + } + c->~Context(); + } + const SchemaType& CurrentSchema() const { return *schemaStack_.template Top()->schema; } Context& CurrentContext() { return *schemaStack_.template Top(); } const Context& CurrentContext() const { return *schemaStack_.template Top(); }