398    typedef typename SchemaDocumentType::ValueType ValueType;
 
  399    typedef typename SchemaDocumentType::AllocatorType AllocatorType;
 
  400    typedef typename SchemaDocumentType::PointerType PointerType;
 
  401    typedef typename ValueType::EncodingType EncodingType;
 
  402    typedef typename EncodingType::Ch Ch;
 
  404    typedef Schema<SchemaDocumentType> SchemaType;
 
  409    Schema(SchemaDocumentType* schemaDocument, 
const PointerType& p, 
const ValueType& value, 
const ValueType& document, AllocatorType* allocator) :
 
  410        allocator_(allocator),
 
  411        uri_(schemaDocument->GetURI(), *allocator),
 
  412        pointer_(p, allocator),
 
  413        typeless_(schemaDocument->GetTypeless()),
 
  417        type_((1 << kTotalSchemaType) - 1), 
 
  419        notValidatorIndex_(),
 
  421        additionalPropertiesSchema_(),
 
  422        patternProperties_(),
 
  423        patternPropertyCount_(),
 
  427        additionalProperties_(
true),
 
  430        hasSchemaDependencies_(),
 
  431        additionalItemsSchema_(),
 
  437        additionalItems_(
true),
 
  442        exclusiveMinimum_(
false),
 
  443        exclusiveMaximum_(
false),
 
  444        defaultValueLength_(0)
 
  446        typedef typename ValueType::ConstValueIterator ConstValueIterator;
 
  447        typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
 
  449        if (!value.IsObject())
 
  452        if (
const ValueType* v = GetMember(value, GetTypeString())) {
 
  456            else if (v->IsArray())
 
  457                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
 
  461        if (
const ValueType* v = GetMember(value, GetEnumString()))
 
  462            if (v->IsArray() && v->Size() > 0) {
 
  463                enum_ = 
static_cast<uint64_t*
>(allocator_->Malloc(
sizeof(uint64_t) * v->Size()));
 
  464                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
 
  466                    char buffer[256u + 24];
 
  468                    EnumHasherType h(&hasherAllocator, 256);
 
  470                    enum_[enumCount_++] = h.GetHashCode();
 
  474        if (schemaDocument) {
 
  475            AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
 
  476            AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
 
  477            AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
 
  480        if (
const ValueType* v = GetMember(value, GetNotString())) {
 
  481            schemaDocument->CreateSchema(¬_, p.Append(GetNotString(), allocator_), *v, document);
 
  482            notValidatorIndex_ = validatorCount_;
 
  488        const ValueType* properties = GetMember(value, GetPropertiesString());
 
  489        const ValueType* required = GetMember(value, GetRequiredString());
 
  490        const ValueType* dependencies = GetMember(value, GetDependenciesString());
 
  495            if (properties && properties->IsObject())
 
  496                for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
 
  497                    AddUniqueElement(allProperties, itr->name);
 
  499            if (required && required->IsArray())
 
  500                for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
 
  502                        AddUniqueElement(allProperties, *itr);
 
  504            if (dependencies && dependencies->IsObject())
 
  505                for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
 
  506                    AddUniqueElement(allProperties, itr->name);
 
  507                    if (itr->value.IsArray())
 
  508                        for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
 
  510                                AddUniqueElement(allProperties, *i);
 
  513            if (allProperties.Size() > 0) {
 
  514                propertyCount_ = allProperties.Size();
 
  515                properties_ = 
static_cast<Property*
>(allocator_->Malloc(
sizeof(Property) * propertyCount_));
 
  516                for (
SizeType i = 0; i < propertyCount_; i++) {
 
  517                    new (&properties_[i]) Property();
 
  518                    properties_[i].name = allProperties[i];
 
  519                    properties_[i].schema = typeless_;
 
  524        if (properties && properties->IsObject()) {
 
  525            PointerType q = p.Append(GetPropertiesString(), allocator_);
 
  526            for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
 
  528                if (FindPropertyIndex(itr->name, &index))
 
  529                    schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
 
  533        if (
const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
 
  534            PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
 
  535            patternProperties_ = 
static_cast<PatternProperty*
>(allocator_->Malloc(
sizeof(PatternProperty) * v->MemberCount()));
 
  536            patternPropertyCount_ = 0;
 
  538            for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
 
  539                new (&patternProperties_[patternPropertyCount_]) PatternProperty();
 
  540                patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
 
  541                schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
 
  542                patternPropertyCount_++;
 
  546        if (required && required->IsArray())
 
  547            for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
 
  548                if (itr->IsString()) {
 
  550                    if (FindPropertyIndex(*itr, &index)) {
 
  551                        properties_[index].required = 
true;
 
  556        if (dependencies && dependencies->IsObject()) {
 
  557            PointerType q = p.Append(GetDependenciesString(), allocator_);
 
  558            hasDependencies_ = 
true;
 
  559            for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
 
  561                if (FindPropertyIndex(itr->name, &sourceIndex)) {
 
  562                    if (itr->value.IsArray()) {
 
  563                        properties_[sourceIndex].dependencies = 
static_cast<bool*
>(allocator_->Malloc(
sizeof(
bool) * propertyCount_));
 
  564                        std::memset(properties_[sourceIndex].dependencies, 0, 
sizeof(
bool)* propertyCount_);
 
  565                        for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
 
  567                            if (FindPropertyIndex(*targetItr, &targetIndex))
 
  568                                properties_[sourceIndex].dependencies[targetIndex] = 
true;
 
  571                    else if (itr->value.IsObject()) {
 
  572                        hasSchemaDependencies_ = 
true;
 
  573                        schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
 
  574                        properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
 
  581        if (
const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
 
  583                additionalProperties_ = v->GetBool();
 
  584            else if (v->IsObject())
 
  585                schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
 
  588        AssignIfExist(minProperties_, value, GetMinPropertiesString());
 
  589        AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
 
  592        if (
const ValueType* v = GetMember(value, GetItemsString())) {
 
  593            PointerType q = p.Append(GetItemsString(), allocator_);
 
  595                schemaDocument->CreateSchema(&itemsList_, q, *v, document);
 
  596            else if (v->IsArray()) { 
 
  597                itemsTuple_ = 
static_cast<const Schema**
>(allocator_->Malloc(
sizeof(
const Schema*) * v->Size()));
 
  599                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
 
  600                    schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
 
  604        AssignIfExist(minItems_, value, GetMinItemsString());
 
  605        AssignIfExist(maxItems_, value, GetMaxItemsString());
 
  607        if (
const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
 
  609                additionalItems_ = v->GetBool();
 
  610            else if (v->IsObject())
 
  611                schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
 
  614        AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
 
  617        AssignIfExist(minLength_, value, GetMinLengthString());
 
  618        AssignIfExist(maxLength_, value, GetMaxLengthString());
 
  620        if (
const ValueType* v = GetMember(value, GetPatternString()))
 
  621            pattern_ = CreatePattern(*v);
 
  624        if (
const ValueType* v = GetMember(value, GetMinimumString()))
 
  626                minimum_.CopyFrom(*v, *allocator_);
 
  628        if (
const ValueType* v = GetMember(value, GetMaximumString()))
 
  630                maximum_.CopyFrom(*v, *allocator_);
 
  632        AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
 
  633        AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
 
  635        if (
const ValueType* v = GetMember(value, GetMultipleOfString()))
 
  636            if (v->IsNumber() && v->GetDouble() > 0.0)
 
  637                multipleOf_.CopyFrom(*v, *allocator_);
 
  640        if (
const ValueType* v = GetMember(value, GetDefaultValueString()))
 
  642                defaultValueLength_ = v->GetStringLength();
 
  647        AllocatorType::Free(enum_);
 
  649            for (
SizeType i = 0; i < propertyCount_; i++)
 
  650                properties_[i].~Property();
 
  651            AllocatorType::Free(properties_);
 
  653        if (patternProperties_) {
 
  654            for (
SizeType i = 0; i < patternPropertyCount_; i++)
 
  655                patternProperties_[i].~PatternProperty();
 
  656            AllocatorType::Free(patternProperties_);
 
  658        AllocatorType::Free(itemsTuple_);
 
  659#if RAPIDJSON_SCHEMA_HAS_REGEX 
  661            pattern_->~BESRegexType();
 
  662            AllocatorType::Free(pattern_);
 
  667    const SValue& GetURI()
 const {
 
  671    const PointerType& GetPointer()
 const {
 
  675    bool BeginValue(Context& context)
 const {
 
  676        if (context.inArray) {
 
  678                context.valueUniqueness = 
true;
 
  681                context.valueSchema = itemsList_;
 
  682            else if (itemsTuple_) {
 
  683                if (context.arrayElementIndex < itemsTupleCount_)
 
  684                    context.valueSchema = itemsTuple_[context.arrayElementIndex];
 
  685                else if (additionalItemsSchema_)
 
  686                    context.valueSchema = additionalItemsSchema_;
 
  687                else if (additionalItems_)
 
  688                    context.valueSchema = typeless_;
 
  690                    context.error_handler.DisallowedItem(context.arrayElementIndex);
 
  691                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
 
  695                context.valueSchema = typeless_;
 
  697            context.arrayElementIndex++;
 
  702    RAPIDJSON_FORCEINLINE 
bool EndValue(Context& context)
 const {
 
  703        if (context.patternPropertiesValidatorCount > 0) {
 
  704            bool otherValid = 
false;
 
  705            SizeType count = context.patternPropertiesValidatorCount;
 
  706            if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
 
  707                otherValid = context.patternPropertiesValidators[--count]->IsValid();
 
  709            bool patternValid = 
true;
 
  710            for (
SizeType i = 0; i < count; i++)
 
  711                if (!context.patternPropertiesValidators[i]->IsValid()) {
 
  712                    patternValid = 
false;
 
  716            if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
 
  718                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count);
 
  719                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 
  722            else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
 
  723                if (!patternValid || !otherValid) {
 
  724                    context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
 
  725                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 
  728            else if (!patternValid && !otherValid) { 
 
  729                context.error_handler.PropertyViolations(context.patternPropertiesValidators, count + 1);
 
  730                RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
 
  735            const uint64_t h = context.factory.GetHashCode(context.hasher);
 
  736            for (
SizeType i = 0; i < enumCount_; i++)
 
  739            context.error_handler.DisallowedValue();
 
  740            RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
 
  745            for (
SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
 
  746                if (!context.validators[i]->IsValid()) {
 
  747                    context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
 
  748                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
 
  751        if (anyOf_.schemas) {
 
  752            for (
SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
 
  753                if (context.validators[i]->IsValid())
 
  755            context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
 
  756            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
 
  760        if (oneOf_.schemas) {
 
  761            bool oneValid = 
false;
 
  762            for (
SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
 
  763                if (context.validators[i]->IsValid()) {
 
  765                        context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
 
  766                        RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
 
  771                context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count);
 
  772                RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
 
  776        if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
 
  777            context.error_handler.Disallowed();
 
  778            RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
 
  784    bool Null(Context& context)
 const {
 
  785        if (!(type_ & (1 << kNullSchemaType))) {
 
  786            DisallowedType(context, GetNullString());
 
  787            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  789        return CreateParallelValidator(context);
 
  792    bool Bool(Context& context, 
bool)
 const {
 
  793        if (!(type_ & (1 << kBooleanSchemaType))) {
 
  794            DisallowedType(context, GetBooleanString());
 
  795            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  797        return CreateParallelValidator(context);
 
  800    bool Int(Context& context, 
int i)
 const {
 
  801        if (!CheckInt(context, i))
 
  803        return CreateParallelValidator(context);
 
  806    bool Uint(Context& context, 
unsigned u)
 const {
 
  807        if (!CheckUint(context, u))
 
  809        return CreateParallelValidator(context);
 
  812    bool Int64(Context& context, int64_t i)
 const {
 
  813        if (!CheckInt(context, i))
 
  815        return CreateParallelValidator(context);
 
  818    bool Uint64(Context& context, uint64_t u)
 const {
 
  819        if (!CheckUint(context, u))
 
  821        return CreateParallelValidator(context);
 
  824    bool Double(Context& context, 
double d)
 const {
 
  825        if (!(type_ & (1 << kNumberSchemaType))) {
 
  826            DisallowedType(context, GetNumberString());
 
  827            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  830        if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
 
  833        if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
 
  836        if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
 
  839        return CreateParallelValidator(context);
 
  842    bool String(Context& context, 
const Ch* str, 
SizeType length, 
bool)
 const {
 
  843        if (!(type_ & (1 << kStringSchemaType))) {
 
  844            DisallowedType(context, GetStringString());
 
  845            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  848        if (minLength_ != 0 || maxLength_ != 
SizeType(~0)) {
 
  850            if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
 
  851                if (count < minLength_) {
 
  852                    context.error_handler.TooShort(str, length, minLength_);
 
  853                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
 
  855                if (count > maxLength_) {
 
  856                    context.error_handler.TooLong(str, length, maxLength_);
 
  857                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
 
  862        if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
 
  863            context.error_handler.DoesNotMatch(str, length);
 
  864            RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
 
  867        return CreateParallelValidator(context);
 
  870    bool StartObject(Context& context)
 const {
 
  871        if (!(type_ & (1 << kObjectSchemaType))) {
 
  872            DisallowedType(context, GetObjectString());
 
  873            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  876        if (hasDependencies_ || hasRequired_) {
 
  877            context.propertyExist = 
static_cast<bool*
>(context.factory.MallocState(
sizeof(
bool) * propertyCount_));
 
  878            std::memset(context.propertyExist, 0, 
sizeof(
bool) * propertyCount_);
 
  881        if (patternProperties_) { 
 
  882            SizeType count = patternPropertyCount_ + 1; 
 
  883            context.patternPropertiesSchemas = 
static_cast<const SchemaType**
>(context.factory.MallocState(
sizeof(
const SchemaType*) * count));
 
  884            context.patternPropertiesSchemaCount = 0;
 
  885            std::memset(context.patternPropertiesSchemas, 0, 
sizeof(SchemaType*) * count);
 
  888        return CreateParallelValidator(context);
 
  891    bool Key(Context& context, 
const Ch* str, 
SizeType len, 
bool)
 const {
 
  892        if (patternProperties_) {
 
  893            context.patternPropertiesSchemaCount = 0;
 
  894            for (
SizeType i = 0; i < patternPropertyCount_; i++)
 
  895                if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
 
  896                    context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
 
  897                    context.valueSchema = typeless_;
 
  902        if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
 
  903            if (context.patternPropertiesSchemaCount > 0) {
 
  904                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
 
  905                context.valueSchema = typeless_;
 
  906                context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
 
  909                context.valueSchema = properties_[index].schema;
 
  911            if (context.propertyExist)
 
  912                context.propertyExist[index] = 
true;
 
  917        if (additionalPropertiesSchema_) {
 
  918            if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
 
  919                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
 
  920                context.valueSchema = typeless_;
 
  921                context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
 
  924                context.valueSchema = additionalPropertiesSchema_;
 
  927        else if (additionalProperties_) {
 
  928            context.valueSchema = typeless_;
 
  932        if (context.patternPropertiesSchemaCount == 0) { 
 
  933            context.error_handler.DisallowedProperty(str, len);
 
  934            RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
 
  940    bool EndObject(Context& context, 
SizeType memberCount)
 const {
 
  942            context.error_handler.StartMissingProperties();
 
  943            for (
SizeType index = 0; index < propertyCount_; index++)
 
  944                if (properties_[index].required && !context.propertyExist[index])
 
  945                    if (properties_[index].schema->defaultValueLength_ == 0 )
 
  946                        context.error_handler.AddMissingProperty(properties_[index].name);
 
  947            if (context.error_handler.EndMissingProperties())
 
  948                RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
 
  951        if (memberCount < minProperties_) {
 
  952            context.error_handler.TooFewProperties(memberCount, minProperties_);
 
  953            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
 
  956        if (memberCount > maxProperties_) {
 
  957            context.error_handler.TooManyProperties(memberCount, maxProperties_);
 
  958            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
 
  961        if (hasDependencies_) {
 
  962            context.error_handler.StartDependencyErrors();
 
  963            for (
SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
 
  964                const Property& source = properties_[sourceIndex];
 
  965                if (context.propertyExist[sourceIndex]) {
 
  966                    if (source.dependencies) {
 
  967                        context.error_handler.StartMissingDependentProperties();
 
  968                        for (
SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
 
  969                            if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
 
  970                                context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
 
  971                        context.error_handler.EndMissingDependentProperties(source.name);
 
  973                    else if (source.dependenciesSchema) {
 
  974                        ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
 
  975                        if (!dependenciesValidator->IsValid())
 
  976                            context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
 
  980            if (context.error_handler.EndDependencyErrors())
 
  981                RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
 
  987    bool StartArray(Context& context)
 const {
 
  988        if (!(type_ & (1 << kArraySchemaType))) {
 
  989            DisallowedType(context, GetArrayString());
 
  990            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
  993        context.arrayElementIndex = 0;
 
  994        context.inArray = 
true;
 
  996        return CreateParallelValidator(context);
 
  999    bool EndArray(Context& context, 
SizeType elementCount)
 const {
 
 1000        context.inArray = 
false;
 
 1002        if (elementCount < minItems_) {
 
 1003            context.error_handler.TooFewItems(elementCount, minItems_);
 
 1004            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
 
 1007        if (elementCount > maxItems_) {
 
 1008            context.error_handler.TooManyItems(elementCount, maxItems_);
 
 1009            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
 
 1016#define RAPIDJSON_STRING_(name, ...) \ 
 1017    static const ValueType& Get##name##String() {\ 
 1018        static const Ch s[] = { __VA_ARGS__, '\0' };\ 
 1019        static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\ 
 1023    RAPIDJSON_STRING_(Null, 
'n', 
'u', 
'l', 
'l')
 
 1024    RAPIDJSON_STRING_(Boolean, 
'b', 
'o', 
'o', 
'l', 
'e', 
'a', 
'n')
 
 1025    RAPIDJSON_STRING_(Object, 
'o', 
'b', 
'j', 
'e', 
'c', 
't')
 
 1026    RAPIDJSON_STRING_(Array, 
'a', 
'r', 
'r', 
'a', 
'y')
 
 1027    RAPIDJSON_STRING_(String, 
's', 
't', 
'r', 
'i', 
'n', 
'g')
 
 1028    RAPIDJSON_STRING_(Number, 
'n', 
'u', 
'm', 
'b', 
'e', 
'r')
 
 1029    RAPIDJSON_STRING_(Integer, 
'i', 
'n', 
't', 
'e', 
'g', 
'e', 
'r')
 
 1030    RAPIDJSON_STRING_(
Type, 
't', 
'y', 
'p', 
'e')
 
 1031    RAPIDJSON_STRING_(Enum, 
'e', 
'n', 
'u', 
'm')
 
 1032    RAPIDJSON_STRING_(AllOf, 
'a', 
'l', 
'l', 
'O', 
'f')
 
 1033    RAPIDJSON_STRING_(AnyOf, 
'a', 
'n', 
'y', 
'O', 
'f')
 
 1034    RAPIDJSON_STRING_(OneOf, 
'o', 
'n', 
'e', 
'O', 
'f')
 
 1035    RAPIDJSON_STRING_(Not, 
'n', 
'o', 
't')
 
 1036    RAPIDJSON_STRING_(Properties, 
'p', 
'r', 
'o', 
'p', 
'e', 
'r', 
't', 
'i', 
'e', 
's')
 
 1037    RAPIDJSON_STRING_(Required, 
'r', 
'e', 
'q', 
'u', 
'i', 
'r', 
'e', 
'd')
 
 1038    RAPIDJSON_STRING_(Dependencies, 
'd', 
'e', 
'p', 
'e', 
'n', 
'd', 
'e', 
'n', 
'c', 
'i', 
'e', 
's')
 
 1039    RAPIDJSON_STRING_(PatternProperties, 
'p', 
'a', 
't', 
't', 
'e', 
'r', 
'n', 
'P', 
'r', 
'o', 
'p', 
'e', 
'r', 
't', 
'i', 
'e', 
's')
 
 1040    RAPIDJSON_STRING_(AdditionalProperties, 
'a', 
'd', 
'd', 
'i', 
't', 
'i', 
'o', 
'n', 
'a', 
'l', 
'P', 
'r', 
'o', 
'p', 
'e', 
'r', 
't', 
'i', 
'e', 
's')
 
 1041    RAPIDJSON_STRING_(MinProperties, 
'm', 
'i', 
'n', 
'P', 
'r', 
'o', 
'p', 
'e', 
'r', 
't', 
'i', 
'e', 
's')
 
 1042    RAPIDJSON_STRING_(MaxProperties, 
'm', 
'a', 
'x', 
'P', 
'r', 
'o', 
'p', 
'e', 
'r', 
't', 
'i', 
'e', 
's')
 
 1043    RAPIDJSON_STRING_(Items, 
'i', 
't', 
'e', 
'm', 
's')
 
 1044    RAPIDJSON_STRING_(MinItems, 
'm', 
'i', 
'n', 
'I', 
't', 
'e', 
'm', 
's')
 
 1045    RAPIDJSON_STRING_(MaxItems, 
'm', 
'a', 
'x', 
'I', 
't', 
'e', 
'm', 
's')
 
 1046    RAPIDJSON_STRING_(AdditionalItems, 
'a', 
'd', 
'd', 
'i', 
't', 
'i', 
'o', 
'n', 
'a', 
'l', 
'I', 
't', 
'e', 
'm', 
's')
 
 1047    RAPIDJSON_STRING_(UniqueItems, 
'u', 
'n', 
'i', 
'q', 
'u', 
'e', 
'I', 
't', 
'e', 
'm', 
's')
 
 1048    RAPIDJSON_STRING_(MinLength, 
'm', 
'i', 
'n', 
'L', 
'e', 
'n', 
'g', 
't', 
'h')
 
 1049    RAPIDJSON_STRING_(MaxLength, 
'm', 
'a', 
'x', 
'L', 
'e', 
'n', 
'g', 
't', 
'h')
 
 1050    RAPIDJSON_STRING_(Pattern, 
'p', 
'a', 
't', 
't', 
'e', 
'r', 
'n')
 
 1051    RAPIDJSON_STRING_(Minimum, 
'm', 
'i', 
'n', 
'i', 
'm', 
'u', 
'm')
 
 1052    RAPIDJSON_STRING_(Maximum, 
'm', 
'a', 
'x', 
'i', 
'm', 
'u', 
'm')
 
 1053    RAPIDJSON_STRING_(ExclusiveMinimum, 
'e', 
'x', 
'c', 
'l', 
'u', 
's', 
'i', 
'v', 
'e', 
'M', 
'i', 
'n', 
'i', 
'm', 
'u', 
'm')
 
 1054    RAPIDJSON_STRING_(ExclusiveMaximum, 
'e', 
'x', 
'c', 
'l', 
'u', 
's', 
'i', 
'v', 
'e', 
'M', 
'a', 
'x', 
'i', 
'm', 
'u', 
'm')
 
 1055    RAPIDJSON_STRING_(MultipleOf, 
'm', 
'u', 
'l', 
't', 
'i', 
'p', 
'l', 
'e', 
'O', 
'f')
 
 1056    RAPIDJSON_STRING_(DefaultValue, 
'd', 
'e', 
'f', 
'a', 
'u', 
'l', 
't')
 
 1058#undef RAPIDJSON_STRING_ 
 1061    enum SchemaValueType {
 
 1072#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 
 1074#elif RAPIDJSON_SCHEMA_USE_STDREGEX 
 1075        typedef std::basic_regex<Ch> BESRegexType;
 
 1077        typedef char BESRegexType;
 
 1080    struct SchemaArray {
 
 1081        SchemaArray() : schemas(), count() {}
 
 1082        ~SchemaArray() { AllocatorType::Free(schemas); }
 
 1083        const SchemaType** schemas;
 
 1088    template <
typename V1, 
typename V2>
 
 1089    void AddUniqueElement(V1& a, 
const V2& v) {
 
 1090        for (
typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
 
 1093        V1 c(v, *allocator_);
 
 1094        a.PushBack(c, *allocator_);
 
 1097    static const ValueType* GetMember(
const ValueType& value, 
const ValueType& name) {
 
 1098        typename ValueType::ConstMemberIterator itr = value.FindMember(name);
 
 1099        return itr != value.MemberEnd() ? &(itr->value) : 0;
 
 1102    static void AssignIfExist(
bool& out, 
const ValueType& value, 
const ValueType& name) {
 
 1103        if (
const ValueType* v = GetMember(value, name))
 
 1108    static void AssignIfExist(
SizeType& out, 
const ValueType& value, 
const ValueType& name) {
 
 1109        if (
const ValueType* v = GetMember(value, name))
 
 1110            if (v->IsUint64() && v->GetUint64() <= 
SizeType(~0))
 
 1111                out = 
static_cast<SizeType>(v->GetUint64());
 
 1114    void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, 
const PointerType& p, 
const ValueType& value, 
const ValueType& name, 
const ValueType& document) {
 
 1115        if (
const ValueType* v = GetMember(value, name)) {
 
 1116            if (v->IsArray() && v->Size() > 0) {
 
 1117                PointerType q = p.Append(name, allocator_);
 
 1118                out.count = v->Size();
 
 1119                out.schemas = 
static_cast<const Schema**
>(allocator_->Malloc(out.count * 
sizeof(
const Schema*)));
 
 1120                memset(out.schemas, 0, 
sizeof(Schema*)* out.count);
 
 1121                for (
SizeType i = 0; i < out.count; i++)
 
 1122                    schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
 
 1123                out.begin = validatorCount_;
 
 1124                validatorCount_ += out.count;
 
 1129#if RAPIDJSON_SCHEMA_USE_INTERNALREGEX 
 1130    template <
typename ValueType>
 
 1131    BESRegexType* CreatePattern(
const ValueType& value) {
 
 1132        if (value.IsString()) {
 
 1133            BESRegexType* r = 
new (allocator_->Malloc(
sizeof(BESRegexType))) BESRegexType(value.GetString(), allocator_);
 
 1134            if (!r->IsValid()) {
 
 1136                AllocatorType::Free(r);
 
 1144    static bool IsPatternMatch(
const BESRegexType* pattern, 
const Ch *str, 
SizeType) {
 
 1146        return rs.Search(str);
 
 1148#elif RAPIDJSON_SCHEMA_USE_STDREGEX 
 1149    template <
typename ValueType>
 
 1150    BESRegexType* CreatePattern(
const ValueType& value) {
 
 1151        if (value.IsString()) {
 
 1152            BESRegexType *r = 
static_cast<BESRegexType*
>(allocator_->Malloc(
sizeof(BESRegexType)));
 
 1154                return new (r) BESRegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
 
 1156            catch (
const std::regex_error&) {
 
 1157                AllocatorType::Free(r);
 
 1163    static bool IsPatternMatch(
const BESRegexType* pattern, 
const Ch *str, 
SizeType length) {
 
 1164        std::match_results<const Ch*> r;
 
 1165        return std::regex_search(str, str + length, r, *pattern);
 
 1168    template <
typename ValueType>
 
 1169    BESRegexType* CreatePattern(
const ValueType&) { 
return 0; }
 
 1171    static bool IsPatternMatch(
const BESRegexType*, 
const Ch *, 
SizeType) { 
return true; }
 
 1174    void AddType(
const ValueType& type) {
 
 1175        if      (type == GetNullString()   ) type_ |= 1 << kNullSchemaType;
 
 1176        else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
 
 1177        else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
 
 1178        else if (type == GetArrayString()  ) type_ |= 1 << kArraySchemaType;
 
 1179        else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
 
 1180        else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
 
 1181        else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
 
 1184    bool CreateParallelValidator(Context& context)
 const {
 
 1185        if (enum_ || context.arrayUniqueness)
 
 1186            context.hasher = context.factory.CreateHasher();
 
 1188        if (validatorCount_) {
 
 1191            context.validatorCount = validatorCount_;
 
 1194                CreateSchemaValidators(context, allOf_);
 
 1197                CreateSchemaValidators(context, anyOf_);
 
 1200                CreateSchemaValidators(context, oneOf_);
 
 1203                context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
 
 1205            if (hasSchemaDependencies_) {
 
 1206                for (
SizeType i = 0; i < propertyCount_; i++)
 
 1207                    if (properties_[i].dependenciesSchema)
 
 1208                        context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
 
 1215    void CreateSchemaValidators(Context& context, 
const SchemaArray& schemas)
 const {
 
 1216        for (
SizeType i = 0; i < schemas.count; i++)
 
 1217            context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
 
 1221    bool FindPropertyIndex(
const ValueType& name, 
SizeType* outIndex)
 const {
 
 1222        SizeType len = name.GetStringLength();
 
 1223        const Ch* str = name.GetString();
 
 1224        for (
SizeType index = 0; index < propertyCount_; index++)
 
 1225            if (properties_[index].name.GetStringLength() == len && 
 
 1226                (std::memcmp(properties_[index].name.GetString(), str, 
sizeof(Ch) * len) == 0))
 
 1234    bool CheckInt(Context& context, int64_t i)
 const {
 
 1235        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
 
 1236            DisallowedType(context, GetIntegerString());
 
 1237            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
 1240        if (!minimum_.IsNull()) {
 
 1241            if (minimum_.IsInt64()) {
 
 1242                if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
 
 1243                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 
 1244                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 
 1247            else if (minimum_.IsUint64()) {
 
 1248                context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 
 1249                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); 
 
 1251            else if (!CheckDoubleMinimum(context, 
static_cast<double>(i)))
 
 1255        if (!maximum_.IsNull()) {
 
 1256            if (maximum_.IsInt64()) {
 
 1257                if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
 
 1258                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 
 1259                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 
 1262            else if (maximum_.IsUint64()) { }
 
 1264            else if (!CheckDoubleMaximum(context, 
static_cast<double>(i)))
 
 1268        if (!multipleOf_.IsNull()) {
 
 1269            if (multipleOf_.IsUint64()) {
 
 1270                if (
static_cast<uint64_t
>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
 
 1271                    context.error_handler.NotMultipleOf(i, multipleOf_);
 
 1272                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 
 1275            else if (!CheckDoubleMultipleOf(context, 
static_cast<double>(i)))
 
 1282    bool CheckUint(Context& context, uint64_t i)
 const {
 
 1283        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
 
 1284            DisallowedType(context, GetIntegerString());
 
 1285            RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
 
 1288        if (!minimum_.IsNull()) {
 
 1289            if (minimum_.IsUint64()) {
 
 1290                if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
 
 1291                    context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
 
 1292                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 
 1295            else if (minimum_.IsInt64())
 
 1297            else if (!CheckDoubleMinimum(context, 
static_cast<double>(i)))
 
 1301        if (!maximum_.IsNull()) {
 
 1302            if (maximum_.IsUint64()) {
 
 1303                if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
 
 1304                    context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 
 1305                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 
 1308            else if (maximum_.IsInt64()) {
 
 1309                context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
 
 1310                RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); 
 
 1312            else if (!CheckDoubleMaximum(context, 
static_cast<double>(i)))
 
 1316        if (!multipleOf_.IsNull()) {
 
 1317            if (multipleOf_.IsUint64()) {
 
 1318                if (i % multipleOf_.GetUint64() != 0) {
 
 1319                    context.error_handler.NotMultipleOf(i, multipleOf_);
 
 1320                    RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 
 1323            else if (!CheckDoubleMultipleOf(context, 
static_cast<double>(i)))
 
 1330    bool CheckDoubleMinimum(Context& context, 
double d)
 const {
 
 1331        if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
 
 1332            context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
 
 1333            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
 
 1338    bool CheckDoubleMaximum(Context& context, 
double d)
 const {
 
 1339        if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
 
 1340            context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
 
 1341            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
 
 1346    bool CheckDoubleMultipleOf(Context& context, 
double d)
 const {
 
 1347        double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
 
 1348        double q = std::floor(a / b);
 
 1349        double r = a - q * b;
 
 1351            context.error_handler.NotMultipleOf(d, multipleOf_);
 
 1352            RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
 
 1357    void DisallowedType(Context& context, 
const ValueType& actualType)
 const {
 
 1358        ErrorHandler& eh = context.error_handler;
 
 1359        eh.StartDisallowedType();
 
 1361        if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
 
 1362        if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
 
 1363        if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
 
 1364        if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
 
 1365        if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
 
 1367        if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
 
 1368        else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
 
 1370        eh.EndDisallowedType(actualType);
 
 1374        Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(
false) {}
 
 1375        ~Property() { AllocatorType::Free(dependencies); }
 
 1377        const SchemaType* schema;
 
 1378        const SchemaType* dependenciesSchema;
 
 1379        SizeType dependenciesValidatorIndex;
 
 1384    struct PatternProperty {
 
 1385        PatternProperty() : schema(), pattern() {}
 
 1386        ~PatternProperty() { 
 
 1388                pattern->~BESRegexType();
 
 1389                AllocatorType::Free(pattern);
 
 1392        const SchemaType* schema;
 
 1393        BESRegexType* pattern;
 
 1396    AllocatorType* allocator_;
 
 1398    PointerType pointer_;
 
 1399    const SchemaType* typeless_;
 
 1405    const SchemaType* not_;
 
 1410    Property* properties_;
 
 1411    const SchemaType* additionalPropertiesSchema_;
 
 1412    PatternProperty* patternProperties_;
 
 1417    bool additionalProperties_;
 
 1418    bool hasDependencies_;
 
 1420    bool hasSchemaDependencies_;
 
 1422    const SchemaType* additionalItemsSchema_;
 
 1423    const SchemaType* itemsList_;
 
 1424    const SchemaType** itemsTuple_;
 
 1428    bool additionalItems_;
 
 1431    BESRegexType* pattern_;
 
 1438    bool exclusiveMinimum_;
 
 1439    bool exclusiveMaximum_;
 
 
 1769    typedef typename SchemaDocumentType::SchemaType SchemaType;
 
 1770    typedef typename SchemaDocumentType::PointerType PointerType;
 
 1771    typedef typename SchemaType::EncodingType EncodingType;
 
 1772    typedef typename SchemaType::SValue SValue;
 
 1773    typedef typename EncodingType::Ch Ch;
 
 1785        const SchemaDocumentType& schemaDocument,
 
 1786        StateAllocator* allocator = 0, 
 
 1787        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
 
 1788        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
 
 1790        schemaDocument_(&schemaDocument),
 
 1791        root_(schemaDocument.GetRoot()),
 
 1792        stateAllocator_(allocator),
 
 1793        ownStateAllocator_(0),
 
 1794        schemaStack_(allocator, schemaStackCapacity),
 
 1795        documentStack_(allocator, documentStackCapacity),
 
 1799        missingDependents_(),
 
 1801#if RAPIDJSON_SCHEMA_VERBOSE
 
 
 1815        const SchemaDocumentType& schemaDocument,
 
 1816        OutputHandler& outputHandler,
 
 1817        StateAllocator* allocator = 0, 
 
 1818        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
 
 1819        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
 
 1821        schemaDocument_(&schemaDocument),
 
 1822        root_(schemaDocument.GetRoot()),
 
 1823        stateAllocator_(allocator),
 
 1824        ownStateAllocator_(0),
 
 1825        schemaStack_(allocator, schemaStackCapacity),
 
 1826        documentStack_(allocator, documentStackCapacity),
 
 1827        outputHandler_(&outputHandler),
 
 1830        missingDependents_(),
 
 1832#if RAPIDJSON_SCHEMA_VERBOSE
 
 
 1846        while (!schemaStack_.Empty())
 
 1848        documentStack_.Clear();
 
 1850        currentError_.SetNull();
 
 1851        missingDependents_.SetNull();
 
 
 1861    const ValueType& 
GetError()
 const { 
return error_; }
 
 1865        return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
 
 
 1870        return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
 
 
 1875        if (documentStack_.Empty()) {
 
 1876            return PointerType();
 
 1879            return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / 
sizeof(Ch));
 
 
 1883    void NotMultipleOf(int64_t actual, 
const SValue& expected) {
 
 1884        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
 
 1886    void NotMultipleOf(uint64_t actual, 
const SValue& expected) {
 
 1887        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
 
 1889    void NotMultipleOf(
double actual, 
const SValue& expected) {
 
 1890        AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
 
 1892    void AboveMaximum(int64_t actual, 
const SValue& expected, 
bool exclusive) {
 
 1893        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
 
 1894            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 
 1896    void AboveMaximum(uint64_t actual, 
const SValue& expected, 
bool exclusive) {
 
 1897        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
 
 1898            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 
 1900    void AboveMaximum(
double actual, 
const SValue& expected, 
bool exclusive) {
 
 1901        AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
 
 1902            exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
 
 1904    void BelowMinimum(int64_t actual, 
const SValue& expected, 
bool exclusive) {
 
 1905        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
 
 1906            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 
 1908    void BelowMinimum(uint64_t actual, 
const SValue& expected, 
bool exclusive) {
 
 1909        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
 
 1910            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 
 1912    void BelowMinimum(
double actual, 
const SValue& expected, 
bool exclusive) {
 
 1913        AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
 
 1914            exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
 
 1918        AddNumberError(SchemaType::GetMaxLengthString(),
 
 1919            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
 
 1922        AddNumberError(SchemaType::GetMinLengthString(),
 
 1923            ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
 
 1925    void DoesNotMatch(
const Ch* str, 
SizeType length) {
 
 1926        currentError_.SetObject();
 
 1927        currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
 
 1928        AddCurrentError(SchemaType::GetPatternString());
 
 1931    void DisallowedItem(
SizeType index) {
 
 1932        currentError_.SetObject();
 
 1933        currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
 
 1934        AddCurrentError(SchemaType::GetAdditionalItemsString(), 
true);
 
 1937        AddNumberError(SchemaType::GetMinItemsString(),
 
 1938            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 
 1941        AddNumberError(SchemaType::GetMaxItemsString(),
 
 1942            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 
 1946        duplicates.PushBack(index1, GetStateAllocator());
 
 1947        duplicates.PushBack(index2, GetStateAllocator());
 
 1948        currentError_.SetObject();
 
 1949        currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
 
 1950        AddCurrentError(SchemaType::GetUniqueItemsString(), 
true);
 
 1954        AddNumberError(SchemaType::GetMaxPropertiesString(),
 
 1955            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 
 1958        AddNumberError(SchemaType::GetMinPropertiesString(),
 
 1959            ValueType(actualCount).Move(), SValue(expectedCount).Move());
 
 1961    void StartMissingProperties() {
 
 1962        currentError_.SetArray();
 
 1964    void AddMissingProperty(
const SValue& name) {
 
 1965        currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
 
 1967    bool EndMissingProperties() {
 
 1968        if (currentError_.Empty())
 
 1971        error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
 
 1972        currentError_ = error;
 
 1973        AddCurrentError(SchemaType::GetRequiredString());
 
 1976    void PropertyViolations(ISchemaValidator** subvalidators, 
SizeType count) {
 
 1977        for (
SizeType i = 0; i < count; ++i)
 
 1980    void DisallowedProperty(
const Ch* name, 
SizeType length) {
 
 1981        currentError_.SetObject();
 
 1982        currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
 
 1983        AddCurrentError(SchemaType::GetAdditionalPropertiesString(), 
true);
 
 1986    void StartDependencyErrors() {
 
 1987        currentError_.SetObject();
 
 1989    void StartMissingDependentProperties() {
 
 1990        missingDependents_.SetArray();
 
 1992    void AddMissingDependentProperty(
const SValue& targetName) {
 
 1993        missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
 
 1995    void EndMissingDependentProperties(
const SValue& sourceName) {
 
 1996        if (!missingDependents_.Empty())
 
 1997            currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
 
 1998                missingDependents_, GetStateAllocator());
 
 2000    void AddDependencySchemaError(
const SValue& sourceName, ISchemaValidator* subvalidator) {
 
 2001        currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
 
 2004    bool EndDependencyErrors() {
 
 2005        if (currentError_.ObjectEmpty())
 
 2008        error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
 
 2009        currentError_ = error;
 
 2010        AddCurrentError(SchemaType::GetDependenciesString());
 
 2014    void DisallowedValue() {
 
 2015        currentError_.SetObject();
 
 2016        AddCurrentError(SchemaType::GetEnumString());
 
 2018    void StartDisallowedType() {
 
 2019        currentError_.SetArray();
 
 2021    void AddExpectedType(
const typename SchemaType::ValueType& expectedType) {
 
 2022        currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
 
 2024    void EndDisallowedType(
const typename SchemaType::ValueType& actualType) {
 
 2026        error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
 
 2027        error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
 
 2028        currentError_ = error;
 
 2029        AddCurrentError(SchemaType::GetTypeString());
 
 2031    void NotAllOf(ISchemaValidator** subvalidators, 
SizeType count) {
 
 2032        for (
SizeType i = 0; i < count; ++i) {
 
 2036    void NoneOf(ISchemaValidator** subvalidators, 
SizeType count) {
 
 2037        AddErrorArray(SchemaType::GetAnyOfString(), subvalidators, count);
 
 2039    void NotOneOf(ISchemaValidator** subvalidators, 
SizeType count) {
 
 2040        AddErrorArray(SchemaType::GetOneOfString(), subvalidators, count);
 
 2043        currentError_.SetObject();
 
 2044        AddCurrentError(SchemaType::GetNotString());
 
 2047#define RAPIDJSON_STRING_(name, ...) \ 
 2048    static const StringRefType& Get##name##String() {\ 
 2049        static const Ch s[] = { __VA_ARGS__, '\0' };\ 
 2050        static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \ 
 2054    RAPIDJSON_STRING_(InstanceRef, 
'i', 
'n', 
's', 
't', 
'a', 
'n', 
'c', 
'e', 
'R', 
'e', 
'f')
 
 2055    RAPIDJSON_STRING_(SchemaRef, 
's', 
'c', 
'h', 
'e', 
'm', 
'a', 
'R', 
'e', 
'f')
 
 2056    RAPIDJSON_STRING_(Expected, 
'e', 
'x', 
'p', 
'e', 
'c', 
't', 
'e', 
'd')
 
 2057    RAPIDJSON_STRING_(Actual, 
'a', 
'c', 
't', 
'u', 
'a', 
'l')
 
 2058    RAPIDJSON_STRING_(Disallowed, 
'd', 
'i', 
's', 
'a', 
'l', 
'l', 
'o', 
'w', 
'e', 
'd')
 
 2059    RAPIDJSON_STRING_(Missing, 
'm', 
'i', 
's', 
's', 
'i', 
'n', 
'g')
 
 2060    RAPIDJSON_STRING_(Errors, 
'e', 
'r', 
'r', 
'o', 
'r', 
's')
 
 2061    RAPIDJSON_STRING_(Duplicates, 
'd', 
'u', 
'p', 
'l', 
'i', 
'c', 
'a', 
't', 
'e', 
's')
 
 2063#undef RAPIDJSON_STRING_ 
 2065#if RAPIDJSON_SCHEMA_VERBOSE 
 2066#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \ 
 2067RAPIDJSON_MULTILINEMACRO_BEGIN\ 
 2068    *documentStack_.template Push<Ch>() = '\0';\ 
 2069    documentStack_.template Pop<Ch>(1);\ 
 2070    internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\ 
 2071RAPIDJSON_MULTILINEMACRO_END 
 2073#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() 
 2076#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\ 
 2077    if (!valid_) return false; \ 
 2078    if (!BeginValue() || !CurrentSchema().method arg1) {\ 
 2079        RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\ 
 2080        return valid_ = false;\ 
 2083#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\ 
 2084    for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\ 
 2085        if (context->hasher)\ 
 2086            static_cast<HasherType*>(context->hasher)->method arg2;\ 
 2087        if (context->validators)\ 
 2088            for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\ 
 2089                static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\ 
 2090        if (context->patternPropertiesValidators)\ 
 2091            for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\ 
 2092                static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\ 
 2095#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\ 
 2096    return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2) 
 2098#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \ 
 2099    RAPIDJSON_SCHEMA_HANDLE_BEGIN_   (method, arg1);\ 
 2100    RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\ 
 2101    RAPIDJSON_SCHEMA_HANDLE_END_     (method, arg2) 
 2103    bool Null()             { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null,   (CurrentContext()), ( )); }
 
 2104    bool Bool(
bool b)       { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool,   (CurrentContext(), b), (b)); }
 
 2105    bool Int(
int i)         { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int,    (CurrentContext(), i), (i)); }
 
 2106    bool Uint(
unsigned u)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint,   (CurrentContext(), u), (u)); }
 
 2107    bool Int64(int64_t i)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64,  (CurrentContext(), i), (i)); }
 
 2108    bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
 
 2109    bool Double(
double d)   { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
 
 2110    bool RawNumber(
const Ch* str, 
SizeType length, 
bool copy)
 
 2111                                    { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
 
 2112    bool String(
const Ch* str, 
SizeType length, 
bool copy)
 
 2113                                    { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
 
 2115    bool StartObject() {
 
 2116        RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
 
 2117        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
 
 2118        return valid_ = !outputHandler_ || outputHandler_->StartObject();
 
 2121    bool Key(
const Ch* str, 
SizeType len, 
bool copy) {
 
 2122        if (!valid_) 
return false;
 
 2123        AppendToken(str, len);
 
 2124        if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) 
return valid_ = 
false;
 
 2125        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
 
 2126        return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
 
 2129    bool EndObject(
SizeType memberCount) { 
 
 2130        if (!valid_) 
return false;
 
 2131        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
 
 2132        if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) 
return valid_ = 
false;
 
 2133        RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
 
 2137        RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
 
 2138        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
 
 2139        return valid_ = !outputHandler_ || outputHandler_->StartArray();
 
 2142    bool EndArray(
SizeType elementCount) {
 
 2143        if (!valid_) 
return false;
 
 2144        RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
 
 2145        if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) 
return valid_ = 
false;
 
 2146        RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
 
 2149#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_ 
 2150#undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_ 
 2151#undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_ 
 2152#undef RAPIDJSON_SCHEMA_HANDLE_VALUE_ 
 2155    virtual ISchemaValidator* CreateSchemaValidator(
const SchemaType& root) {
 
 2157#
if RAPIDJSON_SCHEMA_VERBOSE
 
 2160        &GetStateAllocator());
 
 2163    virtual void DestroySchemaValidator(ISchemaValidator* validator) {
 
 2166        StateAllocator::Free(v);
 
 2169    virtual void* CreateHasher() {
 
 2170        return new (GetStateAllocator().Malloc(
sizeof(HasherType))) HasherType(&GetStateAllocator());
 
 2173    virtual uint64_t GetHashCode(
void* hasher) {
 
 2174        return static_cast<HasherType*
>(hasher)->GetHashCode();
 
 2177    virtual void DestroryHasher(
void* hasher) {
 
 2178        HasherType* h = 
static_cast<HasherType*
>(hasher);
 
 2180        StateAllocator::Free(h);
 
 2183    virtual void* MallocState(
size_t size) {
 
 2184        return GetStateAllocator().Malloc(size);
 
 2187    virtual void FreeState(
void* p) {
 
 2188        StateAllocator::Free(p);
 
 2192    typedef typename SchemaType::Context Context;
 
 2193    typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
 
 2194    typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
 
 2197        const SchemaDocumentType& schemaDocument,
 
 2198        const SchemaType& root,
 
 2199        const char* basePath, 
size_t basePathSize,
 
 2200#
if RAPIDJSON_SCHEMA_VERBOSE
 
 2203        StateAllocator* allocator = 0,
 
 2204        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
 
 2205        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
 
 2207        schemaDocument_(&schemaDocument),
 
 2209        stateAllocator_(allocator),
 
 2210        ownStateAllocator_(0),
 
 2211        schemaStack_(allocator, schemaStackCapacity),
 
 2212        documentStack_(allocator, documentStackCapacity),
 
 2216        missingDependents_(),
 
 2218#if RAPIDJSON_SCHEMA_VERBOSE
 
 2222        if (basePath && basePathSize)
 
 2223            memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
 
 2226    StateAllocator& GetStateAllocator() {
 
 2227        if (!stateAllocator_)
 
 2228            stateAllocator_ = ownStateAllocator_ = 
RAPIDJSON_NEW(StateAllocator)();
 
 2229        return *stateAllocator_;
 
 2233        if (schemaStack_.Empty())
 
 2236            if (CurrentContext().inArray)
 
 2237                internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
 
 2239            if (!CurrentSchema().BeginValue(CurrentContext()))
 
 2242            SizeType count = CurrentContext().patternPropertiesSchemaCount;
 
 2243            const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
 
 2244            typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
 
 2245            bool valueUniqueness = CurrentContext().valueUniqueness;
 
 2247            PushSchema(*CurrentContext().valueSchema);
 
 2250                CurrentContext().objectPatternValidatorType = patternValidatorType;
 
 2251                ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
 
 2252                SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
 
 2253                va = 
static_cast<ISchemaValidator**
>(MallocState(
sizeof(ISchemaValidator*) * count));
 
 2254                for (
SizeType i = 0; i < count; i++)
 
 2255                    va[validatorCount++] = CreateSchemaValidator(*sa[i]);
 
 2258            CurrentContext().arrayUniqueness = valueUniqueness;
 
 2264        if (!CurrentSchema().EndValue(CurrentContext()))
 
 2267#if RAPIDJSON_SCHEMA_VERBOSE 
 2268        GenericStringBuffer<EncodingType> sb;
 
 2269        schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
 
 2271        *documentStack_.template Push<Ch>() = 
'\0';
 
 2272        documentStack_.template Pop<Ch>(1);
 
 2273        internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
 
 2276        uint64_t h = CurrentContext().arrayUniqueness ? 
static_cast<HasherType*
>(CurrentContext().hasher)->GetHashCode() : 0;
 
 2280        if (!schemaStack_.Empty()) {
 
 2281            Context& context = CurrentContext();
 
 2282            if (context.valueUniqueness) {
 
 2283                HashCodeArray* a = 
static_cast<HashCodeArray*
>(context.arrayElementHashCodes);
 
 2285                    CurrentContext().arrayElementHashCodes = a = 
new (GetStateAllocator().Malloc(
sizeof(HashCodeArray))) HashCodeArray(
kArrayType);
 
 2287                    if (itr->GetUint64() == h) {
 
 2288                        DuplicateItems(
static_cast<SizeType>(itr - a->Begin()), a->Size());
 
 2289                        RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
 
 2291                a->PushBack(h, GetStateAllocator());
 
 2296        while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != 
'/')
 
 2302    void AppendToken(
const Ch* str, 
SizeType len) {
 
 2303        documentStack_.template Reserve<Ch>(1 + len * 2); 
 
 2304        *documentStack_.template PushUnsafe<Ch>() = 
'/';
 
 2305        for (
SizeType i = 0; i < len; i++) {
 
 2306            if (str[i] == 
'~') {
 
 2307                *documentStack_.template PushUnsafe<Ch>() = 
'~';
 
 2308                *documentStack_.template PushUnsafe<Ch>() = 
'0';
 
 2310            else if (str[i] == 
'/') {
 
 2311                *documentStack_.template PushUnsafe<Ch>() = 
'~';
 
 2312                *documentStack_.template PushUnsafe<Ch>() = 
'1';
 
 2315                *documentStack_.template PushUnsafe<Ch>() = str[i];
 
 2319    RAPIDJSON_FORCEINLINE 
void PushSchema(
const SchemaType& schema) { 
new (schemaStack_.template Push<Context>()) Context(*
this, *
this, &schema); }
 
 2321    RAPIDJSON_FORCEINLINE 
void PopSchema() {
 
 2322        Context* c = schemaStack_.template Pop<Context>(1);
 
 2323        if (HashCodeArray* a = 
static_cast<HashCodeArray*
>(c->arrayElementHashCodes)) {
 
 2324            a->~HashCodeArray();
 
 2325            StateAllocator::Free(a);
 
 2330    void AddErrorLocation(ValueType& result, 
bool parent) {
 
 2331        GenericStringBuffer<EncodingType> sb;
 
 2333        ((parent && instancePointer.GetTokenCount() > 0)
 
 2334            ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
 
 2335            : instancePointer).StringifyUriFragment(sb);
 
 2336        ValueType instanceRef(sb.GetString(), 
static_cast<SizeType>(sb.
GetSize() / 
sizeof(Ch)),
 
 2337            GetStateAllocator());
 
 2338        result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
 
 2340        memcpy(sb.Push(CurrentSchema().GetURI().GetStringLength()),
 
 2341            CurrentSchema().GetURI().GetString(),
 
 2342            CurrentSchema().GetURI().GetStringLength() * 
sizeof(Ch));
 
 2344        ValueType schemaRef(sb.GetString(), 
static_cast<SizeType>(sb.
GetSize() / 
sizeof(Ch)),
 
 2345            GetStateAllocator());
 
 2346        result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
 
 2349    void AddError(ValueType& keyword, ValueType& error) {
 
 2351        if (member == error_.MemberEnd())
 
 2352            error_.AddMember(keyword, error, GetStateAllocator());
 
 2354            if (member->value.IsObject()) {
 
 2356                errors.PushBack(member->value, GetStateAllocator());
 
 2357                member->value = errors;
 
 2359            member->value.PushBack(error, GetStateAllocator());
 
 2363    void AddCurrentError(
const typename SchemaType::ValueType& keyword, 
bool parent = 
false) {
 
 2364        AddErrorLocation(currentError_, parent);
 
 2365        AddError(ValueType(keyword, GetStateAllocator(), 
false).Move(), currentError_);
 
 2368    void MergeError(ValueType& other) {
 
 2370            AddError(it->name, it->value);
 
 2374    void AddNumberError(
const typename SchemaType::ValueType& keyword, ValueType& actual, 
const SValue& expected,
 
 2375        const typename SchemaType::ValueType& (*exclusive)() = 0) {
 
 2376        currentError_.SetObject();
 
 2377        currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
 
 2378        currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
 
 2380            currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), 
true, GetStateAllocator());
 
 2381        AddCurrentError(keyword);
 
 2384    void AddErrorArray(
const typename SchemaType::ValueType& keyword,
 
 2385        ISchemaValidator** subvalidators, 
SizeType count) {
 
 2387        for (
SizeType i = 0; i < count; ++i)
 
 2388            errors.PushBack(
static_cast<GenericSchemaValidator*
>(subvalidators[i])->GetError(), GetStateAllocator());
 
 2389        currentError_.SetObject();
 
 2390        currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
 
 2391        AddCurrentError(keyword);
 
 2394    const SchemaType& CurrentSchema()
 const { 
return *schemaStack_.template Top<Context>()->schema; }
 
 2395    Context& CurrentContext() { 
return *schemaStack_.template Top<Context>(); }
 
 2396    const Context& CurrentContext()
 const { 
return *schemaStack_.template Top<Context>(); }
 
 2398    static const size_t kDefaultSchemaStackCapacity = 1024;
 
 2399    static const size_t kDefaultDocumentStackCapacity = 256;
 
 2400    const SchemaDocumentType* schemaDocument_;
 
 2401    const SchemaType& root_;
 
 2402    StateAllocator* stateAllocator_;
 
 2403    StateAllocator* ownStateAllocator_;
 
 2404    internal::Stack<StateAllocator> schemaStack_;    
 
 2405    internal::Stack<StateAllocator> documentStack_;  
 
 2406    OutputHandler* outputHandler_;
 
 2408    ValueType currentError_;
 
 2409    ValueType missingDependents_;
 
 2411#if RAPIDJSON_SCHEMA_VERBOSE