15 #ifndef RAPIDJSON_SCHEMA_H_ 16 #define RAPIDJSON_SCHEMA_H_ 20 #include "stringbuffer.h" 25 #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX) 26 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1 28 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0 31 #if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800)) 32 #define RAPIDJSON_SCHEMA_USE_STDREGEX 1 34 #define RAPIDJSON_SCHEMA_USE_STDREGEX 0 37 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 38 #include "internal/regex.h" 39 #elif RAPIDJSON_SCHEMA_USE_STDREGEX 43 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX 44 #define RAPIDJSON_SCHEMA_HAS_REGEX 1 46 #define RAPIDJSON_SCHEMA_HAS_REGEX 0 49 #ifndef RAPIDJSON_SCHEMA_VERBOSE 50 #define RAPIDJSON_SCHEMA_VERBOSE 0 53 #if RAPIDJSON_SCHEMA_VERBOSE 54 #include "stringbuffer.h" 60 RAPIDJSON_DIAG_OFF(effc++)
64 RAPIDJSON_DIAG_OFF(weak-vtables)
65 RAPIDJSON_DIAG_OFF(exit-time-destructors)
66 RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
67 RAPIDJSON_DIAG_OFF(variadic-macros)
68 #elif defined(_MSC_VER) 69 RAPIDJSON_DIAG_OFF(4512)
77 #if RAPIDJSON_SCHEMA_VERBOSE 81 inline void PrintInvalidKeyword(
const char* keyword) {
82 printf(
"Fail keyword: %s\n", keyword);
85 inline void PrintInvalidKeyword(
const wchar_t* keyword) {
86 wprintf(L
"Fail keyword: %ls\n", keyword);
89 inline void PrintInvalidDocument(
const char* document) {
90 printf(
"Fail document: %s\n\n", document);
93 inline void PrintInvalidDocument(
const wchar_t* document) {
94 wprintf(L
"Fail document: %ls\n\n", document);
97 inline void PrintValidatorPointers(
unsigned depth,
const char* s,
const char* d) {
98 printf(
"S: %*s%s\nD: %*s%s\n\n", depth * 4,
" ", s, depth * 4,
" ", d);
101 inline void PrintValidatorPointers(
unsigned depth,
const wchar_t* s,
const wchar_t* d) {
102 wprintf(L
"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L
" ", s, depth * 4, L
" ", d);
107 #endif // RAPIDJSON_SCHEMA_VERBOSE 112 #if RAPIDJSON_SCHEMA_VERBOSE 113 #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword) 115 #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) 118 #define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\ 119 RAPIDJSON_MULTILINEMACRO_BEGIN\ 120 context.invalidCode = code;\ 121 context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\ 122 RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\ 124 RAPIDJSON_MULTILINEMACRO_END 135 #ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS 136 #define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags 143 kValidateNoFlags = 0,
144 kValidateContinueOnErrorFlag = 1,
151 template <
typename ValueType,
typename Allocator>
156 template <
typename SchemaDocumentType>
165 virtual bool IsValid()
const = 0;
166 virtual void SetValidateFlags(
unsigned flags) = 0;
167 virtual unsigned GetValidateFlags()
const = 0;
173 template <
typename SchemaType>
177 virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType&,
const bool inheritContinueOnErrors) = 0;
179 virtual void* CreateHasher() = 0;
180 virtual uint64_t GetHashCode(
void* hasher) = 0;
181 virtual void DestroryHasher(
void* hasher) = 0;
182 virtual void* MallocState(
size_t size) = 0;
183 virtual void FreeState(
void* p) = 0;
189 template <
typename SchemaType>
192 typedef typename SchemaType::Ch Ch;
193 typedef typename SchemaType::SValue SValue;
197 virtual void NotMultipleOf(int64_t actual,
const SValue& expected) = 0;
198 virtual void NotMultipleOf(uint64_t actual,
const SValue& expected) = 0;
199 virtual void NotMultipleOf(
double actual,
const SValue& expected) = 0;
200 virtual void AboveMaximum(int64_t actual,
const SValue& expected,
bool exclusive) = 0;
201 virtual void AboveMaximum(uint64_t actual,
const SValue& expected,
bool exclusive) = 0;
202 virtual void AboveMaximum(
double actual,
const SValue& expected,
bool exclusive) = 0;
203 virtual void BelowMinimum(int64_t actual,
const SValue& expected,
bool exclusive) = 0;
204 virtual void BelowMinimum(uint64_t actual,
const SValue& expected,
bool exclusive) = 0;
205 virtual void BelowMinimum(
double actual,
const SValue& expected,
bool exclusive) = 0;
207 virtual void TooLong(
const Ch* str, SizeType length, SizeType expected) = 0;
208 virtual void TooShort(
const Ch* str, SizeType length, SizeType expected) = 0;
209 virtual void DoesNotMatch(
const Ch* str, SizeType length) = 0;
211 virtual void DisallowedItem(SizeType index) = 0;
212 virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;
213 virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;
214 virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;
216 virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;
217 virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;
218 virtual void StartMissingProperties() = 0;
219 virtual void AddMissingProperty(
const SValue& name) = 0;
220 virtual bool EndMissingProperties() = 0;
221 virtual void PropertyViolations(
ISchemaValidator** subvalidators, SizeType count) = 0;
222 virtual void DisallowedProperty(
const Ch* name, SizeType length) = 0;
224 virtual void StartDependencyErrors() = 0;
225 virtual void StartMissingDependentProperties() = 0;
226 virtual void AddMissingDependentProperty(
const SValue& targetName) = 0;
227 virtual void EndMissingDependentProperties(
const SValue& sourceName) = 0;
228 virtual void AddDependencySchemaError(
const SValue& souceName,
ISchemaValidator* subvalidator) = 0;
229 virtual bool EndDependencyErrors() = 0;
232 virtual void StartDisallowedType() = 0;
233 virtual void AddExpectedType(
const typename SchemaType::ValueType& expectedType) = 0;
234 virtual void EndDisallowedType(
const typename SchemaType::ValueType& actualType) = 0;
235 virtual void NotAllOf(
ISchemaValidator** subvalidators, SizeType count) = 0;
237 virtual void NotOneOf(
ISchemaValidator** subvalidators, SizeType count,
bool matched) = 0;
238 virtual void Disallowed() = 0;
246 template<
typename Encoding,
typename Allocator>
249 typedef typename Encoding::Ch Ch;
251 Hasher(Allocator* allocator = 0,
size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
253 bool Null() {
return WriteType(kNullType); }
254 bool Bool(
bool b) {
return WriteType(b ? kTrueType : kFalseType); }
255 bool Int(
int i) { Number n; n.u.i = i; n.d =
static_cast<double>(i);
return WriteNumber(n); }
256 bool Uint(
unsigned u) { Number n; n.u.u = u; n.d =
static_cast<double>(u);
return WriteNumber(n); }
257 bool Int64(int64_t i) { Number n; n.u.i = i; n.d =
static_cast<double>(i);
return WriteNumber(n); }
258 bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d =
static_cast<double>(u);
return WriteNumber(n); }
261 if (d < 0) n.u.i =
static_cast<int64_t
>(d);
262 else n.u.u =
static_cast<uint64_t
>(d);
264 return WriteNumber(n);
267 bool RawNumber(
const Ch* str, SizeType len,
bool) {
268 WriteBuffer(kNumberType, str, len *
sizeof(Ch));
272 bool String(
const Ch* str, SizeType len,
bool) {
273 WriteBuffer(kStringType, str, len *
sizeof(Ch));
277 bool StartObject() {
return true; }
278 bool Key(
const Ch* str, SizeType len,
bool copy) {
return String(str, len, copy); }
279 bool EndObject(SizeType memberCount) {
280 uint64_t h = Hash(0, kObjectType);
281 uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
282 for (SizeType i = 0; i < memberCount; i++)
283 h ^= Hash(kv[i * 2], kv[i * 2 + 1]);
284 *stack_.template Push<uint64_t>() = h;
288 bool StartArray() {
return true; }
289 bool EndArray(SizeType elementCount) {
290 uint64_t h = Hash(0, kArrayType);
291 uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
292 for (SizeType i = 0; i < elementCount; i++)
294 *stack_.template Push<uint64_t>() = h;
298 bool IsValid()
const {
return stack_.GetSize() ==
sizeof(uint64_t); }
300 uint64_t GetHashCode()
const {
302 return *stack_.template Top<uint64_t>();
306 static const size_t kDefaultSize = 256;
315 bool WriteType(Type type) {
return WriteBuffer(type, 0, 0); }
317 bool WriteNumber(
const Number& n) {
return WriteBuffer(kNumberType, &n,
sizeof(n)); }
319 bool WriteBuffer(Type type,
const void* data,
size_t len) {
321 uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
322 const unsigned char* d =
static_cast<const unsigned char*
>(data);
323 for (
size_t i = 0; i < len; i++)
325 *stack_.template Push<uint64_t>() = h;
329 static uint64_t Hash(uint64_t h, uint64_t d) {
330 static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
342 template <
typename SchemaDocumentType>
347 typedef typename SchemaType::ValueType ValueType;
348 typedef typename ValueType::Ch Ch;
350 enum PatternValidatorType {
351 kPatternValidatorOnly,
352 kPatternValidatorWithProperty,
353 kPatternValidatorWithAdditionalProperty
364 arrayElementHashCodes(),
367 patternPropertiesValidators(),
368 patternPropertiesValidatorCount(),
369 patternPropertiesSchemas(),
370 patternPropertiesSchemaCount(),
371 valuePatternValidatorType(kPatternValidatorOnly),
374 valueUniqueness(
false),
375 arrayUniqueness(
false)
381 factory.DestroryHasher(hasher);
383 for (SizeType i = 0; i < validatorCount; i++)
384 factory.DestroySchemaValidator(validators[i]);
385 factory.FreeState(validators);
387 if (patternPropertiesValidators) {
388 for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
389 factory.DestroySchemaValidator(patternPropertiesValidators[i]);
390 factory.FreeState(patternPropertiesValidators);
392 if (patternPropertiesSchemas)
393 factory.FreeState(patternPropertiesSchemas);
395 factory.FreeState(propertyExist);
398 SchemaValidatorFactoryType& factory;
400 const SchemaType* schema;
401 const SchemaType* valueSchema;
402 const Ch* invalidKeyword;
405 void* arrayElementHashCodes;
407 SizeType validatorCount;
409 SizeType patternPropertiesValidatorCount;
410 const SchemaType** patternPropertiesSchemas;
411 SizeType patternPropertiesSchemaCount;
412 PatternValidatorType valuePatternValidatorType;
413 PatternValidatorType objectPatternValidatorType;
414 SizeType arrayElementIndex;
417 bool valueUniqueness;
418 bool arrayUniqueness;
424 template <
typename SchemaDocumentType>
427 typedef typename SchemaDocumentType::ValueType ValueType;
428 typedef typename SchemaDocumentType::AllocatorType AllocatorType;
429 typedef typename SchemaDocumentType::PointerType PointerType;
430 typedef typename ValueType::EncodingType EncodingType;
431 typedef typename EncodingType::Ch Ch;
439 Schema(SchemaDocumentType* schemaDocument,
const PointerType& p,
const ValueType&
value,
const ValueType& document, AllocatorType* allocator,
const UriType&
id = UriType()) :
440 allocator_(allocator),
441 uri_(schemaDocument->GetURI(), *allocator),
443 pointer_(p, allocator),
444 typeless_(schemaDocument->GetTypeless()),
448 type_((1 << kTotalSchemaType) - 1),
450 notValidatorIndex_(),
452 additionalPropertiesSchema_(),
453 patternProperties_(),
454 patternPropertyCount_(),
457 maxProperties_(SizeType(~0)),
458 additionalProperties_(
true),
461 hasSchemaDependencies_(),
462 additionalItemsSchema_(),
467 maxItems_(SizeType(~0)),
468 additionalItems_(
true),
472 maxLength_(~SizeType(0)),
473 exclusiveMinimum_(
false),
474 exclusiveMaximum_(
false),
475 defaultValueLength_(0)
477 typedef typename ValueType::ConstValueIterator ConstValueIterator;
478 typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
484 if (
this != typeless_) {
485 typedef typename SchemaDocumentType::SchemaEntry SchemaEntry;
486 SchemaEntry *entry = schemaDocument->schemaMap_.template Push<SchemaEntry>();
487 new (entry) SchemaEntry(pointer_,
this,
true, allocator_);
488 schemaDocument->AddSchemaRefs(
this);
491 if (!value.IsObject())
495 if (
const ValueType* v = GetMember(value, GetIdString())) {
497 UriType local(*v, allocator);
498 id_ = local.Resolve(id_, allocator);
502 if (
const ValueType* v = GetMember(value, GetTypeString())) {
506 else if (v->IsArray())
507 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
511 if (
const ValueType* v = GetMember(value, GetEnumString())) {
512 if (v->IsArray() && v->Size() > 0) {
513 enum_ =
static_cast<uint64_t*
>(allocator_->Malloc(
sizeof(uint64_t) * v->Size()));
514 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
518 EnumHasherType h(&hasherAllocator, 256);
520 enum_[enumCount_++] = h.GetHashCode();
525 if (schemaDocument) {
526 AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
527 AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
528 AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
530 if (
const ValueType* v = GetMember(value, GetNotString())) {
531 schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_);
532 notValidatorIndex_ = validatorCount_;
539 const ValueType* properties = GetMember(value, GetPropertiesString());
540 const ValueType* required = GetMember(value, GetRequiredString());
541 const ValueType* dependencies = GetMember(value, GetDependenciesString());
544 SValue allProperties(kArrayType);
546 if (properties && properties->IsObject())
547 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
548 AddUniqueElement(allProperties, itr->name);
550 if (required && required->IsArray())
551 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
553 AddUniqueElement(allProperties, *itr);
555 if (dependencies && dependencies->IsObject())
556 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
557 AddUniqueElement(allProperties, itr->name);
558 if (itr->value.IsArray())
559 for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
561 AddUniqueElement(allProperties, *i);
564 if (allProperties.Size() > 0) {
565 propertyCount_ = allProperties.Size();
566 properties_ =
static_cast<Property*
>(allocator_->Malloc(
sizeof(Property) * propertyCount_));
567 for (SizeType i = 0; i < propertyCount_; i++) {
568 new (&properties_[i]) Property();
569 properties_[i].name = allProperties[i];
570 properties_[i].schema = typeless_;
575 if (properties && properties->IsObject()) {
576 PointerType q = p.Append(GetPropertiesString(), allocator_);
577 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
579 if (FindPropertyIndex(itr->name, &index))
580 schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
584 if (
const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
585 PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
586 patternProperties_ =
static_cast<PatternProperty*
>(allocator_->Malloc(
sizeof(PatternProperty) * v->MemberCount()));
587 patternPropertyCount_ = 0;
589 for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
590 new (&patternProperties_[patternPropertyCount_]) PatternProperty();
591 patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
592 schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
593 patternPropertyCount_++;
597 if (required && required->IsArray())
598 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
599 if (itr->IsString()) {
601 if (FindPropertyIndex(*itr, &index)) {
602 properties_[index].required =
true;
607 if (dependencies && dependencies->IsObject()) {
608 PointerType q = p.Append(GetDependenciesString(), allocator_);
609 hasDependencies_ =
true;
610 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
611 SizeType sourceIndex;
612 if (FindPropertyIndex(itr->name, &sourceIndex)) {
613 if (itr->value.IsArray()) {
614 properties_[sourceIndex].dependencies =
static_cast<bool*
>(allocator_->Malloc(
sizeof(
bool) * propertyCount_));
615 std::memset(properties_[sourceIndex].dependencies, 0,
sizeof(
bool)* propertyCount_);
616 for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
617 SizeType targetIndex;
618 if (FindPropertyIndex(*targetItr, &targetIndex))
619 properties_[sourceIndex].dependencies[targetIndex] =
true;
622 else if (itr->value.IsObject()) {
623 hasSchemaDependencies_ =
true;
624 schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_);
625 properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
632 if (
const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
634 additionalProperties_ = v->GetBool();
635 else if (v->IsObject())
636 schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_);
639 AssignIfExist(minProperties_, value, GetMinPropertiesString());
640 AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
643 if (
const ValueType* v = GetMember(value, GetItemsString())) {
644 PointerType q = p.Append(GetItemsString(), allocator_);
646 schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_);
647 else if (v->IsArray()) {
648 itemsTuple_ =
static_cast<const Schema**
>(allocator_->Malloc(
sizeof(
const Schema*) * v->Size()));
650 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
651 schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_);
655 AssignIfExist(minItems_, value, GetMinItemsString());
656 AssignIfExist(maxItems_, value, GetMaxItemsString());
658 if (
const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
660 additionalItems_ = v->GetBool();
661 else if (v->IsObject())
662 schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_);
665 AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
668 AssignIfExist(minLength_, value, GetMinLengthString());
669 AssignIfExist(maxLength_, value, GetMaxLengthString());
671 if (
const ValueType* v = GetMember(value, GetPatternString()))
672 pattern_ = CreatePattern(*v);
675 if (
const ValueType* v = GetMember(value, GetMinimumString()))
677 minimum_.CopyFrom(*v, *allocator_);
679 if (
const ValueType* v = GetMember(value, GetMaximumString()))
681 maximum_.CopyFrom(*v, *allocator_);
683 AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
684 AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
686 if (
const ValueType* v = GetMember(value, GetMultipleOfString()))
687 if (v->IsNumber() && v->GetDouble() > 0.0)
688 multipleOf_.CopyFrom(*v, *allocator_);
691 if (
const ValueType* v = GetMember(value, GetDefaultValueString()))
693 defaultValueLength_ = v->GetStringLength();
698 AllocatorType::Free(enum_);
700 for (SizeType i = 0; i < propertyCount_; i++)
701 properties_[i].~Property();
702 AllocatorType::Free(properties_);
704 if (patternProperties_) {
705 for (SizeType i = 0; i < patternPropertyCount_; i++)
706 patternProperties_[i].~PatternProperty();
707 AllocatorType::Free(patternProperties_);
709 AllocatorType::Free(itemsTuple_);
710 #if RAPIDJSON_SCHEMA_HAS_REGEX 712 pattern_->~RegexType();
713 AllocatorType::Free(pattern_);
718 const SValue& GetURI()
const {
722 const UriType& GetId()
const {
726 const PointerType& GetPointer()
const {
730 bool BeginValue(Context& context)
const {
731 if (context.inArray) {
733 context.valueUniqueness =
true;
736 context.valueSchema = itemsList_;
737 else if (itemsTuple_) {
738 if (context.arrayElementIndex < itemsTupleCount_)
739 context.valueSchema = itemsTuple_[context.arrayElementIndex];
740 else if (additionalItemsSchema_)
741 context.valueSchema = additionalItemsSchema_;
742 else if (additionalItems_)
743 context.valueSchema = typeless_;
745 context.error_handler.DisallowedItem(context.arrayElementIndex);
747 context.valueSchema = typeless_;
749 context.arrayElementIndex++;
754 context.valueSchema = typeless_;
756 context.arrayElementIndex++;
761 RAPIDJSON_FORCEINLINE
bool EndValue(Context& context)
const {
763 if (context.patternPropertiesValidatorCount > 0) {
764 bool otherValid =
false;
765 SizeType count = context.patternPropertiesValidatorCount;
766 if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
767 otherValid = context.patternPropertiesValidators[--count]->IsValid();
769 bool patternValid =
true;
770 for (SizeType i = 0; i < count; i++)
771 if (!context.patternPropertiesValidators[i]->IsValid()) {
772 patternValid =
false;
776 if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
778 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
782 else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
783 if (!patternValid || !otherValid) {
784 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
788 else if (!patternValid && !otherValid) {
789 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
795 if (enum_ && context.hasher) {
796 const uint64_t h = context.factory.GetHashCode(context.hasher);
797 for (SizeType i = 0; i < enumCount_; i++)
806 if (context.validatorCount > 0) {
808 for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
809 if (!context.validators[i]->IsValid()) {
810 context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
814 if (anyOf_.schemas) {
815 for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
816 if (context.validators[i]->IsValid())
818 context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
823 if (oneOf_.schemas) {
824 bool oneValid =
false;
825 for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
826 if (context.validators[i]->IsValid()) {
828 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count,
true);
834 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count,
false);
839 if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
840 context.error_handler.Disallowed();
848 bool Null(Context& context)
const {
849 if (!(type_ & (1 << kNullSchemaType))) {
850 DisallowedType(context, GetNullString());
853 return CreateParallelValidator(context);
856 bool Bool(Context& context,
bool)
const {
857 if (!(type_ & (1 << kBooleanSchemaType))) {
858 DisallowedType(context, GetBooleanString());
861 return CreateParallelValidator(context);
864 bool Int(Context& context,
int i)
const {
865 if (!CheckInt(context, i))
867 return CreateParallelValidator(context);
870 bool Uint(Context& context,
unsigned u)
const {
871 if (!CheckUint(context, u))
873 return CreateParallelValidator(context);
876 bool Int64(Context& context, int64_t i)
const {
877 if (!CheckInt(context, i))
879 return CreateParallelValidator(context);
882 bool Uint64(Context& context, uint64_t u)
const {
883 if (!CheckUint(context, u))
885 return CreateParallelValidator(context);
888 bool Double(Context& context,
double d)
const {
889 if (!(type_ & (1 << kNumberSchemaType))) {
890 DisallowedType(context, GetNumberString());
894 if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
897 if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
900 if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
903 return CreateParallelValidator(context);
906 bool String(Context& context,
const Ch* str, SizeType length,
bool)
const {
907 if (!(type_ & (1 << kStringSchemaType))) {
908 DisallowedType(context, GetStringString());
912 if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
914 if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
915 if (count < minLength_) {
916 context.error_handler.TooShort(str, length, minLength_);
919 if (count > maxLength_) {
920 context.error_handler.TooLong(str, length, maxLength_);
926 if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
927 context.error_handler.DoesNotMatch(str, length);
931 return CreateParallelValidator(context);
934 bool StartObject(Context& context)
const {
935 if (!(type_ & (1 << kObjectSchemaType))) {
936 DisallowedType(context, GetObjectString());
940 if (hasDependencies_ || hasRequired_) {
941 context.propertyExist =
static_cast<bool*
>(context.factory.MallocState(
sizeof(
bool) * propertyCount_));
942 std::memset(context.propertyExist, 0,
sizeof(
bool) * propertyCount_);
945 if (patternProperties_) {
946 SizeType count = patternPropertyCount_ + 1;
947 context.patternPropertiesSchemas =
static_cast<const SchemaType**
>(context.factory.MallocState(
sizeof(
const SchemaType*) * count));
948 context.patternPropertiesSchemaCount = 0;
949 std::memset(context.patternPropertiesSchemas, 0,
sizeof(SchemaType*) * count);
952 return CreateParallelValidator(context);
955 bool Key(Context& context,
const Ch* str, SizeType len,
bool)
const {
956 if (patternProperties_) {
957 context.patternPropertiesSchemaCount = 0;
958 for (SizeType i = 0; i < patternPropertyCount_; i++)
959 if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
960 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
961 context.valueSchema = typeless_;
966 if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
967 if (context.patternPropertiesSchemaCount > 0) {
968 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
969 context.valueSchema = typeless_;
970 context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
973 context.valueSchema = properties_[index].schema;
975 if (context.propertyExist)
976 context.propertyExist[index] =
true;
981 if (additionalPropertiesSchema_) {
982 if (context.patternPropertiesSchemaCount > 0) {
983 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
984 context.valueSchema = typeless_;
985 context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
988 context.valueSchema = additionalPropertiesSchema_;
991 else if (additionalProperties_) {
992 context.valueSchema = typeless_;
996 if (context.patternPropertiesSchemaCount == 0) {
998 context.valueSchema = typeless_;
999 context.error_handler.DisallowedProperty(str, len);
1006 bool EndObject(Context& context, SizeType memberCount)
const {
1008 context.error_handler.StartMissingProperties();
1009 for (SizeType index = 0; index < propertyCount_; index++)
1010 if (properties_[index].required && !context.propertyExist[index])
1011 if (properties_[index].schema->defaultValueLength_ == 0 )
1012 context.error_handler.AddMissingProperty(properties_[index].name);
1013 if (context.error_handler.EndMissingProperties())
1017 if (memberCount < minProperties_) {
1018 context.error_handler.TooFewProperties(memberCount, minProperties_);
1022 if (memberCount > maxProperties_) {
1023 context.error_handler.TooManyProperties(memberCount, maxProperties_);
1027 if (hasDependencies_) {
1028 context.error_handler.StartDependencyErrors();
1029 for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
1030 const Property& source = properties_[sourceIndex];
1031 if (context.propertyExist[sourceIndex]) {
1032 if (source.dependencies) {
1033 context.error_handler.StartMissingDependentProperties();
1034 for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
1035 if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
1036 context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
1037 context.error_handler.EndMissingDependentProperties(source.name);
1039 else if (source.dependenciesSchema) {
1040 ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
1041 if (!dependenciesValidator->IsValid())
1042 context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
1046 if (context.error_handler.EndDependencyErrors())
1053 bool StartArray(Context& context)
const {
1054 context.arrayElementIndex = 0;
1055 context.inArray =
true;
1057 if (!(type_ & (1 << kArraySchemaType))) {
1058 DisallowedType(context, GetArrayString());
1062 return CreateParallelValidator(context);
1065 bool EndArray(Context& context, SizeType elementCount)
const {
1066 context.inArray =
false;
1068 if (elementCount < minItems_) {
1069 context.error_handler.TooFewItems(elementCount, minItems_);
1073 if (elementCount > maxItems_) {
1074 context.error_handler.TooManyItems(elementCount, maxItems_);
1081 static const ValueType& GetValidateErrorKeyword(
ValidateErrorCode validateErrorCode) {
1082 switch (validateErrorCode) {
1114 default:
return GetNullString();
1120 #define RAPIDJSON_STRING_(name, ...) \ 1121 static const ValueType& Get##name##String() {\ 1122 static const Ch s[] = { __VA_ARGS__, '\0' };\ 1123 static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\ 1127 RAPIDJSON_STRING_(Null,
'n',
'u',
'l',
'l')
1128 RAPIDJSON_STRING_(Boolean,
'b',
'o',
'o',
'l',
'e',
'a',
'n')
1129 RAPIDJSON_STRING_(Object,
'o',
'b',
'j',
'e',
'c',
't')
1130 RAPIDJSON_STRING_(Array,
'a',
'r',
'r',
'a',
'y')
1131 RAPIDJSON_STRING_(String,
's',
't',
'r',
'i',
'n',
'g')
1132 RAPIDJSON_STRING_(Number,
'n',
'u',
'm',
'b',
'e',
'r')
1133 RAPIDJSON_STRING_(Integer,
'i',
'n',
't',
'e',
'g',
'e',
'r')
1134 RAPIDJSON_STRING_(Type,
't',
'y',
'p',
'e')
1135 RAPIDJSON_STRING_(Enum,
'e',
'n',
'u',
'm')
1136 RAPIDJSON_STRING_(AllOf,
'a',
'l',
'l',
'O',
'f')
1137 RAPIDJSON_STRING_(AnyOf,
'a',
'n',
'y',
'O',
'f')
1138 RAPIDJSON_STRING_(OneOf,
'o',
'n',
'e',
'O',
'f')
1139 RAPIDJSON_STRING_(Not,
'n',
'o',
't')
1140 RAPIDJSON_STRING_(Properties,
'p',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1141 RAPIDJSON_STRING_(Required,
'r',
'e',
'q',
'u',
'i',
'r',
'e',
'd')
1142 RAPIDJSON_STRING_(Dependencies,
'd',
'e',
'p',
'e',
'n',
'd',
'e',
'n',
'c',
'i',
'e',
's')
1143 RAPIDJSON_STRING_(PatternProperties,
'p',
'a',
't',
't',
'e',
'r',
'n',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1144 RAPIDJSON_STRING_(AdditionalProperties,
'a',
'd',
'd',
'i',
't',
'i',
'o',
'n',
'a',
'l',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1145 RAPIDJSON_STRING_(MinProperties,
'm',
'i',
'n',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1146 RAPIDJSON_STRING_(MaxProperties,
'm',
'a',
'x',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1147 RAPIDJSON_STRING_(Items,
'i',
't',
'e',
'm',
's')
1148 RAPIDJSON_STRING_(MinItems,
'm',
'i',
'n',
'I',
't',
'e',
'm',
's')
1149 RAPIDJSON_STRING_(MaxItems,
'm',
'a',
'x',
'I',
't',
'e',
'm',
's')
1150 RAPIDJSON_STRING_(AdditionalItems,
'a',
'd',
'd',
'i',
't',
'i',
'o',
'n',
'a',
'l',
'I',
't',
'e',
'm',
's')
1151 RAPIDJSON_STRING_(UniqueItems,
'u',
'n',
'i',
'q',
'u',
'e',
'I',
't',
'e',
'm',
's')
1152 RAPIDJSON_STRING_(MinLength,
'm',
'i',
'n',
'L',
'e',
'n',
'g',
't',
'h')
1153 RAPIDJSON_STRING_(MaxLength,
'm',
'a',
'x',
'L',
'e',
'n',
'g',
't',
'h')
1154 RAPIDJSON_STRING_(Pattern,
'p',
'a',
't',
't',
'e',
'r',
'n')
1155 RAPIDJSON_STRING_(Minimum,
'm',
'i',
'n',
'i',
'm',
'u',
'm')
1156 RAPIDJSON_STRING_(Maximum,
'm',
'a',
'x',
'i',
'm',
'u',
'm')
1157 RAPIDJSON_STRING_(ExclusiveMinimum,
'e',
'x',
'c',
'l',
'u',
's',
'i',
'v',
'e',
'M',
'i',
'n',
'i',
'm',
'u',
'm')
1158 RAPIDJSON_STRING_(ExclusiveMaximum,
'e',
'x',
'c',
'l',
'u',
's',
'i',
'v',
'e',
'M',
'a',
'x',
'i',
'm',
'u',
'm')
1159 RAPIDJSON_STRING_(MultipleOf,
'm',
'u',
'l',
't',
'i',
'p',
'l',
'e',
'O',
'f')
1160 RAPIDJSON_STRING_(DefaultValue,
'd',
'e',
'f',
'a',
'u',
'l',
't')
1161 RAPIDJSON_STRING_(Ref,
'$',
'r',
'e',
'f')
1162 RAPIDJSON_STRING_(Id,
'i',
'd')
1164 RAPIDJSON_STRING_(SchemeEnd,
':')
1165 RAPIDJSON_STRING_(AuthStart,
'/',
'/')
1166 RAPIDJSON_STRING_(QueryStart,
'?')
1167 RAPIDJSON_STRING_(FragStart,
'#')
1168 RAPIDJSON_STRING_(Slash,
'/')
1169 RAPIDJSON_STRING_(Dot,
'.')
1171 #undef RAPIDJSON_STRING_ 1174 enum SchemaValueType {
1185 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1187 #elif RAPIDJSON_SCHEMA_USE_STDREGEX 1188 typedef std::basic_regex<Ch> RegexType;
1190 typedef char RegexType;
1193 struct SchemaArray {
1194 SchemaArray() : schemas(), count() {}
1195 ~SchemaArray() { AllocatorType::Free(schemas); }
1196 const SchemaType** schemas;
1201 template <
typename V1,
typename V2>
1202 void AddUniqueElement(V1& a,
const V2& v) {
1203 for (
typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1206 V1 c(v, *allocator_);
1207 a.PushBack(c, *allocator_);
1210 static const ValueType* GetMember(
const ValueType& value,
const ValueType& name) {
1211 typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1212 return itr != value.MemberEnd() ? &(itr->value) : 0;
1215 static void AssignIfExist(
bool& out,
const ValueType& value,
const ValueType& name) {
1216 if (
const ValueType* v = GetMember(value, name))
1221 static void AssignIfExist(SizeType& out,
const ValueType& value,
const ValueType& name) {
1222 if (
const ValueType* v = GetMember(value, name))
1223 if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
1224 out = static_cast<SizeType>(v->GetUint64());
1227 void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument,
const PointerType& p,
const ValueType& value,
const ValueType& name,
const ValueType& document) {
1228 if (
const ValueType* v = GetMember(value, name)) {
1229 if (v->IsArray() && v->Size() > 0) {
1230 PointerType q = p.Append(name, allocator_);
1231 out.count = v->Size();
1232 out.schemas =
static_cast<const Schema**
>(allocator_->Malloc(out.count *
sizeof(
const Schema*)));
1233 memset(out.schemas, 0,
sizeof(Schema*)* out.count);
1234 for (SizeType i = 0; i < out.count; i++)
1235 schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_);
1236 out.begin = validatorCount_;
1237 validatorCount_ += out.count;
1242 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1243 template <
typename ValueType>
1244 RegexType* CreatePattern(
const ValueType& value) {
1245 if (value.IsString()) {
1246 RegexType* r =
new (allocator_->Malloc(
sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1247 if (!r->IsValid()) {
1249 AllocatorType::Free(r);
1257 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str, SizeType) {
1259 return rs.Search(str);
1261 #elif RAPIDJSON_SCHEMA_USE_STDREGEX 1262 template <
typename ValueType>
1263 RegexType* CreatePattern(
const ValueType& value) {
1264 if (value.IsString()) {
1265 RegexType *r =
static_cast<RegexType*
>(allocator_->Malloc(
sizeof(RegexType)));
1267 return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1269 catch (
const std::regex_error&) {
1270 AllocatorType::Free(r);
1276 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str, SizeType length) {
1277 std::match_results<const Ch*> r;
1278 return std::regex_search(str, str + length, r, *pattern);
1281 template <
typename ValueType>
1282 RegexType* CreatePattern(
const ValueType&) {
return 0; }
1284 static bool IsPatternMatch(
const RegexType*,
const Ch *, SizeType) {
return true; }
1285 #endif // RAPIDJSON_SCHEMA_USE_STDREGEX 1287 void AddType(
const ValueType& type) {
1288 if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1289 else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1290 else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1291 else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1292 else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1293 else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1294 else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1297 bool CreateParallelValidator(Context& context)
const {
1298 if (enum_ || context.arrayUniqueness)
1299 context.hasher = context.factory.CreateHasher();
1301 if (validatorCount_) {
1304 context.validatorCount = validatorCount_;
1308 CreateSchemaValidators(context, allOf_,
false);
1311 CreateSchemaValidators(context, anyOf_,
false);
1314 CreateSchemaValidators(context, oneOf_,
false);
1317 context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_,
false);
1319 if (hasSchemaDependencies_) {
1320 for (SizeType i = 0; i < propertyCount_; i++)
1321 if (properties_[i].dependenciesSchema)
1322 context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema,
false);
1329 void CreateSchemaValidators(Context& context,
const SchemaArray& schemas,
const bool inheritContinueOnErrors)
const {
1330 for (SizeType i = 0; i < schemas.count; i++)
1331 context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors);
1335 bool FindPropertyIndex(
const ValueType& name, SizeType* outIndex)
const {
1336 SizeType len = name.GetStringLength();
1337 const Ch* str = name.GetString();
1338 for (SizeType index = 0; index < propertyCount_; index++)
1339 if (properties_[index].name.GetStringLength() == len &&
1340 (std::memcmp(properties_[index].name.GetString(), str,
sizeof(Ch) * len) == 0))
1348 bool CheckInt(Context& context, int64_t i)
const {
1349 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1350 DisallowedType(context, GetIntegerString());
1354 if (!minimum_.IsNull()) {
1355 if (minimum_.IsInt64()) {
1356 if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1357 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1361 else if (minimum_.IsUint64()) {
1362 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1365 else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1369 if (!maximum_.IsNull()) {
1370 if (maximum_.IsInt64()) {
1371 if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1372 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1376 else if (maximum_.IsUint64()) { }
1378 else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1382 if (!multipleOf_.IsNull()) {
1383 if (multipleOf_.IsUint64()) {
1384 if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1385 context.error_handler.NotMultipleOf(i, multipleOf_);
1389 else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1396 bool CheckUint(Context& context, uint64_t i)
const {
1397 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1398 DisallowedType(context, GetIntegerString());
1402 if (!minimum_.IsNull()) {
1403 if (minimum_.IsUint64()) {
1404 if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1405 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1409 else if (minimum_.IsInt64())
1411 else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1415 if (!maximum_.IsNull()) {
1416 if (maximum_.IsUint64()) {
1417 if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1418 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1422 else if (maximum_.IsInt64()) {
1423 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1426 else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1430 if (!multipleOf_.IsNull()) {
1431 if (multipleOf_.IsUint64()) {
1432 if (i % multipleOf_.GetUint64() != 0) {
1433 context.error_handler.NotMultipleOf(i, multipleOf_);
1437 else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1444 bool CheckDoubleMinimum(Context& context,
double d)
const {
1445 if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1446 context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
1452 bool CheckDoubleMaximum(Context& context,
double d)
const {
1453 if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1454 context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
1460 bool CheckDoubleMultipleOf(Context& context,
double d)
const {
1461 double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1462 double q = std::floor(a / b);
1463 double r = a - q * b;
1465 context.error_handler.NotMultipleOf(d, multipleOf_);
1471 void DisallowedType(Context& context,
const ValueType& actualType)
const {
1472 ErrorHandler& eh = context.error_handler;
1473 eh.StartDisallowedType();
1475 if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1476 if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1477 if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1478 if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1479 if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1481 if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1482 else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1484 eh.EndDisallowedType(actualType);
1488 Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(
false) {}
1489 ~Property() { AllocatorType::Free(dependencies); }
1491 const SchemaType* schema;
1492 const SchemaType* dependenciesSchema;
1493 SizeType dependenciesValidatorIndex;
1498 struct PatternProperty {
1499 PatternProperty() : schema(), pattern() {}
1500 ~PatternProperty() {
1502 pattern->~RegexType();
1503 AllocatorType::Free(pattern);
1506 const SchemaType* schema;
1510 AllocatorType* allocator_;
1513 PointerType pointer_;
1514 const SchemaType* typeless_;
1516 SizeType enumCount_;
1520 const SchemaType* not_;
1522 SizeType validatorCount_;
1523 SizeType notValidatorIndex_;
1525 Property* properties_;
1526 const SchemaType* additionalPropertiesSchema_;
1527 PatternProperty* patternProperties_;
1528 SizeType patternPropertyCount_;
1529 SizeType propertyCount_;
1530 SizeType minProperties_;
1531 SizeType maxProperties_;
1532 bool additionalProperties_;
1533 bool hasDependencies_;
1535 bool hasSchemaDependencies_;
1537 const SchemaType* additionalItemsSchema_;
1538 const SchemaType* itemsList_;
1539 const SchemaType** itemsTuple_;
1540 SizeType itemsTupleCount_;
1543 bool additionalItems_;
1546 RegexType* pattern_;
1547 SizeType minLength_;
1548 SizeType maxLength_;
1553 bool exclusiveMinimum_;
1554 bool exclusiveMaximum_;
1556 SizeType defaultValueLength_;
1559 template<
typename Stack,
typename Ch>
1561 RAPIDJSON_FORCEINLINE
static void AppendIndexToken(
Stack& documentStack, SizeType index) {
1562 *documentStack.template Push<Ch>() =
'/';
1564 size_t length =
static_cast<size_t>((
sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
1565 for (
size_t i = 0; i < length; i++)
1566 *documentStack.template Push<Ch>() =
static_cast<Ch
>(buffer[i]);
1571 template <
typename Stack>
1573 RAPIDJSON_FORCEINLINE
static void AppendIndexToken(
Stack& documentStack, SizeType index) {
1574 if (
sizeof(SizeType) == 4) {
1575 char *
buffer = documentStack.template Push<char>(1 + 10);
1577 const char* end = internal::u32toa(index, buffer);
1578 documentStack.template Pop<char>(
static_cast<size_t>(10 - (end - buffer)));
1581 char *
buffer = documentStack.template Push<char>(1 + 20);
1583 const char* end = internal::u64toa(index, buffer);
1584 documentStack.template Pop<char>(
static_cast<size_t>(20 - (end - buffer)));
1594 template <
typename SchemaDocumentType>
1597 typedef typename SchemaDocumentType::Ch Ch;
1598 typedef typename SchemaDocumentType::ValueType ValueType;
1599 typedef typename SchemaDocumentType::AllocatorType AllocatorType;
1602 virtual const SchemaDocumentType* GetRemoteDocument(
const Ch* uri, SizeType length) = 0;
1618 template <
typename ValueT,
typename Allocator = CrtAllocator>
1621 typedef ValueT ValueType;
1623 typedef Allocator AllocatorType;
1624 typedef typename ValueType::EncodingType EncodingType;
1625 typedef typename EncodingType::Ch Ch;
1631 template <
typename,
typename,
typename>
1646 IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0,
1647 const PointerType& pointer = PointerType()) :
1648 remoteProvider_(remoteProvider),
1649 allocator_(allocator),
1653 schemaMap_(allocator, kInitialSchemaMapSize),
1654 schemaRef_(allocator, kInitialSchemaRefSize)
1657 ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
1660 uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
1661 docId_ = UriType(uri_, allocator_);
1663 typeless_ =
static_cast<SchemaType*
>(allocator_->Malloc(
sizeof(SchemaType)));
1664 new (typeless_) SchemaType(
this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_);
1670 if (pointer.GetTokenCount() == 0) {
1671 CreateSchemaRecursive(&root_, pointer, document, document, docId_);
1673 else if (
const ValueType* v = pointer.Get(document)) {
1674 CreateSchema(&root_, pointer, *v, document, docId_);
1679 schemaRef_.ShrinkToFit();
1682 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 1683 GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
1685 remoteProvider_(rhs.remoteProvider_),
1686 allocator_(rhs.allocator_),
1687 ownAllocator_(rhs.ownAllocator_),
1689 typeless_(rhs.typeless_),
1690 schemaMap_(std::move(rhs.schemaMap_)),
1691 schemaRef_(std::move(rhs.schemaRef_)),
1692 uri_(std::move(rhs.uri_)),
1695 rhs.remoteProvider_ = 0;
1697 rhs.ownAllocator_ = 0;
1704 while (!schemaMap_.Empty())
1705 schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
1708 typeless_->~SchemaType();
1709 Allocator::Free(typeless_);
1712 RAPIDJSON_DELETE(ownAllocator_);
1715 const SValue& GetURI()
const {
return uri_; }
1718 const SchemaType&
GetRoot()
const {
return *root_; }
1722 GenericSchemaDocument(
const GenericSchemaDocument&);
1724 GenericSchemaDocument& operator=(
const GenericSchemaDocument&);
1728 struct SchemaEntry {
1729 SchemaEntry(
const PointerType& p, SchemaType* s,
bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
1732 schema->~SchemaType();
1733 Allocator::Free(schema);
1736 PointerType pointer;
1742 void CreateSchemaRecursive(
const SchemaType** schema,
const PointerType& pointer,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1743 if (v.GetType() == kObjectType) {
1744 UriType newid = UriType(CreateSchema(schema, pointer, v, document,
id), allocator_);
1746 for (
typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
1747 CreateSchemaRecursive(0, pointer.
Append(itr->name, allocator_), itr->value, document, newid);
1749 else if (v.GetType() == kArrayType)
1750 for (SizeType i = 0; i < v.Size(); i++)
1751 CreateSchemaRecursive(0, pointer.
Append(i, allocator_), v[i], document, id);
1755 const UriType& CreateSchema(
const SchemaType** schema,
const PointerType& pointer,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1758 if (
const SchemaType* sc = GetSchema(pointer)) {
1761 AddSchemaRefs(const_cast<SchemaType*>(sc));
1763 else if (!HandleRefSchema(pointer, schema, v, document,
id)) {
1765 SchemaType* s =
new (allocator_->Malloc(
sizeof(SchemaType))) SchemaType(
this, pointer, v, document, allocator_,
id);
1773 *schema = typeless_;
1774 AddSchemaRefs(typeless_);
1781 bool HandleRefSchema(
const PointerType& source,
const SchemaType** schema,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1782 typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString());
1783 if (itr == v.MemberEnd())
1787 new (schemaRef_.template Push<SchemaRefPtr>()) SchemaRefPtr(&source);
1789 if (itr->value.IsString()) {
1790 SizeType len = itr->value.GetStringLength();
1793 UriType scopeId = UriType(
id, allocator_);
1794 UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_);
1797 PointerType basePointer = PointerType();
1798 const ValueType *base = FindId(document, ref, basePointer, docId_,
false);
1801 if (remoteProvider_) {
1802 if (
const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref)) {
1803 const Ch* s = ref.GetFragString();
1804 len = ref.GetFragStringLength();
1805 if (len <= 1 || s[1] ==
'/') {
1807 const PointerType pointer(s, len, allocator_);
1808 if (pointer.IsValid()) {
1810 if (
const SchemaType *sc = remoteDocument->GetSchema(pointer)) {
1813 AddSchemaRefs(const_cast<SchemaType *>(sc));
1824 const Ch* s = ref.GetFragString();
1825 len = ref.GetFragStringLength();
1826 if (len <= 1 || s[1] ==
'/') {
1828 const PointerType relPointer(s, len, allocator_);
1829 if (relPointer.IsValid()) {
1831 if (
const ValueType *pv = relPointer.Get(*base)) {
1833 PointerType pointer(basePointer);
1834 for (SizeType i = 0; i < relPointer.GetTokenCount(); i++)
1835 pointer = pointer.
Append(relPointer.GetTokens()[i], allocator_);
1838 if (pointer.IsValid() && !IsCyclicRef(pointer)) {
1841 size_t unresolvedTokenIndex;
1842 scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1843 CreateSchema(schema, pointer, *pv, document, scopeId);
1852 PointerType pointer = PointerType();
1853 if (
const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_),
true, basePointer)) {
1854 if (!IsCyclicRef(pointer)) {
1859 size_t unresolvedTokenIndex;
1860 scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1861 CreateSchema(schema, pointer, *pv, document, scopeId);
1872 *schema = typeless_;
1873 AddSchemaRefs(typeless_);
1881 ValueType* FindId(
const ValueType& doc,
const UriType& finduri, PointerType& resptr,
const UriType& baseuri,
bool full,
const PointerType& here = PointerType())
const {
1883 ValueType* resval = 0;
1884 UriType tempuri = UriType(finduri, allocator_);
1885 UriType localuri = UriType(baseuri, allocator_);
1886 if (doc.GetType() == kObjectType) {
1888 typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString());
1889 if (m != doc.MemberEnd() && m->value.GetType() == kStringType) {
1890 localuri = UriType(m->value, allocator_).
Resolve(baseuri, allocator_);
1893 if (localuri.Match(finduri, full)) {
1894 resval =
const_cast<ValueType *
>(&doc);
1899 for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) {
1900 if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) {
1901 resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_));
1905 }
else if (doc.GetType() == kArrayType) {
1907 for (
typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) {
1908 if (v->GetType() == kObjectType || v->GetType() == kArrayType) {
1909 resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_));
1919 void AddSchemaRefs(SchemaType* schema) {
1920 while (!schemaRef_.Empty()) {
1921 SchemaRefPtr *ref = schemaRef_.template Pop<SchemaRefPtr>(1);
1922 SchemaEntry *entry = schemaMap_.template Push<SchemaEntry>();
1923 new (entry) SchemaEntry(**ref, schema,
false, allocator_);
1928 bool IsCyclicRef(
const PointerType& pointer)
const {
1929 for (
const SchemaRefPtr* ref = schemaRef_.template Bottom<SchemaRefPtr>(); ref != schemaRef_.template End<SchemaRefPtr>(); ++ref)
1930 if (pointer == **ref)
1935 const SchemaType* GetSchema(
const PointerType& pointer)
const {
1936 for (
const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1937 if (pointer == target->pointer)
1938 return target->schema;
1942 PointerType GetPointer(
const SchemaType* schema)
const {
1943 for (
const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1944 if (schema == target->schema)
1945 return target->pointer;
1946 return PointerType();
1949 const SchemaType* GetTypeless()
const {
return typeless_; }
1951 static const size_t kInitialSchemaMapSize = 64;
1952 static const size_t kInitialSchemaRefSize = 64;
1954 IRemoteSchemaDocumentProviderType* remoteProvider_;
1955 Allocator *allocator_;
1956 Allocator *ownAllocator_;
1957 const SchemaType* root_;
1958 SchemaType* typeless_;
1986 typename SchemaDocumentType,
1994 typedef typename SchemaDocumentType::SchemaType SchemaType;
1995 typedef typename SchemaDocumentType::PointerType PointerType;
1996 typedef typename SchemaType::EncodingType EncodingType;
1998 typedef typename EncodingType::Ch Ch;
2010 const SchemaDocumentType& schemaDocument,
2011 StateAllocator* allocator = 0,
2012 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2013 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2015 schemaDocument_(&schemaDocument),
2016 root_(schemaDocument.GetRoot()),
2017 stateAllocator_(allocator),
2018 ownStateAllocator_(0),
2019 schemaStack_(allocator, schemaStackCapacity),
2020 documentStack_(allocator, documentStackCapacity),
2022 error_(kObjectType),
2024 missingDependents_(),
2026 flags_(kValidateDefaultFlags)
2027 #if RAPIDJSON_SCHEMA_VERBOSE
2041 const SchemaDocumentType& schemaDocument,
2042 OutputHandler& outputHandler,
2043 StateAllocator* allocator = 0,
2044 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2045 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2047 schemaDocument_(&schemaDocument),
2048 root_(schemaDocument.GetRoot()),
2049 stateAllocator_(allocator),
2050 ownStateAllocator_(0),
2051 schemaStack_(allocator, schemaStackCapacity),
2052 documentStack_(allocator, documentStackCapacity),
2053 outputHandler_(&outputHandler),
2054 error_(kObjectType),
2056 missingDependents_(),
2058 flags_(kValidateDefaultFlags)
2059 #if RAPIDJSON_SCHEMA_VERBOSE
2068 RAPIDJSON_DELETE(ownStateAllocator_);
2073 while (!schemaStack_.Empty())
2075 documentStack_.Clear();
2082 currentError_.SetNull();
2083 missingDependents_.SetNull();
2091 virtual unsigned GetValidateFlags()
const {
2098 if (!valid_)
return false;
2099 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return false;
2105 const ValueType& GetError()
const {
return error_; }
2110 return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
2116 if (!schemaStack_.Empty())
return CurrentContext().invalidKeyword;
2117 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return (
const Ch*)GetErrorsString();
2124 if (!schemaStack_.Empty())
return CurrentContext().invalidCode;
2125 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return kValidateErrors;
2132 if (documentStack_.Empty()) {
2133 return PointerType();
2136 return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() /
sizeof(Ch));
2140 void NotMultipleOf(int64_t actual,
const SValue& expected) {
2143 void NotMultipleOf(uint64_t actual,
const SValue& expected) {
2146 void NotMultipleOf(
double actual,
const SValue& expected) {
2149 void AboveMaximum(int64_t actual,
const SValue& expected,
bool exclusive) {
2151 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2153 void AboveMaximum(uint64_t actual,
const SValue& expected,
bool exclusive) {
2155 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2157 void AboveMaximum(
double actual,
const SValue& expected,
bool exclusive) {
2159 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2161 void BelowMinimum(int64_t actual,
const SValue& expected,
bool exclusive) {
2163 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2165 void BelowMinimum(uint64_t actual,
const SValue& expected,
bool exclusive) {
2167 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2169 void BelowMinimum(
double actual,
const SValue& expected,
bool exclusive) {
2171 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2174 void TooLong(
const Ch* str, SizeType length, SizeType expected) {
2176 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2178 void TooShort(
const Ch* str, SizeType length, SizeType expected) {
2180 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2182 void DoesNotMatch(
const Ch* str, SizeType length) {
2183 currentError_.SetObject();
2184 currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
2188 void DisallowedItem(SizeType index) {
2189 currentError_.SetObject();
2190 currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
2193 void TooFewItems(SizeType actualCount, SizeType expectedCount) {
2195 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2197 void TooManyItems(SizeType actualCount, SizeType expectedCount) {
2199 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2201 void DuplicateItems(SizeType index1, SizeType index2) {
2202 ValueType duplicates(kArrayType);
2203 duplicates.PushBack(index1, GetStateAllocator());
2204 duplicates.PushBack(index2, GetStateAllocator());
2205 currentError_.SetObject();
2206 currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
2210 void TooManyProperties(SizeType actualCount, SizeType expectedCount) {
2212 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2214 void TooFewProperties(SizeType actualCount, SizeType expectedCount) {
2216 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2218 void StartMissingProperties() {
2219 currentError_.SetArray();
2221 void AddMissingProperty(
const SValue& name) {
2222 currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
2224 bool EndMissingProperties() {
2225 if (currentError_.Empty())
2227 ValueType error(kObjectType);
2228 error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
2229 currentError_ = error;
2233 void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {
2234 for (SizeType i = 0; i < count; ++i)
2235 MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2237 void DisallowedProperty(
const Ch* name, SizeType length) {
2238 currentError_.SetObject();
2239 currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
2243 void StartDependencyErrors() {
2244 currentError_.SetObject();
2246 void StartMissingDependentProperties() {
2247 missingDependents_.SetArray();
2249 void AddMissingDependentProperty(
const SValue& targetName) {
2250 missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
2252 void EndMissingDependentProperties(
const SValue& sourceName) {
2253 if (!missingDependents_.Empty()) {
2255 ValueType error(kObjectType);
2257 error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator());
2258 AddErrorCode(error, code);
2259 AddErrorInstanceLocation(error,
false);
2261 PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(
kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator());
2262 AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator()));
2263 ValueType wrapper(kObjectType);
2264 wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator());
2265 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator());
2268 void AddDependencySchemaError(
const SValue& sourceName, ISchemaValidator* subvalidator) {
2269 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2270 static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
2272 bool EndDependencyErrors() {
2273 if (currentError_.ObjectEmpty())
2275 ValueType error(kObjectType);
2276 error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
2277 currentError_ = error;
2283 currentError_.SetObject();
2284 AddCurrentError(code);
2286 void StartDisallowedType() {
2287 currentError_.SetArray();
2289 void AddExpectedType(
const typename SchemaType::ValueType& expectedType) {
2290 currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2292 void EndDisallowedType(
const typename SchemaType::ValueType& actualType) {
2293 ValueType error(kObjectType);
2294 error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2295 error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2296 currentError_ = error;
2299 void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {
2306 void NoneOf(ISchemaValidator** subvalidators, SizeType count) {
2309 void NotOneOf(ISchemaValidator** subvalidators, SizeType count,
bool matched =
false) {
2313 currentError_.SetObject();
2317 #define RAPIDJSON_STRING_(name, ...) \ 2318 static const StringRefType& Get##name##String() {\ 2319 static const Ch s[] = { __VA_ARGS__, '\0' };\ 2320 static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \ 2324 RAPIDJSON_STRING_(InstanceRef,
'i',
'n',
's',
't',
'a',
'n',
'c',
'e',
'R',
'e',
'f')
2325 RAPIDJSON_STRING_(SchemaRef,
's',
'c',
'h',
'e',
'm',
'a',
'R',
'e',
'f')
2326 RAPIDJSON_STRING_(Expected,
'e',
'x',
'p',
'e',
'c',
't',
'e',
'd')
2327 RAPIDJSON_STRING_(Actual,
'a',
'c',
't',
'u',
'a',
'l')
2328 RAPIDJSON_STRING_(Disallowed,
'd',
'i',
's',
'a',
'l',
'l',
'o',
'w',
'e',
'd')
2329 RAPIDJSON_STRING_(Missing,
'm',
'i',
's',
's',
'i',
'n',
'g')
2330 RAPIDJSON_STRING_(Errors,
'e',
'r',
'r',
'o',
'r',
's')
2331 RAPIDJSON_STRING_(ErrorCode,
'e',
'r',
'r',
'o',
'r',
'C',
'o',
'd',
'e')
2332 RAPIDJSON_STRING_(ErrorMessage,
'e',
'r',
'r',
'o',
'r',
'M',
'e',
's',
's',
'a',
'g',
'e')
2333 RAPIDJSON_STRING_(Duplicates,
'd',
'u',
'p',
'l',
'i',
'c',
'a',
't',
'e',
's')
2335 #undef RAPIDJSON_STRING_ 2337 #if RAPIDJSON_SCHEMA_VERBOSE 2338 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ 2339 RAPIDJSON_MULTILINEMACRO_BEGIN\ 2340 *documentStack_.template Push<Ch>() = '\0';\ 2341 documentStack_.template Pop<Ch>(1);\ 2342 internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\ 2343 RAPIDJSON_MULTILINEMACRO_END 2345 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() 2348 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ 2349 if (!valid_) return false; \ 2350 if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ 2351 RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ 2352 return valid_ = false;\ 2355 #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ 2356 for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\ 2357 if (context->hasher)\ 2358 static_cast<HasherType*>(context->hasher)->method arg2;\ 2359 if (context->validators)\ 2360 for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ 2361 static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\ 2362 if (context->patternPropertiesValidators)\ 2363 for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ 2364 static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\ 2367 #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ 2368 valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ 2371 #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ 2372 RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ 2373 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ 2374 RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) 2376 bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
2377 bool Bool(
bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
2378 bool Int(
int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
2379 bool Uint(
unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
2380 bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
2381 bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
2382 bool Double(
double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
2383 bool RawNumber(
const Ch* str, SizeType length,
bool copy)
2384 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2385 bool String(
const Ch* str, SizeType length,
bool copy)
2386 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2388 bool StartObject() {
2389 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
2390 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
2391 return valid_ = !outputHandler_ || outputHandler_->StartObject();
2394 bool Key(
const Ch* str, SizeType len,
bool copy) {
2395 if (!valid_)
return false;
2396 AppendToken(str, len);
2397 if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors())
return valid_ =
false;
2398 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
2399 return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2402 bool EndObject(SizeType memberCount) {
2403 if (!valid_)
return false;
2404 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
2405 if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors())
return valid_ =
false;
2406 RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
2410 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
2411 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
2412 return valid_ = !outputHandler_ || outputHandler_->StartArray();
2415 bool EndArray(SizeType elementCount) {
2416 if (!valid_)
return false;
2417 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
2418 if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors())
return valid_ =
false;
2419 RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
2422 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ 2423 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ 2424 #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ 2425 #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ 2428 virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType& root,
const bool inheritContinueOnErrors) {
2430 #if RAPIDJSON_SCHEMA_VERBOSE 2433 &GetStateAllocator());
2434 sv->
SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(
unsigned)kValidateContinueOnErrorFlag);
2438 virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2441 StateAllocator::Free(v);
2444 virtual void* CreateHasher() {
2448 virtual uint64_t GetHashCode(
void* hasher) {
2449 return static_cast<HasherType*
>(hasher)->GetHashCode();
2452 virtual void DestroryHasher(
void* hasher) {
2455 StateAllocator::Free(h);
2458 virtual void* MallocState(
size_t size) {
2459 return GetStateAllocator().Malloc(size);
2462 virtual void FreeState(
void* p) {
2463 StateAllocator::Free(p);
2467 typedef typename SchemaType::Context Context;
2472 const SchemaDocumentType& schemaDocument,
2473 const SchemaType& root,
2474 const char* basePath,
size_t basePathSize,
2475 #
if RAPIDJSON_SCHEMA_VERBOSE
2478 StateAllocator* allocator = 0,
2479 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2480 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2482 schemaDocument_(&schemaDocument),
2484 stateAllocator_(allocator),
2485 ownStateAllocator_(0),
2486 schemaStack_(allocator, schemaStackCapacity),
2487 documentStack_(allocator, documentStackCapacity),
2489 error_(kObjectType),
2491 missingDependents_(),
2493 flags_(kValidateDefaultFlags)
2494 #if RAPIDJSON_SCHEMA_VERBOSE 2498 if (basePath && basePathSize)
2499 memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2502 StateAllocator& GetStateAllocator() {
2503 if (!stateAllocator_)
2504 stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();
2505 return *stateAllocator_;
2508 bool GetContinueOnErrors()
const {
2509 return flags_ & kValidateContinueOnErrorFlag;
2513 if (schemaStack_.Empty())
2516 if (CurrentContext().inArray)
2519 if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors())
2522 SizeType count = CurrentContext().patternPropertiesSchemaCount;
2523 const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2524 typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2525 bool valueUniqueness = CurrentContext().valueUniqueness;
2527 PushSchema(*CurrentContext().valueSchema);
2530 CurrentContext().objectPatternValidatorType = patternValidatorType;
2531 ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2532 SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2533 va =
static_cast<ISchemaValidator**
>(MallocState(
sizeof(ISchemaValidator*) * count));
2534 for (SizeType i = 0; i < count; i++)
2535 va[validatorCount++] = CreateSchemaValidator(*sa[i],
true);
2538 CurrentContext().arrayUniqueness = valueUniqueness;
2544 if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors())
2547 #if RAPIDJSON_SCHEMA_VERBOSE 2549 schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2551 *documentStack_.template Push<Ch>() =
'\0';
2552 documentStack_.template Pop<Ch>(1);
2553 internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
2555 void* hasher = CurrentContext().hasher;
2556 uint64_t h = hasher && CurrentContext().arrayUniqueness ?
static_cast<HasherType*
>(hasher)->GetHashCode() : 0;
2560 if (!schemaStack_.Empty()) {
2561 Context& context = CurrentContext();
2563 if (hasher && context.valueUniqueness) {
2564 HashCodeArray* a =
static_cast<HashCodeArray*
>(context.arrayElementHashCodes);
2566 CurrentContext().arrayElementHashCodes = a =
new (GetStateAllocator().Malloc(
sizeof(HashCodeArray))) HashCodeArray(kArrayType);
2568 if (itr->GetUint64() == h) {
2569 DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
2571 if (GetContinueOnErrors()) {
2572 a->PushBack(h, GetStateAllocator());
2573 while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) !=
'/');
2577 a->PushBack(h, GetStateAllocator());
2582 while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) !=
'/')
2588 void AppendToken(
const Ch* str, SizeType len) {
2589 documentStack_.template Reserve<Ch>(1 + len * 2);
2590 *documentStack_.template PushUnsafe<Ch>() =
'/';
2591 for (SizeType i = 0; i < len; i++) {
2592 if (str[i] ==
'~') {
2593 *documentStack_.template PushUnsafe<Ch>() =
'~';
2594 *documentStack_.template PushUnsafe<Ch>() =
'0';
2596 else if (str[i] ==
'/') {
2597 *documentStack_.template PushUnsafe<Ch>() =
'~';
2598 *documentStack_.template PushUnsafe<Ch>() =
'1';
2601 *documentStack_.template PushUnsafe<Ch>() = str[i];
2605 RAPIDJSON_FORCEINLINE
void PushSchema(
const SchemaType& schema) {
new (schemaStack_.template Push<Context>()) Context(*
this, *
this, &schema); }
2607 RAPIDJSON_FORCEINLINE
void PopSchema() {
2608 Context* c = schemaStack_.template Pop<Context>(1);
2609 if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
2610 a->~HashCodeArray();
2611 StateAllocator::Free(a);
2616 void AddErrorInstanceLocation(ValueType& result,
bool parent) {
2618 PointerType instancePointer = GetInvalidDocumentPointer();
2619 ((parent && instancePointer.GetTokenCount() > 0)
2620 ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2621 : instancePointer).StringifyUriFragment(sb);
2622 ValueType instanceRef(sb.GetString(),
static_cast<SizeType
>(sb.
GetSize() /
sizeof(Ch)),
2623 GetStateAllocator());
2624 result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2627 void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) {
2629 SizeType len = CurrentSchema().GetURI().GetStringLength();
2630 if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len *
sizeof(Ch));
2631 if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
2632 else GetInvalidSchemaPointer().StringifyUriFragment(sb);
2633 ValueType schemaRef(sb.GetString(),
static_cast<SizeType
>(sb.
GetSize() /
sizeof(Ch)),
2634 GetStateAllocator());
2635 result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2639 result.AddMember(GetErrorCodeString(), code, GetStateAllocator());
2642 void AddError(ValueType& keyword, ValueType& error) {
2644 if (member == error_.MemberEnd())
2645 error_.AddMember(keyword, error, GetStateAllocator());
2647 if (member->value.IsObject()) {
2648 ValueType errors(kArrayType);
2649 errors.PushBack(member->value, GetStateAllocator());
2650 member->value = errors;
2652 member->value.PushBack(error, GetStateAllocator());
2657 AddErrorCode(currentError_, code);
2658 AddErrorInstanceLocation(currentError_, parent);
2659 AddErrorSchemaLocation(currentError_);
2660 AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(),
false).Move(), currentError_);
2663 void MergeError(ValueType& other) {
2665 AddError(it->name, it->value);
2669 void AddNumberError(
const ValidateErrorCode code, ValueType& actual,
const SValue& expected,
2670 const typename SchemaType::ValueType& (*exclusive)() = 0) {
2671 currentError_.SetObject();
2672 currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2673 currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2675 currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(),
true, GetStateAllocator());
2676 AddCurrentError(code);
2680 ISchemaValidator** subvalidators, SizeType count) {
2681 ValueType errors(kArrayType);
2682 for (SizeType i = 0; i < count; ++i)
2683 errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
2684 currentError_.SetObject();
2685 currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2686 AddCurrentError(code);
2689 const SchemaType& CurrentSchema()
const {
return *schemaStack_.template Top<Context>()->schema; }
2690 Context& CurrentContext() {
return *schemaStack_.template Top<Context>(); }
2691 const Context& CurrentContext()
const {
return *schemaStack_.template Top<Context>(); }
2693 static const size_t kDefaultSchemaStackCapacity = 1024;
2694 static const size_t kDefaultDocumentStackCapacity = 256;
2695 const SchemaDocumentType* schemaDocument_;
2696 const SchemaType& root_;
2697 StateAllocator* stateAllocator_;
2698 StateAllocator* ownStateAllocator_;
2701 OutputHandler* outputHandler_;
2703 ValueType currentError_;
2704 ValueType missingDependents_;
2707 #if RAPIDJSON_SCHEMA_VERBOSE 2728 unsigned parseFlags,
2729 typename InputStream,
2730 typename SourceEncoding,
2731 typename SchemaDocumentType = SchemaDocument,
2735 typedef typename SchemaDocumentType::PointerType PointerType;
2736 typedef typename InputStream::Ch Ch;
2746 template <
typename Handler>
2747 bool operator()(Handler& handler) {
2750 parseResult_ = reader.template Parse<parseFlags>(is_, validator);
2752 isValid_ = validator.
IsValid();
2754 invalidSchemaPointer_ = PointerType();
2755 invalidSchemaKeyword_ = 0;
2756 invalidDocumentPointer_ = PointerType();
2764 error_.CopyFrom(validator.
GetError(), allocator_);
2767 return parseResult_;
2770 const ParseResult& GetParseResult()
const {
return parseResult_; }
2771 bool IsValid()
const {
return isValid_; }
2772 const PointerType& GetInvalidSchemaPointer()
const {
return invalidSchemaPointer_; }
2773 const Ch* GetInvalidSchemaKeyword()
const {
return invalidSchemaKeyword_; }
2774 const PointerType& GetInvalidDocumentPointer()
const {
return invalidDocumentPointer_; }
2775 const ValueType& GetError()
const {
return error_; }
2780 const SchemaDocumentType& sd_;
2783 PointerType invalidSchemaPointer_;
2784 const Ch* invalidSchemaKeyword_;
2785 PointerType invalidDocumentPointer_;
2787 StackAllocator allocator_;
2795 #endif // RAPIDJSON_SCHEMA_H_ Number is greater than the 'maximum' value.
Definition: error.h:167
GenericSchemaDocument(const ValueType &document, const Ch *uri=0, SizeType uriLength=0, IRemoteSchemaDocumentProviderType *remoteProvider=0, Allocator *allocator=0, const PointerType &pointer=PointerType())
Constructor.
Definition: schema.h:1645
#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS
User-defined kValidateDefaultFlags definition.
Definition: schema.h:136
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, OutputHandler &outputHandler, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor with output handler.
Definition: schema.h:2040
virtual bool IsValid() const
Checks whether the current state is valid.
Definition: schema.h:2097
Represents an in-memory output stream.
Definition: fwd.h:59
void Reset()
Reset the internal states.
Definition: schema.h:2072
Object has missing property or schema dependencies.
Definition: error.h:186
size_t GetSize() const
Get the size of string in bytes in the string buffer.
Definition: stringbuffer.h:89
See other errors.
Definition: error.h:185
C-runtime library allocator.
Definition: allocators.h:82
Property has a type that is not allowed by the schema..
Definition: error.h:189
Property matched more than one of the sub-schemas specified by 'oneOf'.
Definition: error.h:192
Object has less members than 'minProperties' value.
Definition: error.h:182
Number is less than the 'minimum' value.
Definition: error.h:169
Array is shorter than the 'minItems' value.
Definition: error.h:177
ValueType & GetError()
Gets the error object.
Definition: schema.h:2104
Property did not match any of the sub-schemas specified by 'anyOf'.
Definition: error.h:194
Number is greater than or equal to the 'maximum' value.
Definition: error.h:168
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
A helper class for parsing with validation.
Definition: schema.h:2733
JSON Schema Validator.
Definition: fwd.h:145
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
Definition: schema.h:2115
Object is missing one or more members required by the schema.
Definition: error.h:183
Default implementation of Handler.
Definition: fwd.h:85
A contiguous memory buffer with an optional growing ability.
Definition: core.h:778
Property matched the sub-schema specified by 'not'.
Definition: error.h:195
Reference to a constant string (not taking a copy)
Definition: document.h:346
Object has additional members that are not allowed by the schema.
Definition: error.h:184
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
Definition: schema.h:2131
void SetValidateFlags(unsigned flags)
Implementation of ISchemaValidator.
Definition: schema.h:2088
Array has duplicate items but 'uniqueItems' is true.
Definition: error.h:178
Array is longer than the 'maxItems' value.
Definition: error.h:176
Default memory allocator used by the parser and DOM.
Definition: allocators.h:129
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor without output handler.
Definition: schema.h:2009
Number is less than or equal to the 'minimum' value.
Definition: error.h:170
ValidateErrorCode
Error codes when validating.
Definition: error.h:162
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
Array has additional items that are not allowed by the schema.
Definition: error.h:179
SchemaValidatingReader(InputStream &is, const SchemaDocumentType &sd)
Constructor.
Definition: schema.h:2744
Property has a value that is not one of its allowed enumerated values.
Definition: error.h:188
Object has more members than 'maxProperties' value.
Definition: error.h:181
Top level error code when kValidateContinueOnErrorsFlag set.
Definition: error.h:163
Property did not match any of the sub-schemas specified by 'oneOf'.
Definition: error.h:191
GenericUri Resolve(const GenericUri &baseuri, Allocator *allocator=0)
Resolve this URI against another (base) URI in accordance with URI resolution rules.
Definition: uri.h:156
A type-unsafe stack for storing different types of data.
Definition: stack.h:37
Definition: allocators.h:422
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:88
JSON schema document.
Definition: fwd.h:136
Property did not match all of the sub-schemas specified by 'allOf'.
Definition: error.h:193
GenericPointer Append(const Token &token, Allocator *allocator=0) const
Append a token and return a new Pointer.
Definition: pointer.h:247
String is longer than the 'maxLength' value.
Definition: error.h:172
const SchemaType & GetRoot() const
Get the root schema.
Definition: schema.h:1718
Regular expression engine with subset of ECMAscript grammar.
Definition: regex.h:110
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
Definition: schema.h:2109
Number is not a multiple of the 'multipleOf' value.
Definition: error.h:166
Result of parsing (wraps ParseErrorCode)
Definition: error.h:106
ValidateErrorCode GetInvalidSchemaCode() const
Gets the error code of invalid schema.
Definition: schema.h:2123
No error.
Definition: error.h:164
String does not match the 'pattern' regular expression.
Definition: error.h:174
String is longer than the 'maxLength' value.
Definition: error.h:173
void ResetError()
Reset the error state.
Definition: schema.h:2080
(Constant) member iterator for a JSON object value
Definition: document.h:186
~GenericSchemaDocument()
Destructor.
Definition: schema.h:1703
~GenericSchemaValidator()
Destructor.
Definition: schema.h:2066
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
Definition: schema.h:1560