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)
72 RAPIDJSON_NAMESPACE_BEGIN
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 151 template <
typename ValueType,
typename Allocator>
152 class GenericSchemaDocument;
156 template <
typename SchemaDocumentType>
162 class ISchemaValidator {
164 virtual ~ISchemaValidator() {}
165 virtual bool IsValid()
const = 0;
166 virtual void SetValidateFlags(
unsigned flags) = 0;
167 virtual unsigned GetValidateFlags()
const = 0;
173 template <
typename SchemaType>
174 class ISchemaStateFactory {
176 virtual ~ISchemaStateFactory() {}
177 virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType&,
const bool inheritContinueOnErrors) = 0;
178 virtual void DestroySchemaValidator(ISchemaValidator* validator) = 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>
190 class IValidationErrorHandler {
192 typedef typename SchemaType::Ch Ch;
193 typedef typename SchemaType::SValue SValue;
195 virtual ~IValidationErrorHandler() {}
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;
213 virtual void TooManyItems(
SizeType actualCount,
SizeType expectedCount) = 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;
236 virtual void NoneOf(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); }
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); }
259 bool Double(
double d) {
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) {
272 bool String(
const Ch* str,
SizeType len,
bool) {
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) {
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) {
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) {
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) {
336 Stack<Allocator> stack_;
342 template <
typename SchemaDocumentType>
343 struct SchemaValidationContext {
344 typedef Schema<SchemaDocumentType> SchemaType;
345 typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
346 typedef IValidationErrorHandler<SchemaType> ErrorHandlerType;
347 typedef typename SchemaType::ValueType ValueType;
348 typedef typename ValueType::Ch Ch;
350 enum PatternValidatorType {
351 kPatternValidatorOnly,
352 kPatternValidatorWithProperty,
353 kPatternValidatorWithAdditionalProperty
356 SchemaValidationContext(SchemaValidatorFactoryType& f, ErrorHandlerType& eh,
const SchemaType* s) :
364 arrayElementHashCodes(),
367 patternPropertiesValidators(),
368 patternPropertiesValidatorCount(),
369 patternPropertiesSchemas(),
370 patternPropertiesSchemaCount(),
371 valuePatternValidatorType(kPatternValidatorOnly),
374 valueUniqueness(false),
375 arrayUniqueness(false)
379 ~SchemaValidationContext() {
381 factory.DestroryHasher(hasher);
383 for (
SizeType i = 0; i < validatorCount; i++) {
385 factory.DestroySchemaValidator(validators[i]);
388 factory.FreeState(validators);
390 if (patternPropertiesValidators) {
391 for (
SizeType i = 0; i < patternPropertiesValidatorCount; i++) {
392 if (patternPropertiesValidators[i]) {
393 factory.DestroySchemaValidator(patternPropertiesValidators[i]);
396 factory.FreeState(patternPropertiesValidators);
398 if (patternPropertiesSchemas)
399 factory.FreeState(patternPropertiesSchemas);
401 factory.FreeState(propertyExist);
404 SchemaValidatorFactoryType& factory;
405 ErrorHandlerType& error_handler;
406 const SchemaType* schema;
407 const SchemaType* valueSchema;
408 const Ch* invalidKeyword;
411 void* arrayElementHashCodes;
412 ISchemaValidator** validators;
414 ISchemaValidator** patternPropertiesValidators;
415 SizeType patternPropertiesValidatorCount;
416 const SchemaType** patternPropertiesSchemas;
417 SizeType patternPropertiesSchemaCount;
418 PatternValidatorType valuePatternValidatorType;
419 PatternValidatorType objectPatternValidatorType;
423 bool valueUniqueness;
424 bool arrayUniqueness;
430 template <
typename SchemaDocumentType>
433 typedef typename SchemaDocumentType::ValueType ValueType;
434 typedef typename SchemaDocumentType::AllocatorType AllocatorType;
435 typedef typename SchemaDocumentType::PointerType PointerType;
436 typedef typename ValueType::EncodingType EncodingType;
437 typedef typename EncodingType::Ch Ch;
438 typedef SchemaValidationContext<SchemaDocumentType> Context;
439 typedef Schema<SchemaDocumentType> SchemaType;
440 typedef GenericValue<EncodingType, AllocatorType> SValue;
441 typedef IValidationErrorHandler<Schema> ErrorHandler;
442 typedef GenericUri<ValueType, AllocatorType> UriType;
443 friend class GenericSchemaDocument<ValueType, AllocatorType>;
445 Schema(SchemaDocumentType* schemaDocument,
const PointerType& p,
const ValueType& value,
const ValueType& document, AllocatorType* allocator,
const UriType&
id = UriType()) :
446 allocator_(allocator),
447 uri_(schemaDocument->GetURI(), *allocator),
449 pointer_(p, allocator),
450 typeless_(schemaDocument->GetTypeless()),
454 type_((1 << kTotalSchemaType) - 1),
456 notValidatorIndex_(),
458 additionalPropertiesSchema_(),
459 patternProperties_(),
460 patternPropertyCount_(),
464 additionalProperties_(true),
467 hasSchemaDependencies_(),
468 additionalItemsSchema_(),
474 additionalItems_(true),
479 exclusiveMinimum_(false),
480 exclusiveMaximum_(false),
481 defaultValueLength_(0)
483 typedef typename ValueType::ConstValueIterator ConstValueIterator;
484 typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
490 if (
this != typeless_) {
491 typedef typename SchemaDocumentType::SchemaEntry SchemaEntry;
492 SchemaEntry *entry = schemaDocument->schemaMap_.template Push<SchemaEntry>();
493 new (entry) SchemaEntry(pointer_,
this,
true, allocator_);
494 schemaDocument->AddSchemaRefs(
this);
497 if (!value.IsObject())
501 if (
const ValueType* v = GetMember(value, GetIdString())) {
503 UriType local(*v, allocator);
504 id_ = local.Resolve(id_, allocator);
508 if (
const ValueType* v = GetMember(value, GetTypeString())) {
512 else if (v->IsArray())
513 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
517 if (
const ValueType* v = GetMember(value, GetEnumString())) {
518 if (v->IsArray() && v->Size() > 0) {
519 enum_ =
static_cast<uint64_t*
>(allocator_->Malloc(
sizeof(uint64_t) * v->Size()));
520 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
521 typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
522 char buffer[256u + 24];
523 MemoryPoolAllocator<> hasherAllocator(buffer,
sizeof(buffer));
524 EnumHasherType h(&hasherAllocator, 256);
526 enum_[enumCount_++] = h.GetHashCode();
531 if (schemaDocument) {
532 AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
533 AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
534 AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
536 if (
const ValueType* v = GetMember(value, GetNotString())) {
537 schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document, id_);
538 notValidatorIndex_ = validatorCount_;
545 const ValueType* properties = GetMember(value, GetPropertiesString());
546 const ValueType* required = GetMember(value, GetRequiredString());
547 const ValueType* dependencies = GetMember(value, GetDependenciesString());
552 if (properties && properties->IsObject())
553 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
554 AddUniqueElement(allProperties, itr->name);
556 if (required && required->IsArray())
557 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
559 AddUniqueElement(allProperties, *itr);
561 if (dependencies && dependencies->IsObject())
562 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
563 AddUniqueElement(allProperties, itr->name);
564 if (itr->value.IsArray())
565 for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
567 AddUniqueElement(allProperties, *i);
570 if (allProperties.Size() > 0) {
571 propertyCount_ = allProperties.Size();
572 properties_ =
static_cast<Property*
>(allocator_->Malloc(
sizeof(Property) * propertyCount_));
573 for (
SizeType i = 0; i < propertyCount_; i++) {
574 new (&properties_[i]) Property();
575 properties_[i].name = allProperties[i];
576 properties_[i].schema = typeless_;
581 if (properties && properties->IsObject()) {
582 PointerType q = p.Append(GetPropertiesString(), allocator_);
583 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
585 if (FindPropertyIndex(itr->name, &index))
586 schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
590 if (
const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
591 PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
592 patternProperties_ =
static_cast<PatternProperty*
>(allocator_->Malloc(
sizeof(PatternProperty) * v->MemberCount()));
593 patternPropertyCount_ = 0;
595 for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
596 new (&patternProperties_[patternPropertyCount_]) PatternProperty();
597 patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
598 schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
599 patternPropertyCount_++;
603 if (required && required->IsArray())
604 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
605 if (itr->IsString()) {
607 if (FindPropertyIndex(*itr, &index)) {
608 properties_[index].required =
true;
613 if (dependencies && dependencies->IsObject()) {
614 PointerType q = p.Append(GetDependenciesString(), allocator_);
615 hasDependencies_ =
true;
616 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
618 if (FindPropertyIndex(itr->name, &sourceIndex)) {
619 if (itr->value.IsArray()) {
620 properties_[sourceIndex].dependencies =
static_cast<bool*
>(allocator_->Malloc(
sizeof(
bool) * propertyCount_));
621 std::memset(properties_[sourceIndex].dependencies, 0,
sizeof(
bool)* propertyCount_);
622 for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
624 if (FindPropertyIndex(*targetItr, &targetIndex))
625 properties_[sourceIndex].dependencies[targetIndex] =
true;
628 else if (itr->value.IsObject()) {
629 hasSchemaDependencies_ =
true;
630 schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_);
631 properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
638 if (
const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
640 additionalProperties_ = v->GetBool();
641 else if (v->IsObject())
642 schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_);
645 AssignIfExist(minProperties_, value, GetMinPropertiesString());
646 AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
649 if (
const ValueType* v = GetMember(value, GetItemsString())) {
650 PointerType q = p.Append(GetItemsString(), allocator_);
652 schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_);
653 else if (v->IsArray()) {
654 itemsTuple_ =
static_cast<const Schema**
>(allocator_->Malloc(
sizeof(
const Schema*) * v->Size()));
656 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
657 schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_);
661 AssignIfExist(minItems_, value, GetMinItemsString());
662 AssignIfExist(maxItems_, value, GetMaxItemsString());
664 if (
const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
666 additionalItems_ = v->GetBool();
667 else if (v->IsObject())
668 schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_);
671 AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
674 AssignIfExist(minLength_, value, GetMinLengthString());
675 AssignIfExist(maxLength_, value, GetMaxLengthString());
677 if (
const ValueType* v = GetMember(value, GetPatternString()))
678 pattern_ = CreatePattern(*v);
681 if (
const ValueType* v = GetMember(value, GetMinimumString()))
683 minimum_.CopyFrom(*v, *allocator_);
685 if (
const ValueType* v = GetMember(value, GetMaximumString()))
687 maximum_.CopyFrom(*v, *allocator_);
689 AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
690 AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
692 if (
const ValueType* v = GetMember(value, GetMultipleOfString()))
693 if (v->IsNumber() && v->GetDouble() > 0.0)
694 multipleOf_.CopyFrom(*v, *allocator_);
697 if (
const ValueType* v = GetMember(value, GetDefaultValueString()))
699 defaultValueLength_ = v->GetStringLength();
704 AllocatorType::Free(enum_);
706 for (
SizeType i = 0; i < propertyCount_; i++)
707 properties_[i].~Property();
708 AllocatorType::Free(properties_);
710 if (patternProperties_) {
711 for (
SizeType i = 0; i < patternPropertyCount_; i++)
712 patternProperties_[i].~PatternProperty();
713 AllocatorType::Free(patternProperties_);
715 AllocatorType::Free(itemsTuple_);
716 #if RAPIDJSON_SCHEMA_HAS_REGEX 718 pattern_->~RegexType();
719 AllocatorType::Free(pattern_);
724 const SValue& GetURI()
const {
728 const UriType& GetId()
const {
732 const PointerType& GetPointer()
const {
736 bool BeginValue(Context& context)
const {
737 if (context.inArray) {
739 context.valueUniqueness =
true;
742 context.valueSchema = itemsList_;
743 else if (itemsTuple_) {
744 if (context.arrayElementIndex < itemsTupleCount_)
745 context.valueSchema = itemsTuple_[context.arrayElementIndex];
746 else if (additionalItemsSchema_)
747 context.valueSchema = additionalItemsSchema_;
748 else if (additionalItems_)
749 context.valueSchema = typeless_;
751 context.error_handler.DisallowedItem(context.arrayElementIndex);
753 context.valueSchema = typeless_;
755 context.arrayElementIndex++;
760 context.valueSchema = typeless_;
762 context.arrayElementIndex++;
767 RAPIDJSON_FORCEINLINE
bool EndValue(Context& context)
const {
769 if (context.patternPropertiesValidatorCount > 0) {
770 bool otherValid =
false;
771 SizeType count = context.patternPropertiesValidatorCount;
772 if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
773 otherValid = context.patternPropertiesValidators[--count]->IsValid();
775 bool patternValid =
true;
776 for (
SizeType i = 0; i < count; i++)
777 if (!context.patternPropertiesValidators[i]->IsValid()) {
778 patternValid =
false;
782 if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
784 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
788 else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
789 if (!patternValid || !otherValid) {
790 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
794 else if (!patternValid && !otherValid) {
795 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
801 if (enum_ && context.hasher) {
802 const uint64_t h = context.factory.GetHashCode(context.hasher);
803 for (
SizeType i = 0; i < enumCount_; i++)
812 if (context.validatorCount > 0) {
814 for (
SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
815 if (!context.validators[i]->IsValid()) {
816 context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
820 if (anyOf_.schemas) {
821 for (
SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
822 if (context.validators[i]->IsValid())
824 context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
829 if (oneOf_.schemas) {
830 bool oneValid =
false;
831 for (
SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
832 if (context.validators[i]->IsValid()) {
834 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count,
true);
840 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count,
false);
845 if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
846 context.error_handler.Disallowed();
854 bool Null(Context& context)
const {
855 if (!(type_ & (1 << kNullSchemaType))) {
856 DisallowedType(context, GetNullString());
859 return CreateParallelValidator(context);
862 bool Bool(Context& context,
bool)
const {
863 if (!(type_ & (1 << kBooleanSchemaType))) {
864 DisallowedType(context, GetBooleanString());
867 return CreateParallelValidator(context);
870 bool Int(Context& context,
int i)
const {
871 if (!CheckInt(context, i))
873 return CreateParallelValidator(context);
876 bool Uint(Context& context,
unsigned u)
const {
877 if (!CheckUint(context, u))
879 return CreateParallelValidator(context);
882 bool Int64(Context& context, int64_t i)
const {
883 if (!CheckInt(context, i))
885 return CreateParallelValidator(context);
888 bool Uint64(Context& context, uint64_t u)
const {
889 if (!CheckUint(context, u))
891 return CreateParallelValidator(context);
894 bool Double(Context& context,
double d)
const {
895 if (!(type_ & (1 << kNumberSchemaType))) {
896 DisallowedType(context, GetNumberString());
900 if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
903 if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
906 if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
909 return CreateParallelValidator(context);
912 bool String(Context& context,
const Ch* str,
SizeType length,
bool)
const {
913 if (!(type_ & (1 << kStringSchemaType))) {
914 DisallowedType(context, GetStringString());
918 if (minLength_ != 0 || maxLength_ !=
SizeType(~0)) {
920 if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
921 if (count < minLength_) {
922 context.error_handler.TooShort(str, length, minLength_);
925 if (count > maxLength_) {
926 context.error_handler.TooLong(str, length, maxLength_);
932 if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
933 context.error_handler.DoesNotMatch(str, length);
937 return CreateParallelValidator(context);
940 bool StartObject(Context& context)
const {
941 if (!(type_ & (1 << kObjectSchemaType))) {
942 DisallowedType(context, GetObjectString());
946 if (hasDependencies_ || hasRequired_) {
947 context.propertyExist =
static_cast<bool*
>(context.factory.MallocState(
sizeof(
bool) * propertyCount_));
948 std::memset(context.propertyExist, 0,
sizeof(
bool) * propertyCount_);
951 if (patternProperties_) {
952 SizeType count = patternPropertyCount_ + 1;
953 context.patternPropertiesSchemas =
static_cast<const SchemaType**
>(context.factory.MallocState(
sizeof(
const SchemaType*) * count));
954 context.patternPropertiesSchemaCount = 0;
955 std::memset(context.patternPropertiesSchemas, 0,
sizeof(SchemaType*) * count);
958 return CreateParallelValidator(context);
961 bool Key(Context& context,
const Ch* str,
SizeType len,
bool)
const {
962 if (patternProperties_) {
963 context.patternPropertiesSchemaCount = 0;
964 for (
SizeType i = 0; i < patternPropertyCount_; i++)
965 if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
966 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
967 context.valueSchema = typeless_;
972 if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
973 if (context.patternPropertiesSchemaCount > 0) {
974 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
975 context.valueSchema = typeless_;
976 context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
979 context.valueSchema = properties_[index].schema;
981 if (context.propertyExist)
982 context.propertyExist[index] =
true;
987 if (additionalPropertiesSchema_) {
988 if (context.patternPropertiesSchemaCount > 0) {
989 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
990 context.valueSchema = typeless_;
991 context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
994 context.valueSchema = additionalPropertiesSchema_;
997 else if (additionalProperties_) {
998 context.valueSchema = typeless_;
1002 if (context.patternPropertiesSchemaCount == 0) {
1004 context.valueSchema = typeless_;
1005 context.error_handler.DisallowedProperty(str, len);
1012 bool EndObject(Context& context,
SizeType memberCount)
const {
1014 context.error_handler.StartMissingProperties();
1015 for (
SizeType index = 0; index < propertyCount_; index++)
1016 if (properties_[index].required && !context.propertyExist[index])
1017 if (properties_[index].schema->defaultValueLength_ == 0 )
1018 context.error_handler.AddMissingProperty(properties_[index].name);
1019 if (context.error_handler.EndMissingProperties())
1023 if (memberCount < minProperties_) {
1024 context.error_handler.TooFewProperties(memberCount, minProperties_);
1028 if (memberCount > maxProperties_) {
1029 context.error_handler.TooManyProperties(memberCount, maxProperties_);
1033 if (hasDependencies_) {
1034 context.error_handler.StartDependencyErrors();
1035 for (
SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
1036 const Property& source = properties_[sourceIndex];
1037 if (context.propertyExist[sourceIndex]) {
1038 if (source.dependencies) {
1039 context.error_handler.StartMissingDependentProperties();
1040 for (
SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
1041 if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
1042 context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
1043 context.error_handler.EndMissingDependentProperties(source.name);
1045 else if (source.dependenciesSchema) {
1046 ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
1047 if (!dependenciesValidator->IsValid())
1048 context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
1052 if (context.error_handler.EndDependencyErrors())
1059 bool StartArray(Context& context)
const {
1060 context.arrayElementIndex = 0;
1061 context.inArray =
true;
1063 if (!(type_ & (1 << kArraySchemaType))) {
1064 DisallowedType(context, GetArrayString());
1068 return CreateParallelValidator(context);
1071 bool EndArray(Context& context,
SizeType elementCount)
const {
1072 context.inArray =
false;
1074 if (elementCount < minItems_) {
1075 context.error_handler.TooFewItems(elementCount, minItems_);
1079 if (elementCount > maxItems_) {
1080 context.error_handler.TooManyItems(elementCount, maxItems_);
1087 static const ValueType& GetValidateErrorKeyword(
ValidateErrorCode validateErrorCode) {
1088 switch (validateErrorCode) {
1120 default:
return GetNullString();
1126 #define RAPIDJSON_STRING_(name, ...) \ 1127 static const ValueType& Get##name##String() {\ 1128 static const Ch s[] = { __VA_ARGS__, '\0' };\ 1129 static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\ 1133 RAPIDJSON_STRING_(Null,
'n',
'u',
'l',
'l')
1134 RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
1135 RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
1136 RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
1137 RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
1138 RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
1139 RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
1140 RAPIDJSON_STRING_(
Type, 't', 'y', 'p', 'e')
1141 RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
1142 RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
1143 RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
1144 RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
1145 RAPIDJSON_STRING_(Not, 'n', 'o', 't')
1146 RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1147 RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
1148 RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
1149 RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1150 RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1151 RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1152 RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1153 RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
1154 RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
1155 RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
1156 RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
1157 RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
1158 RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
1159 RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
1160 RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
1161 RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
1162 RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
1163 RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
1164 RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
1165 RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
1166 RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't')
1167 RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f')
1168 RAPIDJSON_STRING_(Id, 'i', 'd')
1170 RAPIDJSON_STRING_(SchemeEnd, ':')
1171 RAPIDJSON_STRING_(AuthStart, '/', '/')
1172 RAPIDJSON_STRING_(QueryStart, '?')
1173 RAPIDJSON_STRING_(FragStart, '
#') 1174 RAPIDJSON_STRING_(Slash,
'/')
1175 RAPIDJSON_STRING_(Dot, '.')
1177 #undef RAPIDJSON_STRING_ 1180 enum SchemaValueType {
1191 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1192 typedef internal::GenericRegex<EncodingType, AllocatorType> RegexType;
1193 #elif RAPIDJSON_SCHEMA_USE_STDREGEX 1194 typedef std::basic_regex<Ch> RegexType;
1196 typedef char RegexType;
1199 struct SchemaArray {
1200 SchemaArray() : schemas(), count() {}
1201 ~SchemaArray() { AllocatorType::Free(schemas); }
1202 const SchemaType** schemas;
1207 template <
typename V1,
typename V2>
1208 void AddUniqueElement(V1& a,
const V2& v) {
1209 for (
typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1212 V1 c(v, *allocator_);
1213 a.PushBack(c, *allocator_);
1216 static const ValueType* GetMember(
const ValueType& value,
const ValueType& name) {
1217 typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1218 return itr != value.MemberEnd() ? &(itr->value) : 0;
1221 static void AssignIfExist(
bool& out,
const ValueType& value,
const ValueType& name) {
1222 if (
const ValueType* v = GetMember(value, name))
1227 static void AssignIfExist(
SizeType& out,
const ValueType& value,
const ValueType& name) {
1228 if (
const ValueType* v = GetMember(value, name))
1229 if (v->IsUint64() && v->GetUint64() <=
SizeType(~0))
1230 out = static_cast<SizeType>(v->GetUint64());
1233 void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument,
const PointerType& p,
const ValueType& value,
const ValueType& name,
const ValueType& document) {
1234 if (
const ValueType* v = GetMember(value, name)) {
1235 if (v->IsArray() && v->Size() > 0) {
1236 PointerType q = p.Append(name, allocator_);
1237 out.count = v->Size();
1238 out.schemas =
static_cast<const Schema**
>(allocator_->Malloc(out.count *
sizeof(
const Schema*)));
1239 memset(out.schemas, 0,
sizeof(Schema*)* out.count);
1240 for (
SizeType i = 0; i < out.count; i++)
1241 schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_);
1242 out.begin = validatorCount_;
1243 validatorCount_ += out.count;
1248 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1249 template <
typename ValueType>
1250 RegexType* CreatePattern(
const ValueType& value) {
1251 if (value.IsString()) {
1252 RegexType* r =
new (allocator_->Malloc(
sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1253 if (!r->IsValid()) {
1255 AllocatorType::Free(r);
1263 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str,
SizeType) {
1264 GenericRegexSearch<RegexType> rs(*pattern);
1265 return rs.Search(str);
1267 #elif RAPIDJSON_SCHEMA_USE_STDREGEX 1268 template <
typename ValueType>
1269 RegexType* CreatePattern(
const ValueType& value) {
1270 if (value.IsString()) {
1271 RegexType *r =
static_cast<RegexType*
>(allocator_->Malloc(
sizeof(RegexType)));
1273 return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1275 catch (
const std::regex_error&) {
1276 AllocatorType::Free(r);
1282 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str,
SizeType length) {
1283 std::match_results<const Ch*> r;
1284 return std::regex_search(str, str + length, r, *pattern);
1287 template <
typename ValueType>
1288 RegexType* CreatePattern(
const ValueType&) {
return 0; }
1290 static bool IsPatternMatch(
const RegexType*,
const Ch *,
SizeType) {
return true; }
1291 #endif // RAPIDJSON_SCHEMA_USE_STDREGEX 1293 void AddType(
const ValueType& type) {
1294 if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1295 else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1296 else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1297 else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1298 else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1299 else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1300 else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1303 bool CreateParallelValidator(Context& context)
const {
1304 if (enum_ || context.arrayUniqueness)
1305 context.hasher = context.factory.CreateHasher();
1307 if (validatorCount_) {
1309 context.validators =
static_cast<ISchemaValidator**
>(context.factory.MallocState(
sizeof(ISchemaValidator*) * validatorCount_));
1310 std::memset(context.validators, 0,
sizeof(ISchemaValidator*) * validatorCount_);
1311 context.validatorCount = validatorCount_;
1315 CreateSchemaValidators(context, allOf_,
false);
1318 CreateSchemaValidators(context, anyOf_,
false);
1321 CreateSchemaValidators(context, oneOf_,
false);
1324 context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_,
false);
1326 if (hasSchemaDependencies_) {
1327 for (
SizeType i = 0; i < propertyCount_; i++)
1328 if (properties_[i].dependenciesSchema)
1329 context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema,
false);
1336 void CreateSchemaValidators(Context& context,
const SchemaArray& schemas,
const bool inheritContinueOnErrors)
const {
1337 for (
SizeType i = 0; i < schemas.count; i++)
1338 context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors);
1342 bool FindPropertyIndex(
const ValueType& name,
SizeType* outIndex)
const {
1343 SizeType len = name.GetStringLength();
1344 const Ch* str = name.GetString();
1345 for (
SizeType index = 0; index < propertyCount_; index++)
1346 if (properties_[index].name.GetStringLength() == len &&
1347 (std::memcmp(properties_[index].name.GetString(), str,
sizeof(Ch) * len) == 0))
1355 bool CheckInt(Context& context, int64_t i)
const {
1356 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1357 DisallowedType(context, GetIntegerString());
1361 if (!minimum_.IsNull()) {
1362 if (minimum_.IsInt64()) {
1363 if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1364 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1368 else if (minimum_.IsUint64()) {
1369 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1372 else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1376 if (!maximum_.IsNull()) {
1377 if (maximum_.IsInt64()) {
1378 if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1379 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1383 else if (maximum_.IsUint64()) { }
1385 else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1389 if (!multipleOf_.IsNull()) {
1390 if (multipleOf_.IsUint64()) {
1391 if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1392 context.error_handler.NotMultipleOf(i, multipleOf_);
1396 else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1403 bool CheckUint(Context& context, uint64_t i)
const {
1404 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1405 DisallowedType(context, GetIntegerString());
1409 if (!minimum_.IsNull()) {
1410 if (minimum_.IsUint64()) {
1411 if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1412 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1416 else if (minimum_.IsInt64())
1418 else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1422 if (!maximum_.IsNull()) {
1423 if (maximum_.IsUint64()) {
1424 if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1425 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1429 else if (maximum_.IsInt64()) {
1430 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1433 else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1437 if (!multipleOf_.IsNull()) {
1438 if (multipleOf_.IsUint64()) {
1439 if (i % multipleOf_.GetUint64() != 0) {
1440 context.error_handler.NotMultipleOf(i, multipleOf_);
1444 else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1451 bool CheckDoubleMinimum(Context& context,
double d)
const {
1452 if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1453 context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
1459 bool CheckDoubleMaximum(Context& context,
double d)
const {
1460 if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1461 context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
1467 bool CheckDoubleMultipleOf(Context& context,
double d)
const {
1468 double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1469 double q = std::floor(a / b);
1470 double r = a - q * b;
1472 context.error_handler.NotMultipleOf(d, multipleOf_);
1478 void DisallowedType(Context& context,
const ValueType& actualType)
const {
1479 ErrorHandler& eh = context.error_handler;
1480 eh.StartDisallowedType();
1482 if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1483 if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1484 if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1485 if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1486 if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1488 if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1489 else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1491 eh.EndDisallowedType(actualType);
1495 Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
1496 ~Property() { AllocatorType::Free(dependencies); }
1498 const SchemaType* schema;
1499 const SchemaType* dependenciesSchema;
1500 SizeType dependenciesValidatorIndex;
1505 struct PatternProperty {
1506 PatternProperty() : schema(), pattern() {}
1507 ~PatternProperty() {
1509 pattern->~RegexType();
1510 AllocatorType::Free(pattern);
1513 const SchemaType* schema;
1517 AllocatorType* allocator_;
1520 PointerType pointer_;
1521 const SchemaType* typeless_;
1527 const SchemaType* not_;
1532 Property* properties_;
1533 const SchemaType* additionalPropertiesSchema_;
1534 PatternProperty* patternProperties_;
1539 bool additionalProperties_;
1540 bool hasDependencies_;
1542 bool hasSchemaDependencies_;
1544 const SchemaType* additionalItemsSchema_;
1545 const SchemaType* itemsList_;
1546 const SchemaType** itemsTuple_;
1550 bool additionalItems_;
1553 RegexType* pattern_;
1560 bool exclusiveMinimum_;
1561 bool exclusiveMaximum_;
1566 template<
typename Stack,
typename Ch>
1567 struct TokenHelper {
1568 RAPIDJSON_FORCEINLINE
static void AppendIndexToken(Stack& documentStack,
SizeType index) {
1569 *documentStack.template Push<Ch>() =
'/';
1571 size_t length =
static_cast<size_t>((
sizeof(
SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
1572 for (
size_t i = 0; i < length; i++)
1573 *documentStack.template Push<Ch>() =
static_cast<Ch
>(buffer[i]);
1578 template <
typename Stack>
1579 struct TokenHelper<Stack, char> {
1580 RAPIDJSON_FORCEINLINE
static void AppendIndexToken(Stack& documentStack,
SizeType index) {
1582 char *buffer = documentStack.template Push<char>(1 + 10);
1584 const char* end = internal::u32toa(index, buffer);
1585 documentStack.template Pop<char>(
static_cast<size_t>(10 - (end - buffer)));
1588 char *buffer = documentStack.template Push<char>(1 + 20);
1590 const char* end = internal::u64toa(index, buffer);
1591 documentStack.template Pop<char>(
static_cast<size_t>(20 - (end - buffer)));
1601 template <
typename SchemaDocumentType>
1602 class IGenericRemoteSchemaDocumentProvider {
1604 typedef typename SchemaDocumentType::Ch Ch;
1605 typedef typename SchemaDocumentType::ValueType ValueType;
1606 typedef typename SchemaDocumentType::AllocatorType AllocatorType;
1608 virtual ~IGenericRemoteSchemaDocumentProvider() {}
1609 virtual const SchemaDocumentType* GetRemoteDocument(
const Ch* uri,
SizeType length) = 0;
1610 virtual const SchemaDocumentType* GetRemoteDocument(GenericUri<ValueType, AllocatorType> uri) {
return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); }
1625 template <
typename ValueT,
typename Allocator = CrtAllocator>
1626 class GenericSchemaDocument {
1628 typedef ValueT ValueType;
1629 typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
1630 typedef Allocator AllocatorType;
1631 typedef typename ValueType::EncodingType EncodingType;
1632 typedef typename EncodingType::Ch Ch;
1633 typedef internal::Schema<GenericSchemaDocument> SchemaType;
1634 typedef GenericPointer<ValueType, Allocator> PointerType;
1635 typedef GenericValue<EncodingType, AllocatorType> SValue;
1636 typedef GenericUri<ValueType, Allocator> UriType;
1637 friend class internal::Schema<GenericSchemaDocument>;
1638 template <
typename,
typename,
typename>
1639 friend class GenericSchemaValidator;
1655 remoteProvider_(remoteProvider),
1656 allocator_(allocator),
1660 schemaMap_(allocator, kInitialSchemaMapSize),
1661 schemaRef_(allocator, kInitialSchemaRefSize)
1667 uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
1668 docId_ =
UriType(uri_, allocator_);
1670 typeless_ =
static_cast<SchemaType*
>(allocator_->Malloc(
sizeof(SchemaType)));
1677 if (pointer.GetTokenCount() == 0) {
1678 CreateSchemaRecursive(&root_, pointer, document, document, docId_);
1680 else if (
const ValueType* v = pointer.Get(document)) {
1681 CreateSchema(&root_, pointer, *v, document, docId_);
1686 schemaRef_.ShrinkToFit();
1689 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS 1692 remoteProvider_(rhs.remoteProvider_),
1693 allocator_(rhs.allocator_),
1694 ownAllocator_(rhs.ownAllocator_),
1696 typeless_(rhs.typeless_),
1697 schemaMap_(std::move(rhs.schemaMap_)),
1698 schemaRef_(std::move(rhs.schemaRef_)),
1699 uri_(std::move(rhs.uri_)),
1702 rhs.remoteProvider_ = 0;
1704 rhs.ownAllocator_ = 0;
1711 while (!schemaMap_.Empty())
1712 schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
1715 typeless_->~SchemaType();
1716 Allocator::Free(typeless_);
1722 const SValue& GetURI()
const {
return uri_; }
1725 const SchemaType&
GetRoot()
const {
return *root_; }
1733 typedef const PointerType* SchemaRefPtr;
1735 struct SchemaEntry {
1736 SchemaEntry(
const PointerType& p, SchemaType* s,
bool o,
Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
1739 schema->~SchemaType();
1740 Allocator::Free(schema);
1743 PointerType pointer;
1749 void CreateSchemaRecursive(
const SchemaType** schema,
const PointerType& pointer,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1751 UriType newid = UriType(CreateSchema(schema, pointer, v, document,
id), allocator_);
1753 for (
typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
1754 CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid);
1757 for (
SizeType i = 0; i < v.Size(); i++)
1758 CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id);
1762 const UriType& CreateSchema(
const SchemaType** schema,
const PointerType& pointer,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1765 if (
const SchemaType* sc = GetSchema(pointer)) {
1768 AddSchemaRefs(const_cast<SchemaType*>(sc));
1770 else if (!HandleRefSchema(pointer, schema, v, document,
id)) {
1772 SchemaType* s =
new (allocator_->Malloc(
sizeof(SchemaType))) SchemaType(
this, pointer, v, document, allocator_,
id);
1780 *schema = typeless_;
1781 AddSchemaRefs(typeless_);
1788 bool HandleRefSchema(
const PointerType& source,
const SchemaType** schema,
const ValueType& v,
const ValueType& document,
const UriType&
id) {
1789 typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString());
1790 if (itr == v.MemberEnd())
1794 new (schemaRef_.template Push<SchemaRefPtr>()) SchemaRefPtr(&source);
1796 if (itr->value.IsString()) {
1797 SizeType len = itr->value.GetStringLength();
1800 UriType scopeId = UriType(
id, allocator_);
1801 UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_);
1804 PointerType basePointer = PointerType();
1805 const ValueType *base = FindId(document, ref, basePointer, docId_,
false);
1808 if (remoteProvider_) {
1809 if (
const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref)) {
1810 const Ch* s = ref.GetFragString();
1811 len = ref.GetFragStringLength();
1812 if (len <= 1 || s[1] ==
'/') {
1814 const PointerType pointer(s, len, allocator_);
1815 if (pointer.IsValid()) {
1817 if (
const SchemaType *sc = remoteDocument->GetSchema(pointer)) {
1820 AddSchemaRefs(const_cast<SchemaType *>(sc));
1831 const Ch* s = ref.GetFragString();
1832 len = ref.GetFragStringLength();
1833 if (len <= 1 || s[1] ==
'/') {
1835 const PointerType relPointer(s, len, allocator_);
1836 if (relPointer.IsValid()) {
1838 if (
const ValueType *pv = relPointer.Get(*base)) {
1840 PointerType pointer(basePointer);
1841 for (
SizeType i = 0; i < relPointer.GetTokenCount(); i++)
1842 pointer = pointer.Append(relPointer.GetTokens()[i], allocator_);
1845 if (pointer.IsValid() && !IsCyclicRef(pointer)) {
1848 size_t unresolvedTokenIndex;
1849 scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1850 CreateSchema(schema, pointer, *pv, document, scopeId);
1859 PointerType pointer = PointerType();
1860 if (
const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_),
true, basePointer)) {
1861 if (!IsCyclicRef(pointer)) {
1866 size_t unresolvedTokenIndex;
1867 scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1868 CreateSchema(schema, pointer, *pv, document, scopeId);
1879 *schema = typeless_;
1880 AddSchemaRefs(typeless_);
1888 ValueType* FindId(
const ValueType& doc,
const UriType& finduri, PointerType& resptr,
const UriType& baseuri,
bool full,
const PointerType& here = PointerType())
const {
1890 ValueType* resval = 0;
1891 UriType tempuri = UriType(finduri, allocator_);
1892 UriType localuri = UriType(baseuri, allocator_);
1895 typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString());
1896 if (m != doc.MemberEnd() && m->value.GetType() ==
kStringType) {
1897 localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_);
1900 if (localuri.Match(finduri, full)) {
1901 resval =
const_cast<ValueType *
>(&doc);
1906 for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) {
1908 resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_));
1914 for (
typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) {
1916 resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_));
1926 void AddSchemaRefs(SchemaType* schema) {
1927 while (!schemaRef_.Empty()) {
1928 SchemaRefPtr *ref = schemaRef_.template Pop<SchemaRefPtr>(1);
1929 SchemaEntry *entry = schemaMap_.template Push<SchemaEntry>();
1930 new (entry) SchemaEntry(**ref, schema,
false, allocator_);
1935 bool IsCyclicRef(
const PointerType& pointer)
const {
1936 for (
const SchemaRefPtr* ref = schemaRef_.template Bottom<SchemaRefPtr>(); ref != schemaRef_.template End<SchemaRefPtr>(); ++ref)
1937 if (pointer == **ref)
1942 const SchemaType* GetSchema(
const PointerType& pointer)
const {
1943 for (
const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1944 if (pointer == target->pointer)
1945 return target->schema;
1949 PointerType GetPointer(
const SchemaType* schema)
const {
1950 for (
const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1951 if (schema == target->schema)
1952 return target->pointer;
1953 return PointerType();
1956 const SchemaType* GetTypeless()
const {
return typeless_; }
1958 static const size_t kInitialSchemaMapSize = 64;
1959 static const size_t kInitialSchemaRefSize = 64;
1961 IRemoteSchemaDocumentProviderType* remoteProvider_;
1962 Allocator *allocator_;
1963 Allocator *ownAllocator_;
1964 const SchemaType* root_;
1965 SchemaType* typeless_;
1966 internal::Stack<Allocator> schemaMap_;
1967 internal::Stack<Allocator> schemaRef_;
1993 typename SchemaDocumentType,
1994 typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
1995 typename StateAllocator = CrtAllocator>
1996 class GenericSchemaValidator :
1997 public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
1998 public internal::ISchemaValidator,
1999 public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
2001 typedef typename SchemaDocumentType::SchemaType SchemaType;
2002 typedef typename SchemaDocumentType::PointerType PointerType;
2003 typedef typename SchemaType::EncodingType EncodingType;
2004 typedef typename SchemaType::SValue SValue;
2005 typedef typename EncodingType::Ch Ch;
2006 typedef GenericStringRef<Ch> StringRefType;
2007 typedef GenericValue<EncodingType, StateAllocator> ValueType;
2017 const SchemaDocumentType& schemaDocument,
2018 StateAllocator* allocator = 0,
2019 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2020 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2022 schemaDocument_(&schemaDocument),
2023 root_(schemaDocument.GetRoot()),
2024 stateAllocator_(allocator),
2025 ownStateAllocator_(0),
2026 schemaStack_(allocator, schemaStackCapacity),
2027 documentStack_(allocator, documentStackCapacity),
2031 missingDependents_(),
2034 #if RAPIDJSON_SCHEMA_VERBOSE
2048 const SchemaDocumentType& schemaDocument,
2049 OutputHandler& outputHandler,
2050 StateAllocator* allocator = 0,
2051 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2052 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2054 schemaDocument_(&schemaDocument),
2055 root_(schemaDocument.GetRoot()),
2056 stateAllocator_(allocator),
2057 ownStateAllocator_(0),
2058 schemaStack_(allocator, schemaStackCapacity),
2059 documentStack_(allocator, documentStackCapacity),
2060 outputHandler_(&outputHandler),
2063 missingDependents_(),
2066 #if RAPIDJSON_SCHEMA_VERBOSE
2080 while (!schemaStack_.Empty())
2082 documentStack_.Clear();
2089 currentError_.SetNull();
2090 missingDependents_.SetNull();
2098 virtual unsigned GetValidateFlags()
const {
2105 if (!valid_)
return false;
2106 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return false;
2112 const ValueType& GetError()
const {
return error_; }
2117 return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
2123 if (!schemaStack_.Empty())
return CurrentContext().invalidKeyword;
2124 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return (
const Ch*)GetErrorsString();
2131 if (!schemaStack_.Empty())
return CurrentContext().invalidCode;
2132 if (GetContinueOnErrors() && !error_.ObjectEmpty())
return kValidateErrors;
2139 if (documentStack_.Empty()) {
2140 return PointerType();
2143 return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() /
sizeof(Ch));
2147 void NotMultipleOf(int64_t actual,
const SValue& expected) {
2150 void NotMultipleOf(uint64_t actual,
const SValue& expected) {
2153 void NotMultipleOf(
double actual,
const SValue& expected) {
2156 void AboveMaximum(int64_t actual,
const SValue& expected,
bool exclusive) {
2158 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2160 void AboveMaximum(uint64_t actual,
const SValue& expected,
bool exclusive) {
2162 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2164 void AboveMaximum(
double actual,
const SValue& expected,
bool exclusive) {
2166 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2168 void BelowMinimum(int64_t actual,
const SValue& expected,
bool exclusive) {
2170 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2172 void BelowMinimum(uint64_t actual,
const SValue& expected,
bool exclusive) {
2174 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2176 void BelowMinimum(
double actual,
const SValue& expected,
bool exclusive) {
2178 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2183 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2187 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2189 void DoesNotMatch(
const Ch* str,
SizeType length) {
2190 currentError_.SetObject();
2191 currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
2195 void DisallowedItem(
SizeType index) {
2196 currentError_.SetObject();
2197 currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
2202 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2206 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2210 duplicates.PushBack(index1, GetStateAllocator());
2211 duplicates.PushBack(index2, GetStateAllocator());
2212 currentError_.SetObject();
2213 currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
2219 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2223 ValueType(actualCount).Move(), SValue(expectedCount).Move());
2225 void StartMissingProperties() {
2226 currentError_.SetArray();
2228 void AddMissingProperty(
const SValue& name) {
2229 currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
2231 bool EndMissingProperties() {
2232 if (currentError_.Empty())
2235 error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
2236 currentError_ = error;
2240 void PropertyViolations(ISchemaValidator** subvalidators,
SizeType count) {
2241 for (
SizeType i = 0; i < count; ++i)
2242 MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2244 void DisallowedProperty(
const Ch* name,
SizeType length) {
2245 currentError_.SetObject();
2246 currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
2250 void StartDependencyErrors() {
2251 currentError_.SetObject();
2253 void StartMissingDependentProperties() {
2254 missingDependents_.SetArray();
2256 void AddMissingDependentProperty(
const SValue& targetName) {
2257 missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
2259 void EndMissingDependentProperties(
const SValue& sourceName) {
2260 if (!missingDependents_.Empty()) {
2264 error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator());
2265 AddErrorCode(error, code);
2266 AddErrorInstanceLocation(error,
false);
2268 PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(
kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator());
2269 AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator()));
2271 wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator());
2272 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator());
2275 void AddDependencySchemaError(
const SValue& sourceName, ISchemaValidator* subvalidator) {
2276 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2277 static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
2279 bool EndDependencyErrors() {
2280 if (currentError_.ObjectEmpty())
2283 error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
2284 currentError_ = error;
2290 currentError_.SetObject();
2291 AddCurrentError(code);
2293 void StartDisallowedType() {
2294 currentError_.SetArray();
2296 void AddExpectedType(
const typename SchemaType::ValueType& expectedType) {
2297 currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2299 void EndDisallowedType(
const typename SchemaType::ValueType& actualType) {
2301 error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2302 error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2303 currentError_ = error;
2306 void NotAllOf(ISchemaValidator** subvalidators,
SizeType count) {
2313 void NoneOf(ISchemaValidator** subvalidators,
SizeType count) {
2316 void NotOneOf(ISchemaValidator** subvalidators,
SizeType count,
bool matched =
false) {
2320 currentError_.SetObject();
2324 #define RAPIDJSON_STRING_(name, ...) \ 2325 static const StringRefType& Get##name##String() {\ 2326 static const Ch s[] = { __VA_ARGS__, '\0' };\ 2327 static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \ 2331 RAPIDJSON_STRING_(InstanceRef,
'i',
'n',
's',
't',
'a',
'n',
'c',
'e',
'R',
'e',
'f')
2332 RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
2333 RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
2334 RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
2335 RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
2336 RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
2337 RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
2338 RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e')
2339 RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e')
2340 RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
2342 #undef RAPIDJSON_STRING_ 2344 #if RAPIDJSON_SCHEMA_VERBOSE 2345 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ 2346 RAPIDJSON_MULTILINEMACRO_BEGIN\ 2347 *documentStack_.template Push<Ch>() = '\0';\ 2348 documentStack_.template Pop<Ch>(1);\ 2349 internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\ 2350 RAPIDJSON_MULTILINEMACRO_END 2352 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() 2355 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ 2356 if (!valid_) return false; \ 2357 if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\ 2358 RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ 2363 #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ 2364 for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\ 2365 if (context->hasher)\ 2366 static_cast<HasherType*>(context->hasher)->method arg2;\ 2367 if (context->validators)\ 2368 for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ 2369 static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\ 2370 if (context->patternPropertiesValidators)\ 2371 for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ 2372 static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\ 2375 #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ 2376 valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\ 2379 #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ 2380 RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\ 2381 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ 2382 RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2) 2384 bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
2385 bool Bool(
bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
2386 bool Int(
int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
2387 bool Uint(
unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
2388 bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
2389 bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
2390 bool Double(
double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
2391 bool RawNumber(
const Ch* str,
SizeType length,
bool copy)
2392 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2393 bool String(
const Ch* str,
SizeType length,
bool copy)
2394 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2396 bool StartObject() {
2397 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
2398 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
2399 valid_ = !outputHandler_ || outputHandler_->StartObject();
2403 bool Key(
const Ch* str,
SizeType len,
bool copy) {
2404 if (!valid_)
return false;
2405 AppendToken(str, len);
2406 if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) {
2410 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
2411 valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2415 bool EndObject(
SizeType memberCount) {
2416 if (!valid_)
return false;
2417 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
2418 if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) {
2422 RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
2426 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
2427 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
2428 valid_ = !outputHandler_ || outputHandler_->StartArray();
2432 bool EndArray(
SizeType elementCount) {
2433 if (!valid_)
return false;
2434 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
2435 if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) {
2439 RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
2442 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ 2443 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ 2444 #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ 2445 #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ 2448 virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType& root,
const bool inheritContinueOnErrors) {
2449 ISchemaValidator* sv =
new (GetStateAllocator().Malloc(
sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),
2450 #if RAPIDJSON_SCHEMA_VERBOSE 2453 &GetStateAllocator());
2454 sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(
unsigned)kValidateContinueOnErrorFlag);
2458 virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2459 GenericSchemaValidator* v =
static_cast<GenericSchemaValidator*
>(validator);
2460 v->~GenericSchemaValidator();
2461 StateAllocator::Free(v);
2464 virtual void* CreateHasher() {
2465 return new (GetStateAllocator().Malloc(
sizeof(HasherType))) HasherType(&GetStateAllocator());
2468 virtual uint64_t GetHashCode(
void* hasher) {
2469 return static_cast<HasherType*
>(hasher)->GetHashCode();
2472 virtual void DestroryHasher(
void* hasher) {
2473 HasherType* h =
static_cast<HasherType*
>(hasher);
2475 StateAllocator::Free(h);
2478 virtual void* MallocState(
size_t size) {
2479 return GetStateAllocator().Malloc(size);
2482 virtual void FreeState(
void* p) {
2483 StateAllocator::Free(p);
2487 typedef typename SchemaType::Context Context;
2488 typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
2489 typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
2491 GenericSchemaValidator(
2492 const SchemaDocumentType& schemaDocument,
2493 const SchemaType& root,
2494 const char* basePath,
size_t basePathSize,
2495 #
if RAPIDJSON_SCHEMA_VERBOSE
2498 StateAllocator* allocator = 0,
2499 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2500 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2502 schemaDocument_(&schemaDocument),
2504 stateAllocator_(allocator),
2505 ownStateAllocator_(0),
2506 schemaStack_(allocator, schemaStackCapacity),
2507 documentStack_(allocator, documentStackCapacity),
2511 missingDependents_(),
2514 #if RAPIDJSON_SCHEMA_VERBOSE
2518 if (basePath && basePathSize)
2519 memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2522 StateAllocator& GetStateAllocator() {
2523 if (!stateAllocator_)
2524 stateAllocator_ = ownStateAllocator_ =
RAPIDJSON_NEW(StateAllocator)();
2525 return *stateAllocator_;
2528 bool GetContinueOnErrors()
const {
2533 if (schemaStack_.Empty())
2536 if (CurrentContext().inArray)
2537 internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
2539 if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors())
2542 SizeType count = CurrentContext().patternPropertiesSchemaCount;
2543 const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2544 typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2545 bool valueUniqueness = CurrentContext().valueUniqueness;
2547 PushSchema(*CurrentContext().valueSchema);
2550 CurrentContext().objectPatternValidatorType = patternValidatorType;
2551 ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2552 SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2553 va =
static_cast<ISchemaValidator**
>(MallocState(
sizeof(ISchemaValidator*) * count));
2554 std::memset(va, 0,
sizeof(ISchemaValidator*) * count);
2555 for (
SizeType i = 0; i < count; i++)
2556 va[validatorCount++] = CreateSchemaValidator(*sa[i],
true);
2559 CurrentContext().arrayUniqueness = valueUniqueness;
2565 if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors())
2568 #if RAPIDJSON_SCHEMA_VERBOSE 2569 GenericStringBuffer<EncodingType> sb;
2570 schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2572 *documentStack_.template Push<Ch>() =
'\0';
2573 documentStack_.template Pop<Ch>(1);
2574 internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
2576 void* hasher = CurrentContext().hasher;
2577 uint64_t h = hasher && CurrentContext().arrayUniqueness ?
static_cast<HasherType*
>(hasher)->GetHashCode() : 0;
2581 if (!schemaStack_.Empty()) {
2582 Context& context = CurrentContext();
2584 if (hasher && context.valueUniqueness) {
2585 HashCodeArray* a =
static_cast<HashCodeArray*
>(context.arrayElementHashCodes);
2587 CurrentContext().arrayElementHashCodes = a =
new (GetStateAllocator().Malloc(
sizeof(HashCodeArray))) HashCodeArray(
kArrayType);
2588 for (
typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
2589 if (itr->GetUint64() == h) {
2590 DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
2592 if (GetContinueOnErrors()) {
2593 a->PushBack(h, GetStateAllocator());
2594 while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) !=
'/');
2598 a->PushBack(h, GetStateAllocator());
2603 while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) !=
'/')
2609 void AppendToken(
const Ch* str,
SizeType len) {
2610 documentStack_.template Reserve<Ch>(1 + len * 2);
2611 *documentStack_.template PushUnsafe<Ch>() =
'/';
2612 for (
SizeType i = 0; i < len; i++) {
2613 if (str[i] ==
'~') {
2614 *documentStack_.template PushUnsafe<Ch>() =
'~';
2615 *documentStack_.template PushUnsafe<Ch>() =
'0';
2617 else if (str[i] ==
'/') {
2618 *documentStack_.template PushUnsafe<Ch>() =
'~';
2619 *documentStack_.template PushUnsafe<Ch>() =
'1';
2622 *documentStack_.template PushUnsafe<Ch>() = str[i];
2626 RAPIDJSON_FORCEINLINE
void PushSchema(
const SchemaType& schema) {
new (schemaStack_.template Push<Context>()) Context(*
this, *
this, &schema); }
2628 RAPIDJSON_FORCEINLINE
void PopSchema() {
2629 Context* c = schemaStack_.template Pop<Context>(1);
2630 if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
2631 a->~HashCodeArray();
2632 StateAllocator::Free(a);
2637 void AddErrorInstanceLocation(ValueType& result,
bool parent) {
2638 GenericStringBuffer<EncodingType> sb;
2639 PointerType instancePointer = GetInvalidDocumentPointer();
2640 ((parent && instancePointer.GetTokenCount() > 0)
2641 ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2642 : instancePointer).StringifyUriFragment(sb);
2643 ValueType instanceRef(sb.GetString(),
static_cast<SizeType>(sb.GetSize() /
sizeof(Ch)),
2644 GetStateAllocator());
2645 result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2648 void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) {
2649 GenericStringBuffer<EncodingType> sb;
2650 SizeType len = CurrentSchema().GetURI().GetStringLength();
2651 if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len *
sizeof(Ch));
2652 if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
2653 else GetInvalidSchemaPointer().StringifyUriFragment(sb);
2654 ValueType schemaRef(sb.GetString(),
static_cast<SizeType>(sb.GetSize() /
sizeof(Ch)),
2655 GetStateAllocator());
2656 result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2660 result.AddMember(GetErrorCodeString(), code, GetStateAllocator());
2663 void AddError(ValueType& keyword, ValueType& error) {
2664 typename ValueType::MemberIterator member = error_.FindMember(keyword);
2665 if (member == error_.MemberEnd())
2666 error_.AddMember(keyword, error, GetStateAllocator());
2668 if (member->value.IsObject()) {
2670 errors.PushBack(member->value, GetStateAllocator());
2671 member->value = errors;
2673 member->value.PushBack(error, GetStateAllocator());
2678 AddErrorCode(currentError_, code);
2679 AddErrorInstanceLocation(currentError_, parent);
2680 AddErrorSchemaLocation(currentError_);
2681 AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(),
false).Move(), currentError_);
2684 void MergeError(ValueType& other) {
2685 for (
typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {
2686 AddError(it->name, it->value);
2690 void AddNumberError(
const ValidateErrorCode code, ValueType& actual,
const SValue& expected,
2691 const typename SchemaType::ValueType& (*exclusive)() = 0) {
2692 currentError_.SetObject();
2693 currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2694 currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2696 currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(),
true, GetStateAllocator());
2697 AddCurrentError(code);
2701 ISchemaValidator** subvalidators,
SizeType count) {
2703 for (
SizeType i = 0; i < count; ++i)
2704 errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
2705 currentError_.SetObject();
2706 currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2707 AddCurrentError(code);
2710 const SchemaType& CurrentSchema()
const {
return *schemaStack_.template Top<Context>()->schema; }
2711 Context& CurrentContext() {
return *schemaStack_.template Top<Context>(); }
2712 const Context& CurrentContext()
const {
return *schemaStack_.template Top<Context>(); }
2714 static const size_t kDefaultSchemaStackCapacity = 1024;
2715 static const size_t kDefaultDocumentStackCapacity = 256;
2716 const SchemaDocumentType* schemaDocument_;
2717 const SchemaType& root_;
2718 StateAllocator* stateAllocator_;
2719 StateAllocator* ownStateAllocator_;
2720 internal::Stack<StateAllocator> schemaStack_;
2721 internal::Stack<StateAllocator> documentStack_;
2722 OutputHandler* outputHandler_;
2724 ValueType currentError_;
2725 ValueType missingDependents_;
2728 #if RAPIDJSON_SCHEMA_VERBOSE 2733 typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
2749 unsigned parseFlags,
2750 typename InputStream,
2751 typename SourceEncoding,
2753 typename StackAllocator = CrtAllocator>
2756 typedef typename SchemaDocumentType::PointerType PointerType;
2757 typedef typename InputStream::Ch Ch;
2767 template <
typename Handler>
2768 bool operator()(
Handler& handler) {
2771 parseResult_ = reader.template Parse<parseFlags>(is_, validator);
2773 isValid_ = validator.IsValid();
2775 invalidSchemaPointer_ = PointerType();
2776 invalidSchemaKeyword_ = 0;
2777 invalidDocumentPointer_ = PointerType();
2781 invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
2782 invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
2783 invalidSchemaCode_ = validator.GetInvalidSchemaCode();
2784 invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
2785 error_.CopyFrom(validator.GetError(), allocator_);
2788 return parseResult_;
2791 const ParseResult& GetParseResult()
const {
return parseResult_; }
2792 bool IsValid()
const {
return isValid_; }
2793 const PointerType& GetInvalidSchemaPointer()
const {
return invalidSchemaPointer_; }
2794 const Ch* GetInvalidSchemaKeyword()
const {
return invalidSchemaKeyword_; }
2795 const PointerType& GetInvalidDocumentPointer()
const {
return invalidDocumentPointer_; }
2796 const ValueType& GetError()
const {
return error_; }
2801 const SchemaDocumentType& sd_;
2803 ParseResult parseResult_;
2804 PointerType invalidSchemaPointer_;
2805 const Ch* invalidSchemaKeyword_;
2806 PointerType invalidDocumentPointer_;
2808 StackAllocator allocator_;
2813 RAPIDJSON_NAMESPACE_END
2816 #endif // RAPIDJSON_SCHEMA_H_ String does not match the 'pattern' regular expression.
Definition: error.h:174
true
Definition: rapidjson.h:732
#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS
User-defined kValidateDefaultFlags definition.
Definition: schema.h:136
Number is not a multiple of the 'multipleOf' value.
Definition: error.h:166
IGenericRemoteSchemaDocumentProvider< SchemaDocument > IRemoteSchemaDocumentProvider
IGenericRemoteSchemaDocumentProvider using SchemaDocument.
Definition: fwd.h:139
Concept for receiving events from GenericReader upon parsing. The functions return true if no error o...
ValidateFlag
Combination of validate flags.
Definition: schema.h:142
ValidateErrorCode GetInvalidSchemaCode() const
Gets the error code of invalid schema.
Definition: schema.h:2130
Property matched more than one of the sub-schemas specified by 'oneOf'.
Definition: error.h:192
See other errors.
Definition: error.h:185
void SetValidateFlags(unsigned flags)
Implementation of ISchemaValidator.
Definition: schema.h:2095
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
Definition: schema.h:2122
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:320
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:88
Don't stop after first validation error.
Definition: schema.h:144
Number is greater than or equal to the 'maximum' value.
Definition: error.h:168
Object has more members than 'maxProperties' value.
Definition: error.h:181
Number is greater than the 'maximum' value.
Definition: error.h:167
unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS.
Definition: schema.h:145
false
Definition: rapidjson.h:731
String is longer than the 'maxLength' value.
Definition: error.h:172
void ResetError()
Reset the error state.
Definition: schema.h:2087
Top level error code when kValidateContinueOnErrorsFlag set.
Definition: error.h:163
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
Definition: schema.h:2138
ValueType & GetError()
Gets the error object.
Definition: schema.h:2111
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:1652
~GenericSchemaValidator()
Destructor.
Definition: schema.h:2073
Number is less than or equal to the 'minimum' value.
Definition: error.h:170
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:712
Array is longer than the 'maxItems' value.
Definition: error.h:176
virtual bool IsValid() const
Checks whether the current state is valid.
Definition: schema.h:2104
Property matched the sub-schema specified by 'not'.
Definition: error.h:195
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor without output handler.
Definition: schema.h:2016
Number is less than the 'minimum' value.
Definition: error.h:169
Array has duplicate items but 'uniqueItems' is true.
Definition: error.h:178
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
JSON schema document.
Definition: fwd.h:136
Type
Type of JSON value.
Definition: rapidjson.h:729
object
Definition: rapidjson.h:733
void Reset()
Reset the internal states.
Definition: schema.h:2079
ValidateErrorCode
Error codes when validating.
Definition: error.h:162
Array has additional items that are not allowed by the schema.
Definition: error.h:179
array
Definition: rapidjson.h:734
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:716
Object has less members than 'minProperties' value.
Definition: error.h:182
SchemaValidatingReader(InputStream &is, const SchemaDocumentType &sd)
Constructor.
Definition: schema.h:2765
Array is shorter than the 'minItems' value.
Definition: error.h:177
Property did not match all of the sub-schemas specified by 'allOf'.
Definition: error.h:193
~GenericSchemaDocument()
Destructor.
Definition: schema.h:1710
No flags are set.
Definition: schema.h:143
String is longer than the 'maxLength' value.
Definition: error.h:173
null
Definition: rapidjson.h:730
string
Definition: rapidjson.h:735
Property did not match any of the sub-schemas specified by 'anyOf'.
Definition: error.h:194
GenericSchemaDocument< Value, CrtAllocator > SchemaDocument
GenericSchemaDocument using Value type.
Definition: fwd.h:136
Property has a value that is not one of its allowed enumerated values.
Definition: error.h:188
const SchemaType & GetRoot() const
Get the root schema.
Definition: schema.h:1725
No error.
Definition: error.h:164
Object has missing property or schema dependencies.
Definition: error.h:186
JSON Schema Validator.
Definition: fwd.h:145
Object is missing one or more members required by the schema.
Definition: error.h:183
Concept for allocating, resizing and freeing memory block.
Property did not match any of the sub-schemas specified by 'oneOf'.
Definition: error.h:191
A helper class for parsing with validation.
Definition: schema.h:2754
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
Definition: schema.h:2116
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, OutputHandler &outputHandler, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor with output handler.
Definition: schema.h:2047
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
Property has a type that is not allowed by the schema..
Definition: error.h:189
number
Definition: rapidjson.h:736
Object has additional members that are not allowed by the schema.
Definition: error.h:184