399 typedef typename SchemaDocumentType::ValueType ValueType;
400 typedef typename SchemaDocumentType::AllocatorType AllocatorType;
401 typedef typename SchemaDocumentType::PointerType PointerType;
402 typedef typename ValueType::EncodingType EncodingType;
403 typedef typename EncodingType::Ch Ch;
410 Schema(SchemaDocumentType* schemaDocument,
const PointerType& p,
const ValueType& value,
const ValueType& document, AllocatorType* allocator) :
411 allocator_(allocator),
412 uri_(schemaDocument->GetURI(), *allocator),
413 pointer_(p, allocator),
414 typeless_(schemaDocument->GetTypeless()),
418 type_((1 << kTotalSchemaType) - 1),
420 notValidatorIndex_(),
422 additionalPropertiesSchema_(),
423 patternProperties_(),
424 patternPropertyCount_(),
428 additionalProperties_(
true),
431 hasSchemaDependencies_(),
432 additionalItemsSchema_(),
438 additionalItems_(
true),
443 exclusiveMinimum_(
false),
444 exclusiveMaximum_(
false),
445 defaultValueLength_(0)
447 typedef typename ValueType::ConstValueIterator ConstValueIterator;
448 typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
450 if (!value.IsObject())
453 if (
const ValueType* v = GetMember(value, GetTypeString())) {
457 else if (v->IsArray())
458 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
462 if (
const ValueType* v = GetMember(value, GetEnumString()))
463 if (v->IsArray() && v->Size() > 0) {
464 enum_ =
static_cast<uint64_t*
>(allocator_->Malloc(
sizeof(
uint64_t) * v->Size()));
465 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
467 char buffer[256u + 24];
469 EnumHasherType h(&hasherAllocator, 256);
471 enum_[enumCount_++] = h.GetHashCode();
475 if (schemaDocument) {
476 AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
477 AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
478 AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
481 if (
const ValueType* v = GetMember(value, GetNotString())) {
482 schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document);
483 notValidatorIndex_ = validatorCount_;
489 const ValueType* properties = GetMember(value, GetPropertiesString());
490 const ValueType* required = GetMember(value, GetRequiredString());
491 const ValueType* dependencies = GetMember(value, GetDependenciesString());
496 if (properties && properties->IsObject())
497 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
498 AddUniqueElement(allProperties, itr->name);
500 if (required && required->IsArray())
501 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
503 AddUniqueElement(allProperties, *itr);
505 if (dependencies && dependencies->IsObject())
506 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
507 AddUniqueElement(allProperties, itr->name);
508 if (itr->value.IsArray())
509 for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
511 AddUniqueElement(allProperties, *i);
514 if (allProperties.Size() > 0) {
515 propertyCount_ = allProperties.Size();
516 properties_ =
static_cast<Property*
>(allocator_->Malloc(
sizeof(
Property) * propertyCount_));
517 for (
SizeType i = 0; i < propertyCount_; i++) {
519 properties_[i].name = allProperties[i];
520 properties_[i].schema = typeless_;
525 if (properties && properties->IsObject()) {
526 PointerType q = p.Append(GetPropertiesString(), allocator_);
527 for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
529 if (FindPropertyIndex(itr->name, &index))
530 schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
534 if (
const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
535 PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
537 patternPropertyCount_ = 0;
539 for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
541 patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
542 schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
543 patternPropertyCount_++;
547 if (required && required->IsArray())
548 for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
549 if (itr->IsString()) {
551 if (FindPropertyIndex(*itr, &index)) {
552 properties_[index].required =
true;
557 if (dependencies && dependencies->IsObject()) {
558 PointerType q = p.Append(GetDependenciesString(), allocator_);
559 hasDependencies_ =
true;
560 for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
562 if (FindPropertyIndex(itr->name, &sourceIndex)) {
563 if (itr->value.IsArray()) {
564 properties_[sourceIndex].dependencies =
static_cast<bool*
>(allocator_->Malloc(
sizeof(
bool) * propertyCount_));
565 std::memset(properties_[sourceIndex].dependencies, 0,
sizeof(
bool)* propertyCount_);
566 for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
568 if (FindPropertyIndex(*targetItr, &targetIndex))
569 properties_[sourceIndex].dependencies[targetIndex] =
true;
572 else if (itr->value.IsObject()) {
573 hasSchemaDependencies_ =
true;
574 schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
575 properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
582 if (
const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
584 additionalProperties_ = v->GetBool();
585 else if (v->IsObject())
586 schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
589 AssignIfExist(minProperties_, value, GetMinPropertiesString());
590 AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
593 if (
const ValueType* v = GetMember(value, GetItemsString())) {
594 PointerType q = p.Append(GetItemsString(), allocator_);
596 schemaDocument->CreateSchema(&itemsList_, q, *v, document);
597 else if (v->IsArray()) {
598 itemsTuple_ =
static_cast<const Schema**
>(allocator_->Malloc(
sizeof(
const Schema*) * v->Size()));
600 for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
601 schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
605 AssignIfExist(minItems_, value, GetMinItemsString());
606 AssignIfExist(maxItems_, value, GetMaxItemsString());
608 if (
const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
610 additionalItems_ = v->GetBool();
611 else if (v->IsObject())
612 schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
615 AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
618 AssignIfExist(minLength_, value, GetMinLengthString());
619 AssignIfExist(maxLength_, value, GetMaxLengthString());
621 if (
const ValueType* v = GetMember(value, GetPatternString()))
622 pattern_ = CreatePattern(*v);
625 if (
const ValueType* v = GetMember(value, GetMinimumString()))
627 minimum_.CopyFrom(*v, *allocator_);
629 if (
const ValueType* v = GetMember(value, GetMaximumString()))
631 maximum_.CopyFrom(*v, *allocator_);
633 AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
634 AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
636 if (
const ValueType* v = GetMember(value, GetMultipleOfString()))
637 if (v->IsNumber() && v->GetDouble() > 0.0)
638 multipleOf_.CopyFrom(*v, *allocator_);
641 if (
const ValueType* v = GetMember(value, GetDefaultValueString()))
643 defaultValueLength_ = v->GetStringLength();
648 AllocatorType::Free(enum_);
650 for (
SizeType i = 0; i < propertyCount_; i++)
652 AllocatorType::Free(properties_);
654 if (patternProperties_) {
655 for (
SizeType i = 0; i < patternPropertyCount_; i++)
657 AllocatorType::Free(patternProperties_);
659 AllocatorType::Free(itemsTuple_);
660#if RAPIDJSON_SCHEMA_HAS_REGEX
662 pattern_->~RegexType();
663 AllocatorType::Free(pattern_);
668 const SValue& GetURI()
const {
672 const PointerType& GetPointer()
const {
676 bool BeginValue(
Context& context)
const {
677 if (context.inArray) {
679 context.valueUniqueness =
true;
682 context.valueSchema = itemsList_;
683 else if (itemsTuple_) {
684 if (context.arrayElementIndex < itemsTupleCount_)
685 context.valueSchema = itemsTuple_[context.arrayElementIndex];
686 else if (additionalItemsSchema_)
687 context.valueSchema = additionalItemsSchema_;
688 else if (additionalItems_)
689 context.valueSchema = typeless_;
691 context.error_handler.DisallowedItem(context.arrayElementIndex);
692 RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
696 context.valueSchema = typeless_;
698 context.arrayElementIndex++;
703 RAPIDJSON_FORCEINLINE
bool EndValue(
Context& context)
const {
704 if (context.patternPropertiesValidatorCount > 0) {
705 bool otherValid =
false;
706 SizeType count = context.patternPropertiesValidatorCount;
707 if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
708 otherValid = context.patternPropertiesValidators[--count]->IsValid();
710 bool patternValid =
true;
711 for (
SizeType i = 0; i < count; i++)
712 if (!context.patternPropertiesValidators[i]->IsValid()) {
713 patternValid =
false;
717 if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
719 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
720 RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
723 else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
724 if (!patternValid || !otherValid) {
725 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
726 RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
729 else if (!patternValid && !otherValid) {
730 context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
731 RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
736 const uint64_t h = context.factory.GetHashCode(context.hasher);
737 for (
SizeType i = 0; i < enumCount_; i++)
740 context.error_handler.DisallowedValue();
741 RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
746 for (
SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
747 if (!context.validators[i]->IsValid()) {
748 context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
749 RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
752 if (anyOf_.schemas) {
753 for (
SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
754 if (context.validators[i]->IsValid())
756 context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
757 RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
761 if (oneOf_.schemas) {
762 bool oneValid =
false;
763 for (
SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
764 if (context.validators[i]->IsValid()) {
766 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
767 RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
772 context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
773 RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
777 if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
778 context.error_handler.Disallowed();
779 RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
785 bool Null(
Context& context)
const {
786 if (!(type_ & (1 << kNullSchemaType))) {
787 DisallowedType(context, GetNullString());
788 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
790 return CreateParallelValidator(context);
793 bool Bool(
Context& context,
bool)
const {
794 if (!(type_ & (1 << kBooleanSchemaType))) {
795 DisallowedType(context, GetBooleanString());
796 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
798 return CreateParallelValidator(context);
801 bool Int(
Context& context,
int i)
const {
802 if (!CheckInt(context, i))
804 return CreateParallelValidator(context);
807 bool Uint(
Context& context,
unsigned u)
const {
808 if (!CheckUint(context, u))
810 return CreateParallelValidator(context);
814 if (!CheckInt(context, i))
816 return CreateParallelValidator(context);
820 if (!CheckUint(context, u))
822 return CreateParallelValidator(context);
826 if (!(type_ & (1 << kNumberSchemaType))) {
827 DisallowedType(context, GetNumberString());
828 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
831 if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
834 if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
837 if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
840 return CreateParallelValidator(context);
843 bool String(
Context& context,
const Ch* str,
SizeType length,
bool)
const {
844 if (!(type_ & (1 << kStringSchemaType))) {
845 DisallowedType(context, GetStringString());
846 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
849 if (minLength_ != 0 || maxLength_ !=
SizeType(~0)) {
851 if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
852 if (count < minLength_) {
853 context.error_handler.TooShort(str, length, minLength_);
854 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
856 if (count > maxLength_) {
857 context.error_handler.TooLong(str, length, maxLength_);
858 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
863 if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
864 context.error_handler.DoesNotMatch(str, length);
865 RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
868 return CreateParallelValidator(context);
871 bool StartObject(
Context& context)
const {
872 if (!(type_ & (1 << kObjectSchemaType))) {
873 DisallowedType(context, GetObjectString());
874 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
877 if (hasDependencies_ || hasRequired_) {
878 context.propertyExist =
static_cast<bool*
>(context.factory.MallocState(
sizeof(
bool) * propertyCount_));
879 std::memset(context.propertyExist, 0,
sizeof(
bool) * propertyCount_);
882 if (patternProperties_) {
883 SizeType count = patternPropertyCount_ + 1;
884 context.patternPropertiesSchemas =
static_cast<const SchemaType**
>(context.factory.MallocState(
sizeof(
const SchemaType*) * count));
885 context.patternPropertiesSchemaCount = 0;
886 std::memset(context.patternPropertiesSchemas, 0,
sizeof(
SchemaType*) * count);
889 return CreateParallelValidator(context);
893 if (patternProperties_) {
894 context.patternPropertiesSchemaCount = 0;
895 for (
SizeType i = 0; i < patternPropertyCount_; i++)
896 if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
897 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
898 context.valueSchema = typeless_;
903 if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
904 if (context.patternPropertiesSchemaCount > 0) {
905 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
906 context.valueSchema = typeless_;
907 context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
910 context.valueSchema = properties_[index].schema;
912 if (context.propertyExist)
913 context.propertyExist[index] =
true;
918 if (additionalPropertiesSchema_) {
919 if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
920 context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
921 context.valueSchema = typeless_;
922 context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
925 context.valueSchema = additionalPropertiesSchema_;
928 else if (additionalProperties_) {
929 context.valueSchema = typeless_;
933 if (context.patternPropertiesSchemaCount == 0) {
934 context.error_handler.DisallowedProperty(str, len);
935 RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
943 context.error_handler.StartMissingProperties();
944 for (
SizeType index = 0; index < propertyCount_; index++)
945 if (properties_[index].required && !context.propertyExist[index])
946 if (properties_[index].schema->defaultValueLength_ == 0 )
947 context.error_handler.AddMissingProperty(properties_[index].name);
948 if (context.error_handler.EndMissingProperties())
949 RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
952 if (memberCount < minProperties_) {
953 context.error_handler.TooFewProperties(memberCount, minProperties_);
954 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
957 if (memberCount > maxProperties_) {
958 context.error_handler.TooManyProperties(memberCount, maxProperties_);
959 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
962 if (hasDependencies_) {
963 context.error_handler.StartDependencyErrors();
964 for (
SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
965 const Property& source = properties_[sourceIndex];
966 if (context.propertyExist[sourceIndex]) {
967 if (source.dependencies) {
968 context.error_handler.StartMissingDependentProperties();
969 for (
SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
970 if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
971 context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
972 context.error_handler.EndMissingDependentProperties(source.name);
974 else if (source.dependenciesSchema) {
975 ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
976 if (!dependenciesValidator->IsValid())
977 context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
981 if (context.error_handler.EndDependencyErrors())
982 RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
988 bool StartArray(
Context& context)
const {
989 if (!(type_ & (1 << kArraySchemaType))) {
990 DisallowedType(context, GetArrayString());
991 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
994 context.arrayElementIndex = 0;
995 context.inArray =
true;
997 return CreateParallelValidator(context);
1001 context.inArray =
false;
1003 if (elementCount < minItems_) {
1004 context.error_handler.TooFewItems(elementCount, minItems_);
1005 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
1008 if (elementCount > maxItems_) {
1009 context.error_handler.TooManyItems(elementCount, maxItems_);
1010 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
1017#define RAPIDJSON_STRING_(name, ...) \
1018 static const ValueType& Get##name##String() {\
1019 static const Ch s[] = { __VA_ARGS__, '\0' };\
1020 static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
1024 RAPIDJSON_STRING_(Null,
'n',
'u',
'l',
'l')
1025 RAPIDJSON_STRING_(Boolean,
'b',
'o',
'o',
'l',
'e',
'a',
'n')
1026 RAPIDJSON_STRING_(Object,
'o',
'b',
'j',
'e',
'c',
't')
1027 RAPIDJSON_STRING_(Array,
'a',
'r',
'r',
'a',
'y')
1028 RAPIDJSON_STRING_(String,
's',
't',
'r',
'i',
'n',
'g')
1029 RAPIDJSON_STRING_(Number,
'n',
'u',
'm',
'b',
'e',
'r')
1030 RAPIDJSON_STRING_(Integer,
'i',
'n',
't',
'e',
'g',
'e',
'r')
1031 RAPIDJSON_STRING_(
Type,
't',
'y',
'p',
'e')
1032 RAPIDJSON_STRING_(Enum,
'e',
'n',
'u',
'm')
1033 RAPIDJSON_STRING_(AllOf,
'a',
'l',
'l',
'O',
'f')
1034 RAPIDJSON_STRING_(AnyOf,
'a',
'n',
'y',
'O',
'f')
1035 RAPIDJSON_STRING_(OneOf,
'o',
'n',
'e',
'O',
'f')
1036 RAPIDJSON_STRING_(Not,
'n',
'o',
't')
1037 RAPIDJSON_STRING_(Properties,
'p',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1038 RAPIDJSON_STRING_(Required,
'r',
'e',
'q',
'u',
'i',
'r',
'e',
'd')
1039 RAPIDJSON_STRING_(Dependencies,
'd',
'e',
'p',
'e',
'n',
'd',
'e',
'n',
'c',
'i',
'e',
's')
1040 RAPIDJSON_STRING_(PatternProperties,
'p',
'a',
't',
't',
'e',
'r',
'n',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1041 RAPIDJSON_STRING_(AdditionalProperties,
'a',
'd',
'd',
'i',
't',
'i',
'o',
'n',
'a',
'l',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1042 RAPIDJSON_STRING_(MinProperties,
'm',
'i',
'n',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1043 RAPIDJSON_STRING_(MaxProperties,
'm',
'a',
'x',
'P',
'r',
'o',
'p',
'e',
'r',
't',
'i',
'e',
's')
1044 RAPIDJSON_STRING_(Items,
'i',
't',
'e',
'm',
's')
1045 RAPIDJSON_STRING_(MinItems,
'm',
'i',
'n',
'I',
't',
'e',
'm',
's')
1046 RAPIDJSON_STRING_(MaxItems,
'm',
'a',
'x',
'I',
't',
'e',
'm',
's')
1047 RAPIDJSON_STRING_(AdditionalItems,
'a',
'd',
'd',
'i',
't',
'i',
'o',
'n',
'a',
'l',
'I',
't',
'e',
'm',
's')
1048 RAPIDJSON_STRING_(UniqueItems,
'u',
'n',
'i',
'q',
'u',
'e',
'I',
't',
'e',
'm',
's')
1049 RAPIDJSON_STRING_(MinLength,
'm',
'i',
'n',
'L',
'e',
'n',
'g',
't',
'h')
1050 RAPIDJSON_STRING_(MaxLength,
'm',
'a',
'x',
'L',
'e',
'n',
'g',
't',
'h')
1051 RAPIDJSON_STRING_(Pattern,
'p',
'a',
't',
't',
'e',
'r',
'n')
1052 RAPIDJSON_STRING_(Minimum,
'm',
'i',
'n',
'i',
'm',
'u',
'm')
1053 RAPIDJSON_STRING_(Maximum,
'm',
'a',
'x',
'i',
'm',
'u',
'm')
1054 RAPIDJSON_STRING_(ExclusiveMinimum,
'e',
'x',
'c',
'l',
'u',
's',
'i',
'v',
'e',
'M',
'i',
'n',
'i',
'm',
'u',
'm')
1055 RAPIDJSON_STRING_(ExclusiveMaximum,
'e',
'x',
'c',
'l',
'u',
's',
'i',
'v',
'e',
'M',
'a',
'x',
'i',
'm',
'u',
'm')
1056 RAPIDJSON_STRING_(MultipleOf,
'm',
'u',
'l',
't',
'i',
'p',
'l',
'e',
'O',
'f')
1057 RAPIDJSON_STRING_(DefaultValue,
'd',
'e',
'f',
'a',
'u',
'l',
't')
1059#undef RAPIDJSON_STRING_
1062 enum SchemaValueType {
1073#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1075#elif RAPIDJSON_SCHEMA_USE_STDREGEX
1076 typedef std::basic_regex<Ch> RegexType;
1078 typedef char RegexType;
1089 template <
typename V1,
typename V2>
1090 void AddUniqueElement(V1& a,
const V2& v) {
1091 for (
typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1094 V1 c(v, *allocator_);
1095 a.PushBack(c, *allocator_);
1098 static const ValueType* GetMember(
const ValueType& value,
const ValueType& name) {
1099 typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1100 return itr != value.MemberEnd() ? &(itr->value) : 0;
1103 static void AssignIfExist(
bool& out,
const ValueType& value,
const ValueType& name) {
1104 if (
const ValueType* v = GetMember(value, name))
1109 static void AssignIfExist(
SizeType& out,
const ValueType& value,
const ValueType& name) {
1110 if (
const ValueType* v = GetMember(value, name))
1111 if (v->IsUint64() && v->GetUint64() <=
SizeType(~0))
1112 out =
static_cast<SizeType>(v->GetUint64());
1115 void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument,
const PointerType& p,
const ValueType& value,
const ValueType& name,
const ValueType& document) {
1116 if (
const ValueType* v = GetMember(value, name)) {
1117 if (v->IsArray() && v->Size() > 0) {
1118 PointerType q = p.Append(name, allocator_);
1119 out.count = v->Size();
1120 out.schemas =
static_cast<const Schema**
>(allocator_->Malloc(out.count *
sizeof(
const Schema*)));
1121 memset(out.schemas, 0,
sizeof(Schema*)* out.count);
1122 for (
SizeType i = 0; i < out.count; i++)
1123 schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
1124 out.begin = validatorCount_;
1125 validatorCount_ += out.count;
1130#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1131 template <
typename ValueType>
1132 RegexType* CreatePattern(
const ValueType& value) {
1133 if (value.IsString()) {
1134 RegexType* r =
new (allocator_->Malloc(
sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1135 if (!r->IsValid()) {
1137 AllocatorType::Free(r);
1145 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str,
SizeType) {
1146 GenericRegexSearch<RegexType> rs(*pattern);
1147 return rs.Search(str);
1149#elif RAPIDJSON_SCHEMA_USE_STDREGEX
1150 template <
typename ValueType>
1151 RegexType* CreatePattern(
const ValueType& value) {
1152 if (value.IsString()) {
1153 RegexType *r =
static_cast<RegexType*
>(allocator_->Malloc(
sizeof(RegexType)));
1155 return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1157 catch (
const std::regex_error&) {
1158 AllocatorType::Free(r);
1164 static bool IsPatternMatch(
const RegexType* pattern,
const Ch *str,
SizeType length) {
1165 std::match_results<const Ch*> r;
1166 return std::regex_search(str, str + length, r, *pattern);
1169 template <
typename ValueType>
1170 RegexType* CreatePattern(
const ValueType&) {
return 0; }
1172 static bool IsPatternMatch(
const RegexType*,
const Ch *,
SizeType) {
return true; }
1175 void AddType(
const ValueType& type) {
1176 if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1177 else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1178 else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1179 else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1180 else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1181 else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1182 else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1185 bool CreateParallelValidator(Context& context)
const {
1186 if (enum_ || context.arrayUniqueness)
1187 context.hasher = context.factory.CreateHasher();
1189 if (validatorCount_) {
1191 context.validators =
static_cast<ISchemaValidator**
>(context.factory.MallocState(
sizeof(ISchemaValidator*) * validatorCount_));
1192 context.validatorCount = validatorCount_;
1195 CreateSchemaValidators(context, allOf_);
1198 CreateSchemaValidators(context, anyOf_);
1201 CreateSchemaValidators(context, oneOf_);
1204 context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
1206 if (hasSchemaDependencies_) {
1207 for (
SizeType i = 0; i < propertyCount_; i++)
1208 if (properties_[i].dependenciesSchema)
1209 context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
1216 void CreateSchemaValidators(Context& context,
const SchemaArray& schemas)
const {
1217 for (
SizeType i = 0; i < schemas.count; i++)
1218 context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
1222 bool FindPropertyIndex(
const ValueType& name,
SizeType* outIndex)
const {
1224 const Ch* str = name.GetString();
1225 for (
SizeType index = 0; index < propertyCount_; index++)
1226 if (properties_[index].name.GetStringLength() == len &&
1227 (std::memcmp(properties_[index].name.GetString(), str,
sizeof(Ch) * len) == 0))
1235 bool CheckInt(Context& context, int64_t i)
const {
1236 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1237 DisallowedType(context, GetIntegerString());
1238 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1241 if (!minimum_.IsNull()) {
1242 if (minimum_.IsInt64()) {
1243 if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1244 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1245 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1248 else if (minimum_.IsUint64()) {
1249 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1250 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1252 else if (!CheckDoubleMinimum(context,
static_cast<double>(i)))
1256 if (!maximum_.IsNull()) {
1257 if (maximum_.IsInt64()) {
1258 if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1259 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1260 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1263 else if (maximum_.IsUint64()) { }
1265 else if (!CheckDoubleMaximum(context,
static_cast<double>(i)))
1269 if (!multipleOf_.IsNull()) {
1270 if (multipleOf_.IsUint64()) {
1271 if (
static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1272 context.error_handler.NotMultipleOf(i, multipleOf_);
1273 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1276 else if (!CheckDoubleMultipleOf(context,
static_cast<double>(i)))
1283 bool CheckUint(Context& context,
uint64_t i)
const {
1284 if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1285 DisallowedType(context, GetIntegerString());
1286 RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1289 if (!minimum_.IsNull()) {
1290 if (minimum_.IsUint64()) {
1291 if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1292 context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1293 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1296 else if (minimum_.IsInt64())
1298 else if (!CheckDoubleMinimum(context,
static_cast<double>(i)))
1302 if (!maximum_.IsNull()) {
1303 if (maximum_.IsUint64()) {
1304 if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1305 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1306 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1309 else if (maximum_.IsInt64()) {
1310 context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1311 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1313 else if (!CheckDoubleMaximum(context,
static_cast<double>(i)))
1317 if (!multipleOf_.IsNull()) {
1318 if (multipleOf_.IsUint64()) {
1319 if (i % multipleOf_.GetUint64() != 0) {
1320 context.error_handler.NotMultipleOf(i, multipleOf_);
1321 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1324 else if (!CheckDoubleMultipleOf(context,
static_cast<double>(i)))
1331 bool CheckDoubleMinimum(Context& context,
double d)
const {
1332 if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1333 context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
1334 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1339 bool CheckDoubleMaximum(Context& context,
double d)
const {
1340 if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1341 context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
1342 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1347 bool CheckDoubleMultipleOf(Context& context,
double d)
const {
1348 double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1349 double q = std::floor(a / b);
1350 double r = a - q * b;
1352 context.error_handler.NotMultipleOf(d, multipleOf_);
1353 RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1358 void DisallowedType(Context& context,
const ValueType& actualType)
const {
1359 ErrorHandler& eh = context.error_handler;
1360 eh.StartDisallowedType();
1362 if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1363 if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1364 if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1365 if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1366 if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1368 if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1369 else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1371 eh.EndDisallowedType(actualType);
1375 Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(
false) {}
1376 ~Property() { AllocatorType::Free(dependencies); }
1380 SizeType dependenciesValidatorIndex;
1389 pattern->~RegexType();
1390 AllocatorType::Free(pattern);
1397 AllocatorType* allocator_;
1399 PointerType pointer_;
1412 const SchemaType* additionalPropertiesSchema_;
1418 bool additionalProperties_;
1419 bool hasDependencies_;
1421 bool hasSchemaDependencies_;
1429 bool additionalItems_;
1432 RegexType* pattern_;
1439 bool exclusiveMinimum_;
1440 bool exclusiveMaximum_;
1770 typedef typename SchemaDocumentType::SchemaType SchemaType;
1771 typedef typename SchemaDocumentType::PointerType PointerType;
1772 typedef typename SchemaType::EncodingType EncodingType;
1773 typedef typename SchemaType::SValue SValue;
1774 typedef typename EncodingType::Ch Ch;
1786 const SchemaDocumentType& schemaDocument,
1787 StateAllocator* allocator = 0,
1788 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1789 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1791 schemaDocument_(&schemaDocument),
1792 root_(schemaDocument.GetRoot()),
1793 stateAllocator_(allocator),
1794 ownStateAllocator_(0),
1800 missingDependents_(),
1802#if RAPIDJSON_SCHEMA_VERBOSE
1816 const SchemaDocumentType& schemaDocument,
1817 OutputHandler& outputHandler,
1818 StateAllocator* allocator = 0,
1819 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1820 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1822 schemaDocument_(&schemaDocument),
1823 root_(schemaDocument.GetRoot()),
1824 stateAllocator_(allocator),
1825 ownStateAllocator_(0),
1828 outputHandler_(&outputHandler),
1831 missingDependents_(),
1833#if RAPIDJSON_SCHEMA_VERBOSE
1851 currentError_.SetNull();
1852 missingDependents_.SetNull();
1862 const ValueType&
GetError()
const {
return error_; }
1866 return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
1871 return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
1877 return PointerType();
1884 void NotMultipleOf(int64_t actual,
const SValue& expected) {
1885 AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1887 void NotMultipleOf(
uint64_t actual,
const SValue& expected) {
1888 AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1890 void NotMultipleOf(
double actual,
const SValue& expected) {
1891 AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1893 void AboveMaximum(int64_t actual,
const SValue& expected,
bool exclusive) {
1894 AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1895 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1897 void AboveMaximum(
uint64_t actual,
const SValue& expected,
bool exclusive) {
1898 AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1899 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1901 void AboveMaximum(
double actual,
const SValue& expected,
bool exclusive) {
1902 AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1903 exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1905 void BelowMinimum(int64_t actual,
const SValue& expected,
bool exclusive) {
1906 AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1907 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1909 void BelowMinimum(
uint64_t actual,
const SValue& expected,
bool exclusive) {
1910 AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1911 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1913 void BelowMinimum(
double actual,
const SValue& expected,
bool exclusive) {
1914 AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1915 exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1919 AddNumberError(SchemaType::GetMaxLengthString(),
1920 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1923 AddNumberError(SchemaType::GetMinLengthString(),
1924 ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1926 void DoesNotMatch(
const Ch* str,
SizeType length) {
1927 currentError_.SetObject();
1928 currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
1929 AddCurrentError(SchemaType::GetPatternString());
1932 void DisallowedItem(
SizeType index) {
1933 currentError_.SetObject();
1934 currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
1935 AddCurrentError(SchemaType::GetAdditionalItemsString(),
true);
1938 AddNumberError(SchemaType::GetMinItemsString(),
1939 ValueType(actualCount).Move(), SValue(expectedCount).Move());
1942 AddNumberError(SchemaType::GetMaxItemsString(),
1943 ValueType(actualCount).Move(), SValue(expectedCount).Move());
1947 duplicates.PushBack(index1, GetStateAllocator());
1948 duplicates.PushBack(index2, GetStateAllocator());
1949 currentError_.SetObject();
1950 currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
1951 AddCurrentError(SchemaType::GetUniqueItemsString(),
true);
1955 AddNumberError(SchemaType::GetMaxPropertiesString(),
1956 ValueType(actualCount).Move(), SValue(expectedCount).Move());
1959 AddNumberError(SchemaType::GetMinPropertiesString(),
1960 ValueType(actualCount).Move(), SValue(expectedCount).Move());
1962 void StartMissingProperties() {
1963 currentError_.SetArray();
1965 void AddMissingProperty(
const SValue& name) {
1966 currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
1968 bool EndMissingProperties() {
1969 if (currentError_.Empty())
1972 error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
1973 currentError_ = error;
1974 AddCurrentError(SchemaType::GetRequiredString());
1977 void PropertyViolations(ISchemaValidator** subvalidators,
SizeType count) {
1978 for (
SizeType i = 0; i < count; ++i)
1981 void DisallowedProperty(
const Ch* name,
SizeType length) {
1982 currentError_.SetObject();
1983 currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
1984 AddCurrentError(SchemaType::GetAdditionalPropertiesString(),
true);
1987 void StartDependencyErrors() {
1988 currentError_.SetObject();
1990 void StartMissingDependentProperties() {
1991 missingDependents_.SetArray();
1993 void AddMissingDependentProperty(
const SValue& targetName) {
1994 missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
1996 void EndMissingDependentProperties(
const SValue& sourceName) {
1997 if (!missingDependents_.Empty())
1998 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
1999 missingDependents_, GetStateAllocator());
2001 void AddDependencySchemaError(
const SValue& sourceName, ISchemaValidator* subvalidator) {
2002 currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2005 bool EndDependencyErrors() {
2006 if (currentError_.ObjectEmpty())
2009 error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
2010 currentError_ = error;
2011 AddCurrentError(SchemaType::GetDependenciesString());
2015 void DisallowedValue() {
2016 currentError_.SetObject();
2017 AddCurrentError(SchemaType::GetEnumString());
2019 void StartDisallowedType() {
2020 currentError_.SetArray();
2022 void AddExpectedType(
const typename SchemaType::ValueType& expectedType) {
2023 currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2025 void EndDisallowedType(
const typename SchemaType::ValueType& actualType) {
2027 error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2028 error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2029 currentError_ = error;
2030 AddCurrentError(SchemaType::GetTypeString());
2032 void NotAllOf(ISchemaValidator** subvalidators,
SizeType count) {
2033 for (
SizeType i = 0; i < count; ++i) {
2037 void NoneOf(ISchemaValidator** subvalidators,
SizeType count) {
2038 AddErrorArray(SchemaType::GetAnyOfString(), subvalidators, count);
2040 void NotOneOf(ISchemaValidator** subvalidators,
SizeType count) {
2041 AddErrorArray(SchemaType::GetOneOfString(), subvalidators, count);
2044 currentError_.SetObject();
2045 AddCurrentError(SchemaType::GetNotString());
2048#define RAPIDJSON_STRING_(name, ...) \
2049 static const StringRefType& Get##name##String() {\
2050 static const Ch s[] = { __VA_ARGS__, '\0' };\
2051 static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
2055 RAPIDJSON_STRING_(InstanceRef,
'i',
'n',
's',
't',
'a',
'n',
'c',
'e',
'R',
'e',
'f')
2056 RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
2057 RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
2058 RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
2059 RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
2060 RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
2061 RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
2062 RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
2064#undef RAPIDJSON_STRING_
2066#if RAPIDJSON_SCHEMA_VERBOSE
2067#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
2068RAPIDJSON_MULTILINEMACRO_BEGIN\
2069 *documentStack_.template Push<Ch>() = '\0';\
2070 documentStack_.template Pop<Ch>(1);\
2071 internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
2072RAPIDJSON_MULTILINEMACRO_END
2074#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
2077#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
2078 if (!valid_) return false; \
2079 if (!BeginValue() || !CurrentSchema().method arg1) {\
2080 RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
2081 return valid_ = false;\
2084#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
2085 for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
2086 if (context->hasher)\
2087 static_cast<HasherType*>(context->hasher)->method arg2;\
2088 if (context->validators)\
2089 for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
2090 static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
2091 if (context->patternPropertiesValidators)\
2092 for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
2093 static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
2096#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
2097 return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2)
2099#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
2100 RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
2101 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
2102 RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
2104 bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
2105 bool Bool(
bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
2106 bool Int(
int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
2107 bool Uint(
unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
2108 bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(
Int64, (CurrentContext(), i), (i)); }
2109 bool Uint64(
uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
2110 bool Double(
double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
2111 bool RawNumber(
const Ch* str,
SizeType length,
bool copy)
2112 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2113 bool String(
const Ch* str,
SizeType length,
bool copy)
2114 { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2116 bool StartObject() {
2117 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
2118 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
2119 return valid_ = !outputHandler_ || outputHandler_->StartObject();
2122 bool Key(
const Ch* str,
SizeType len,
bool copy) {
2123 if (!valid_)
return false;
2124 AppendToken(str, len);
2125 if (!CurrentSchema().Key(CurrentContext(), str, len, copy))
return valid_ =
false;
2126 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
2127 return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2130 bool EndObject(
SizeType memberCount) {
2131 if (!valid_)
return false;
2132 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
2133 if (!CurrentSchema().EndObject(CurrentContext(), memberCount))
return valid_ =
false;
2134 RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
2138 RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
2139 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
2140 return valid_ = !outputHandler_ || outputHandler_->StartArray();
2143 bool EndArray(
SizeType elementCount) {
2144 if (!valid_)
return false;
2145 RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
2146 if (!CurrentSchema().EndArray(CurrentContext(), elementCount))
return valid_ =
false;
2147 RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
2150#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
2151#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
2152#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
2153#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
2156 virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType& root) {
2158#if RAPIDJSON_SCHEMA_VERBOSE
2161 &GetStateAllocator());
2164 virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2167 StateAllocator::Free(v);
2170 virtual void* CreateHasher() {
2171 return new (GetStateAllocator().Malloc(
sizeof(HasherType))) HasherType(&GetStateAllocator());
2174 virtual uint64_t GetHashCode(
void* hasher) {
2175 return static_cast<HasherType*
>(hasher)->GetHashCode();
2178 virtual void DestroryHasher(
void* hasher) {
2179 HasherType* h =
static_cast<HasherType*
>(hasher);
2181 StateAllocator::Free(h);
2184 virtual void* MallocState(
size_t size) {
2185 return GetStateAllocator().Malloc(size);
2188 virtual void FreeState(
void* p) {
2189 StateAllocator::Free(p);
2193 typedef typename SchemaType::Context Context;
2198 const SchemaDocumentType& schemaDocument,
2199 const SchemaType& root,
2200 const char* basePath,
size_t basePathSize,
2201#
if RAPIDJSON_SCHEMA_VERBOSE
2204 StateAllocator* allocator = 0,
2205 size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2206 size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2208 schemaDocument_(&schemaDocument),
2210 stateAllocator_(allocator),
2211 ownStateAllocator_(0),
2217 missingDependents_(),
2219#if RAPIDJSON_SCHEMA_VERBOSE
2223 if (basePath && basePathSize)
2224 memcpy(
documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2227 StateAllocator& GetStateAllocator() {
2228 if (!stateAllocator_)
2229 stateAllocator_ = ownStateAllocator_ =
RAPIDJSON_NEW(StateAllocator)();
2230 return *stateAllocator_;
2237 if (CurrentContext().inArray)
2240 if (!CurrentSchema().BeginValue(CurrentContext()))
2243 SizeType count = CurrentContext().patternPropertiesSchemaCount;
2244 const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2245 typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2246 bool valueUniqueness = CurrentContext().valueUniqueness;
2248 PushSchema(*CurrentContext().valueSchema);
2251 CurrentContext().objectPatternValidatorType = patternValidatorType;
2252 ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2253 SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2254 va =
static_cast<ISchemaValidator**
>(MallocState(
sizeof(ISchemaValidator*) * count));
2255 for (
SizeType i = 0; i < count; i++)
2256 va[validatorCount++] = CreateSchemaValidator(*sa[i]);
2259 CurrentContext().arrayUniqueness = valueUniqueness;
2265 if (!CurrentSchema().EndValue(CurrentContext()))
2268#if RAPIDJSON_SCHEMA_VERBOSE
2270 schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2274 internal::PrintValidatorPointers(depth_, sb.GetString(),
documentStack_.template Bottom<Ch>());
2277 uint64_t h = CurrentContext().arrayUniqueness ?
static_cast<HasherType*
>(CurrentContext().hasher)->GetHashCode() : 0;
2282 Context& context = CurrentContext();
2283 if (context.valueUniqueness) {
2284 HashCodeArray* a =
static_cast<HashCodeArray*
>(context.arrayElementHashCodes);
2286 CurrentContext().arrayElementHashCodes = a =
new (GetStateAllocator().Malloc(
sizeof(HashCodeArray))) HashCodeArray(
kArrayType);
2288 if (itr->GetUint64() == h) {
2289 DuplicateItems(
static_cast<SizeType>(itr - a->Begin()), a->Size());
2290 RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
2292 a->PushBack(h, GetStateAllocator());
2303 void AppendToken(
const Ch* str,
SizeType len) {
2307 if (str[i] ==
'~') {
2311 else if (str[i] ==
'/') {
2320 RAPIDJSON_FORCEINLINE
void PushSchema(
const SchemaType& schema) {
new (
schemaStack_.template Push<Context>()) Context(*
this, *
this, &schema); }
2322 RAPIDJSON_FORCEINLINE
void PopSchema() {
2324 if (HashCodeArray* a =
static_cast<HashCodeArray*
>(c->arrayElementHashCodes)) {
2325 a->~HashCodeArray();
2326 StateAllocator::Free(a);
2331 void AddErrorLocation(ValueType& result,
bool parent) {
2334 ((parent && instancePointer.GetTokenCount() > 0)
2335 ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2336 : instancePointer).StringifyUriFragment(sb);
2337 ValueType instanceRef(sb.GetString(),
static_cast<SizeType>(sb.
GetSize() /
sizeof(Ch)),
2338 GetStateAllocator());
2339 result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2341 memcpy(sb.Push(CurrentSchema().GetURI().GetStringLength()),
2342 CurrentSchema().GetURI().GetString(),
2343 CurrentSchema().GetURI().GetStringLength() *
sizeof(Ch));
2345 ValueType schemaRef(sb.GetString(),
static_cast<SizeType>(sb.
GetSize() /
sizeof(Ch)),
2346 GetStateAllocator());
2347 result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2350 void AddError(ValueType& keyword, ValueType& error) {
2352 if (member == error_.MemberEnd())
2353 error_.AddMember(keyword, error, GetStateAllocator());
2355 if (member->value.IsObject()) {
2357 errors.PushBack(member->value, GetStateAllocator());
2358 member->value = errors;
2360 member->value.PushBack(error, GetStateAllocator());
2364 void AddCurrentError(
const typename SchemaType::ValueType& keyword,
bool parent =
false) {
2365 AddErrorLocation(currentError_, parent);
2366 AddError(ValueType(keyword, GetStateAllocator(),
false).Move(), currentError_);
2369 void MergeError(ValueType& other) {
2371 AddError(it->name, it->value);
2375 void AddNumberError(
const typename SchemaType::ValueType& keyword, ValueType& actual,
const SValue& expected,
2376 const typename SchemaType::ValueType& (*exclusive)() = 0) {
2377 currentError_.SetObject();
2378 currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2379 currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2381 currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(),
true, GetStateAllocator());
2382 AddCurrentError(keyword);
2385 void AddErrorArray(
const typename SchemaType::ValueType& keyword,
2386 ISchemaValidator** subvalidators,
SizeType count) {
2388 for (
SizeType i = 0; i < count; ++i)
2390 currentError_.SetObject();
2391 currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2392 AddCurrentError(keyword);
2395 const SchemaType& CurrentSchema()
const {
return *
schemaStack_.template Top<Context>()->schema; }
2396 Context& CurrentContext() {
return *
schemaStack_.template Top<Context>(); }
2397 const Context& CurrentContext()
const {
return *
schemaStack_.template Top<Context>(); }
2399 static const size_t kDefaultSchemaStackCapacity = 1024;
2400 static const size_t kDefaultDocumentStackCapacity = 256;
2401 const SchemaDocumentType* schemaDocument_;
2402 const SchemaType& root_;
2403 StateAllocator* stateAllocator_;
2404 StateAllocator* ownStateAllocator_;
2407 OutputHandler* outputHandler_;
2412#if RAPIDJSON_SCHEMA_VERBOSE