mirror of
				https://github.com/Tencent/rapidjson.git
				synced 2025-10-28 11:31:57 +01:00 
			
		
		
		
	Schema code simplification
This commit is contained in:
		| @@ -89,8 +89,8 @@ struct BaseSchemaArray { | |||||||
|  |  | ||||||
| template <typename Encoding> | template <typename Encoding> | ||||||
| struct SchemaValidationContext { | struct SchemaValidationContext { | ||||||
|     SchemaValidationContext(/*ISchemaValidatorFactory<Encoding>* factory, */const BaseSchema<Encoding>* s) :  |     SchemaValidationContext(const BaseSchema<Encoding>* s) :  | ||||||
|         /*schemaValidatorFactory(factory), */schema(s), valueSchema(), multiTypeSchema(), notValidator(), objectDependencies(), inArray(false) |         schema(s), valueSchema(), multiTypeSchema(), notValidator(), objectDependencies(), inArray(false) | ||||||
|     { |     { | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -99,7 +99,6 @@ struct SchemaValidationContext { | |||||||
|         delete[] objectDependencies; |         delete[] objectDependencies; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     //ISchemaValidatorFactory<Encoding>* schemaValidatorFactory; |  | ||||||
|     const BaseSchema<Encoding>* schema; |     const BaseSchema<Encoding>* schema; | ||||||
|     const BaseSchema<Encoding>* valueSchema; |     const BaseSchema<Encoding>* valueSchema; | ||||||
|     const BaseSchema<Encoding>* multiTypeSchema; |     const BaseSchema<Encoding>* multiTypeSchema; | ||||||
| @@ -122,6 +121,7 @@ public: | |||||||
|     template <typename ValueType> |     template <typename ValueType> | ||||||
|     BaseSchema(const ValueType& value) :  |     BaseSchema(const ValueType& value) :  | ||||||
|         not_(), |         not_(), | ||||||
|  |         type_((1 << kTotalSchemaType) - 1), // typeless | ||||||
|         properties_(), |         properties_(), | ||||||
|         additionalPropertySchema_(), |         additionalPropertySchema_(), | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
| @@ -152,328 +152,158 @@ public: | |||||||
|         exclusiveMinimum_(false), |         exclusiveMinimum_(false), | ||||||
|         exclusiveMaximum_(false) |         exclusiveMaximum_(false) | ||||||
|     { |     { | ||||||
|         type_ = (1 << kTotalSchemaType) - 1; // typeless |         typedef typename ValueType::ConstValueIterator ConstValueIterator; | ||||||
|  |         typedef typename ValueType::ConstMemberIterator ConstMemberIterator; | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator typeItr = value.FindMember("type"); |         if (!value.IsObject()) | ||||||
|         if (typeItr != value.MemberEnd()) { |             return; | ||||||
|             if (typeItr->value.IsString()) { |  | ||||||
|  |         if (const ValueType* v = GetMember(value, "type")) { | ||||||
|             type_ = 0; |             type_ = 0; | ||||||
|                 AddType(typeItr->value); |             if (v->IsString()) | ||||||
|             } |                 AddType(*v); | ||||||
|             else if (typeItr->value.IsArray()) { |             else if (v->IsArray()) | ||||||
|                 type_ = 0; |                 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) | ||||||
|                 for (typename ValueType::ConstValueIterator itr = typeItr->value.Begin(); itr != typeItr->value.End(); ++itr)  |  | ||||||
|                     AddType(*itr); |                     AddType(*itr); | ||||||
|         } |         } | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator enumItr = value.FindMember("enum"); |         if (const ValueType* v = GetMember(value, "enum")) | ||||||
|         if (enumItr != value.MemberEnd()) { |             if (v->IsArray() && v->Size() > 0) | ||||||
|             if (enumItr->value.IsArray() && enumItr->value.Size() > 0) |                 enum_.CopyFrom(*v, allocator_); | ||||||
|                 enum_.CopyFrom(enumItr->value, allocator_); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator allOfItr = value.FindMember("allOf"); |         AssigIfExist(allOf_, value, "allOf"); | ||||||
|         if (allOfItr != value.MemberEnd()) |         AssigIfExist(anyOf_, value, "anyOf"); | ||||||
|             CreateLogicalSchemas(allOfItr->value, allOf_); |         AssigIfExist(oneOf_, value, "oneOf"); | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator anyOfItr = value.FindMember("anyOf"); |         if (const ValueType* v = GetMember(value, "not")) | ||||||
|         if (anyOfItr != value.MemberEnd()) |             not_ = new BaseSchema<Encoding>(*v); | ||||||
|             CreateLogicalSchemas(anyOfItr->value, anyOf_); |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator oneOfItr = value.FindMember("oneOf"); |  | ||||||
|         if (oneOfItr != value.MemberEnd()) |  | ||||||
|             CreateLogicalSchemas(oneOfItr->value, oneOf_); |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator notItr = value.FindMember("not"); |  | ||||||
|         if (notItr != value.MemberEnd()) { |  | ||||||
|             if (notItr->value.IsObject()) |  | ||||||
|                 not_ = new BaseSchema<Encoding>(notItr->value); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Object |         // Object | ||||||
|         typename ValueType::ConstMemberIterator propretiesItr = value.FindMember("properties"); |         if (const ValueType* v = GetMember(value, "properties")) | ||||||
|         if (propretiesItr != value.MemberEnd()) { |             if (v->IsObject()) { | ||||||
|             const ValueType& properties = propretiesItr->value; |                 properties_ = new Property[v->MemberCount()]; | ||||||
|             properties_ = new Property[properties.MemberCount()]; |  | ||||||
|                 propertyCount_ = 0; |                 propertyCount_ = 0; | ||||||
|  |                 for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { | ||||||
|             for (typename ValueType::ConstMemberIterator propertyItr = properties.MemberBegin(); propertyItr != properties.MemberEnd(); ++propertyItr) { |                     properties_[propertyCount_].name.SetString(itr->name.GetString(), itr->name.GetStringLength(), allocator_); | ||||||
|                 properties_[propertyCount_].name.SetString(propertyItr->name.GetString(), propertyItr->name.GetStringLength(), BaseSchema<Encoding>::allocator_); |                     properties_[propertyCount_].schema = new BaseSchema(itr->value); | ||||||
|                 properties_[propertyCount_].schema = new BaseSchema(propertyItr->value);    // TODO: Check error |  | ||||||
|                     propertyCount_++; |                     propertyCount_++; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|         typename ValueType::ConstMemberIterator patternPropretiesItr = value.FindMember("patternProperties"); |         if (const ValueType* v = GetMember(value, "patternProperties")) { | ||||||
|         if (patternPropretiesItr != value.MemberEnd()) { |             patternProperties_ = new PatternProperty[v->MemberCount()]; | ||||||
|             const ValueType& patternProperties = patternPropretiesItr->value; |  | ||||||
|             patternProperties_ = new PatternProperty[patternProperties.MemberCount()]; |  | ||||||
|             patternPropertyCount_ = 0; |             patternPropertyCount_ = 0; | ||||||
|  |  | ||||||
|             for (typename ValueType::ConstMemberIterator propertyItr = patternProperties.MemberBegin(); propertyItr != patternProperties.MemberEnd(); ++propertyItr) { |             for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { | ||||||
| #if RAPIDJSON_SCHEMA_USE_STDREGEX |                 patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name); | ||||||
|                 try { |                 patternProperties_[patternPropertyCount_].schema = new BaseSchema<Encoding>(itr->value);    // TODO: Check error | ||||||
|                     patternProperties_[patternPropertyCount_].pattern = new std::basic_regex<Ch>( |  | ||||||
|                         propertyItr->name.GetString(), |  | ||||||
|                         std::size_t(propertyItr->name.GetStringLength()), |  | ||||||
|                         std::regex_constants::ECMAScript); |  | ||||||
|                 } |  | ||||||
|                 catch (const std::regex_error&) { |  | ||||||
|                     // Error |  | ||||||
|                 } |  | ||||||
| #endif |  | ||||||
|                 patternProperties_[patternPropertyCount_].schema = new BaseSchema<Encoding>(propertyItr->value);    // TODO: Check error |  | ||||||
|                 patternPropertyCount_++; |                 patternPropertyCount_++; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         // Establish required after properties |         if (const ValueType* v = GetMember(value, "required")) | ||||||
|         typename ValueType::ConstMemberIterator requiredItr = value.FindMember("required"); |             if (v->IsArray()) | ||||||
|         if (requiredItr != value.MemberEnd()) { |                 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) | ||||||
|             if (requiredItr->value.IsArray()) { |  | ||||||
|                 for (typename ValueType::ConstValueIterator itr = requiredItr->value.Begin(); itr != requiredItr->value.End(); ++itr) { |  | ||||||
|                     if (itr->IsString()) { |                     if (itr->IsString()) { | ||||||
|                         SizeType index; |                         SizeType index; | ||||||
|                         if (FindPropertyIndex(*itr, &index)) { |                         if (FindPropertyIndex(*itr, &index)) { | ||||||
|                             properties_[index].required = true; |                             properties_[index].required = true; | ||||||
|                             requiredCount_++; |                             requiredCount_++; | ||||||
|                         } |                         } | ||||||
|                         else { |  | ||||||
|                             // Error |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     else { |  | ||||||
|                         // Error |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|         // Establish dependencies after properties |         if (const ValueType* v = GetMember(value, "dependencies")) | ||||||
|         typename ValueType::ConstMemberIterator dependenciesItr = value.FindMember("dependencies"); |             if (v->IsObject()) { | ||||||
|         if (dependenciesItr != value.MemberEnd()) { |  | ||||||
|             if (dependenciesItr->value.IsObject()) { |  | ||||||
|                 hasDependencies_ = true; |                 hasDependencies_ = true; | ||||||
|                 for (typename ValueType::ConstMemberIterator itr = dependenciesItr->value.MemberBegin(); itr != dependenciesItr->value.MemberEnd(); ++itr) { |                 for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) { | ||||||
|                     SizeType sourceIndex; |                     SizeType sourceIndex; | ||||||
|                     if (FindPropertyIndex(itr->name, &sourceIndex)) { |                     if (FindPropertyIndex(itr->name, &sourceIndex)) { | ||||||
|  |                         if (itr->value.IsArray()) { | ||||||
|                             properties_[sourceIndex].dependencies = new bool[propertyCount_]; |                             properties_[sourceIndex].dependencies = new bool[propertyCount_]; | ||||||
|                             std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); |                             std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_); | ||||||
|                         if (itr->value.IsArray()) { |                             for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { | ||||||
|                             for (typename ValueType::ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) { |  | ||||||
|                                 SizeType targetIndex; |                                 SizeType targetIndex; | ||||||
|                                 if (FindPropertyIndex(*targetItr, &targetIndex)) { |                                 if (FindPropertyIndex(*targetItr, &targetIndex)) | ||||||
|                                     properties_[sourceIndex].dependencies[targetIndex] = true; |                                     properties_[sourceIndex].dependencies[targetIndex] = true; | ||||||
|                             } |                             } | ||||||
|                                 else { |                         } | ||||||
|                                     // Error |                         else if (itr->value.IsObject()) { | ||||||
|  |                             // TODO | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                         else { |  | ||||||
|                             // Error |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                     else { |  | ||||||
|                         // Error |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|             } |             } | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator additionalPropretiesItr = value.FindMember("additionalProperties"); |         if (const ValueType* v = GetMember(value, "additionalProperties")) { | ||||||
|         if (additionalPropretiesItr != value.MemberEnd()) { |             if (v->IsBool()) | ||||||
|             if (additionalPropretiesItr->value.IsBool()) |                 additionalProperty_ = v->GetBool(); | ||||||
|                 additionalProperty_ = additionalPropretiesItr->value.GetBool(); |             else if (v->IsObject()) | ||||||
|             else if (additionalPropretiesItr->value.IsObject()) |                 additionalPropertySchema_ = new BaseSchema<Encoding>(*v); | ||||||
|                 additionalPropertySchema_ = new BaseSchema<Encoding>(additionalPropretiesItr->value); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator minPropertiesItr = value.FindMember("minProperties"); |         AssignIfExist(minProperties_, value, "minProperties"); | ||||||
|         if (minPropertiesItr != value.MemberEnd()) { |         AssignIfExist(maxProperties_, value, "maxProperties"); | ||||||
|             if (minPropertiesItr->value.IsUint64() && minPropertiesItr->value.GetUint64() <= SizeType(~0)) |  | ||||||
|                 minProperties_ = static_cast<SizeType>(minPropertiesItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator maxPropertiesItr = value.FindMember("maxProperties"); |  | ||||||
|         if (maxPropertiesItr != value.MemberEnd()) { |  | ||||||
|             if (maxPropertiesItr->value.IsUint64() && maxPropertiesItr->value.GetUint64() <= SizeType(~0)) |  | ||||||
|                 maxProperties_ = static_cast<SizeType>(maxPropertiesItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Array |         // Array | ||||||
|         typename ValueType::ConstMemberIterator itemsItr = value.FindMember("items"); |         if (const ValueType* v = GetMember(value, "items")) { | ||||||
|         if (itemsItr != value.MemberEnd()) { |             if (v->IsObject()) // List validation | ||||||
|             if (itemsItr->value.IsObject()) |                 itemsList_ = new BaseSchema<Encoding>(*v); | ||||||
|                 itemsList_ = new BaseSchema<Encoding>(itemsItr->value); // List validation |             else if (v->IsArray()) { // Tuple validation | ||||||
|             else if (itemsItr->value.IsArray()) { |                 itemsTuple_ = new BaseSchema<Encoding>*[v->Size()]; | ||||||
|                 // Tuple validation |                 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) | ||||||
|                 itemsTuple_ = new BaseSchema<Encoding>*[itemsItr->value.Size()]; |                     itemsTuple_[itemsTupleCount_++] = new BaseSchema<Encoding>(*itr); | ||||||
|                 for (typename ValueType::ConstValueIterator itr = itemsItr->value.Begin(); itr != itemsItr->value.End(); ++itr) { |  | ||||||
|                     itemsTuple_[itemsTupleCount_] = new BaseSchema<Encoding>(*itr); |  | ||||||
|                     itemsTupleCount_++; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator minItemsItr = value.FindMember("minItems"); |         AssignIfExist(minItems_, value, "minItems"); | ||||||
|         if (minItemsItr != value.MemberEnd()) { |         AssignIfExist(maxItems_, value, "maxItems"); | ||||||
|             if (minItemsItr->value.IsUint64() && minItemsItr->value.GetUint64() <= SizeType(~0)) |         AssignIfExist(additionalItems_, value, "additionalItems"); | ||||||
|                 minItems_ = static_cast<SizeType>(minItemsItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator maxItemsItr = value.FindMember("maxItems"); |  | ||||||
|         if (maxItemsItr != value.MemberEnd()) { |  | ||||||
|             if (maxItemsItr->value.IsUint64() && maxItemsItr->value.GetUint64() <= SizeType(~0)) |  | ||||||
|                 maxItems_ = static_cast<SizeType>(maxItemsItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator additionalItemsItr = value.FindMember("additionalItems"); |  | ||||||
|         if (additionalItemsItr != value.MemberEnd()) { |  | ||||||
|             if (additionalItemsItr->value.IsBool()) |  | ||||||
|                 additionalItems_ = additionalItemsItr->value.GetBool(); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // String |         // String | ||||||
|         typename ValueType::ConstMemberIterator minLengthItr = value.FindMember("minLength"); |         AssignIfExist(minLength_, value, "minLength"); | ||||||
|         if (minLengthItr != value.MemberEnd()) { |         AssignIfExist(maxLength_, value, "maxLength"); | ||||||
|             if (minLengthItr->value.IsUint64() && minLengthItr->value.GetUint64() <= ~SizeType(0)) |  | ||||||
|                 minLength_ = static_cast<SizeType>(minLengthItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator maxLengthItr = value.FindMember("maxLength"); |  | ||||||
|         if (maxLengthItr != value.MemberEnd()) { |  | ||||||
|             if (maxLengthItr->value.IsUint64() && maxLengthItr->value.GetUint64() <= ~SizeType(0)) |  | ||||||
|                 maxLength_ = static_cast<SizeType>(maxLengthItr->value.GetUint64()); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|         typename ValueType::ConstMemberIterator patternItr = value.FindMember("pattern"); |         if (const ValueType* v = GetMember(value, "pattern")) | ||||||
|         if (patternItr != value.MemberEnd()) { |             pattern_ = CreatePattern(*v); | ||||||
|             if (patternItr->value.IsString()) { |  | ||||||
| #if RAPIDJSON_SCHEMA_USE_STDREGEX |  | ||||||
|                 try { |  | ||||||
|                     pattern_ = new std::basic_regex<Ch>( |  | ||||||
|                         patternItr->value.GetString(), |  | ||||||
|                         std::size_t(patternItr->value.GetStringLength()), |  | ||||||
|                         std::regex_constants::ECMAScript); |  | ||||||
|                 } |  | ||||||
|                 catch (const std::regex_error&) { |  | ||||||
|                     // Error |  | ||||||
|                 } |  | ||||||
| #endif // RAPIDJSON_SCHEMA_USE_STDREGEX |  | ||||||
|             } |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| #endif // RAPIDJSON_SCHEMA_HAS_REGEX | #endif // RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|  |  | ||||||
|         // Number |         // Number | ||||||
|         typename ValueType::ConstMemberIterator minimumItr = value.FindMember("minimum"); |         ConstMemberIterator minimumItr = value.FindMember("minimum"); | ||||||
|         if (minimumItr != value.MemberEnd()) { |         if (minimumItr != value.MemberEnd()) | ||||||
|             if (minimumItr->value.IsNumber()) |             if (minimumItr->value.IsNumber()) | ||||||
|                 minimum_ = minimumItr->value.GetDouble(); |                 minimum_ = minimumItr->value.GetDouble(); | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator maximumItr = value.FindMember("maximum"); |         ConstMemberIterator maximumItr = value.FindMember("maximum"); | ||||||
|         if (maximumItr != value.MemberEnd()) { |         if (maximumItr != value.MemberEnd()) | ||||||
|             if (maximumItr->value.IsNumber()) |             if (maximumItr->value.IsNumber()) | ||||||
|                 maximum_ = maximumItr->value.GetDouble(); |                 maximum_ = maximumItr->value.GetDouble(); | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator exclusiveMinimumItr = value.FindMember("exclusiveMinimum"); |         AssignIfExist(exclusiveMinimum_, value, "exclusiveMinimum"); | ||||||
|         if (exclusiveMinimumItr != value.MemberEnd()) { |         AssignIfExist(exclusiveMaximum_, value, "exclusiveMaximum"); | ||||||
|             if (exclusiveMinimumItr->value.IsBool()) |  | ||||||
|                 exclusiveMinimum_ = exclusiveMinimumItr->value.GetBool(); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator exclusiveMaximumItr = value.FindMember("exclusiveMaximum"); |         ConstMemberIterator multipleOfItr = value.FindMember("multipleOf"); | ||||||
|         if (exclusiveMaximumItr != value.MemberEnd()) { |  | ||||||
|             if (exclusiveMaximumItr->value.IsBool()) |  | ||||||
|                 exclusiveMaximum_ = exclusiveMaximumItr->value.GetBool(); |  | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         typename ValueType::ConstMemberIterator multipleOfItr = value.FindMember("multipleOf"); |  | ||||||
|         if (multipleOfItr != value.MemberEnd()) { |         if (multipleOfItr != value.MemberEnd()) { | ||||||
|             if (multipleOfItr->value.IsNumber()) { |             if (multipleOfItr->value.IsNumber()) { | ||||||
|                 multipleOf_ = multipleOfItr->value.GetDouble(); |                 multipleOf_ = multipleOfItr->value.GetDouble(); | ||||||
|                 hasMultipleOf_ = true; |                 hasMultipleOf_ = true; | ||||||
|             } |             } | ||||||
|             else { |  | ||||||
|                 // Error |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     ~BaseSchema() { |     ~BaseSchema() { | ||||||
|         delete not_; |         delete not_; | ||||||
|  |  | ||||||
|         delete [] properties_; |         delete [] properties_; | ||||||
|         delete additionalPropertySchema_; |         delete additionalPropertySchema_; | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|         delete [] patternProperties_; |         delete [] patternProperties_; | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         delete itemsList_; |         delete itemsList_; | ||||||
|         for (SizeType i = 0; i < itemsTupleCount_; i++) |         for (SizeType i = 0; i < itemsTupleCount_; i++) | ||||||
|             delete itemsTuple_[i]; |             delete itemsTuple_[i]; | ||||||
|         delete [] itemsTuple_; |         delete [] itemsTuple_; | ||||||
|  |  | ||||||
| #if RAPIDJSON_SCHEMA_USE_STDREGEX | #if RAPIDJSON_SCHEMA_USE_STDREGEX | ||||||
|         delete pattern_; |         delete pattern_; | ||||||
| #endif | #endif | ||||||
| @@ -500,21 +330,19 @@ public: | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool EndValue(Context& context) const { |     bool EndValue(Context& context) const { | ||||||
|         if (allOf_.schemas) { |         if (allOf_.schemas) | ||||||
|             for (SizeType i_ = 0; i_ < allOf_.count; i_++) |             for (SizeType i_ = 0; i_ < allOf_.count; i_++) | ||||||
|                 if (!context.allOfValidators.validators[i_]->IsValid()) |                 if (!context.allOfValidators.validators[i_]->IsValid()) | ||||||
|                     return false; |                     return false; | ||||||
|         } |          | ||||||
|         if (anyOf_.schemas) { |         if (anyOf_.schemas) { | ||||||
|             bool anyValid = false; |  | ||||||
|             for (SizeType i_ = 0; i_ < anyOf_.count; i_++) |             for (SizeType i_ = 0; i_ < anyOf_.count; i_++) | ||||||
|                 if (context.anyOfValidators.validators[i_]->IsValid()) { |                 if (context.anyOfValidators.validators[i_]->IsValid()) | ||||||
|                     anyValid = true; |                     goto foundAny; | ||||||
|                     break; |  | ||||||
|                 } |  | ||||||
|             if (!anyValid) |  | ||||||
|             return false; |             return false; | ||||||
|  |             foundAny:; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (oneOf_.schemas) { |         if (oneOf_.schemas) { | ||||||
|             CreateSchemaValidators(context, context.oneOfValidators, oneOf_); |             CreateSchemaValidators(context, context.oneOfValidators, oneOf_); | ||||||
|             bool oneValid = false; |             bool oneValid = false; | ||||||
| @@ -528,11 +356,8 @@ public: | |||||||
|             if (!oneValid) |             if (!oneValid) | ||||||
|                 return false; |                 return false; | ||||||
|         } |         } | ||||||
|         if (not_) { |  | ||||||
|             if (context.notValidator->IsValid()) |         return !not_ || !context.notValidator->IsValid(); | ||||||
|                 return false; |  | ||||||
|         } |  | ||||||
|         return true; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool Null(Context& context) const {  |     bool Null(Context& context) const {  | ||||||
| @@ -599,14 +424,9 @@ public: | |||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|         if (pattern_) { |         if (pattern_ && !IsPatternMatch(*pattern_, str, length)) | ||||||
| #if RAPIDJSON_SCHEMA_USE_STDREGEX |  | ||||||
|             std::match_results<const Ch*> r; |  | ||||||
|             if (!std::regex_search(str, str + length, r, *pattern_)) |  | ||||||
|             return false; |             return false; | ||||||
| #endif // RAPIDJSON_SCHEMA_USE_STDREGEX | #endif | ||||||
|         } |  | ||||||
| #endif // RAPIDJSON_SCHEMA_HAS_REGEX |  | ||||||
|  |  | ||||||
|         return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(str, length).Move()); |         return !enum_.IsArray() || CheckEnum(GenericValue<Encoding>(str, length).Move()); | ||||||
|     } |     } | ||||||
| @@ -643,19 +463,12 @@ public: | |||||||
|         } |         } | ||||||
|  |  | ||||||
| #if RAPIDJSON_SCHEMA_HAS_REGEX | #if RAPIDJSON_SCHEMA_HAS_REGEX | ||||||
|         if (patternProperties_) { |         if (patternProperties_) | ||||||
|             for (SizeType i = 0; i < patternPropertyCount_; i++) { |             for (SizeType i = 0; i < patternPropertyCount_; i++) | ||||||
| #if RAPIDJSON_SCHEMA_USE_STDREGEX |                 if (patternProperties_[i].pattern && IsPatternMatch(*patternProperties_[i].pattern, str, len)) { | ||||||
|                 if (patternProperties_[i].pattern) { |  | ||||||
|                     std::match_results<const Ch*> r; |  | ||||||
|                     if (std::regex_search(str, str + len, r, *patternProperties_[i].pattern)) { |  | ||||||
|                     context.valueSchema = patternProperties_[i].schema; |                     context.valueSchema = patternProperties_[i].schema; | ||||||
|                     return true; |                     return true; | ||||||
|                 } |                 } | ||||||
|                 } |  | ||||||
| #endif // RAPIDJSON_SCHEMA_USE_STDREGEX |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|         if (additionalPropertySchema_) { |         if (additionalPropertySchema_) { | ||||||
| @@ -678,13 +491,12 @@ public: | |||||||
|         if (context.objectRequiredCount != requiredCount_ || memberCount < minProperties_ || memberCount > maxProperties_) |         if (context.objectRequiredCount != requiredCount_ || memberCount < minProperties_ || memberCount > maxProperties_) | ||||||
|             return false; |             return false; | ||||||
|  |  | ||||||
|         if (hasDependencies_) { |         if (hasDependencies_) | ||||||
|             for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) |             for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) | ||||||
|                 if (context.objectDependencies[sourceIndex] && properties_[sourceIndex].dependencies) |                 if (context.objectDependencies[sourceIndex] && properties_[sourceIndex].dependencies) | ||||||
|                     for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) |                     for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++) | ||||||
|                         if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex]) |                         if (properties_[sourceIndex].dependencies[targetIndex] && !context.objectDependencies[targetIndex]) | ||||||
|                             return false; |                             return false; | ||||||
|         } |  | ||||||
|  |  | ||||||
|         return true; |         return true; | ||||||
|     } |     } | ||||||
| @@ -708,39 +520,70 @@ public: | |||||||
|         return elementCount >= minItems_ && elementCount <= maxItems_; |         return elementCount >= minItems_ && elementCount <= maxItems_; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| #undef RAPIDJSON_BASESCHEMA_HANDLER_LGOICAL_ | private: | ||||||
| #undef RAPIDJSON_BASESCHEMA_HANDLER_ |  | ||||||
|  |  | ||||||
| protected: |  | ||||||
|     static const BaseSchema<Encoding>* GetTypeless() { |     static const BaseSchema<Encoding>* GetTypeless() { | ||||||
|         static BaseSchema<Encoding> typeless(Value(kObjectType).Move()); |         static BaseSchema<Encoding> typeless(Value(kObjectType).Move()); | ||||||
|         return &typeless; |         return &typeless; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void AddType(const Value& type) { |     template <typename ValueType> | ||||||
|         if      (type == Value("null"   ).Move()) type_ |= 1 << kNullSchemaType; |     static const ValueType* GetMember(const ValueType& value, const char* name) { | ||||||
|         else if (type == Value("boolean").Move()) type_ |= 1 << kBooleanSchemaType; |         typename ValueType::ConstMemberIterator itr = value.FindMember(name); | ||||||
|         else if (type == Value("object" ).Move()) type_ |= 1 << kObjectSchemaType; |         return itr != value.MemberEnd() ? &(itr->value) : 0; | ||||||
|         else if (type == Value("array"  ).Move()) type_ |= 1 << kArraySchemaType; |     } | ||||||
|         else if (type == Value("string" ).Move()) type_ |= 1 << kStringSchemaType; |  | ||||||
|         else if (type == Value("integer").Move()) type_ |= 1 << kIntegerSchemaType; |     template <typename ValueType> | ||||||
|         else if (type == Value("number" ).Move()) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); |     static void AssignIfExist(bool& out, const ValueType& value, const char* name) { | ||||||
|         else { |         if (const ValueType* v = GetMember(value, name)) | ||||||
|             // Error |             if (v->IsBool()) | ||||||
|  |                 out = v->GetBool(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename ValueType> | ||||||
|  |     static void AssignIfExist(SizeType& out, const ValueType& value, const char* name) { | ||||||
|  |         if (const ValueType* v = GetMember(value, name)) | ||||||
|  |             if (v->IsUint64() && v->GetUint64() <= SizeType(~0)) | ||||||
|  |                 out = static_cast<SizeType>(v->GetUint64()); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename ValueType> | ||||||
|  |     static void AssigIfExist(BaseSchemaArray<Encoding>& out, const ValueType& value, const char* name) { | ||||||
|  |         if (const ValueType* v = GetMember(value, name)) | ||||||
|  |             if (v->IsArray() && v->Size() > 0) { | ||||||
|  |                 out.count = v->Size(); | ||||||
|  |                 out.schemas = new BaseSchema*[out.count]; | ||||||
|  |                 memset(out.schemas, 0, sizeof(BaseSchema*)* out.count); | ||||||
|  |                 for (SizeType i = 0; i < out.count; i++) | ||||||
|  |                     out.schemas[i] = new BaseSchema<Encoding>((*v)[i]); | ||||||
|             } |             } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void CreateLogicalSchemas(const Value& logic, BaseSchemaArray<Encoding>& logicSchemas) { | #if RAPIDJSON_SCHEMA_USE_STDREGEX | ||||||
|         if (logic.IsArray() && logic.Size() > 0) { |     template <typename ValueType> | ||||||
|             logicSchemas.count = logic.Size(); |     static std::basic_regex<Ch>* CreatePattern(const ValueType& value) { | ||||||
|             logicSchemas.schemas = new BaseSchema*[logicSchemas.count]; |         if (value.IsString()) | ||||||
|             memset(logicSchemas.schemas, 0, sizeof(BaseSchema*) * logicSchemas.count); |             try { | ||||||
|             for (SizeType i = 0; i < logicSchemas.count; i++) |                 return new std::basic_regex<Ch>(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript); | ||||||
|                 logicSchemas.schemas[i] = new BaseSchema<Encoding>(logic[i]); |  | ||||||
|             } |             } | ||||||
|         else { |             catch (const std::regex_error&) { | ||||||
|             // Error |  | ||||||
|             } |             } | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     static bool IsPatternMatch(const std::basic_regex<Ch>& pattern, const Ch *str, SizeType length) { | ||||||
|  |         std::match_results<const Ch*> r; | ||||||
|  |         return std::regex_search(str, str + length, r, pattern); | ||||||
|  |     } | ||||||
|  | #endif // RAPIDJSON_SCHEMA_USE_STDREGEX | ||||||
|  |  | ||||||
|  |     void AddType(const Value& type) { | ||||||
|  |         if      (type == "null"   ) type_ |= 1 << kNullSchemaType; | ||||||
|  |         else if (type == "boolean") type_ |= 1 << kBooleanSchemaType; | ||||||
|  |         else if (type == "object" ) type_ |= 1 << kObjectSchemaType; | ||||||
|  |         else if (type == "array"  ) type_ |= 1 << kArraySchemaType; | ||||||
|  |         else if (type == "string" ) type_ |= 1 << kStringSchemaType; | ||||||
|  |         else if (type == "integer") type_ |= 1 << kIntegerSchemaType; | ||||||
|  |         else if (type == "number" ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool CheckEnum(const GenericValue<Encoding>& v) const { |     bool CheckEnum(const GenericValue<Encoding>& v) const { | ||||||
| @@ -755,7 +598,7 @@ protected: | |||||||
|         if (anyOf_.schemas) CreateSchemaValidators(context, context.anyOfValidators, anyOf_); |         if (anyOf_.schemas) CreateSchemaValidators(context, context.anyOfValidators, anyOf_); | ||||||
|         if (oneOf_.schemas) CreateSchemaValidators(context, context.oneOfValidators, oneOf_); |         if (oneOf_.schemas) CreateSchemaValidators(context, context.oneOfValidators, oneOf_); | ||||||
|         if (not_ && !context.notValidator) |         if (not_ && !context.notValidator) | ||||||
|             context.notValidator = new GenericSchemaValidator<Encoding>(*not_);//context.schemaValidatorFactory->CreateSchemaValidator(*not_); |             context.notValidator = new GenericSchemaValidator<Encoding>(*not_); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void CreateSchemaValidators(Context& context, SchemaValidatorArray<Encoding>& validators, const BaseSchemaArray<Encoding>& schemas) const { |     void CreateSchemaValidators(Context& context, SchemaValidatorArray<Encoding>& validators, const BaseSchemaArray<Encoding>& schemas) const { | ||||||
| @@ -770,25 +613,21 @@ protected: | |||||||
|     // O(n) |     // O(n) | ||||||
|     template <typename ValueType> |     template <typename ValueType> | ||||||
|     bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { |     bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const { | ||||||
|         for (SizeType index = 0; index < propertyCount_; index++) { |         for (SizeType index = 0; index < propertyCount_; index++) | ||||||
|             if (properties_[index].name == name) { |             if (properties_[index].name == name) { | ||||||
|                 *outIndex = index; |                 *outIndex = index; | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // O(n) |     // O(n) | ||||||
|     bool FindPropertyIndex(const Ch* str, SizeType length, SizeType* outIndex) const { |     bool FindPropertyIndex(const Ch* str, SizeType length, SizeType* outIndex) const { | ||||||
|         for (SizeType index = 0; index < propertyCount_; index++) { |         for (SizeType index = 0; index < propertyCount_; index++) | ||||||
|             if (properties_[index].name.GetStringLength() == length &&  |             if (properties_[index].name.GetStringLength() == length && std::memcmp(properties_[index].name.GetString(), str, length) == 0) { | ||||||
|                 std::memcmp(properties_[index].name.GetString(), str, length) == 0) |  | ||||||
|             { |  | ||||||
|                 *outIndex = index; |                 *outIndex = index; | ||||||
|                 return true; |                 return true; | ||||||
|             } |             } | ||||||
|         } |  | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -884,8 +723,6 @@ public: | |||||||
|         delete root_; |         delete root_; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     bool IsValid() const { return root_ != 0; } |  | ||||||
|  |  | ||||||
| private: | private: | ||||||
|     BaseSchema<Encoding>* root_; |     BaseSchema<Encoding>* root_; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -21,7 +21,6 @@ using namespace rapidjson; | |||||||
|  |  | ||||||
| #define VALIDATE(schema, json, expected) \ | #define VALIDATE(schema, json, expected) \ | ||||||
| {\ | {\ | ||||||
|     ASSERT_TRUE(schema.IsValid());\ |  | ||||||
|     SchemaValidator validator(schema);\ |     SchemaValidator validator(schema);\ | ||||||
|     Document d;\ |     Document d;\ | ||||||
|     /*printf("\n%s\n", json);*/\ |     /*printf("\n%s\n", json);*/\ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 miloyip
					miloyip