Clean up schema

This commit is contained in:
miloyip 2015-05-09 14:22:04 +08:00
parent f0c3fa84fc
commit 422aebf3ac

View File

@ -42,16 +42,8 @@ RAPIDJSON_DIAG_OFF(effc++)
RAPIDJSON_NAMESPACE_BEGIN RAPIDJSON_NAMESPACE_BEGIN
enum SchemaValueType { ///////////////////////////////////////////////////////////////////////////////
kNullSchemaType, // Forward declarations
kBooleanSchemaType,
kObjectSchemaType,
kArraySchemaType,
kStringSchemaType,
kNumberSchemaType,
kIntegerSchemaType,
kTotalSchemaType
};
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class Schema; class Schema;
@ -59,8 +51,8 @@ class Schema;
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class GenericSchemaDocument; class GenericSchemaDocument;
template <typename Encoding, typename OutputHandler, typename StateAllocator> ///////////////////////////////////////////////////////////////////////////////
class GenericSchemaValidator; // ISchemaValidator
class ISchemaValidator { class ISchemaValidator {
public: public:
@ -68,6 +60,9 @@ public:
virtual bool IsValid() const = 0; virtual bool IsValid() const = 0;
}; };
///////////////////////////////////////////////////////////////////////////////
// ISchemaValidatorFactory
template <typename SchemaType> template <typename SchemaType>
class ISchemaValidatorFactory { class ISchemaValidatorFactory {
public: public:
@ -75,6 +70,9 @@ public:
virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) const = 0; virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) const = 0;
}; };
///////////////////////////////////////////////////////////////////////////////
// SchemaValidatorArray
struct SchemaValidatorArray { struct SchemaValidatorArray {
SchemaValidatorArray() : validators(), count() {} SchemaValidatorArray() : validators(), count() {}
~SchemaValidatorArray() { ~SchemaValidatorArray() {
@ -87,6 +85,9 @@ struct SchemaValidatorArray {
SizeType count; SizeType count;
}; };
///////////////////////////////////////////////////////////////////////////////
// SchemaArray
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct SchemaArray { struct SchemaArray {
SchemaArray() : schemas(), count() {} SchemaArray() : schemas(), count() {}
@ -94,22 +95,24 @@ struct SchemaArray {
delete[] schemas; delete[] schemas;
} }
Schema<Encoding, Allocator>** schemas; const Schema<Encoding, Allocator>** schemas;
SizeType count; SizeType count;
}; };
enum PatternValidatorType { ///////////////////////////////////////////////////////////////////////////////
kPatternValidatorOnly, // SchemaValidationContext
kPatternValidatorWithProperty,
kPatternValidatorWithAdditionalProperty
};
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
struct SchemaValidationContext { struct SchemaValidationContext {
typedef Schema<Encoding, Allocator> SchemaType; typedef Schema<Encoding, Allocator> SchemaType;
typedef GenericSchemaValidator<SchemaType, BaseReaderHandler<>, CrtAllocator> SchemaValidatorType;
typedef ISchemaValidatorFactory<SchemaType> SchemaValidatorFactoryType; typedef ISchemaValidatorFactory<SchemaType> SchemaValidatorFactoryType;
enum PatternValidatorType {
kPatternValidatorOnly,
kPatternValidatorWithProperty,
kPatternValidatorWithAdditionalProperty
};
SchemaValidationContext(const SchemaValidatorFactoryType* f, const SchemaType* s) : SchemaValidationContext(const SchemaValidatorFactoryType* f, const SchemaType* s) :
factory(f), factory(f),
schema(s), schema(s),
@ -151,6 +154,9 @@ struct SchemaValidationContext {
bool inArray; bool inArray;
}; };
///////////////////////////////////////////////////////////////////////////////
// Schema
template <typename Encoding, typename Allocator> template <typename Encoding, typename Allocator>
class Schema { class Schema {
public: public:
@ -160,10 +166,10 @@ public:
typedef GenericSchemaDocument<Encoding, Allocator> SchemaDocumentType; typedef GenericSchemaDocument<Encoding, Allocator> SchemaDocumentType;
typedef Schema<Encoding, Allocator> SchemaType; typedef Schema<Encoding, Allocator> SchemaType;
typedef GenericValue<Encoding, Allocator> ValueType; typedef GenericValue<Encoding, Allocator> ValueType;
typedef GenericPointer<ValueType> PointerType; // typedef GenericPointer<ValueType> PointerType;
friend class GenericSchemaDocument<Encoding, Allocator>; friend class GenericSchemaDocument<Encoding, Allocator>;
template <typename ValueType> template <typename ValueType, typename PointerType>
Schema(SchemaDocumentType* document, const PointerType& p, const ValueType& value) : Schema(SchemaDocumentType* document, const PointerType& p, const ValueType& value) :
not_(), not_(),
ref_(), ref_(),
@ -334,7 +340,7 @@ public:
itemsList_ = document->CreateSchema(p, *v); itemsList_ = document->CreateSchema(p, *v);
else if (v->IsArray()) { // Tuple validation else if (v->IsArray()) { // Tuple validation
PointerType q = p.Append("items"); PointerType q = p.Append("items");
itemsTuple_ = new Schema*[v->Size()]; itemsTuple_ = new const Schema*[v->Size()];
SizeType index = 0; SizeType index = 0;
for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++) for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
itemsTuple_[itemsTupleCount_++] = document->CreateSchema(q.Append(index), *itr); itemsTuple_[itemsTupleCount_++] = document->CreateSchema(q.Append(index), *itr);
@ -416,7 +422,7 @@ public:
if (context.patternPropertiesValidators.count > 0) { if (context.patternPropertiesValidators.count > 0) {
bool otherValid = false; bool otherValid = false;
SizeType count = context.patternPropertiesValidators.count; SizeType count = context.patternPropertiesValidators.count;
if (context.objectPatternValidatorType != kPatternValidatorOnly) if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
otherValid = context.patternPropertiesValidators.validators[--count]->IsValid(); otherValid = context.patternPropertiesValidators.validators[--count]->IsValid();
bool patternValid = true; bool patternValid = true;
@ -426,11 +432,11 @@ public:
break; break;
} }
if (context.objectPatternValidatorType == kPatternValidatorOnly) { if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
if (!patternValid) if (!patternValid)
return false; return false;
} }
else if (context.objectPatternValidatorType == kPatternValidatorWithProperty) { else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
if (!patternValid || !otherValid) if (!patternValid || !otherValid)
return false; return false;
} }
@ -579,7 +585,7 @@ public:
if (context.patternPropertiesSchemaCount > 0) { if (context.patternPropertiesSchemaCount > 0) {
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = propertySchema; context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = propertySchema;
context.valueSchema = GetTypeless(); context.valueSchema = GetTypeless();
context.valuePatternValidatorType = kPatternValidatorWithProperty; context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
} }
else else
context.valueSchema = propertySchema; context.valueSchema = propertySchema;
@ -597,7 +603,7 @@ public:
if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) { if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_; context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
context.valueSchema = GetTypeless(); context.valueSchema = GetTypeless();
context.valuePatternValidatorType = kPatternValidatorWithAdditionalProperty; context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
} }
else else
context.valueSchema = additionalPropertiesSchema_; context.valueSchema = additionalPropertiesSchema_;
@ -648,18 +654,27 @@ public:
} }
private: private:
enum SchemaValueType {
kNullSchemaType,
kBooleanSchemaType,
kObjectSchemaType,
kArraySchemaType,
kStringSchemaType,
kNumberSchemaType,
kIntegerSchemaType,
kTotalSchemaType
};
#if RAPIDJSON_SCHEMA_USE_STDREGEX #if RAPIDJSON_SCHEMA_USE_STDREGEX
typedef std::basic_regex<Ch> RegexType; typedef std::basic_regex<Ch> RegexType;
#else #else
typedef char RegexType; typedef char RegexType;
#endif #endif
typedef GenericSchemaValidator<Encoding, BaseReaderHandler<>, CrtAllocator> SchemaValidatorType;
typedef SchemaArray<Encoding, Allocator> SchemaArrayType; typedef SchemaArray<Encoding, Allocator> SchemaArrayType;
typedef SchemaValidatorArray SchemaValidatorArrayType;
static const SchemaType* GetTypeless() { static const SchemaType* GetTypeless() {
static SchemaType typeless(0, PointerType(), Value(kObjectType).Move()); static SchemaType typeless(0, Pointer(), Value(kObjectType).Move());
return &typeless; return &typeless;
} }
@ -692,13 +707,13 @@ private:
out = static_cast<SizeType>(v->GetUint64()); out = static_cast<SizeType>(v->GetUint64());
} }
template <typename DocumentType, typename ValueType> template <typename DocumentType, typename ValueType, typename PointerType>
static void AssigIfExist(SchemaArrayType& out, const DocumentType& document, const PointerType& p, const ValueType& value, const char* name) { static void AssigIfExist(SchemaArrayType& out, const DocumentType& document, const PointerType& p, const ValueType& value, const char* name) {
if (const ValueType* v = GetMember(value, name)) { if (const ValueType* v = GetMember(value, name)) {
if (v->IsArray() && v->Size() > 0) { if (v->IsArray() && v->Size() > 0) {
PointerType q = p.Append(name); PointerType q = p.Append(name);
out.count = v->Size(); out.count = v->Size();
out.schemas = new Schema*[out.count]; out.schemas = new const Schema*[out.count];
memset(out.schemas, 0, sizeof(Schema*)* out.count); memset(out.schemas, 0, sizeof(Schema*)* out.count);
for (SizeType i = 0; i < out.count; i++) for (SizeType i = 0; i < out.count; i++)
out.schemas[i] = document->CreateSchema(q.Append(i), (*v)[i]); out.schemas[i] = document->CreateSchema(q.Append(i), (*v)[i]);
@ -763,7 +778,7 @@ private:
} }
} }
void CreateSchemaValidators(Context& context, SchemaValidatorArrayType& validators, const SchemaArrayType& schemas) const { void CreateSchemaValidators(Context& context, SchemaValidatorArray& validators, const SchemaArrayType& schemas) const {
if (!validators.validators) { if (!validators.validators) {
validators.validators = new ISchemaValidator*[schemas.count]; validators.validators = new ISchemaValidator*[schemas.count];
validators.count = schemas.count; validators.count = schemas.count;
@ -820,8 +835,8 @@ private:
struct PatternProperty { struct PatternProperty {
PatternProperty() : schema(), pattern() {} PatternProperty() : schema(), pattern() {}
~PatternProperty() { delete pattern; } ~PatternProperty() { delete pattern; }
SchemaType* schema; const SchemaType* schema;
RegexType* pattern; const RegexType* pattern;
}; };
Allocator allocator_; Allocator allocator_;
@ -829,12 +844,12 @@ private:
SchemaArrayType allOf_; SchemaArrayType allOf_;
SchemaArrayType anyOf_; SchemaArrayType anyOf_;
SchemaArrayType oneOf_; SchemaArrayType oneOf_;
SchemaType* not_; const SchemaType* not_;
SchemaType* ref_; const SchemaType* ref_;
unsigned type_; // bitmask of kSchemaType unsigned type_; // bitmask of kSchemaType
Property* properties_; Property* properties_;
SchemaType* additionalPropertiesSchema_; const SchemaType* additionalPropertiesSchema_;
PatternProperty* patternProperties_; PatternProperty* patternProperties_;
SizeType patternPropertyCount_; SizeType patternPropertyCount_;
SizeType propertyCount_; SizeType propertyCount_;
@ -845,15 +860,15 @@ private:
bool hasDependencies_; bool hasDependencies_;
bool hasSchemaDependencies_; bool hasSchemaDependencies_;
SchemaType* additionalItemsSchema_; const SchemaType* additionalItemsSchema_;
SchemaType* itemsList_; const SchemaType* itemsList_;
SchemaType** itemsTuple_; const SchemaType** itemsTuple_;
SizeType itemsTupleCount_; SizeType itemsTupleCount_;
SizeType minItems_; SizeType minItems_;
SizeType maxItems_; SizeType maxItems_;
bool additionalItems_; bool additionalItems_;
RegexType* pattern_; const RegexType* pattern_;
SizeType minLength_; SizeType minLength_;
SizeType maxLength_; SizeType maxLength_;
@ -865,6 +880,9 @@ private:
bool exclusiveMaximum_; bool exclusiveMaximum_;
}; };
///////////////////////////////////////////////////////////////////////////////
// GenericSchemaDocument
template <typename Encoding, typename Allocator = MemoryPoolAllocator<> > template <typename Encoding, typename Allocator = MemoryPoolAllocator<> >
class GenericSchemaDocument { class GenericSchemaDocument {
public: public:
@ -930,7 +948,7 @@ private:
}; };
template <typename ValueType> template <typename ValueType>
SchemaType* CreateSchema(const GenericPointer<ValueType>& pointer, const ValueType& v) { const SchemaType* CreateSchema(const GenericPointer<ValueType>& pointer, const ValueType& v) {
RAPIDJSON_ASSERT(pointer.IsValid()); RAPIDJSON_ASSERT(pointer.IsValid());
SchemaType* schema = new SchemaType(this, pointer, v); SchemaType* schema = new SchemaType(this, pointer, v);
new (schemaMap_.template Push<SchemaEntry<ValueType> >()) SchemaEntry<ValueType>(pointer, schema); new (schemaMap_.template Push<SchemaEntry<ValueType> >()) SchemaEntry<ValueType>(pointer, schema);
@ -950,7 +968,7 @@ private:
static const size_t kInitialSchemaMapSize = 1024; static const size_t kInitialSchemaMapSize = 1024;
static const size_t kInitialSchemaRefSize = 1024; static const size_t kInitialSchemaRefSize = 1024;
SchemaType* root_; //!< Root schema. const SchemaType* root_; //!< Root schema.
SchemaType** schemas_; //!< ALl schemas are owned by SchemaDocument SchemaType** schemas_; //!< ALl schemas are owned by SchemaDocument
size_t schemaCount_; //!< Number of schemas owned size_t schemaCount_; //!< Number of schemas owned
internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
@ -959,6 +977,9 @@ private:
typedef GenericSchemaDocument<UTF8<> > SchemaDocument; typedef GenericSchemaDocument<UTF8<> > SchemaDocument;
///////////////////////////////////////////////////////////////////////////////
// GenericSchemaValidator
template <typename SchemaType, typename OutputHandler = BaseReaderHandler<typename SchemaType::EncodingType>, typename StateAllocator = CrtAllocator > template <typename SchemaType, typename OutputHandler = BaseReaderHandler<typename SchemaType::EncodingType>, typename StateAllocator = CrtAllocator >
class GenericSchemaValidator : public ISchemaValidatorFactory<SchemaType>, public ISchemaValidator { class GenericSchemaValidator : public ISchemaValidatorFactory<SchemaType>, public ISchemaValidator {
public: public:
@ -1124,7 +1145,7 @@ private:
SizeType count = CurrentContext().patternPropertiesSchemaCount; SizeType count = CurrentContext().patternPropertiesSchemaCount;
const SchemaType** sa = CurrentContext().patternPropertiesSchemas; const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType; typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
if (CurrentContext().valueSchema) if (CurrentContext().valueSchema)
PushSchema(*CurrentContext().valueSchema); PushSchema(*CurrentContext().valueSchema);