git repos / blockattack-game

blame: source/code/Libs/include/cereal/external/rapidjson/schema.h

normal view · raw

6c5f2c01 sago007 2017-03-15 17:56 1
// Tencent is pleased to support the open source community by making RapidJSON available->
6c5f2c01 sago007 2017-03-15 17:56 2
// 
6c5f2c01 sago007 2017-03-15 17:56 3
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
6c5f2c01 sago007 2017-03-15 17:56 4
//
6c5f2c01 sago007 2017-03-15 17:56 5
// Licensed under the MIT License (the "License"); you may not use this file except
6c5f2c01 sago007 2017-03-15 17:56 6
// in compliance with the License-> You may obtain a copy of the License at
6c5f2c01 sago007 2017-03-15 17:56 7
//
6c5f2c01 sago007 2017-03-15 17:56 8
// http://opensource->org/licenses/MIT
6c5f2c01 sago007 2017-03-15 17:56 9
//
6c5f2c01 sago007 2017-03-15 17:56 10
// Unless required by applicable law or agreed to in writing, software distributed 
6c5f2c01 sago007 2017-03-15 17:56 11
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 
6c5f2c01 sago007 2017-03-15 17:56 12
// CONDITIONS OF ANY KIND, either express or implied-> See the License for the 
6c5f2c01 sago007 2017-03-15 17:56 13
// specific language governing permissions and limitations under the License->
6c5f2c01 sago007 2017-03-15 17:56 14
6c5f2c01 sago007 2017-03-15 17:56 15
#ifndef CEREAL_RAPIDJSON_SCHEMA_H_
6c5f2c01 sago007 2017-03-15 17:56 16
#define CEREAL_RAPIDJSON_SCHEMA_H_
6c5f2c01 sago007 2017-03-15 17:56 17
6c5f2c01 sago007 2017-03-15 17:56 18
#include "document.h"
6c5f2c01 sago007 2017-03-15 17:56 19
#include "pointer.h"
6c5f2c01 sago007 2017-03-15 17:56 20
#include <cmath> // abs, floor
6c5f2c01 sago007 2017-03-15 17:56 21
6c5f2c01 sago007 2017-03-15 17:56 22
#if !defined(CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
6c5f2c01 sago007 2017-03-15 17:56 23
#define CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
6c5f2c01 sago007 2017-03-15 17:56 24
#else
6c5f2c01 sago007 2017-03-15 17:56 25
#define CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
6c5f2c01 sago007 2017-03-15 17:56 26
#endif
6c5f2c01 sago007 2017-03-15 17:56 27
6c5f2c01 sago007 2017-03-15 17:56 28
#if !CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX && !defined(CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
6c5f2c01 sago007 2017-03-15 17:56 29
#define CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX 1
6c5f2c01 sago007 2017-03-15 17:56 30
#else
6c5f2c01 sago007 2017-03-15 17:56 31
#define CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX 0
6c5f2c01 sago007 2017-03-15 17:56 32
#endif
6c5f2c01 sago007 2017-03-15 17:56 33
6c5f2c01 sago007 2017-03-15 17:56 34
#if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
6c5f2c01 sago007 2017-03-15 17:56 35
#include "internal/regex.h"
6c5f2c01 sago007 2017-03-15 17:56 36
#elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
6c5f2c01 sago007 2017-03-15 17:56 37
#include <regex>
6c5f2c01 sago007 2017-03-15 17:56 38
#endif
6c5f2c01 sago007 2017-03-15 17:56 39
6c5f2c01 sago007 2017-03-15 17:56 40
#if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX || CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
6c5f2c01 sago007 2017-03-15 17:56 41
#define CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX 1
6c5f2c01 sago007 2017-03-15 17:56 42
#else
6c5f2c01 sago007 2017-03-15 17:56 43
#define CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX 0
6c5f2c01 sago007 2017-03-15 17:56 44
#endif
6c5f2c01 sago007 2017-03-15 17:56 45
6c5f2c01 sago007 2017-03-15 17:56 46
#ifndef CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 47
#define CEREAL_RAPIDJSON_SCHEMA_VERBOSE 0
6c5f2c01 sago007 2017-03-15 17:56 48
#endif
6c5f2c01 sago007 2017-03-15 17:56 49
6c5f2c01 sago007 2017-03-15 17:56 50
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 51
#include "stringbuffer.h"
6c5f2c01 sago007 2017-03-15 17:56 52
#endif
6c5f2c01 sago007 2017-03-15 17:56 53
6c5f2c01 sago007 2017-03-15 17:56 54
CEREAL_RAPIDJSON_DIAG_PUSH
6c5f2c01 sago007 2017-03-15 17:56 55
6c5f2c01 sago007 2017-03-15 17:56 56
#if defined(__GNUC__)
6c5f2c01 sago007 2017-03-15 17:56 57
CEREAL_RAPIDJSON_DIAG_OFF(effc++)
6c5f2c01 sago007 2017-03-15 17:56 58
#endif
6c5f2c01 sago007 2017-03-15 17:56 59
6c5f2c01 sago007 2017-03-15 17:56 60
#ifdef __clang__
6c5f2c01 sago007 2017-03-15 17:56 61
CEREAL_RAPIDJSON_DIAG_OFF(weak-vtables)
6c5f2c01 sago007 2017-03-15 17:56 62
CEREAL_RAPIDJSON_DIAG_OFF(exit-time-destructors)
6c5f2c01 sago007 2017-03-15 17:56 63
CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
6c5f2c01 sago007 2017-03-15 17:56 64
CEREAL_RAPIDJSON_DIAG_OFF(variadic-macros)
6c5f2c01 sago007 2017-03-15 17:56 65
#endif
6c5f2c01 sago007 2017-03-15 17:56 66
6c5f2c01 sago007 2017-03-15 17:56 67
#ifdef _MSC_VER
6c5f2c01 sago007 2017-03-15 17:56 68
CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
6c5f2c01 sago007 2017-03-15 17:56 69
#endif
6c5f2c01 sago007 2017-03-15 17:56 70
6c5f2c01 sago007 2017-03-15 17:56 71
CEREAL_RAPIDJSON_NAMESPACE_BEGIN
6c5f2c01 sago007 2017-03-15 17:56 72
6c5f2c01 sago007 2017-03-15 17:56 73
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 74
// Verbose Utilities
6c5f2c01 sago007 2017-03-15 17:56 75
6c5f2c01 sago007 2017-03-15 17:56 76
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 77
6c5f2c01 sago007 2017-03-15 17:56 78
namespace internal {
6c5f2c01 sago007 2017-03-15 17:56 79
6c5f2c01 sago007 2017-03-15 17:56 80
inline void PrintInvalidKeyword(const char* keyword) {
6c5f2c01 sago007 2017-03-15 17:56 81
    printf("Fail keyword: %s\n", keyword);
6c5f2c01 sago007 2017-03-15 17:56 82
}
6c5f2c01 sago007 2017-03-15 17:56 83
6c5f2c01 sago007 2017-03-15 17:56 84
inline void PrintInvalidKeyword(const wchar_t* keyword) {
6c5f2c01 sago007 2017-03-15 17:56 85
    wprintf(L"Fail keyword: %ls\n", keyword);
6c5f2c01 sago007 2017-03-15 17:56 86
}
6c5f2c01 sago007 2017-03-15 17:56 87
6c5f2c01 sago007 2017-03-15 17:56 88
inline void PrintInvalidDocument(const char* document) {
6c5f2c01 sago007 2017-03-15 17:56 89
    printf("Fail document: %s\n\n", document);
6c5f2c01 sago007 2017-03-15 17:56 90
}
6c5f2c01 sago007 2017-03-15 17:56 91
6c5f2c01 sago007 2017-03-15 17:56 92
inline void PrintInvalidDocument(const wchar_t* document) {
6c5f2c01 sago007 2017-03-15 17:56 93
    wprintf(L"Fail document: %ls\n\n", document);
6c5f2c01 sago007 2017-03-15 17:56 94
}
6c5f2c01 sago007 2017-03-15 17:56 95
6c5f2c01 sago007 2017-03-15 17:56 96
inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
6c5f2c01 sago007 2017-03-15 17:56 97
    printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
6c5f2c01 sago007 2017-03-15 17:56 98
}
6c5f2c01 sago007 2017-03-15 17:56 99
6c5f2c01 sago007 2017-03-15 17:56 100
inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
6c5f2c01 sago007 2017-03-15 17:56 101
    wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
6c5f2c01 sago007 2017-03-15 17:56 102
}
6c5f2c01 sago007 2017-03-15 17:56 103
6c5f2c01 sago007 2017-03-15 17:56 104
} // namespace internal
6c5f2c01 sago007 2017-03-15 17:56 105
6c5f2c01 sago007 2017-03-15 17:56 106
#endif // CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 107
6c5f2c01 sago007 2017-03-15 17:56 108
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 109
// CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN
6c5f2c01 sago007 2017-03-15 17:56 110
6c5f2c01 sago007 2017-03-15 17:56 111
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 112
#define CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
6c5f2c01 sago007 2017-03-15 17:56 113
#else
6c5f2c01 sago007 2017-03-15 17:56 114
#define CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
6c5f2c01 sago007 2017-03-15 17:56 115
#endif
6c5f2c01 sago007 2017-03-15 17:56 116
6c5f2c01 sago007 2017-03-15 17:56 117
#define CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
6c5f2c01 sago007 2017-03-15 17:56 118
CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN\
6c5f2c01 sago007 2017-03-15 17:56 119
    context.invalidKeyword = keyword.GetString();\
6c5f2c01 sago007 2017-03-15 17:56 120
    CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
6c5f2c01 sago007 2017-03-15 17:56 121
    return false;\
6c5f2c01 sago007 2017-03-15 17:56 122
CEREAL_RAPIDJSON_MULTILINEMACRO_END
6c5f2c01 sago007 2017-03-15 17:56 123
6c5f2c01 sago007 2017-03-15 17:56 124
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 125
// Forward declarations
6c5f2c01 sago007 2017-03-15 17:56 126
6c5f2c01 sago007 2017-03-15 17:56 127
template <typename ValueType, typename Allocator>
6c5f2c01 sago007 2017-03-15 17:56 128
class GenericSchemaDocument;
6c5f2c01 sago007 2017-03-15 17:56 129
6c5f2c01 sago007 2017-03-15 17:56 130
namespace internal {
6c5f2c01 sago007 2017-03-15 17:56 131
6c5f2c01 sago007 2017-03-15 17:56 132
template <typename SchemaDocumentType>
6c5f2c01 sago007 2017-03-15 17:56 133
class Schema;
6c5f2c01 sago007 2017-03-15 17:56 134
6c5f2c01 sago007 2017-03-15 17:56 135
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 136
// ISchemaValidator
6c5f2c01 sago007 2017-03-15 17:56 137
6c5f2c01 sago007 2017-03-15 17:56 138
class ISchemaValidator {
6c5f2c01 sago007 2017-03-15 17:56 139
public:
6c5f2c01 sago007 2017-03-15 17:56 140
    virtual ~ISchemaValidator() {}
6c5f2c01 sago007 2017-03-15 17:56 141
    virtual bool IsValid() const = 0;
6c5f2c01 sago007 2017-03-15 17:56 142
};
6c5f2c01 sago007 2017-03-15 17:56 143
6c5f2c01 sago007 2017-03-15 17:56 144
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 145
// ISchemaStateFactory
6c5f2c01 sago007 2017-03-15 17:56 146
6c5f2c01 sago007 2017-03-15 17:56 147
template <typename SchemaType>
6c5f2c01 sago007 2017-03-15 17:56 148
class ISchemaStateFactory {
6c5f2c01 sago007 2017-03-15 17:56 149
public:
6c5f2c01 sago007 2017-03-15 17:56 150
    virtual ~ISchemaStateFactory() {}
6c5f2c01 sago007 2017-03-15 17:56 151
    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
6c5f2c01 sago007 2017-03-15 17:56 152
    virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
6c5f2c01 sago007 2017-03-15 17:56 153
    virtual void* CreateHasher() = 0;
6c5f2c01 sago007 2017-03-15 17:56 154
    virtual uint64_t GetHashCode(void* hasher) = 0;
6c5f2c01 sago007 2017-03-15 17:56 155
    virtual void DestroryHasher(void* hasher) = 0;
6c5f2c01 sago007 2017-03-15 17:56 156
    virtual void* MallocState(size_t size) = 0;
6c5f2c01 sago007 2017-03-15 17:56 157
    virtual void FreeState(void* p) = 0;
6c5f2c01 sago007 2017-03-15 17:56 158
};
6c5f2c01 sago007 2017-03-15 17:56 159
6c5f2c01 sago007 2017-03-15 17:56 160
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 161
// Hasher
6c5f2c01 sago007 2017-03-15 17:56 162
6c5f2c01 sago007 2017-03-15 17:56 163
// For comparison of compound value
6c5f2c01 sago007 2017-03-15 17:56 164
template<typename Encoding, typename Allocator>
6c5f2c01 sago007 2017-03-15 17:56 165
class Hasher {
6c5f2c01 sago007 2017-03-15 17:56 166
public:
6c5f2c01 sago007 2017-03-15 17:56 167
    typedef typename Encoding::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 168
6c5f2c01 sago007 2017-03-15 17:56 169
    Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
6c5f2c01 sago007 2017-03-15 17:56 170
6c5f2c01 sago007 2017-03-15 17:56 171
    bool Null() { return WriteType(kNullType); }
6c5f2c01 sago007 2017-03-15 17:56 172
    bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
6c5f2c01 sago007 2017-03-15 17:56 173
    bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
6c5f2c01 sago007 2017-03-15 17:56 174
    bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
6c5f2c01 sago007 2017-03-15 17:56 175
    bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
6c5f2c01 sago007 2017-03-15 17:56 176
    bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
6c5f2c01 sago007 2017-03-15 17:56 177
    bool Double(double d) { 
6c5f2c01 sago007 2017-03-15 17:56 178
        Number n; 
6c5f2c01 sago007 2017-03-15 17:56 179
        if (d < 0) n.u.i = static_cast<int64_t>(d);
6c5f2c01 sago007 2017-03-15 17:56 180
        else       n.u.u = static_cast<uint64_t>(d); 
6c5f2c01 sago007 2017-03-15 17:56 181
        n.d = d;
6c5f2c01 sago007 2017-03-15 17:56 182
        return WriteNumber(n);
6c5f2c01 sago007 2017-03-15 17:56 183
    }
6c5f2c01 sago007 2017-03-15 17:56 184
6c5f2c01 sago007 2017-03-15 17:56 185
    bool RawNumber(const Ch* str, SizeType len, bool) {
6c5f2c01 sago007 2017-03-15 17:56 186
        WriteBuffer(kNumberType, str, len * sizeof(Ch));
6c5f2c01 sago007 2017-03-15 17:56 187
        return true;
6c5f2c01 sago007 2017-03-15 17:56 188
    }
6c5f2c01 sago007 2017-03-15 17:56 189
6c5f2c01 sago007 2017-03-15 17:56 190
    bool String(const Ch* str, SizeType len, bool) {
6c5f2c01 sago007 2017-03-15 17:56 191
        WriteBuffer(kStringType, str, len * sizeof(Ch));
6c5f2c01 sago007 2017-03-15 17:56 192
        return true;
6c5f2c01 sago007 2017-03-15 17:56 193
    }
6c5f2c01 sago007 2017-03-15 17:56 194
6c5f2c01 sago007 2017-03-15 17:56 195
    bool StartObject() { return true; }
6c5f2c01 sago007 2017-03-15 17:56 196
    bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
6c5f2c01 sago007 2017-03-15 17:56 197
    bool EndObject(SizeType memberCount) { 
6c5f2c01 sago007 2017-03-15 17:56 198
        uint64_t h = Hash(0, kObjectType);
6c5f2c01 sago007 2017-03-15 17:56 199
        uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
6c5f2c01 sago007 2017-03-15 17:56 200
        for (SizeType i = 0; i < memberCount; i++)
6c5f2c01 sago007 2017-03-15 17:56 201
            h ^= Hash(kv[i * 2], kv[i * 2 + 1]);  // Use xor to achieve member order insensitive
6c5f2c01 sago007 2017-03-15 17:56 202
        *stack_.template Push<uint64_t>() = h;
6c5f2c01 sago007 2017-03-15 17:56 203
        return true;
6c5f2c01 sago007 2017-03-15 17:56 204
    }
6c5f2c01 sago007 2017-03-15 17:56 205
    
6c5f2c01 sago007 2017-03-15 17:56 206
    bool StartArray() { return true; }
6c5f2c01 sago007 2017-03-15 17:56 207
    bool EndArray(SizeType elementCount) { 
6c5f2c01 sago007 2017-03-15 17:56 208
        uint64_t h = Hash(0, kArrayType);
6c5f2c01 sago007 2017-03-15 17:56 209
        uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
6c5f2c01 sago007 2017-03-15 17:56 210
        for (SizeType i = 0; i < elementCount; i++)
6c5f2c01 sago007 2017-03-15 17:56 211
            h = Hash(h, e[i]); // Use hash to achieve element order sensitive
6c5f2c01 sago007 2017-03-15 17:56 212
        *stack_.template Push<uint64_t>() = h;
6c5f2c01 sago007 2017-03-15 17:56 213
        return true;
6c5f2c01 sago007 2017-03-15 17:56 214
    }
6c5f2c01 sago007 2017-03-15 17:56 215
6c5f2c01 sago007 2017-03-15 17:56 216
    bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
6c5f2c01 sago007 2017-03-15 17:56 217
6c5f2c01 sago007 2017-03-15 17:56 218
    uint64_t GetHashCode() const {
6c5f2c01 sago007 2017-03-15 17:56 219
        CEREAL_RAPIDJSON_ASSERT(IsValid());
6c5f2c01 sago007 2017-03-15 17:56 220
        return *stack_.template Top<uint64_t>();
6c5f2c01 sago007 2017-03-15 17:56 221
    }
6c5f2c01 sago007 2017-03-15 17:56 222
6c5f2c01 sago007 2017-03-15 17:56 223
private:
6c5f2c01 sago007 2017-03-15 17:56 224
    static const size_t kDefaultSize = 256;
6c5f2c01 sago007 2017-03-15 17:56 225
    struct Number {
6c5f2c01 sago007 2017-03-15 17:56 226
        union U {
6c5f2c01 sago007 2017-03-15 17:56 227
            uint64_t u;
6c5f2c01 sago007 2017-03-15 17:56 228
            int64_t i;
6c5f2c01 sago007 2017-03-15 17:56 229
        }u;
6c5f2c01 sago007 2017-03-15 17:56 230
        double d;
6c5f2c01 sago007 2017-03-15 17:56 231
    };
6c5f2c01 sago007 2017-03-15 17:56 232
6c5f2c01 sago007 2017-03-15 17:56 233
    bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
6c5f2c01 sago007 2017-03-15 17:56 234
    
6c5f2c01 sago007 2017-03-15 17:56 235
    bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
6c5f2c01 sago007 2017-03-15 17:56 236
    
6c5f2c01 sago007 2017-03-15 17:56 237
    bool WriteBuffer(Type type, const void* data, size_t len) {
6c5f2c01 sago007 2017-03-15 17:56 238
        // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
6c5f2c01 sago007 2017-03-15 17:56 239
        uint64_t h = Hash(CEREAL_RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
6c5f2c01 sago007 2017-03-15 17:56 240
        const unsigned char* d = static_cast<const unsigned char*>(data);
6c5f2c01 sago007 2017-03-15 17:56 241
        for (size_t i = 0; i < len; i++)
6c5f2c01 sago007 2017-03-15 17:56 242
            h = Hash(h, d[i]);
6c5f2c01 sago007 2017-03-15 17:56 243
        *stack_.template Push<uint64_t>() = h;
6c5f2c01 sago007 2017-03-15 17:56 244
        return true;
6c5f2c01 sago007 2017-03-15 17:56 245
    }
6c5f2c01 sago007 2017-03-15 17:56 246
6c5f2c01 sago007 2017-03-15 17:56 247
    static uint64_t Hash(uint64_t h, uint64_t d) {
6c5f2c01 sago007 2017-03-15 17:56 248
        static const uint64_t kPrime = CEREAL_RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
6c5f2c01 sago007 2017-03-15 17:56 249
        h ^= d;
6c5f2c01 sago007 2017-03-15 17:56 250
        h *= kPrime;
6c5f2c01 sago007 2017-03-15 17:56 251
        return h;
6c5f2c01 sago007 2017-03-15 17:56 252
    }
6c5f2c01 sago007 2017-03-15 17:56 253
6c5f2c01 sago007 2017-03-15 17:56 254
    Stack<Allocator> stack_;
6c5f2c01 sago007 2017-03-15 17:56 255
};
6c5f2c01 sago007 2017-03-15 17:56 256
6c5f2c01 sago007 2017-03-15 17:56 257
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 258
// SchemaValidationContext
6c5f2c01 sago007 2017-03-15 17:56 259
6c5f2c01 sago007 2017-03-15 17:56 260
template <typename SchemaDocumentType>
6c5f2c01 sago007 2017-03-15 17:56 261
struct SchemaValidationContext {
6c5f2c01 sago007 2017-03-15 17:56 262
    typedef Schema<SchemaDocumentType> SchemaType;
6c5f2c01 sago007 2017-03-15 17:56 263
    typedef ISchemaStateFactory<SchemaType> SchemaValidatorFactoryType;
6c5f2c01 sago007 2017-03-15 17:56 264
    typedef typename SchemaType::ValueType ValueType;
6c5f2c01 sago007 2017-03-15 17:56 265
    typedef typename ValueType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 266
6c5f2c01 sago007 2017-03-15 17:56 267
    enum PatternValidatorType {
6c5f2c01 sago007 2017-03-15 17:56 268
        kPatternValidatorOnly,
6c5f2c01 sago007 2017-03-15 17:56 269
        kPatternValidatorWithProperty,
6c5f2c01 sago007 2017-03-15 17:56 270
        kPatternValidatorWithAdditionalProperty
6c5f2c01 sago007 2017-03-15 17:56 271
    };
6c5f2c01 sago007 2017-03-15 17:56 272
6c5f2c01 sago007 2017-03-15 17:56 273
    SchemaValidationContext(SchemaValidatorFactoryType& f, const SchemaType* s) :
6c5f2c01 sago007 2017-03-15 17:56 274
        factory(f),
6c5f2c01 sago007 2017-03-15 17:56 275
        schema(s),
6c5f2c01 sago007 2017-03-15 17:56 276
        valueSchema(),
6c5f2c01 sago007 2017-03-15 17:56 277
        invalidKeyword(),
6c5f2c01 sago007 2017-03-15 17:56 278
        hasher(),
6c5f2c01 sago007 2017-03-15 17:56 279
        arrayElementHashCodes(),
6c5f2c01 sago007 2017-03-15 17:56 280
        validators(),
6c5f2c01 sago007 2017-03-15 17:56 281
        validatorCount(),
6c5f2c01 sago007 2017-03-15 17:56 282
        patternPropertiesValidators(),
6c5f2c01 sago007 2017-03-15 17:56 283
        patternPropertiesValidatorCount(),
6c5f2c01 sago007 2017-03-15 17:56 284
        patternPropertiesSchemas(),
6c5f2c01 sago007 2017-03-15 17:56 285
        patternPropertiesSchemaCount(),
6c5f2c01 sago007 2017-03-15 17:56 286
        valuePatternValidatorType(kPatternValidatorOnly),
6c5f2c01 sago007 2017-03-15 17:56 287
        propertyExist(),
6c5f2c01 sago007 2017-03-15 17:56 288
        inArray(false),
6c5f2c01 sago007 2017-03-15 17:56 289
        valueUniqueness(false),
6c5f2c01 sago007 2017-03-15 17:56 290
        arrayUniqueness(false)
6c5f2c01 sago007 2017-03-15 17:56 291
    {
6c5f2c01 sago007 2017-03-15 17:56 292
    }
6c5f2c01 sago007 2017-03-15 17:56 293
6c5f2c01 sago007 2017-03-15 17:56 294
    ~SchemaValidationContext() {
6c5f2c01 sago007 2017-03-15 17:56 295
        if (hasher)
6c5f2c01 sago007 2017-03-15 17:56 296
            factory.DestroryHasher(hasher);
6c5f2c01 sago007 2017-03-15 17:56 297
        if (validators) {
6c5f2c01 sago007 2017-03-15 17:56 298
            for (SizeType i = 0; i < validatorCount; i++)
6c5f2c01 sago007 2017-03-15 17:56 299
                factory.DestroySchemaValidator(validators[i]);
6c5f2c01 sago007 2017-03-15 17:56 300
            factory.FreeState(validators);
6c5f2c01 sago007 2017-03-15 17:56 301
        }
6c5f2c01 sago007 2017-03-15 17:56 302
        if (patternPropertiesValidators) {
6c5f2c01 sago007 2017-03-15 17:56 303
            for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
6c5f2c01 sago007 2017-03-15 17:56 304
                factory.DestroySchemaValidator(patternPropertiesValidators[i]);
6c5f2c01 sago007 2017-03-15 17:56 305
            factory.FreeState(patternPropertiesValidators);
6c5f2c01 sago007 2017-03-15 17:56 306
        }
6c5f2c01 sago007 2017-03-15 17:56 307
        if (patternPropertiesSchemas)
6c5f2c01 sago007 2017-03-15 17:56 308
            factory.FreeState(patternPropertiesSchemas);
6c5f2c01 sago007 2017-03-15 17:56 309
        if (propertyExist)
6c5f2c01 sago007 2017-03-15 17:56 310
            factory.FreeState(propertyExist);
6c5f2c01 sago007 2017-03-15 17:56 311
    }
6c5f2c01 sago007 2017-03-15 17:56 312
6c5f2c01 sago007 2017-03-15 17:56 313
    SchemaValidatorFactoryType& factory;
6c5f2c01 sago007 2017-03-15 17:56 314
    const SchemaType* schema;
6c5f2c01 sago007 2017-03-15 17:56 315
    const SchemaType* valueSchema;
6c5f2c01 sago007 2017-03-15 17:56 316
    const Ch* invalidKeyword;
6c5f2c01 sago007 2017-03-15 17:56 317
    void* hasher; // Only validator access
6c5f2c01 sago007 2017-03-15 17:56 318
    void* arrayElementHashCodes; // Only validator access this
6c5f2c01 sago007 2017-03-15 17:56 319
    ISchemaValidator** validators;
6c5f2c01 sago007 2017-03-15 17:56 320
    SizeType validatorCount;
6c5f2c01 sago007 2017-03-15 17:56 321
    ISchemaValidator** patternPropertiesValidators;
6c5f2c01 sago007 2017-03-15 17:56 322
    SizeType patternPropertiesValidatorCount;
6c5f2c01 sago007 2017-03-15 17:56 323
    const SchemaType** patternPropertiesSchemas;
6c5f2c01 sago007 2017-03-15 17:56 324
    SizeType patternPropertiesSchemaCount;
6c5f2c01 sago007 2017-03-15 17:56 325
    PatternValidatorType valuePatternValidatorType;
6c5f2c01 sago007 2017-03-15 17:56 326
    PatternValidatorType objectPatternValidatorType;
6c5f2c01 sago007 2017-03-15 17:56 327
    SizeType arrayElementIndex;
6c5f2c01 sago007 2017-03-15 17:56 328
    bool* propertyExist;
6c5f2c01 sago007 2017-03-15 17:56 329
    bool inArray;
6c5f2c01 sago007 2017-03-15 17:56 330
    bool valueUniqueness;
6c5f2c01 sago007 2017-03-15 17:56 331
    bool arrayUniqueness;
6c5f2c01 sago007 2017-03-15 17:56 332
};
6c5f2c01 sago007 2017-03-15 17:56 333
6c5f2c01 sago007 2017-03-15 17:56 334
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 335
// Schema
6c5f2c01 sago007 2017-03-15 17:56 336
6c5f2c01 sago007 2017-03-15 17:56 337
template <typename SchemaDocumentType>
6c5f2c01 sago007 2017-03-15 17:56 338
class Schema {
6c5f2c01 sago007 2017-03-15 17:56 339
public:
6c5f2c01 sago007 2017-03-15 17:56 340
    typedef typename SchemaDocumentType::ValueType ValueType;
6c5f2c01 sago007 2017-03-15 17:56 341
    typedef typename SchemaDocumentType::AllocatorType AllocatorType;
6c5f2c01 sago007 2017-03-15 17:56 342
    typedef typename SchemaDocumentType::PointerType PointerType;
6c5f2c01 sago007 2017-03-15 17:56 343
    typedef typename ValueType::EncodingType EncodingType;
6c5f2c01 sago007 2017-03-15 17:56 344
    typedef typename EncodingType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 345
    typedef SchemaValidationContext<SchemaDocumentType> Context;
6c5f2c01 sago007 2017-03-15 17:56 346
    typedef Schema<SchemaDocumentType> SchemaType;
6c5f2c01 sago007 2017-03-15 17:56 347
    typedef GenericValue<EncodingType, AllocatorType> SValue;
6c5f2c01 sago007 2017-03-15 17:56 348
    friend class GenericSchemaDocument<ValueType, AllocatorType>;
6c5f2c01 sago007 2017-03-15 17:56 349
6c5f2c01 sago007 2017-03-15 17:56 350
    Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
6c5f2c01 sago007 2017-03-15 17:56 351
        allocator_(allocator),
6c5f2c01 sago007 2017-03-15 17:56 352
        enum_(),
6c5f2c01 sago007 2017-03-15 17:56 353
        enumCount_(),
6c5f2c01 sago007 2017-03-15 17:56 354
        not_(),
6c5f2c01 sago007 2017-03-15 17:56 355
        type_((1 << kTotalSchemaType) - 1), // typeless
6c5f2c01 sago007 2017-03-15 17:56 356
        validatorCount_(),
6c5f2c01 sago007 2017-03-15 17:56 357
        properties_(),
6c5f2c01 sago007 2017-03-15 17:56 358
        additionalPropertiesSchema_(),
6c5f2c01 sago007 2017-03-15 17:56 359
        patternProperties_(),
6c5f2c01 sago007 2017-03-15 17:56 360
        patternPropertyCount_(),
6c5f2c01 sago007 2017-03-15 17:56 361
        propertyCount_(),
6c5f2c01 sago007 2017-03-15 17:56 362
        minProperties_(),
6c5f2c01 sago007 2017-03-15 17:56 363
        maxProperties_(SizeType(~0)),
6c5f2c01 sago007 2017-03-15 17:56 364
        additionalProperties_(true),
6c5f2c01 sago007 2017-03-15 17:56 365
        hasDependencies_(),
6c5f2c01 sago007 2017-03-15 17:56 366
        hasRequired_(),
6c5f2c01 sago007 2017-03-15 17:56 367
        hasSchemaDependencies_(),
6c5f2c01 sago007 2017-03-15 17:56 368
        additionalItemsSchema_(),
6c5f2c01 sago007 2017-03-15 17:56 369
        itemsList_(),
6c5f2c01 sago007 2017-03-15 17:56 370
        itemsTuple_(),
6c5f2c01 sago007 2017-03-15 17:56 371
        itemsTupleCount_(),
6c5f2c01 sago007 2017-03-15 17:56 372
        minItems_(),
6c5f2c01 sago007 2017-03-15 17:56 373
        maxItems_(SizeType(~0)),
6c5f2c01 sago007 2017-03-15 17:56 374
        additionalItems_(true),
6c5f2c01 sago007 2017-03-15 17:56 375
        uniqueItems_(false),
6c5f2c01 sago007 2017-03-15 17:56 376
        pattern_(),
6c5f2c01 sago007 2017-03-15 17:56 377
        minLength_(0),
6c5f2c01 sago007 2017-03-15 17:56 378
        maxLength_(~SizeType(0)),
6c5f2c01 sago007 2017-03-15 17:56 379
        exclusiveMinimum_(false),
6c5f2c01 sago007 2017-03-15 17:56 380
        exclusiveMaximum_(false)
6c5f2c01 sago007 2017-03-15 17:56 381
    {
6c5f2c01 sago007 2017-03-15 17:56 382
        typedef typename SchemaDocumentType::ValueType ValueType;
6c5f2c01 sago007 2017-03-15 17:56 383
        typedef typename ValueType::ConstValueIterator ConstValueIterator;
6c5f2c01 sago007 2017-03-15 17:56 384
        typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
6c5f2c01 sago007 2017-03-15 17:56 385
6c5f2c01 sago007 2017-03-15 17:56 386
        if (!value.IsObject())
6c5f2c01 sago007 2017-03-15 17:56 387
            return;
6c5f2c01 sago007 2017-03-15 17:56 388
6c5f2c01 sago007 2017-03-15 17:56 389
        if (const ValueType* v = GetMember(value, GetTypeString())) {
6c5f2c01 sago007 2017-03-15 17:56 390
            type_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 391
            if (v->IsString())
6c5f2c01 sago007 2017-03-15 17:56 392
                AddType(*v);
6c5f2c01 sago007 2017-03-15 17:56 393
            else if (v->IsArray())
6c5f2c01 sago007 2017-03-15 17:56 394
                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 395
                    AddType(*itr);
6c5f2c01 sago007 2017-03-15 17:56 396
        }
6c5f2c01 sago007 2017-03-15 17:56 397
6c5f2c01 sago007 2017-03-15 17:56 398
        if (const ValueType* v = GetMember(value, GetEnumString()))
6c5f2c01 sago007 2017-03-15 17:56 399
            if (v->IsArray() && v->Size() > 0) {
6c5f2c01 sago007 2017-03-15 17:56 400
                enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
6c5f2c01 sago007 2017-03-15 17:56 401
                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
6c5f2c01 sago007 2017-03-15 17:56 402
                    typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
6c5f2c01 sago007 2017-03-15 17:56 403
                    char buffer[256 + 24];
6c5f2c01 sago007 2017-03-15 17:56 404
                    MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
6c5f2c01 sago007 2017-03-15 17:56 405
                    EnumHasherType h(&hasherAllocator, 256);
6c5f2c01 sago007 2017-03-15 17:56 406
                    itr->Accept(h);
6c5f2c01 sago007 2017-03-15 17:56 407
                    enum_[enumCount_++] = h.GetHashCode();
6c5f2c01 sago007 2017-03-15 17:56 408
                }
6c5f2c01 sago007 2017-03-15 17:56 409
            }
6c5f2c01 sago007 2017-03-15 17:56 410
6c5f2c01 sago007 2017-03-15 17:56 411
        if (schemaDocument) {
6c5f2c01 sago007 2017-03-15 17:56 412
            AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
6c5f2c01 sago007 2017-03-15 17:56 413
            AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
6c5f2c01 sago007 2017-03-15 17:56 414
            AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
6c5f2c01 sago007 2017-03-15 17:56 415
        }
6c5f2c01 sago007 2017-03-15 17:56 416
6c5f2c01 sago007 2017-03-15 17:56 417
        if (const ValueType* v = GetMember(value, GetNotString())) {
6c5f2c01 sago007 2017-03-15 17:56 418
            schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
6c5f2c01 sago007 2017-03-15 17:56 419
            notValidatorIndex_ = validatorCount_;
6c5f2c01 sago007 2017-03-15 17:56 420
            validatorCount_++;
6c5f2c01 sago007 2017-03-15 17:56 421
        }
6c5f2c01 sago007 2017-03-15 17:56 422
6c5f2c01 sago007 2017-03-15 17:56 423
        // Object
6c5f2c01 sago007 2017-03-15 17:56 424
6c5f2c01 sago007 2017-03-15 17:56 425
        const ValueType* properties = GetMember(value, GetPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 426
        const ValueType* required = GetMember(value, GetRequiredString());
6c5f2c01 sago007 2017-03-15 17:56 427
        const ValueType* dependencies = GetMember(value, GetDependenciesString());
6c5f2c01 sago007 2017-03-15 17:56 428
        {
6c5f2c01 sago007 2017-03-15 17:56 429
            // Gather properties from properties/required/dependencies
6c5f2c01 sago007 2017-03-15 17:56 430
            SValue allProperties(kArrayType);
6c5f2c01 sago007 2017-03-15 17:56 431
6c5f2c01 sago007 2017-03-15 17:56 432
            if (properties && properties->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 433
                for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 434
                    AddUniqueElement(allProperties, itr->name);
6c5f2c01 sago007 2017-03-15 17:56 435
            
6c5f2c01 sago007 2017-03-15 17:56 436
            if (required && required->IsArray())
6c5f2c01 sago007 2017-03-15 17:56 437
                for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 438
                    if (itr->IsString())
6c5f2c01 sago007 2017-03-15 17:56 439
                        AddUniqueElement(allProperties, *itr);
6c5f2c01 sago007 2017-03-15 17:56 440
6c5f2c01 sago007 2017-03-15 17:56 441
            if (dependencies && dependencies->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 442
                for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
6c5f2c01 sago007 2017-03-15 17:56 443
                    AddUniqueElement(allProperties, itr->name);
6c5f2c01 sago007 2017-03-15 17:56 444
                    if (itr->value.IsArray())
6c5f2c01 sago007 2017-03-15 17:56 445
                        for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
6c5f2c01 sago007 2017-03-15 17:56 446
                            if (i->IsString())
6c5f2c01 sago007 2017-03-15 17:56 447
                                AddUniqueElement(allProperties, *i);
6c5f2c01 sago007 2017-03-15 17:56 448
                }
6c5f2c01 sago007 2017-03-15 17:56 449
6c5f2c01 sago007 2017-03-15 17:56 450
            if (allProperties.Size() > 0) {
6c5f2c01 sago007 2017-03-15 17:56 451
                propertyCount_ = allProperties.Size();
6c5f2c01 sago007 2017-03-15 17:56 452
                properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
6c5f2c01 sago007 2017-03-15 17:56 453
                for (SizeType i = 0; i < propertyCount_; i++) {
6c5f2c01 sago007 2017-03-15 17:56 454
                    new (&properties_[i]) Property();
6c5f2c01 sago007 2017-03-15 17:56 455
                    properties_[i].name = allProperties[i];
6c5f2c01 sago007 2017-03-15 17:56 456
                    properties_[i].schema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 457
                }
6c5f2c01 sago007 2017-03-15 17:56 458
            }
6c5f2c01 sago007 2017-03-15 17:56 459
        }
6c5f2c01 sago007 2017-03-15 17:56 460
6c5f2c01 sago007 2017-03-15 17:56 461
        if (properties && properties->IsObject()) {
6c5f2c01 sago007 2017-03-15 17:56 462
            PointerType q = p.Append(GetPropertiesString(), allocator_);
6c5f2c01 sago007 2017-03-15 17:56 463
            for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
6c5f2c01 sago007 2017-03-15 17:56 464
                SizeType index;
6c5f2c01 sago007 2017-03-15 17:56 465
                if (FindPropertyIndex(itr->name, &index))
6c5f2c01 sago007 2017-03-15 17:56 466
                    schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
6c5f2c01 sago007 2017-03-15 17:56 467
            }
6c5f2c01 sago007 2017-03-15 17:56 468
        }
6c5f2c01 sago007 2017-03-15 17:56 469
6c5f2c01 sago007 2017-03-15 17:56 470
        if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
6c5f2c01 sago007 2017-03-15 17:56 471
            PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
6c5f2c01 sago007 2017-03-15 17:56 472
            patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
6c5f2c01 sago007 2017-03-15 17:56 473
            patternPropertyCount_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 474
6c5f2c01 sago007 2017-03-15 17:56 475
            for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
6c5f2c01 sago007 2017-03-15 17:56 476
                new (&patternProperties_[patternPropertyCount_]) PatternProperty();
6c5f2c01 sago007 2017-03-15 17:56 477
                patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
6c5f2c01 sago007 2017-03-15 17:56 478
                schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
6c5f2c01 sago007 2017-03-15 17:56 479
                patternPropertyCount_++;
6c5f2c01 sago007 2017-03-15 17:56 480
            }
6c5f2c01 sago007 2017-03-15 17:56 481
        }
6c5f2c01 sago007 2017-03-15 17:56 482
6c5f2c01 sago007 2017-03-15 17:56 483
        if (required && required->IsArray())
6c5f2c01 sago007 2017-03-15 17:56 484
            for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 485
                if (itr->IsString()) {
6c5f2c01 sago007 2017-03-15 17:56 486
                    SizeType index;
6c5f2c01 sago007 2017-03-15 17:56 487
                    if (FindPropertyIndex(*itr, &index)) {
6c5f2c01 sago007 2017-03-15 17:56 488
                        properties_[index].required = true;
6c5f2c01 sago007 2017-03-15 17:56 489
                        hasRequired_ = true;
6c5f2c01 sago007 2017-03-15 17:56 490
                    }
6c5f2c01 sago007 2017-03-15 17:56 491
                }
6c5f2c01 sago007 2017-03-15 17:56 492
6c5f2c01 sago007 2017-03-15 17:56 493
        if (dependencies && dependencies->IsObject()) {
6c5f2c01 sago007 2017-03-15 17:56 494
            PointerType q = p.Append(GetDependenciesString(), allocator_);
6c5f2c01 sago007 2017-03-15 17:56 495
            hasDependencies_ = true;
6c5f2c01 sago007 2017-03-15 17:56 496
            for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
6c5f2c01 sago007 2017-03-15 17:56 497
                SizeType sourceIndex;
6c5f2c01 sago007 2017-03-15 17:56 498
                if (FindPropertyIndex(itr->name, &sourceIndex)) {
6c5f2c01 sago007 2017-03-15 17:56 499
                    if (itr->value.IsArray()) {
6c5f2c01 sago007 2017-03-15 17:56 500
                        properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
6c5f2c01 sago007 2017-03-15 17:56 501
                        std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
6c5f2c01 sago007 2017-03-15 17:56 502
                        for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
6c5f2c01 sago007 2017-03-15 17:56 503
                            SizeType targetIndex;
6c5f2c01 sago007 2017-03-15 17:56 504
                            if (FindPropertyIndex(*targetItr, &targetIndex))
6c5f2c01 sago007 2017-03-15 17:56 505
                                properties_[sourceIndex].dependencies[targetIndex] = true;
6c5f2c01 sago007 2017-03-15 17:56 506
                        }
6c5f2c01 sago007 2017-03-15 17:56 507
                    }
6c5f2c01 sago007 2017-03-15 17:56 508
                    else if (itr->value.IsObject()) {
6c5f2c01 sago007 2017-03-15 17:56 509
                        hasSchemaDependencies_ = true;
6c5f2c01 sago007 2017-03-15 17:56 510
                        schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
6c5f2c01 sago007 2017-03-15 17:56 511
                        properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
6c5f2c01 sago007 2017-03-15 17:56 512
                        validatorCount_++;
6c5f2c01 sago007 2017-03-15 17:56 513
                    }
6c5f2c01 sago007 2017-03-15 17:56 514
                }
6c5f2c01 sago007 2017-03-15 17:56 515
            }
6c5f2c01 sago007 2017-03-15 17:56 516
        }
6c5f2c01 sago007 2017-03-15 17:56 517
6c5f2c01 sago007 2017-03-15 17:56 518
        if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
6c5f2c01 sago007 2017-03-15 17:56 519
            if (v->IsBool())
6c5f2c01 sago007 2017-03-15 17:56 520
                additionalProperties_ = v->GetBool();
6c5f2c01 sago007 2017-03-15 17:56 521
            else if (v->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 522
                schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
6c5f2c01 sago007 2017-03-15 17:56 523
        }
6c5f2c01 sago007 2017-03-15 17:56 524
6c5f2c01 sago007 2017-03-15 17:56 525
        AssignIfExist(minProperties_, value, GetMinPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 526
        AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 527
6c5f2c01 sago007 2017-03-15 17:56 528
        // Array
6c5f2c01 sago007 2017-03-15 17:56 529
        if (const ValueType* v = GetMember(value, GetItemsString())) {
6c5f2c01 sago007 2017-03-15 17:56 530
            PointerType q = p.Append(GetItemsString(), allocator_);
6c5f2c01 sago007 2017-03-15 17:56 531
            if (v->IsObject()) // List validation
6c5f2c01 sago007 2017-03-15 17:56 532
                schemaDocument->CreateSchema(&itemsList_, q, *v, document);
6c5f2c01 sago007 2017-03-15 17:56 533
            else if (v->IsArray()) { // Tuple validation
6c5f2c01 sago007 2017-03-15 17:56 534
                itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
6c5f2c01 sago007 2017-03-15 17:56 535
                SizeType index = 0;
6c5f2c01 sago007 2017-03-15 17:56 536
                for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
6c5f2c01 sago007 2017-03-15 17:56 537
                    schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
6c5f2c01 sago007 2017-03-15 17:56 538
            }
6c5f2c01 sago007 2017-03-15 17:56 539
        }
6c5f2c01 sago007 2017-03-15 17:56 540
6c5f2c01 sago007 2017-03-15 17:56 541
        AssignIfExist(minItems_, value, GetMinItemsString());
6c5f2c01 sago007 2017-03-15 17:56 542
        AssignIfExist(maxItems_, value, GetMaxItemsString());
6c5f2c01 sago007 2017-03-15 17:56 543
6c5f2c01 sago007 2017-03-15 17:56 544
        if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
6c5f2c01 sago007 2017-03-15 17:56 545
            if (v->IsBool())
6c5f2c01 sago007 2017-03-15 17:56 546
                additionalItems_ = v->GetBool();
6c5f2c01 sago007 2017-03-15 17:56 547
            else if (v->IsObject())
6c5f2c01 sago007 2017-03-15 17:56 548
                schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
6c5f2c01 sago007 2017-03-15 17:56 549
        }
6c5f2c01 sago007 2017-03-15 17:56 550
6c5f2c01 sago007 2017-03-15 17:56 551
        AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
6c5f2c01 sago007 2017-03-15 17:56 552
6c5f2c01 sago007 2017-03-15 17:56 553
        // String
6c5f2c01 sago007 2017-03-15 17:56 554
        AssignIfExist(minLength_, value, GetMinLengthString());
6c5f2c01 sago007 2017-03-15 17:56 555
        AssignIfExist(maxLength_, value, GetMaxLengthString());
6c5f2c01 sago007 2017-03-15 17:56 556
6c5f2c01 sago007 2017-03-15 17:56 557
        if (const ValueType* v = GetMember(value, GetPatternString()))
6c5f2c01 sago007 2017-03-15 17:56 558
            pattern_ = CreatePattern(*v);
6c5f2c01 sago007 2017-03-15 17:56 559
6c5f2c01 sago007 2017-03-15 17:56 560
        // Number
6c5f2c01 sago007 2017-03-15 17:56 561
        if (const ValueType* v = GetMember(value, GetMinimumString()))
6c5f2c01 sago007 2017-03-15 17:56 562
            if (v->IsNumber())
6c5f2c01 sago007 2017-03-15 17:56 563
                minimum_.CopyFrom(*v, *allocator_);
6c5f2c01 sago007 2017-03-15 17:56 564
6c5f2c01 sago007 2017-03-15 17:56 565
        if (const ValueType* v = GetMember(value, GetMaximumString()))
6c5f2c01 sago007 2017-03-15 17:56 566
            if (v->IsNumber())
6c5f2c01 sago007 2017-03-15 17:56 567
                maximum_.CopyFrom(*v, *allocator_);
6c5f2c01 sago007 2017-03-15 17:56 568
6c5f2c01 sago007 2017-03-15 17:56 569
        AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
6c5f2c01 sago007 2017-03-15 17:56 570
        AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
6c5f2c01 sago007 2017-03-15 17:56 571
6c5f2c01 sago007 2017-03-15 17:56 572
        if (const ValueType* v = GetMember(value, GetMultipleOfString()))
6c5f2c01 sago007 2017-03-15 17:56 573
            if (v->IsNumber() && v->GetDouble() > 0.0)
6c5f2c01 sago007 2017-03-15 17:56 574
                multipleOf_.CopyFrom(*v, *allocator_);
6c5f2c01 sago007 2017-03-15 17:56 575
    }
6c5f2c01 sago007 2017-03-15 17:56 576
6c5f2c01 sago007 2017-03-15 17:56 577
    ~Schema() {
6c5f2c01 sago007 2017-03-15 17:56 578
        if (allocator_) {
6c5f2c01 sago007 2017-03-15 17:56 579
            allocator_->Free(enum_);
6c5f2c01 sago007 2017-03-15 17:56 580
        }
6c5f2c01 sago007 2017-03-15 17:56 581
        if (properties_) {
6c5f2c01 sago007 2017-03-15 17:56 582
            for (SizeType i = 0; i < propertyCount_; i++)
6c5f2c01 sago007 2017-03-15 17:56 583
                properties_[i].~Property();
6c5f2c01 sago007 2017-03-15 17:56 584
            AllocatorType::Free(properties_);
6c5f2c01 sago007 2017-03-15 17:56 585
        }
6c5f2c01 sago007 2017-03-15 17:56 586
        if (patternProperties_) {
6c5f2c01 sago007 2017-03-15 17:56 587
            for (SizeType i = 0; i < patternPropertyCount_; i++)
6c5f2c01 sago007 2017-03-15 17:56 588
                patternProperties_[i].~PatternProperty();
6c5f2c01 sago007 2017-03-15 17:56 589
            AllocatorType::Free(patternProperties_);
6c5f2c01 sago007 2017-03-15 17:56 590
        }
6c5f2c01 sago007 2017-03-15 17:56 591
        AllocatorType::Free(itemsTuple_);
6c5f2c01 sago007 2017-03-15 17:56 592
#if CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX
6c5f2c01 sago007 2017-03-15 17:56 593
        if (pattern_) {
6c5f2c01 sago007 2017-03-15 17:56 594
            pattern_->~RegexType();
6c5f2c01 sago007 2017-03-15 17:56 595
            allocator_->Free(pattern_);
6c5f2c01 sago007 2017-03-15 17:56 596
        }
6c5f2c01 sago007 2017-03-15 17:56 597
#endif
6c5f2c01 sago007 2017-03-15 17:56 598
    }
6c5f2c01 sago007 2017-03-15 17:56 599
6c5f2c01 sago007 2017-03-15 17:56 600
    bool BeginValue(Context& context) const {
6c5f2c01 sago007 2017-03-15 17:56 601
        if (context.inArray) {
6c5f2c01 sago007 2017-03-15 17:56 602
            if (uniqueItems_)
6c5f2c01 sago007 2017-03-15 17:56 603
                context.valueUniqueness = true;
6c5f2c01 sago007 2017-03-15 17:56 604
6c5f2c01 sago007 2017-03-15 17:56 605
            if (itemsList_)
6c5f2c01 sago007 2017-03-15 17:56 606
                context.valueSchema = itemsList_;
6c5f2c01 sago007 2017-03-15 17:56 607
            else if (itemsTuple_) {
6c5f2c01 sago007 2017-03-15 17:56 608
                if (context.arrayElementIndex < itemsTupleCount_)
6c5f2c01 sago007 2017-03-15 17:56 609
                    context.valueSchema = itemsTuple_[context.arrayElementIndex];
6c5f2c01 sago007 2017-03-15 17:56 610
                else if (additionalItemsSchema_)
6c5f2c01 sago007 2017-03-15 17:56 611
                    context.valueSchema = additionalItemsSchema_;
6c5f2c01 sago007 2017-03-15 17:56 612
                else if (additionalItems_)
6c5f2c01 sago007 2017-03-15 17:56 613
                    context.valueSchema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 614
                else
6c5f2c01 sago007 2017-03-15 17:56 615
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
6c5f2c01 sago007 2017-03-15 17:56 616
            }
6c5f2c01 sago007 2017-03-15 17:56 617
            else
6c5f2c01 sago007 2017-03-15 17:56 618
                context.valueSchema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 619
6c5f2c01 sago007 2017-03-15 17:56 620
            context.arrayElementIndex++;
6c5f2c01 sago007 2017-03-15 17:56 621
        }
6c5f2c01 sago007 2017-03-15 17:56 622
        return true;
6c5f2c01 sago007 2017-03-15 17:56 623
    }
6c5f2c01 sago007 2017-03-15 17:56 624
6c5f2c01 sago007 2017-03-15 17:56 625
    CEREAL_RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
6c5f2c01 sago007 2017-03-15 17:56 626
        if (context.patternPropertiesValidatorCount > 0) {
6c5f2c01 sago007 2017-03-15 17:56 627
            bool otherValid = false;
6c5f2c01 sago007 2017-03-15 17:56 628
            SizeType count = context.patternPropertiesValidatorCount;
6c5f2c01 sago007 2017-03-15 17:56 629
            if (context.objectPatternValidatorType != Context::kPatternValidatorOnly)
6c5f2c01 sago007 2017-03-15 17:56 630
                otherValid = context.patternPropertiesValidators[--count]->IsValid();
6c5f2c01 sago007 2017-03-15 17:56 631
6c5f2c01 sago007 2017-03-15 17:56 632
            bool patternValid = true;
6c5f2c01 sago007 2017-03-15 17:56 633
            for (SizeType i = 0; i < count; i++)
6c5f2c01 sago007 2017-03-15 17:56 634
                if (!context.patternPropertiesValidators[i]->IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 635
                    patternValid = false;
6c5f2c01 sago007 2017-03-15 17:56 636
                    break;
6c5f2c01 sago007 2017-03-15 17:56 637
                }
6c5f2c01 sago007 2017-03-15 17:56 638
6c5f2c01 sago007 2017-03-15 17:56 639
            if (context.objectPatternValidatorType == Context::kPatternValidatorOnly) {
6c5f2c01 sago007 2017-03-15 17:56 640
                if (!patternValid)
6c5f2c01 sago007 2017-03-15 17:56 641
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 642
            }
6c5f2c01 sago007 2017-03-15 17:56 643
            else if (context.objectPatternValidatorType == Context::kPatternValidatorWithProperty) {
6c5f2c01 sago007 2017-03-15 17:56 644
                if (!patternValid || !otherValid)
6c5f2c01 sago007 2017-03-15 17:56 645
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 646
            }
6c5f2c01 sago007 2017-03-15 17:56 647
            else if (!patternValid && !otherValid) // kPatternValidatorWithAdditionalProperty)
6c5f2c01 sago007 2017-03-15 17:56 648
                CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 649
        }
6c5f2c01 sago007 2017-03-15 17:56 650
6c5f2c01 sago007 2017-03-15 17:56 651
        if (enum_) {
6c5f2c01 sago007 2017-03-15 17:56 652
            const uint64_t h = context.factory.GetHashCode(context.hasher);
6c5f2c01 sago007 2017-03-15 17:56 653
            for (SizeType i = 0; i < enumCount_; i++)
6c5f2c01 sago007 2017-03-15 17:56 654
                if (enum_[i] == h)
6c5f2c01 sago007 2017-03-15 17:56 655
                    goto foundEnum;
6c5f2c01 sago007 2017-03-15 17:56 656
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetEnumString());
6c5f2c01 sago007 2017-03-15 17:56 657
            foundEnum:;
6c5f2c01 sago007 2017-03-15 17:56 658
        }
6c5f2c01 sago007 2017-03-15 17:56 659
6c5f2c01 sago007 2017-03-15 17:56 660
        if (allOf_.schemas)
6c5f2c01 sago007 2017-03-15 17:56 661
            for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
6c5f2c01 sago007 2017-03-15 17:56 662
                if (!context.validators[i]->IsValid())
6c5f2c01 sago007 2017-03-15 17:56 663
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
6c5f2c01 sago007 2017-03-15 17:56 664
        
6c5f2c01 sago007 2017-03-15 17:56 665
        if (anyOf_.schemas) {
6c5f2c01 sago007 2017-03-15 17:56 666
            for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
6c5f2c01 sago007 2017-03-15 17:56 667
                if (context.validators[i]->IsValid())
6c5f2c01 sago007 2017-03-15 17:56 668
                    goto foundAny;
6c5f2c01 sago007 2017-03-15 17:56 669
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
6c5f2c01 sago007 2017-03-15 17:56 670
            foundAny:;
6c5f2c01 sago007 2017-03-15 17:56 671
        }
6c5f2c01 sago007 2017-03-15 17:56 672
6c5f2c01 sago007 2017-03-15 17:56 673
        if (oneOf_.schemas) {
6c5f2c01 sago007 2017-03-15 17:56 674
            bool oneValid = false;
6c5f2c01 sago007 2017-03-15 17:56 675
            for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
6c5f2c01 sago007 2017-03-15 17:56 676
                if (context.validators[i]->IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 677
                    if (oneValid)
6c5f2c01 sago007 2017-03-15 17:56 678
                        CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
6c5f2c01 sago007 2017-03-15 17:56 679
                    else
6c5f2c01 sago007 2017-03-15 17:56 680
                        oneValid = true;
6c5f2c01 sago007 2017-03-15 17:56 681
                }
6c5f2c01 sago007 2017-03-15 17:56 682
            if (!oneValid)
6c5f2c01 sago007 2017-03-15 17:56 683
                CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
6c5f2c01 sago007 2017-03-15 17:56 684
        }
6c5f2c01 sago007 2017-03-15 17:56 685
6c5f2c01 sago007 2017-03-15 17:56 686
        if (not_ && context.validators[notValidatorIndex_]->IsValid())
6c5f2c01 sago007 2017-03-15 17:56 687
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetNotString());
6c5f2c01 sago007 2017-03-15 17:56 688
6c5f2c01 sago007 2017-03-15 17:56 689
        return true;
6c5f2c01 sago007 2017-03-15 17:56 690
    }
6c5f2c01 sago007 2017-03-15 17:56 691
6c5f2c01 sago007 2017-03-15 17:56 692
    bool Null(Context& context) const { 
6c5f2c01 sago007 2017-03-15 17:56 693
        if (!(type_ & (1 << kNullSchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 694
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 695
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 696
    }
6c5f2c01 sago007 2017-03-15 17:56 697
    
6c5f2c01 sago007 2017-03-15 17:56 698
    bool Bool(Context& context, bool) const { 
6c5f2c01 sago007 2017-03-15 17:56 699
        if (!(type_ & (1 << kBooleanSchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 700
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 701
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 702
    }
6c5f2c01 sago007 2017-03-15 17:56 703
6c5f2c01 sago007 2017-03-15 17:56 704
    bool Int(Context& context, int i) const {
6c5f2c01 sago007 2017-03-15 17:56 705
        if (!CheckInt(context, i))
6c5f2c01 sago007 2017-03-15 17:56 706
            return false;
6c5f2c01 sago007 2017-03-15 17:56 707
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 708
    }
6c5f2c01 sago007 2017-03-15 17:56 709
6c5f2c01 sago007 2017-03-15 17:56 710
    bool Uint(Context& context, unsigned u) const {
6c5f2c01 sago007 2017-03-15 17:56 711
        if (!CheckUint(context, u))
6c5f2c01 sago007 2017-03-15 17:56 712
            return false;
6c5f2c01 sago007 2017-03-15 17:56 713
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 714
    }
6c5f2c01 sago007 2017-03-15 17:56 715
6c5f2c01 sago007 2017-03-15 17:56 716
    bool Int64(Context& context, int64_t i) const {
6c5f2c01 sago007 2017-03-15 17:56 717
        if (!CheckInt(context, i))
6c5f2c01 sago007 2017-03-15 17:56 718
            return false;
6c5f2c01 sago007 2017-03-15 17:56 719
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 720
    }
6c5f2c01 sago007 2017-03-15 17:56 721
6c5f2c01 sago007 2017-03-15 17:56 722
    bool Uint64(Context& context, uint64_t u) const {
6c5f2c01 sago007 2017-03-15 17:56 723
        if (!CheckUint(context, u))
6c5f2c01 sago007 2017-03-15 17:56 724
            return false;
6c5f2c01 sago007 2017-03-15 17:56 725
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 726
    }
6c5f2c01 sago007 2017-03-15 17:56 727
6c5f2c01 sago007 2017-03-15 17:56 728
    bool Double(Context& context, double d) const {
6c5f2c01 sago007 2017-03-15 17:56 729
        if (!(type_ & (1 << kNumberSchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 730
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 731
6c5f2c01 sago007 2017-03-15 17:56 732
        if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
6c5f2c01 sago007 2017-03-15 17:56 733
            return false;
6c5f2c01 sago007 2017-03-15 17:56 734
6c5f2c01 sago007 2017-03-15 17:56 735
        if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
6c5f2c01 sago007 2017-03-15 17:56 736
            return false;
6c5f2c01 sago007 2017-03-15 17:56 737
        
6c5f2c01 sago007 2017-03-15 17:56 738
        if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
6c5f2c01 sago007 2017-03-15 17:56 739
            return false;
6c5f2c01 sago007 2017-03-15 17:56 740
        
6c5f2c01 sago007 2017-03-15 17:56 741
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 742
    }
6c5f2c01 sago007 2017-03-15 17:56 743
    
6c5f2c01 sago007 2017-03-15 17:56 744
    bool String(Context& context, const Ch* str, SizeType length, bool) const {
6c5f2c01 sago007 2017-03-15 17:56 745
        if (!(type_ & (1 << kStringSchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 746
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 747
6c5f2c01 sago007 2017-03-15 17:56 748
        if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
6c5f2c01 sago007 2017-03-15 17:56 749
            SizeType count;
6c5f2c01 sago007 2017-03-15 17:56 750
            if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
6c5f2c01 sago007 2017-03-15 17:56 751
                if (count < minLength_)
6c5f2c01 sago007 2017-03-15 17:56 752
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
6c5f2c01 sago007 2017-03-15 17:56 753
                if (count > maxLength_)
6c5f2c01 sago007 2017-03-15 17:56 754
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
6c5f2c01 sago007 2017-03-15 17:56 755
            }
6c5f2c01 sago007 2017-03-15 17:56 756
        }
6c5f2c01 sago007 2017-03-15 17:56 757
6c5f2c01 sago007 2017-03-15 17:56 758
        if (pattern_ && !IsPatternMatch(pattern_, str, length))
6c5f2c01 sago007 2017-03-15 17:56 759
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
6c5f2c01 sago007 2017-03-15 17:56 760
6c5f2c01 sago007 2017-03-15 17:56 761
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 762
    }
6c5f2c01 sago007 2017-03-15 17:56 763
6c5f2c01 sago007 2017-03-15 17:56 764
    bool StartObject(Context& context) const { 
6c5f2c01 sago007 2017-03-15 17:56 765
        if (!(type_ & (1 << kObjectSchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 766
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 767
6c5f2c01 sago007 2017-03-15 17:56 768
        if (hasDependencies_ || hasRequired_) {
6c5f2c01 sago007 2017-03-15 17:56 769
            context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
6c5f2c01 sago007 2017-03-15 17:56 770
            std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
6c5f2c01 sago007 2017-03-15 17:56 771
        }
6c5f2c01 sago007 2017-03-15 17:56 772
6c5f2c01 sago007 2017-03-15 17:56 773
        if (patternProperties_) { // pre-allocate schema array
6c5f2c01 sago007 2017-03-15 17:56 774
            SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
6c5f2c01 sago007 2017-03-15 17:56 775
            context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
6c5f2c01 sago007 2017-03-15 17:56 776
            context.patternPropertiesSchemaCount = 0;
6c5f2c01 sago007 2017-03-15 17:56 777
            std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
6c5f2c01 sago007 2017-03-15 17:56 778
        }
6c5f2c01 sago007 2017-03-15 17:56 779
6c5f2c01 sago007 2017-03-15 17:56 780
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 781
    }
6c5f2c01 sago007 2017-03-15 17:56 782
    
6c5f2c01 sago007 2017-03-15 17:56 783
    bool Key(Context& context, const Ch* str, SizeType len, bool) const {
6c5f2c01 sago007 2017-03-15 17:56 784
        if (patternProperties_) {
6c5f2c01 sago007 2017-03-15 17:56 785
            context.patternPropertiesSchemaCount = 0;
6c5f2c01 sago007 2017-03-15 17:56 786
            for (SizeType i = 0; i < patternPropertyCount_; i++)
6c5f2c01 sago007 2017-03-15 17:56 787
                if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len))
6c5f2c01 sago007 2017-03-15 17:56 788
                    context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
6c5f2c01 sago007 2017-03-15 17:56 789
        }
6c5f2c01 sago007 2017-03-15 17:56 790
6c5f2c01 sago007 2017-03-15 17:56 791
        SizeType index;
6c5f2c01 sago007 2017-03-15 17:56 792
        if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
6c5f2c01 sago007 2017-03-15 17:56 793
            if (context.patternPropertiesSchemaCount > 0) {
6c5f2c01 sago007 2017-03-15 17:56 794
                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
6c5f2c01 sago007 2017-03-15 17:56 795
                context.valueSchema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 796
                context.valuePatternValidatorType = Context::kPatternValidatorWithProperty;
6c5f2c01 sago007 2017-03-15 17:56 797
            }
6c5f2c01 sago007 2017-03-15 17:56 798
            else
6c5f2c01 sago007 2017-03-15 17:56 799
                context.valueSchema = properties_[index].schema;
6c5f2c01 sago007 2017-03-15 17:56 800
6c5f2c01 sago007 2017-03-15 17:56 801
            if (context.propertyExist)
6c5f2c01 sago007 2017-03-15 17:56 802
                context.propertyExist[index] = true;
6c5f2c01 sago007 2017-03-15 17:56 803
6c5f2c01 sago007 2017-03-15 17:56 804
            return true;
6c5f2c01 sago007 2017-03-15 17:56 805
        }
6c5f2c01 sago007 2017-03-15 17:56 806
6c5f2c01 sago007 2017-03-15 17:56 807
        if (additionalPropertiesSchema_) {
6c5f2c01 sago007 2017-03-15 17:56 808
            if (additionalPropertiesSchema_ && context.patternPropertiesSchemaCount > 0) {
6c5f2c01 sago007 2017-03-15 17:56 809
                context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
6c5f2c01 sago007 2017-03-15 17:56 810
                context.valueSchema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 811
                context.valuePatternValidatorType = Context::kPatternValidatorWithAdditionalProperty;
6c5f2c01 sago007 2017-03-15 17:56 812
            }
6c5f2c01 sago007 2017-03-15 17:56 813
            else
6c5f2c01 sago007 2017-03-15 17:56 814
                context.valueSchema = additionalPropertiesSchema_;
6c5f2c01 sago007 2017-03-15 17:56 815
            return true;
6c5f2c01 sago007 2017-03-15 17:56 816
        }
6c5f2c01 sago007 2017-03-15 17:56 817
        else if (additionalProperties_) {
6c5f2c01 sago007 2017-03-15 17:56 818
            context.valueSchema = GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 819
            return true;
6c5f2c01 sago007 2017-03-15 17:56 820
        }
6c5f2c01 sago007 2017-03-15 17:56 821
6c5f2c01 sago007 2017-03-15 17:56 822
        if (context.patternPropertiesSchemaCount == 0) // patternProperties are not additional properties
6c5f2c01 sago007 2017-03-15 17:56 823
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 824
6c5f2c01 sago007 2017-03-15 17:56 825
        return true;
6c5f2c01 sago007 2017-03-15 17:56 826
    }
6c5f2c01 sago007 2017-03-15 17:56 827
6c5f2c01 sago007 2017-03-15 17:56 828
    bool EndObject(Context& context, SizeType memberCount) const {
6c5f2c01 sago007 2017-03-15 17:56 829
        if (hasRequired_)
6c5f2c01 sago007 2017-03-15 17:56 830
            for (SizeType index = 0; index < propertyCount_; index++)
6c5f2c01 sago007 2017-03-15 17:56 831
                if (properties_[index].required)
6c5f2c01 sago007 2017-03-15 17:56 832
                    if (!context.propertyExist[index])
6c5f2c01 sago007 2017-03-15 17:56 833
                        CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
6c5f2c01 sago007 2017-03-15 17:56 834
6c5f2c01 sago007 2017-03-15 17:56 835
        if (memberCount < minProperties_)
6c5f2c01 sago007 2017-03-15 17:56 836
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 837
6c5f2c01 sago007 2017-03-15 17:56 838
        if (memberCount > maxProperties_)
6c5f2c01 sago007 2017-03-15 17:56 839
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
6c5f2c01 sago007 2017-03-15 17:56 840
6c5f2c01 sago007 2017-03-15 17:56 841
        if (hasDependencies_) {
6c5f2c01 sago007 2017-03-15 17:56 842
            for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++)
6c5f2c01 sago007 2017-03-15 17:56 843
                if (context.propertyExist[sourceIndex]) {
6c5f2c01 sago007 2017-03-15 17:56 844
                    if (properties_[sourceIndex].dependencies) {
6c5f2c01 sago007 2017-03-15 17:56 845
                        for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
6c5f2c01 sago007 2017-03-15 17:56 846
                            if (properties_[sourceIndex].dependencies[targetIndex] && !context.propertyExist[targetIndex])
6c5f2c01 sago007 2017-03-15 17:56 847
                                CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
6c5f2c01 sago007 2017-03-15 17:56 848
                    }
6c5f2c01 sago007 2017-03-15 17:56 849
                    else if (properties_[sourceIndex].dependenciesSchema)
6c5f2c01 sago007 2017-03-15 17:56 850
                        if (!context.validators[properties_[sourceIndex].dependenciesValidatorIndex]->IsValid())
6c5f2c01 sago007 2017-03-15 17:56 851
                            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
6c5f2c01 sago007 2017-03-15 17:56 852
                }
6c5f2c01 sago007 2017-03-15 17:56 853
        }
6c5f2c01 sago007 2017-03-15 17:56 854
6c5f2c01 sago007 2017-03-15 17:56 855
        return true;
6c5f2c01 sago007 2017-03-15 17:56 856
    }
6c5f2c01 sago007 2017-03-15 17:56 857
6c5f2c01 sago007 2017-03-15 17:56 858
    bool StartArray(Context& context) const { 
6c5f2c01 sago007 2017-03-15 17:56 859
        if (!(type_ & (1 << kArraySchemaType)))
6c5f2c01 sago007 2017-03-15 17:56 860
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 861
6c5f2c01 sago007 2017-03-15 17:56 862
        context.arrayElementIndex = 0;
6c5f2c01 sago007 2017-03-15 17:56 863
        context.inArray = true;
6c5f2c01 sago007 2017-03-15 17:56 864
6c5f2c01 sago007 2017-03-15 17:56 865
        return CreateParallelValidator(context);
6c5f2c01 sago007 2017-03-15 17:56 866
    }
6c5f2c01 sago007 2017-03-15 17:56 867
6c5f2c01 sago007 2017-03-15 17:56 868
    bool EndArray(Context& context, SizeType elementCount) const { 
6c5f2c01 sago007 2017-03-15 17:56 869
        context.inArray = false;
6c5f2c01 sago007 2017-03-15 17:56 870
        
6c5f2c01 sago007 2017-03-15 17:56 871
        if (elementCount < minItems_)
6c5f2c01 sago007 2017-03-15 17:56 872
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
6c5f2c01 sago007 2017-03-15 17:56 873
        
6c5f2c01 sago007 2017-03-15 17:56 874
        if (elementCount > maxItems_)
6c5f2c01 sago007 2017-03-15 17:56 875
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
6c5f2c01 sago007 2017-03-15 17:56 876
6c5f2c01 sago007 2017-03-15 17:56 877
        return true;
6c5f2c01 sago007 2017-03-15 17:56 878
    }
6c5f2c01 sago007 2017-03-15 17:56 879
6c5f2c01 sago007 2017-03-15 17:56 880
    // Generate functions for string literal according to Ch
6c5f2c01 sago007 2017-03-15 17:56 881
#define CEREAL_RAPIDJSON_STRING_(name, ...) \
6c5f2c01 sago007 2017-03-15 17:56 882
    static const ValueType& Get##name##String() {\
6c5f2c01 sago007 2017-03-15 17:56 883
        static const Ch s[] = { __VA_ARGS__, '\0' };\
6c5f2c01 sago007 2017-03-15 17:56 884
        static const ValueType v(s, sizeof(s) / sizeof(Ch) - 1);\
6c5f2c01 sago007 2017-03-15 17:56 885
        return v;\
6c5f2c01 sago007 2017-03-15 17:56 886
    }
6c5f2c01 sago007 2017-03-15 17:56 887
6c5f2c01 sago007 2017-03-15 17:56 888
    CEREAL_RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
6c5f2c01 sago007 2017-03-15 17:56 889
    CEREAL_RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
6c5f2c01 sago007 2017-03-15 17:56 890
    CEREAL_RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
6c5f2c01 sago007 2017-03-15 17:56 891
    CEREAL_RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
6c5f2c01 sago007 2017-03-15 17:56 892
    CEREAL_RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
6c5f2c01 sago007 2017-03-15 17:56 893
    CEREAL_RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
6c5f2c01 sago007 2017-03-15 17:56 894
    CEREAL_RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
6c5f2c01 sago007 2017-03-15 17:56 895
    CEREAL_RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
6c5f2c01 sago007 2017-03-15 17:56 896
    CEREAL_RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
6c5f2c01 sago007 2017-03-15 17:56 897
    CEREAL_RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
6c5f2c01 sago007 2017-03-15 17:56 898
    CEREAL_RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
6c5f2c01 sago007 2017-03-15 17:56 899
    CEREAL_RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
6c5f2c01 sago007 2017-03-15 17:56 900
    CEREAL_RAPIDJSON_STRING_(Not, 'n', 'o', 't')
6c5f2c01 sago007 2017-03-15 17:56 901
    CEREAL_RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 902
    CEREAL_RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
6c5f2c01 sago007 2017-03-15 17:56 903
    CEREAL_RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 904
    CEREAL_RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 905
    CEREAL_RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 906
    CEREAL_RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 907
    CEREAL_RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
6c5f2c01 sago007 2017-03-15 17:56 908
    CEREAL_RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
6c5f2c01 sago007 2017-03-15 17:56 909
    CEREAL_RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
6c5f2c01 sago007 2017-03-15 17:56 910
    CEREAL_RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
6c5f2c01 sago007 2017-03-15 17:56 911
    CEREAL_RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
6c5f2c01 sago007 2017-03-15 17:56 912
    CEREAL_RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
6c5f2c01 sago007 2017-03-15 17:56 913
    CEREAL_RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
6c5f2c01 sago007 2017-03-15 17:56 914
    CEREAL_RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
6c5f2c01 sago007 2017-03-15 17:56 915
    CEREAL_RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
6c5f2c01 sago007 2017-03-15 17:56 916
    CEREAL_RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
6c5f2c01 sago007 2017-03-15 17:56 917
    CEREAL_RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
6c5f2c01 sago007 2017-03-15 17:56 918
    CEREAL_RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
6c5f2c01 sago007 2017-03-15 17:56 919
    CEREAL_RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
6c5f2c01 sago007 2017-03-15 17:56 920
    CEREAL_RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
6c5f2c01 sago007 2017-03-15 17:56 921
6c5f2c01 sago007 2017-03-15 17:56 922
#undef CEREAL_RAPIDJSON_STRING_
6c5f2c01 sago007 2017-03-15 17:56 923
6c5f2c01 sago007 2017-03-15 17:56 924
private:
6c5f2c01 sago007 2017-03-15 17:56 925
    enum SchemaValueType {
6c5f2c01 sago007 2017-03-15 17:56 926
        kNullSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 927
        kBooleanSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 928
        kObjectSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 929
        kArraySchemaType,
6c5f2c01 sago007 2017-03-15 17:56 930
        kStringSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 931
        kNumberSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 932
        kIntegerSchemaType,
6c5f2c01 sago007 2017-03-15 17:56 933
        kTotalSchemaType
6c5f2c01 sago007 2017-03-15 17:56 934
    };
6c5f2c01 sago007 2017-03-15 17:56 935
6c5f2c01 sago007 2017-03-15 17:56 936
#if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
6c5f2c01 sago007 2017-03-15 17:56 937
        typedef internal::GenericRegex<EncodingType> RegexType;
6c5f2c01 sago007 2017-03-15 17:56 938
#elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
6c5f2c01 sago007 2017-03-15 17:56 939
        typedef std::basic_regex<Ch> RegexType;
6c5f2c01 sago007 2017-03-15 17:56 940
#else
6c5f2c01 sago007 2017-03-15 17:56 941
        typedef char RegexType;
6c5f2c01 sago007 2017-03-15 17:56 942
#endif
6c5f2c01 sago007 2017-03-15 17:56 943
6c5f2c01 sago007 2017-03-15 17:56 944
    struct SchemaArray {
6c5f2c01 sago007 2017-03-15 17:56 945
        SchemaArray() : schemas(), count() {}
6c5f2c01 sago007 2017-03-15 17:56 946
        ~SchemaArray() { AllocatorType::Free(schemas); }
6c5f2c01 sago007 2017-03-15 17:56 947
        const SchemaType** schemas;
6c5f2c01 sago007 2017-03-15 17:56 948
        SizeType begin; // begin index of context.validators
6c5f2c01 sago007 2017-03-15 17:56 949
        SizeType count;
6c5f2c01 sago007 2017-03-15 17:56 950
    };
6c5f2c01 sago007 2017-03-15 17:56 951
6c5f2c01 sago007 2017-03-15 17:56 952
    static const SchemaType* GetTypeless() {
6c5f2c01 sago007 2017-03-15 17:56 953
        static SchemaType typeless(0, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), 0);
6c5f2c01 sago007 2017-03-15 17:56 954
        return &typeless;
6c5f2c01 sago007 2017-03-15 17:56 955
    }
6c5f2c01 sago007 2017-03-15 17:56 956
6c5f2c01 sago007 2017-03-15 17:56 957
    template <typename V1, typename V2>
6c5f2c01 sago007 2017-03-15 17:56 958
    void AddUniqueElement(V1& a, const V2& v) {
6c5f2c01 sago007 2017-03-15 17:56 959
        for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 960
            if (*itr == v)
6c5f2c01 sago007 2017-03-15 17:56 961
                return;
6c5f2c01 sago007 2017-03-15 17:56 962
        V1 c(v, *allocator_);
6c5f2c01 sago007 2017-03-15 17:56 963
        a.PushBack(c, *allocator_);
6c5f2c01 sago007 2017-03-15 17:56 964
    }
6c5f2c01 sago007 2017-03-15 17:56 965
6c5f2c01 sago007 2017-03-15 17:56 966
    static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
6c5f2c01 sago007 2017-03-15 17:56 967
        typename ValueType::ConstMemberIterator itr = value.FindMember(name);
6c5f2c01 sago007 2017-03-15 17:56 968
        return itr != value.MemberEnd() ? &(itr->value) : 0;
6c5f2c01 sago007 2017-03-15 17:56 969
    }
6c5f2c01 sago007 2017-03-15 17:56 970
6c5f2c01 sago007 2017-03-15 17:56 971
    static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
6c5f2c01 sago007 2017-03-15 17:56 972
        if (const ValueType* v = GetMember(value, name))
6c5f2c01 sago007 2017-03-15 17:56 973
            if (v->IsBool())
6c5f2c01 sago007 2017-03-15 17:56 974
                out = v->GetBool();
6c5f2c01 sago007 2017-03-15 17:56 975
    }
6c5f2c01 sago007 2017-03-15 17:56 976
6c5f2c01 sago007 2017-03-15 17:56 977
    static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
6c5f2c01 sago007 2017-03-15 17:56 978
        if (const ValueType* v = GetMember(value, name))
6c5f2c01 sago007 2017-03-15 17:56 979
            if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
6c5f2c01 sago007 2017-03-15 17:56 980
                out = static_cast<SizeType>(v->GetUint64());
6c5f2c01 sago007 2017-03-15 17:56 981
    }
6c5f2c01 sago007 2017-03-15 17:56 982
6c5f2c01 sago007 2017-03-15 17:56 983
    void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
6c5f2c01 sago007 2017-03-15 17:56 984
        if (const ValueType* v = GetMember(value, name)) {
6c5f2c01 sago007 2017-03-15 17:56 985
            if (v->IsArray() && v->Size() > 0) {
6c5f2c01 sago007 2017-03-15 17:56 986
                PointerType q = p.Append(name, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 987
                out.count = v->Size();
6c5f2c01 sago007 2017-03-15 17:56 988
                out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
6c5f2c01 sago007 2017-03-15 17:56 989
                memset(out.schemas, 0, sizeof(Schema*)* out.count);
6c5f2c01 sago007 2017-03-15 17:56 990
                for (SizeType i = 0; i < out.count; i++)
6c5f2c01 sago007 2017-03-15 17:56 991
                    schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
6c5f2c01 sago007 2017-03-15 17:56 992
                out.begin = validatorCount_;
6c5f2c01 sago007 2017-03-15 17:56 993
                validatorCount_ += out.count;
6c5f2c01 sago007 2017-03-15 17:56 994
            }
6c5f2c01 sago007 2017-03-15 17:56 995
        }
6c5f2c01 sago007 2017-03-15 17:56 996
    }
6c5f2c01 sago007 2017-03-15 17:56 997
6c5f2c01 sago007 2017-03-15 17:56 998
#if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
6c5f2c01 sago007 2017-03-15 17:56 999
    template <typename ValueType>
6c5f2c01 sago007 2017-03-15 17:56 1000
    RegexType* CreatePattern(const ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1001
        if (value.IsString()) {
6c5f2c01 sago007 2017-03-15 17:56 1002
            RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString());
6c5f2c01 sago007 2017-03-15 17:56 1003
            if (!r->IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 1004
                r->~RegexType();
6c5f2c01 sago007 2017-03-15 17:56 1005
                AllocatorType::Free(r);
6c5f2c01 sago007 2017-03-15 17:56 1006
                r = 0;
6c5f2c01 sago007 2017-03-15 17:56 1007
            }
6c5f2c01 sago007 2017-03-15 17:56 1008
            return r;
6c5f2c01 sago007 2017-03-15 17:56 1009
        }
6c5f2c01 sago007 2017-03-15 17:56 1010
        return 0;
6c5f2c01 sago007 2017-03-15 17:56 1011
    }
6c5f2c01 sago007 2017-03-15 17:56 1012
6c5f2c01 sago007 2017-03-15 17:56 1013
    static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
6c5f2c01 sago007 2017-03-15 17:56 1014
        return pattern->Search(str);
6c5f2c01 sago007 2017-03-15 17:56 1015
    }
6c5f2c01 sago007 2017-03-15 17:56 1016
#elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
6c5f2c01 sago007 2017-03-15 17:56 1017
    template <typename ValueType>
6c5f2c01 sago007 2017-03-15 17:56 1018
    RegexType* CreatePattern(const ValueType& value) {
6c5f2c01 sago007 2017-03-15 17:56 1019
        if (value.IsString())
6c5f2c01 sago007 2017-03-15 17:56 1020
            try {
6c5f2c01 sago007 2017-03-15 17:56 1021
                return new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
6c5f2c01 sago007 2017-03-15 17:56 1022
            }
6c5f2c01 sago007 2017-03-15 17:56 1023
            catch (const std::regex_error&) {
6c5f2c01 sago007 2017-03-15 17:56 1024
            }
6c5f2c01 sago007 2017-03-15 17:56 1025
        return 0;
6c5f2c01 sago007 2017-03-15 17:56 1026
    }
6c5f2c01 sago007 2017-03-15 17:56 1027
6c5f2c01 sago007 2017-03-15 17:56 1028
    static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
6c5f2c01 sago007 2017-03-15 17:56 1029
        std::match_results<const Ch*> r;
6c5f2c01 sago007 2017-03-15 17:56 1030
        return std::regex_search(str, str + length, r, *pattern);
6c5f2c01 sago007 2017-03-15 17:56 1031
    }
6c5f2c01 sago007 2017-03-15 17:56 1032
#else
6c5f2c01 sago007 2017-03-15 17:56 1033
    template <typename ValueType>
6c5f2c01 sago007 2017-03-15 17:56 1034
    RegexType* CreatePattern(const ValueType&) { return 0; }
6c5f2c01 sago007 2017-03-15 17:56 1035
6c5f2c01 sago007 2017-03-15 17:56 1036
    static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
6c5f2c01 sago007 2017-03-15 17:56 1037
#endif // CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
6c5f2c01 sago007 2017-03-15 17:56 1038
6c5f2c01 sago007 2017-03-15 17:56 1039
    void AddType(const ValueType& type) {
6c5f2c01 sago007 2017-03-15 17:56 1040
        if      (type == GetNullString()   ) type_ |= 1 << kNullSchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1041
        else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1042
        else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1043
        else if (type == GetArrayString()  ) type_ |= 1 << kArraySchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1044
        else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1045
        else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1046
        else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
6c5f2c01 sago007 2017-03-15 17:56 1047
    }
6c5f2c01 sago007 2017-03-15 17:56 1048
6c5f2c01 sago007 2017-03-15 17:56 1049
    bool CreateParallelValidator(Context& context) const {
6c5f2c01 sago007 2017-03-15 17:56 1050
        if (enum_ || context.arrayUniqueness)
6c5f2c01 sago007 2017-03-15 17:56 1051
            context.hasher = context.factory.CreateHasher();
6c5f2c01 sago007 2017-03-15 17:56 1052
6c5f2c01 sago007 2017-03-15 17:56 1053
        if (validatorCount_) {
6c5f2c01 sago007 2017-03-15 17:56 1054
            CEREAL_RAPIDJSON_ASSERT(context.validators == 0);
6c5f2c01 sago007 2017-03-15 17:56 1055
            context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
6c5f2c01 sago007 2017-03-15 17:56 1056
            context.validatorCount = validatorCount_;
6c5f2c01 sago007 2017-03-15 17:56 1057
6c5f2c01 sago007 2017-03-15 17:56 1058
            if (allOf_.schemas)
6c5f2c01 sago007 2017-03-15 17:56 1059
                CreateSchemaValidators(context, allOf_);
6c5f2c01 sago007 2017-03-15 17:56 1060
6c5f2c01 sago007 2017-03-15 17:56 1061
            if (anyOf_.schemas)
6c5f2c01 sago007 2017-03-15 17:56 1062
                CreateSchemaValidators(context, anyOf_);
6c5f2c01 sago007 2017-03-15 17:56 1063
            
6c5f2c01 sago007 2017-03-15 17:56 1064
            if (oneOf_.schemas)
6c5f2c01 sago007 2017-03-15 17:56 1065
                CreateSchemaValidators(context, oneOf_);
6c5f2c01 sago007 2017-03-15 17:56 1066
            
6c5f2c01 sago007 2017-03-15 17:56 1067
            if (not_)
6c5f2c01 sago007 2017-03-15 17:56 1068
                context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_);
6c5f2c01 sago007 2017-03-15 17:56 1069
            
6c5f2c01 sago007 2017-03-15 17:56 1070
            if (hasSchemaDependencies_) {
6c5f2c01 sago007 2017-03-15 17:56 1071
                for (SizeType i = 0; i < propertyCount_; i++)
6c5f2c01 sago007 2017-03-15 17:56 1072
                    if (properties_[i].dependenciesSchema)
6c5f2c01 sago007 2017-03-15 17:56 1073
                        context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
6c5f2c01 sago007 2017-03-15 17:56 1074
            }
6c5f2c01 sago007 2017-03-15 17:56 1075
        }
6c5f2c01 sago007 2017-03-15 17:56 1076
6c5f2c01 sago007 2017-03-15 17:56 1077
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1078
    }
6c5f2c01 sago007 2017-03-15 17:56 1079
6c5f2c01 sago007 2017-03-15 17:56 1080
    void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
6c5f2c01 sago007 2017-03-15 17:56 1081
        for (SizeType i = 0; i < schemas.count; i++)
6c5f2c01 sago007 2017-03-15 17:56 1082
            context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
6c5f2c01 sago007 2017-03-15 17:56 1083
    }
6c5f2c01 sago007 2017-03-15 17:56 1084
6c5f2c01 sago007 2017-03-15 17:56 1085
    // O(n)
6c5f2c01 sago007 2017-03-15 17:56 1086
    bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
6c5f2c01 sago007 2017-03-15 17:56 1087
        SizeType len = name.GetStringLength();
6c5f2c01 sago007 2017-03-15 17:56 1088
        const Ch* str = name.GetString();
6c5f2c01 sago007 2017-03-15 17:56 1089
        for (SizeType index = 0; index < propertyCount_; index++)
6c5f2c01 sago007 2017-03-15 17:56 1090
            if (properties_[index].name.GetStringLength() == len && 
6c5f2c01 sago007 2017-03-15 17:56 1091
                (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
6c5f2c01 sago007 2017-03-15 17:56 1092
            {
6c5f2c01 sago007 2017-03-15 17:56 1093
                *outIndex = index;
6c5f2c01 sago007 2017-03-15 17:56 1094
                return true;
6c5f2c01 sago007 2017-03-15 17:56 1095
            }
6c5f2c01 sago007 2017-03-15 17:56 1096
        return false;
6c5f2c01 sago007 2017-03-15 17:56 1097
    }
6c5f2c01 sago007 2017-03-15 17:56 1098
6c5f2c01 sago007 2017-03-15 17:56 1099
    bool CheckInt(Context& context, int64_t i) const {
6c5f2c01 sago007 2017-03-15 17:56 1100
        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
6c5f2c01 sago007 2017-03-15 17:56 1101
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 1102
6c5f2c01 sago007 2017-03-15 17:56 1103
        if (!minimum_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1104
            if (minimum_.IsInt64()) {
6c5f2c01 sago007 2017-03-15 17:56 1105
                if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64())
6c5f2c01 sago007 2017-03-15 17:56 1106
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
6c5f2c01 sago007 2017-03-15 17:56 1107
            }
6c5f2c01 sago007 2017-03-15 17:56 1108
            else if (minimum_.IsUint64()) {
6c5f2c01 sago007 2017-03-15 17:56 1109
                CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
6c5f2c01 sago007 2017-03-15 17:56 1110
            }
6c5f2c01 sago007 2017-03-15 17:56 1111
            else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1112
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1113
        }
6c5f2c01 sago007 2017-03-15 17:56 1114
6c5f2c01 sago007 2017-03-15 17:56 1115
        if (!maximum_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1116
            if (maximum_.IsInt64()) {
6c5f2c01 sago007 2017-03-15 17:56 1117
                if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64())
6c5f2c01 sago007 2017-03-15 17:56 1118
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
6c5f2c01 sago007 2017-03-15 17:56 1119
            }
6c5f2c01 sago007 2017-03-15 17:56 1120
            else if (maximum_.IsUint64())
6c5f2c01 sago007 2017-03-15 17:56 1121
                /* do nothing */; // i <= max(int64_t) < maximum_.GetUint64()
6c5f2c01 sago007 2017-03-15 17:56 1122
            else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1123
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1124
        }
6c5f2c01 sago007 2017-03-15 17:56 1125
6c5f2c01 sago007 2017-03-15 17:56 1126
        if (!multipleOf_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1127
            if (multipleOf_.IsUint64()) {
6c5f2c01 sago007 2017-03-15 17:56 1128
                if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0)
6c5f2c01 sago007 2017-03-15 17:56 1129
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
6c5f2c01 sago007 2017-03-15 17:56 1130
            }
6c5f2c01 sago007 2017-03-15 17:56 1131
            else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1132
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1133
        }
6c5f2c01 sago007 2017-03-15 17:56 1134
6c5f2c01 sago007 2017-03-15 17:56 1135
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1136
    }
6c5f2c01 sago007 2017-03-15 17:56 1137
6c5f2c01 sago007 2017-03-15 17:56 1138
    bool CheckUint(Context& context, uint64_t i) const {
6c5f2c01 sago007 2017-03-15 17:56 1139
        if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType))))
6c5f2c01 sago007 2017-03-15 17:56 1140
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
6c5f2c01 sago007 2017-03-15 17:56 1141
6c5f2c01 sago007 2017-03-15 17:56 1142
        if (!minimum_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1143
            if (minimum_.IsUint64()) {
6c5f2c01 sago007 2017-03-15 17:56 1144
                if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64())
6c5f2c01 sago007 2017-03-15 17:56 1145
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
6c5f2c01 sago007 2017-03-15 17:56 1146
            }
6c5f2c01 sago007 2017-03-15 17:56 1147
            else if (minimum_.IsInt64())
6c5f2c01 sago007 2017-03-15 17:56 1148
                /* do nothing */; // i >= 0 > minimum.Getint64()
6c5f2c01 sago007 2017-03-15 17:56 1149
            else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1150
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1151
        }
6c5f2c01 sago007 2017-03-15 17:56 1152
6c5f2c01 sago007 2017-03-15 17:56 1153
        if (!maximum_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1154
            if (maximum_.IsUint64()) {
6c5f2c01 sago007 2017-03-15 17:56 1155
                if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64())
6c5f2c01 sago007 2017-03-15 17:56 1156
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
6c5f2c01 sago007 2017-03-15 17:56 1157
            }
6c5f2c01 sago007 2017-03-15 17:56 1158
            else if (maximum_.IsInt64())
6c5f2c01 sago007 2017-03-15 17:56 1159
                CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
6c5f2c01 sago007 2017-03-15 17:56 1160
            else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1161
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1162
        }
6c5f2c01 sago007 2017-03-15 17:56 1163
6c5f2c01 sago007 2017-03-15 17:56 1164
        if (!multipleOf_.IsNull()) {
6c5f2c01 sago007 2017-03-15 17:56 1165
            if (multipleOf_.IsUint64()) {
6c5f2c01 sago007 2017-03-15 17:56 1166
                if (i % multipleOf_.GetUint64() != 0)
6c5f2c01 sago007 2017-03-15 17:56 1167
                    CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
6c5f2c01 sago007 2017-03-15 17:56 1168
            }
6c5f2c01 sago007 2017-03-15 17:56 1169
            else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
6c5f2c01 sago007 2017-03-15 17:56 1170
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1171
        }
6c5f2c01 sago007 2017-03-15 17:56 1172
6c5f2c01 sago007 2017-03-15 17:56 1173
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1174
    }
6c5f2c01 sago007 2017-03-15 17:56 1175
6c5f2c01 sago007 2017-03-15 17:56 1176
    bool CheckDoubleMinimum(Context& context, double d) const {
6c5f2c01 sago007 2017-03-15 17:56 1177
        if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble())
6c5f2c01 sago007 2017-03-15 17:56 1178
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
6c5f2c01 sago007 2017-03-15 17:56 1179
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1180
    }
6c5f2c01 sago007 2017-03-15 17:56 1181
6c5f2c01 sago007 2017-03-15 17:56 1182
    bool CheckDoubleMaximum(Context& context, double d) const {
6c5f2c01 sago007 2017-03-15 17:56 1183
        if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble())
6c5f2c01 sago007 2017-03-15 17:56 1184
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
6c5f2c01 sago007 2017-03-15 17:56 1185
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1186
    }
6c5f2c01 sago007 2017-03-15 17:56 1187
6c5f2c01 sago007 2017-03-15 17:56 1188
    bool CheckDoubleMultipleOf(Context& context, double d) const {
6c5f2c01 sago007 2017-03-15 17:56 1189
        double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
6c5f2c01 sago007 2017-03-15 17:56 1190
        double q = std::floor(a / b);
6c5f2c01 sago007 2017-03-15 17:56 1191
        double r = a - q * b;
6c5f2c01 sago007 2017-03-15 17:56 1192
        if (r > 0.0)
6c5f2c01 sago007 2017-03-15 17:56 1193
            CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
6c5f2c01 sago007 2017-03-15 17:56 1194
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1195
    }
6c5f2c01 sago007 2017-03-15 17:56 1196
6c5f2c01 sago007 2017-03-15 17:56 1197
    struct Property {
6c5f2c01 sago007 2017-03-15 17:56 1198
        Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
6c5f2c01 sago007 2017-03-15 17:56 1199
        ~Property() { AllocatorType::Free(dependencies); }
6c5f2c01 sago007 2017-03-15 17:56 1200
        SValue name;
6c5f2c01 sago007 2017-03-15 17:56 1201
        const SchemaType* schema;
6c5f2c01 sago007 2017-03-15 17:56 1202
        const SchemaType* dependenciesSchema;
6c5f2c01 sago007 2017-03-15 17:56 1203
        SizeType dependenciesValidatorIndex;
6c5f2c01 sago007 2017-03-15 17:56 1204
        bool* dependencies;
6c5f2c01 sago007 2017-03-15 17:56 1205
        bool required;
6c5f2c01 sago007 2017-03-15 17:56 1206
    };
6c5f2c01 sago007 2017-03-15 17:56 1207
6c5f2c01 sago007 2017-03-15 17:56 1208
    struct PatternProperty {
6c5f2c01 sago007 2017-03-15 17:56 1209
        PatternProperty() : schema(), pattern() {}
6c5f2c01 sago007 2017-03-15 17:56 1210
        ~PatternProperty() { 
6c5f2c01 sago007 2017-03-15 17:56 1211
            if (pattern) {
6c5f2c01 sago007 2017-03-15 17:56 1212
                pattern->~RegexType();
6c5f2c01 sago007 2017-03-15 17:56 1213
                AllocatorType::Free(pattern);
6c5f2c01 sago007 2017-03-15 17:56 1214
            }
6c5f2c01 sago007 2017-03-15 17:56 1215
        }
6c5f2c01 sago007 2017-03-15 17:56 1216
        const SchemaType* schema;
6c5f2c01 sago007 2017-03-15 17:56 1217
        RegexType* pattern;
6c5f2c01 sago007 2017-03-15 17:56 1218
    };
6c5f2c01 sago007 2017-03-15 17:56 1219
6c5f2c01 sago007 2017-03-15 17:56 1220
    AllocatorType* allocator_;
6c5f2c01 sago007 2017-03-15 17:56 1221
    uint64_t* enum_;
6c5f2c01 sago007 2017-03-15 17:56 1222
    SizeType enumCount_;
6c5f2c01 sago007 2017-03-15 17:56 1223
    SchemaArray allOf_;
6c5f2c01 sago007 2017-03-15 17:56 1224
    SchemaArray anyOf_;
6c5f2c01 sago007 2017-03-15 17:56 1225
    SchemaArray oneOf_;
6c5f2c01 sago007 2017-03-15 17:56 1226
    const SchemaType* not_;
6c5f2c01 sago007 2017-03-15 17:56 1227
    unsigned type_; // bitmask of kSchemaType
6c5f2c01 sago007 2017-03-15 17:56 1228
    SizeType validatorCount_;
6c5f2c01 sago007 2017-03-15 17:56 1229
    SizeType notValidatorIndex_;
6c5f2c01 sago007 2017-03-15 17:56 1230
6c5f2c01 sago007 2017-03-15 17:56 1231
    Property* properties_;
6c5f2c01 sago007 2017-03-15 17:56 1232
    const SchemaType* additionalPropertiesSchema_;
6c5f2c01 sago007 2017-03-15 17:56 1233
    PatternProperty* patternProperties_;
6c5f2c01 sago007 2017-03-15 17:56 1234
    SizeType patternPropertyCount_;
6c5f2c01 sago007 2017-03-15 17:56 1235
    SizeType propertyCount_;
6c5f2c01 sago007 2017-03-15 17:56 1236
    SizeType minProperties_;
6c5f2c01 sago007 2017-03-15 17:56 1237
    SizeType maxProperties_;
6c5f2c01 sago007 2017-03-15 17:56 1238
    bool additionalProperties_;
6c5f2c01 sago007 2017-03-15 17:56 1239
    bool hasDependencies_;
6c5f2c01 sago007 2017-03-15 17:56 1240
    bool hasRequired_;
6c5f2c01 sago007 2017-03-15 17:56 1241
    bool hasSchemaDependencies_;
6c5f2c01 sago007 2017-03-15 17:56 1242
6c5f2c01 sago007 2017-03-15 17:56 1243
    const SchemaType* additionalItemsSchema_;
6c5f2c01 sago007 2017-03-15 17:56 1244
    const SchemaType* itemsList_;
6c5f2c01 sago007 2017-03-15 17:56 1245
    const SchemaType** itemsTuple_;
6c5f2c01 sago007 2017-03-15 17:56 1246
    SizeType itemsTupleCount_;
6c5f2c01 sago007 2017-03-15 17:56 1247
    SizeType minItems_;
6c5f2c01 sago007 2017-03-15 17:56 1248
    SizeType maxItems_;
6c5f2c01 sago007 2017-03-15 17:56 1249
    bool additionalItems_;
6c5f2c01 sago007 2017-03-15 17:56 1250
    bool uniqueItems_;
6c5f2c01 sago007 2017-03-15 17:56 1251
6c5f2c01 sago007 2017-03-15 17:56 1252
    RegexType* pattern_;
6c5f2c01 sago007 2017-03-15 17:56 1253
    SizeType minLength_;
6c5f2c01 sago007 2017-03-15 17:56 1254
    SizeType maxLength_;
6c5f2c01 sago007 2017-03-15 17:56 1255
6c5f2c01 sago007 2017-03-15 17:56 1256
    SValue minimum_;
6c5f2c01 sago007 2017-03-15 17:56 1257
    SValue maximum_;
6c5f2c01 sago007 2017-03-15 17:56 1258
    SValue multipleOf_;
6c5f2c01 sago007 2017-03-15 17:56 1259
    bool exclusiveMinimum_;
6c5f2c01 sago007 2017-03-15 17:56 1260
    bool exclusiveMaximum_;
6c5f2c01 sago007 2017-03-15 17:56 1261
};
6c5f2c01 sago007 2017-03-15 17:56 1262
6c5f2c01 sago007 2017-03-15 17:56 1263
template<typename Stack, typename Ch>
6c5f2c01 sago007 2017-03-15 17:56 1264
struct TokenHelper {
6c5f2c01 sago007 2017-03-15 17:56 1265
    CEREAL_RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
6c5f2c01 sago007 2017-03-15 17:56 1266
        *documentStack.template Push<Ch>() = '/';
6c5f2c01 sago007 2017-03-15 17:56 1267
        char buffer[21];
6c5f2c01 sago007 2017-03-15 17:56 1268
        size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
6c5f2c01 sago007 2017-03-15 17:56 1269
        for (size_t i = 0; i < length; i++)
6c5f2c01 sago007 2017-03-15 17:56 1270
            *documentStack.template Push<Ch>() = buffer[i];
6c5f2c01 sago007 2017-03-15 17:56 1271
    }
6c5f2c01 sago007 2017-03-15 17:56 1272
};
6c5f2c01 sago007 2017-03-15 17:56 1273
6c5f2c01 sago007 2017-03-15 17:56 1274
// Partial specialized version for char to prevent buffer copying.
6c5f2c01 sago007 2017-03-15 17:56 1275
template <typename Stack>
6c5f2c01 sago007 2017-03-15 17:56 1276
struct TokenHelper<Stack, char> {
6c5f2c01 sago007 2017-03-15 17:56 1277
    CEREAL_RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
6c5f2c01 sago007 2017-03-15 17:56 1278
        if (sizeof(SizeType) == 4) {
6c5f2c01 sago007 2017-03-15 17:56 1279
            char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
6c5f2c01 sago007 2017-03-15 17:56 1280
            *buffer++ = '/';
6c5f2c01 sago007 2017-03-15 17:56 1281
            const char* end = internal::u32toa(index, buffer);
6c5f2c01 sago007 2017-03-15 17:56 1282
             documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
6c5f2c01 sago007 2017-03-15 17:56 1283
        }
6c5f2c01 sago007 2017-03-15 17:56 1284
        else {
6c5f2c01 sago007 2017-03-15 17:56 1285
            char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
6c5f2c01 sago007 2017-03-15 17:56 1286
            *buffer++ = '/';
6c5f2c01 sago007 2017-03-15 17:56 1287
            const char* end = internal::u64toa(index, buffer);
6c5f2c01 sago007 2017-03-15 17:56 1288
            documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
6c5f2c01 sago007 2017-03-15 17:56 1289
        }
6c5f2c01 sago007 2017-03-15 17:56 1290
    }
6c5f2c01 sago007 2017-03-15 17:56 1291
};
6c5f2c01 sago007 2017-03-15 17:56 1292
6c5f2c01 sago007 2017-03-15 17:56 1293
} // namespace internal
6c5f2c01 sago007 2017-03-15 17:56 1294
6c5f2c01 sago007 2017-03-15 17:56 1295
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1296
// IGenericRemoteSchemaDocumentProvider
6c5f2c01 sago007 2017-03-15 17:56 1297
6c5f2c01 sago007 2017-03-15 17:56 1298
template <typename SchemaDocumentType>
6c5f2c01 sago007 2017-03-15 17:56 1299
class IGenericRemoteSchemaDocumentProvider {
6c5f2c01 sago007 2017-03-15 17:56 1300
public:
6c5f2c01 sago007 2017-03-15 17:56 1301
    typedef typename SchemaDocumentType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1302
6c5f2c01 sago007 2017-03-15 17:56 1303
    virtual ~IGenericRemoteSchemaDocumentProvider() {}
6c5f2c01 sago007 2017-03-15 17:56 1304
    virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
6c5f2c01 sago007 2017-03-15 17:56 1305
};
6c5f2c01 sago007 2017-03-15 17:56 1306
6c5f2c01 sago007 2017-03-15 17:56 1307
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1308
// GenericSchemaDocument
6c5f2c01 sago007 2017-03-15 17:56 1309
6c5f2c01 sago007 2017-03-15 17:56 1310
//! JSON schema document.
6c5f2c01 sago007 2017-03-15 17:56 1311
/*!
6c5f2c01 sago007 2017-03-15 17:56 1312
    A JSON schema document is a compiled version of a JSON schema.
6c5f2c01 sago007 2017-03-15 17:56 1313
    It is basically a tree of internal::Schema.
6c5f2c01 sago007 2017-03-15 17:56 1314
6c5f2c01 sago007 2017-03-15 17:56 1315
    \note This is an immutable class (i.e. its instance cannot be modified after construction).
6c5f2c01 sago007 2017-03-15 17:56 1316
    \tparam ValueT Type of JSON value (e.g. \c Value ), which also determine the encoding.
6c5f2c01 sago007 2017-03-15 17:56 1317
    \tparam Allocator Allocator type for allocating memory of this document.
6c5f2c01 sago007 2017-03-15 17:56 1318
*/
6c5f2c01 sago007 2017-03-15 17:56 1319
template <typename ValueT, typename Allocator = CrtAllocator>
6c5f2c01 sago007 2017-03-15 17:56 1320
class GenericSchemaDocument {
6c5f2c01 sago007 2017-03-15 17:56 1321
public:
6c5f2c01 sago007 2017-03-15 17:56 1322
    typedef ValueT ValueType;
6c5f2c01 sago007 2017-03-15 17:56 1323
    typedef IGenericRemoteSchemaDocumentProvider<GenericSchemaDocument> IRemoteSchemaDocumentProviderType;
6c5f2c01 sago007 2017-03-15 17:56 1324
    typedef Allocator AllocatorType;
6c5f2c01 sago007 2017-03-15 17:56 1325
    typedef typename ValueType::EncodingType EncodingType;
6c5f2c01 sago007 2017-03-15 17:56 1326
    typedef typename EncodingType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1327
    typedef internal::Schema<GenericSchemaDocument> SchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1328
    typedef GenericPointer<ValueType, Allocator> PointerType;
6c5f2c01 sago007 2017-03-15 17:56 1329
    friend class internal::Schema<GenericSchemaDocument>;
6c5f2c01 sago007 2017-03-15 17:56 1330
    template <typename, typename, typename>
6c5f2c01 sago007 2017-03-15 17:56 1331
    friend class GenericSchemaValidator;
6c5f2c01 sago007 2017-03-15 17:56 1332
6c5f2c01 sago007 2017-03-15 17:56 1333
    //! Constructor.
6c5f2c01 sago007 2017-03-15 17:56 1334
    /*!
6c5f2c01 sago007 2017-03-15 17:56 1335
        Compile a JSON document into schema document.
6c5f2c01 sago007 2017-03-15 17:56 1336
6c5f2c01 sago007 2017-03-15 17:56 1337
        \param document A JSON document as source.
6c5f2c01 sago007 2017-03-15 17:56 1338
        \param remoteProvider An optional remote schema document provider for resolving remote reference. Can be null.
6c5f2c01 sago007 2017-03-15 17:56 1339
        \param allocator An optional allocator instance for allocating memory. Can be null.
6c5f2c01 sago007 2017-03-15 17:56 1340
    */
6c5f2c01 sago007 2017-03-15 17:56 1341
    explicit GenericSchemaDocument(const ValueType& document, IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
6c5f2c01 sago007 2017-03-15 17:56 1342
        remoteProvider_(remoteProvider),
6c5f2c01 sago007 2017-03-15 17:56 1343
        allocator_(allocator),
6c5f2c01 sago007 2017-03-15 17:56 1344
        ownAllocator_(),
6c5f2c01 sago007 2017-03-15 17:56 1345
        root_(),
6c5f2c01 sago007 2017-03-15 17:56 1346
        schemaMap_(allocator, kInitialSchemaMapSize),
6c5f2c01 sago007 2017-03-15 17:56 1347
        schemaRef_(allocator, kInitialSchemaRefSize)
6c5f2c01 sago007 2017-03-15 17:56 1348
    {
6c5f2c01 sago007 2017-03-15 17:56 1349
        if (!allocator_)
6c5f2c01 sago007 2017-03-15 17:56 1350
            ownAllocator_ = allocator_ = CEREAL_RAPIDJSON_NEW(Allocator());
6c5f2c01 sago007 2017-03-15 17:56 1351
6c5f2c01 sago007 2017-03-15 17:56 1352
        // Generate root schema, it will call CreateSchema() to create sub-schemas,
6c5f2c01 sago007 2017-03-15 17:56 1353
        // And call AddRefSchema() if there are $ref.
6c5f2c01 sago007 2017-03-15 17:56 1354
        CreateSchemaRecursive(&root_, PointerType(), document, document);
6c5f2c01 sago007 2017-03-15 17:56 1355
6c5f2c01 sago007 2017-03-15 17:56 1356
        // Resolve $ref
6c5f2c01 sago007 2017-03-15 17:56 1357
        while (!schemaRef_.Empty()) {
6c5f2c01 sago007 2017-03-15 17:56 1358
            SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
6c5f2c01 sago007 2017-03-15 17:56 1359
            if (const SchemaType* s = GetSchema(refEntry->target)) {
6c5f2c01 sago007 2017-03-15 17:56 1360
                if (refEntry->schema)
6c5f2c01 sago007 2017-03-15 17:56 1361
                    *refEntry->schema = s;
6c5f2c01 sago007 2017-03-15 17:56 1362
6c5f2c01 sago007 2017-03-15 17:56 1363
                // Create entry in map if not exist
6c5f2c01 sago007 2017-03-15 17:56 1364
                if (!GetSchema(refEntry->source)) {
6c5f2c01 sago007 2017-03-15 17:56 1365
                    new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1366
                }
6c5f2c01 sago007 2017-03-15 17:56 1367
            }
6c5f2c01 sago007 2017-03-15 17:56 1368
            refEntry->~SchemaRefEntry();
6c5f2c01 sago007 2017-03-15 17:56 1369
        }
6c5f2c01 sago007 2017-03-15 17:56 1370
6c5f2c01 sago007 2017-03-15 17:56 1371
        CEREAL_RAPIDJSON_ASSERT(root_ != 0);
6c5f2c01 sago007 2017-03-15 17:56 1372
6c5f2c01 sago007 2017-03-15 17:56 1373
        schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
6c5f2c01 sago007 2017-03-15 17:56 1374
    }
6c5f2c01 sago007 2017-03-15 17:56 1375
6c5f2c01 sago007 2017-03-15 17:56 1376
#if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
6c5f2c01 sago007 2017-03-15 17:56 1377
    //! Move constructor in C++11
6c5f2c01 sago007 2017-03-15 17:56 1378
    GenericSchemaDocument(GenericSchemaDocument&& rhs) CEREAL_RAPIDJSON_NOEXCEPT :
6c5f2c01 sago007 2017-03-15 17:56 1379
        remoteProvider_(rhs.remoteProvider_),
6c5f2c01 sago007 2017-03-15 17:56 1380
        allocator_(rhs.allocator_),
6c5f2c01 sago007 2017-03-15 17:56 1381
        ownAllocator_(rhs.ownAllocator_),
6c5f2c01 sago007 2017-03-15 17:56 1382
        root_(rhs.root_),
6c5f2c01 sago007 2017-03-15 17:56 1383
        schemaMap_(std::move(rhs.schemaMap_)),
6c5f2c01 sago007 2017-03-15 17:56 1384
        schemaRef_(std::move(rhs.schemaRef_))
6c5f2c01 sago007 2017-03-15 17:56 1385
    {
6c5f2c01 sago007 2017-03-15 17:56 1386
        rhs.remoteProvider_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 1387
        rhs.allocator_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 1388
        rhs.ownAllocator_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 1389
    }
6c5f2c01 sago007 2017-03-15 17:56 1390
#endif
6c5f2c01 sago007 2017-03-15 17:56 1391
6c5f2c01 sago007 2017-03-15 17:56 1392
    //! Destructor
6c5f2c01 sago007 2017-03-15 17:56 1393
    ~GenericSchemaDocument() {
6c5f2c01 sago007 2017-03-15 17:56 1394
        while (!schemaMap_.Empty())
6c5f2c01 sago007 2017-03-15 17:56 1395
            schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
6c5f2c01 sago007 2017-03-15 17:56 1396
6c5f2c01 sago007 2017-03-15 17:56 1397
        CEREAL_RAPIDJSON_DELETE(ownAllocator_);
6c5f2c01 sago007 2017-03-15 17:56 1398
    }
6c5f2c01 sago007 2017-03-15 17:56 1399
6c5f2c01 sago007 2017-03-15 17:56 1400
    //! Get the root schema.
6c5f2c01 sago007 2017-03-15 17:56 1401
    const SchemaType& GetRoot() const { return *root_; }
6c5f2c01 sago007 2017-03-15 17:56 1402
6c5f2c01 sago007 2017-03-15 17:56 1403
private:
6c5f2c01 sago007 2017-03-15 17:56 1404
    //! Prohibit copying
6c5f2c01 sago007 2017-03-15 17:56 1405
    GenericSchemaDocument(const GenericSchemaDocument&);
6c5f2c01 sago007 2017-03-15 17:56 1406
    //! Prohibit assignment
6c5f2c01 sago007 2017-03-15 17:56 1407
    GenericSchemaDocument& operator=(const GenericSchemaDocument&);
6c5f2c01 sago007 2017-03-15 17:56 1408
6c5f2c01 sago007 2017-03-15 17:56 1409
    struct SchemaRefEntry {
6c5f2c01 sago007 2017-03-15 17:56 1410
        SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
6c5f2c01 sago007 2017-03-15 17:56 1411
        PointerType source;
6c5f2c01 sago007 2017-03-15 17:56 1412
        PointerType target;
6c5f2c01 sago007 2017-03-15 17:56 1413
        const SchemaType** schema;
6c5f2c01 sago007 2017-03-15 17:56 1414
    };
6c5f2c01 sago007 2017-03-15 17:56 1415
6c5f2c01 sago007 2017-03-15 17:56 1416
    struct SchemaEntry {
6c5f2c01 sago007 2017-03-15 17:56 1417
        SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
6c5f2c01 sago007 2017-03-15 17:56 1418
        ~SchemaEntry() {
6c5f2c01 sago007 2017-03-15 17:56 1419
            if (owned) {
6c5f2c01 sago007 2017-03-15 17:56 1420
                schema->~SchemaType();
6c5f2c01 sago007 2017-03-15 17:56 1421
                Allocator::Free(schema);
6c5f2c01 sago007 2017-03-15 17:56 1422
            }
6c5f2c01 sago007 2017-03-15 17:56 1423
        }
6c5f2c01 sago007 2017-03-15 17:56 1424
        PointerType pointer;
6c5f2c01 sago007 2017-03-15 17:56 1425
        SchemaType* schema;
6c5f2c01 sago007 2017-03-15 17:56 1426
        bool owned;
6c5f2c01 sago007 2017-03-15 17:56 1427
    };
6c5f2c01 sago007 2017-03-15 17:56 1428
6c5f2c01 sago007 2017-03-15 17:56 1429
    void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
6c5f2c01 sago007 2017-03-15 17:56 1430
        if (schema)
6c5f2c01 sago007 2017-03-15 17:56 1431
            *schema = SchemaType::GetTypeless();
6c5f2c01 sago007 2017-03-15 17:56 1432
6c5f2c01 sago007 2017-03-15 17:56 1433
        if (v.GetType() == kObjectType) {
6c5f2c01 sago007 2017-03-15 17:56 1434
            const SchemaType* s = GetSchema(pointer);
6c5f2c01 sago007 2017-03-15 17:56 1435
            if (!s)
6c5f2c01 sago007 2017-03-15 17:56 1436
                CreateSchema(schema, pointer, v, document);
6c5f2c01 sago007 2017-03-15 17:56 1437
6c5f2c01 sago007 2017-03-15 17:56 1438
            for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 1439
                CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
6c5f2c01 sago007 2017-03-15 17:56 1440
        }
6c5f2c01 sago007 2017-03-15 17:56 1441
        else if (v.GetType() == kArrayType)
6c5f2c01 sago007 2017-03-15 17:56 1442
            for (SizeType i = 0; i < v.Size(); i++)
6c5f2c01 sago007 2017-03-15 17:56 1443
                CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
6c5f2c01 sago007 2017-03-15 17:56 1444
    }
6c5f2c01 sago007 2017-03-15 17:56 1445
6c5f2c01 sago007 2017-03-15 17:56 1446
    void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
6c5f2c01 sago007 2017-03-15 17:56 1447
        CEREAL_RAPIDJSON_ASSERT(pointer.IsValid());
6c5f2c01 sago007 2017-03-15 17:56 1448
        if (v.IsObject()) {
6c5f2c01 sago007 2017-03-15 17:56 1449
            if (!HandleRefSchema(pointer, schema, v, document)) {
6c5f2c01 sago007 2017-03-15 17:56 1450
                SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1451
                new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1452
                if (schema)
6c5f2c01 sago007 2017-03-15 17:56 1453
                    *schema = s;
6c5f2c01 sago007 2017-03-15 17:56 1454
            }
6c5f2c01 sago007 2017-03-15 17:56 1455
        }
6c5f2c01 sago007 2017-03-15 17:56 1456
    }
6c5f2c01 sago007 2017-03-15 17:56 1457
6c5f2c01 sago007 2017-03-15 17:56 1458
    bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
6c5f2c01 sago007 2017-03-15 17:56 1459
        static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
6c5f2c01 sago007 2017-03-15 17:56 1460
        static const ValueType kRefValue(kRefString, 4);
6c5f2c01 sago007 2017-03-15 17:56 1461
6c5f2c01 sago007 2017-03-15 17:56 1462
        typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
6c5f2c01 sago007 2017-03-15 17:56 1463
        if (itr == v.MemberEnd())
6c5f2c01 sago007 2017-03-15 17:56 1464
            return false;
6c5f2c01 sago007 2017-03-15 17:56 1465
6c5f2c01 sago007 2017-03-15 17:56 1466
        if (itr->value.IsString()) {
6c5f2c01 sago007 2017-03-15 17:56 1467
            SizeType len = itr->value.GetStringLength();
6c5f2c01 sago007 2017-03-15 17:56 1468
            if (len > 0) {
6c5f2c01 sago007 2017-03-15 17:56 1469
                const Ch* s = itr->value.GetString();
6c5f2c01 sago007 2017-03-15 17:56 1470
                SizeType i = 0;
6c5f2c01 sago007 2017-03-15 17:56 1471
                while (i < len && s[i] != '#') // Find the first #
6c5f2c01 sago007 2017-03-15 17:56 1472
                    i++;
6c5f2c01 sago007 2017-03-15 17:56 1473
6c5f2c01 sago007 2017-03-15 17:56 1474
                if (i > 0) { // Remote reference, resolve immediately
6c5f2c01 sago007 2017-03-15 17:56 1475
                    if (remoteProvider_) {
6c5f2c01 sago007 2017-03-15 17:56 1476
                        if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i - 1)) {
6c5f2c01 sago007 2017-03-15 17:56 1477
                            PointerType pointer(&s[i], len - i, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1478
                            if (pointer.IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 1479
                                if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
6c5f2c01 sago007 2017-03-15 17:56 1480
                                    if (schema)
6c5f2c01 sago007 2017-03-15 17:56 1481
                                        *schema = sc;
6c5f2c01 sago007 2017-03-15 17:56 1482
                                    return true;
6c5f2c01 sago007 2017-03-15 17:56 1483
                                }
6c5f2c01 sago007 2017-03-15 17:56 1484
                            }
6c5f2c01 sago007 2017-03-15 17:56 1485
                        }
6c5f2c01 sago007 2017-03-15 17:56 1486
                    }
6c5f2c01 sago007 2017-03-15 17:56 1487
                }
6c5f2c01 sago007 2017-03-15 17:56 1488
                else if (s[i] == '#') { // Local reference, defer resolution
6c5f2c01 sago007 2017-03-15 17:56 1489
                    PointerType pointer(&s[i], len - i, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1490
                    if (pointer.IsValid()) {
6c5f2c01 sago007 2017-03-15 17:56 1491
                        if (const ValueType* nv = pointer.Get(document))
6c5f2c01 sago007 2017-03-15 17:56 1492
                            if (HandleRefSchema(source, schema, *nv, document))
6c5f2c01 sago007 2017-03-15 17:56 1493
                                return true;
6c5f2c01 sago007 2017-03-15 17:56 1494
6c5f2c01 sago007 2017-03-15 17:56 1495
                        new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
6c5f2c01 sago007 2017-03-15 17:56 1496
                        return true;
6c5f2c01 sago007 2017-03-15 17:56 1497
                    }
6c5f2c01 sago007 2017-03-15 17:56 1498
                }
6c5f2c01 sago007 2017-03-15 17:56 1499
            }
6c5f2c01 sago007 2017-03-15 17:56 1500
        }
6c5f2c01 sago007 2017-03-15 17:56 1501
        return false;
6c5f2c01 sago007 2017-03-15 17:56 1502
    }
6c5f2c01 sago007 2017-03-15 17:56 1503
6c5f2c01 sago007 2017-03-15 17:56 1504
    const SchemaType* GetSchema(const PointerType& pointer) const {
6c5f2c01 sago007 2017-03-15 17:56 1505
        for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
6c5f2c01 sago007 2017-03-15 17:56 1506
            if (pointer == target->pointer)
6c5f2c01 sago007 2017-03-15 17:56 1507
                return target->schema;
6c5f2c01 sago007 2017-03-15 17:56 1508
        return 0;
6c5f2c01 sago007 2017-03-15 17:56 1509
    }
6c5f2c01 sago007 2017-03-15 17:56 1510
6c5f2c01 sago007 2017-03-15 17:56 1511
    PointerType GetPointer(const SchemaType* schema) const {
6c5f2c01 sago007 2017-03-15 17:56 1512
        for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
6c5f2c01 sago007 2017-03-15 17:56 1513
            if (schema == target->schema)
6c5f2c01 sago007 2017-03-15 17:56 1514
                return target->pointer;
6c5f2c01 sago007 2017-03-15 17:56 1515
        return PointerType();
6c5f2c01 sago007 2017-03-15 17:56 1516
    }
6c5f2c01 sago007 2017-03-15 17:56 1517
6c5f2c01 sago007 2017-03-15 17:56 1518
    static const size_t kInitialSchemaMapSize = 64;
6c5f2c01 sago007 2017-03-15 17:56 1519
    static const size_t kInitialSchemaRefSize = 64;
6c5f2c01 sago007 2017-03-15 17:56 1520
6c5f2c01 sago007 2017-03-15 17:56 1521
    IRemoteSchemaDocumentProviderType* remoteProvider_;
6c5f2c01 sago007 2017-03-15 17:56 1522
    Allocator *allocator_;
6c5f2c01 sago007 2017-03-15 17:56 1523
    Allocator *ownAllocator_;
6c5f2c01 sago007 2017-03-15 17:56 1524
    const SchemaType* root_;                //!< Root schema.
6c5f2c01 sago007 2017-03-15 17:56 1525
    internal::Stack<Allocator> schemaMap_;  // Stores created Pointer -> Schemas
6c5f2c01 sago007 2017-03-15 17:56 1526
    internal::Stack<Allocator> schemaRef_;  // Stores Pointer from $ref and schema which holds the $ref
6c5f2c01 sago007 2017-03-15 17:56 1527
};
6c5f2c01 sago007 2017-03-15 17:56 1528
6c5f2c01 sago007 2017-03-15 17:56 1529
//! GenericSchemaDocument using Value type.
6c5f2c01 sago007 2017-03-15 17:56 1530
typedef GenericSchemaDocument<Value> SchemaDocument;
6c5f2c01 sago007 2017-03-15 17:56 1531
//! IGenericRemoteSchemaDocumentProvider using SchemaDocument.
6c5f2c01 sago007 2017-03-15 17:56 1532
typedef IGenericRemoteSchemaDocumentProvider<SchemaDocument> IRemoteSchemaDocumentProvider;
6c5f2c01 sago007 2017-03-15 17:56 1533
6c5f2c01 sago007 2017-03-15 17:56 1534
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1535
// GenericSchemaValidator
6c5f2c01 sago007 2017-03-15 17:56 1536
6c5f2c01 sago007 2017-03-15 17:56 1537
//! JSON Schema Validator.
6c5f2c01 sago007 2017-03-15 17:56 1538
/*!
6c5f2c01 sago007 2017-03-15 17:56 1539
    A SAX style JSON schema validator.
6c5f2c01 sago007 2017-03-15 17:56 1540
    It uses a \c GenericSchemaDocument to validate SAX events.
6c5f2c01 sago007 2017-03-15 17:56 1541
    It delegates the incoming SAX events to an output handler.
6c5f2c01 sago007 2017-03-15 17:56 1542
    The default output handler does nothing.
6c5f2c01 sago007 2017-03-15 17:56 1543
    It can be reused multiple times by calling \c Reset().
6c5f2c01 sago007 2017-03-15 17:56 1544
6c5f2c01 sago007 2017-03-15 17:56 1545
    \tparam SchemaDocumentType Type of schema document.
6c5f2c01 sago007 2017-03-15 17:56 1546
    \tparam OutputHandler Type of output handler. Default handler does nothing.
6c5f2c01 sago007 2017-03-15 17:56 1547
    \tparam StateAllocator Allocator for storing the internal validation states.
6c5f2c01 sago007 2017-03-15 17:56 1548
*/
6c5f2c01 sago007 2017-03-15 17:56 1549
template <
6c5f2c01 sago007 2017-03-15 17:56 1550
    typename SchemaDocumentType,
6c5f2c01 sago007 2017-03-15 17:56 1551
    typename OutputHandler = BaseReaderHandler<typename SchemaDocumentType::SchemaType::EncodingType>,
6c5f2c01 sago007 2017-03-15 17:56 1552
    typename StateAllocator = CrtAllocator>
6c5f2c01 sago007 2017-03-15 17:56 1553
class GenericSchemaValidator :
6c5f2c01 sago007 2017-03-15 17:56 1554
    public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>, 
6c5f2c01 sago007 2017-03-15 17:56 1555
    public internal::ISchemaValidator
6c5f2c01 sago007 2017-03-15 17:56 1556
{
6c5f2c01 sago007 2017-03-15 17:56 1557
public:
6c5f2c01 sago007 2017-03-15 17:56 1558
    typedef typename SchemaDocumentType::SchemaType SchemaType;
6c5f2c01 sago007 2017-03-15 17:56 1559
    typedef typename SchemaDocumentType::PointerType PointerType;
6c5f2c01 sago007 2017-03-15 17:56 1560
    typedef typename SchemaType::EncodingType EncodingType;
6c5f2c01 sago007 2017-03-15 17:56 1561
    typedef typename EncodingType::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1562
6c5f2c01 sago007 2017-03-15 17:56 1563
    //! Constructor without output handler.
6c5f2c01 sago007 2017-03-15 17:56 1564
    /*!
6c5f2c01 sago007 2017-03-15 17:56 1565
        \param schemaDocument The schema document to conform to.
6c5f2c01 sago007 2017-03-15 17:56 1566
        \param allocator Optional allocator for storing internal validation states.
6c5f2c01 sago007 2017-03-15 17:56 1567
        \param schemaStackCapacity Optional initial capacity of schema path stack.
6c5f2c01 sago007 2017-03-15 17:56 1568
        \param documentStackCapacity Optional initial capacity of document path stack.
6c5f2c01 sago007 2017-03-15 17:56 1569
    */
6c5f2c01 sago007 2017-03-15 17:56 1570
    GenericSchemaValidator(
6c5f2c01 sago007 2017-03-15 17:56 1571
        const SchemaDocumentType& schemaDocument,
6c5f2c01 sago007 2017-03-15 17:56 1572
        StateAllocator* allocator = 0, 
6c5f2c01 sago007 2017-03-15 17:56 1573
        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
6c5f2c01 sago007 2017-03-15 17:56 1574
        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
6c5f2c01 sago007 2017-03-15 17:56 1575
        :
6c5f2c01 sago007 2017-03-15 17:56 1576
        schemaDocument_(&schemaDocument),
6c5f2c01 sago007 2017-03-15 17:56 1577
        root_(schemaDocument.GetRoot()),
6c5f2c01 sago007 2017-03-15 17:56 1578
        outputHandler_(GetNullHandler()),
6c5f2c01 sago007 2017-03-15 17:56 1579
        stateAllocator_(allocator),
6c5f2c01 sago007 2017-03-15 17:56 1580
        ownStateAllocator_(0),
6c5f2c01 sago007 2017-03-15 17:56 1581
        schemaStack_(allocator, schemaStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1582
        documentStack_(allocator, documentStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1583
        valid_(true)
6c5f2c01 sago007 2017-03-15 17:56 1584
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1585
        , depth_(0)
6c5f2c01 sago007 2017-03-15 17:56 1586
#endif
6c5f2c01 sago007 2017-03-15 17:56 1587
    {
6c5f2c01 sago007 2017-03-15 17:56 1588
    }
6c5f2c01 sago007 2017-03-15 17:56 1589
6c5f2c01 sago007 2017-03-15 17:56 1590
    //! Constructor with output handler.
6c5f2c01 sago007 2017-03-15 17:56 1591
    /*!
6c5f2c01 sago007 2017-03-15 17:56 1592
        \param schemaDocument The schema document to conform to.
6c5f2c01 sago007 2017-03-15 17:56 1593
        \param allocator Optional allocator for storing internal validation states.
6c5f2c01 sago007 2017-03-15 17:56 1594
        \param schemaStackCapacity Optional initial capacity of schema path stack.
6c5f2c01 sago007 2017-03-15 17:56 1595
        \param documentStackCapacity Optional initial capacity of document path stack.
6c5f2c01 sago007 2017-03-15 17:56 1596
    */
6c5f2c01 sago007 2017-03-15 17:56 1597
    GenericSchemaValidator(
6c5f2c01 sago007 2017-03-15 17:56 1598
        const SchemaDocumentType& schemaDocument,
6c5f2c01 sago007 2017-03-15 17:56 1599
        OutputHandler& outputHandler,
6c5f2c01 sago007 2017-03-15 17:56 1600
        StateAllocator* allocator = 0, 
6c5f2c01 sago007 2017-03-15 17:56 1601
        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
6c5f2c01 sago007 2017-03-15 17:56 1602
        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
6c5f2c01 sago007 2017-03-15 17:56 1603
        :
6c5f2c01 sago007 2017-03-15 17:56 1604
        schemaDocument_(&schemaDocument),
6c5f2c01 sago007 2017-03-15 17:56 1605
        root_(schemaDocument.GetRoot()),
6c5f2c01 sago007 2017-03-15 17:56 1606
        outputHandler_(outputHandler),
6c5f2c01 sago007 2017-03-15 17:56 1607
        stateAllocator_(allocator),
6c5f2c01 sago007 2017-03-15 17:56 1608
        ownStateAllocator_(0),
6c5f2c01 sago007 2017-03-15 17:56 1609
        schemaStack_(allocator, schemaStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1610
        documentStack_(allocator, documentStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1611
        valid_(true)
6c5f2c01 sago007 2017-03-15 17:56 1612
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1613
        , depth_(0)
6c5f2c01 sago007 2017-03-15 17:56 1614
#endif
6c5f2c01 sago007 2017-03-15 17:56 1615
    {
6c5f2c01 sago007 2017-03-15 17:56 1616
    }
6c5f2c01 sago007 2017-03-15 17:56 1617
6c5f2c01 sago007 2017-03-15 17:56 1618
    //! Destructor.
6c5f2c01 sago007 2017-03-15 17:56 1619
    ~GenericSchemaValidator() {
6c5f2c01 sago007 2017-03-15 17:56 1620
        Reset();
6c5f2c01 sago007 2017-03-15 17:56 1621
        CEREAL_RAPIDJSON_DELETE(ownStateAllocator_);
6c5f2c01 sago007 2017-03-15 17:56 1622
    }
6c5f2c01 sago007 2017-03-15 17:56 1623
6c5f2c01 sago007 2017-03-15 17:56 1624
    //! Reset the internal states.
6c5f2c01 sago007 2017-03-15 17:56 1625
    void Reset() {
6c5f2c01 sago007 2017-03-15 17:56 1626
        while (!schemaStack_.Empty())
6c5f2c01 sago007 2017-03-15 17:56 1627
            PopSchema();
6c5f2c01 sago007 2017-03-15 17:56 1628
        documentStack_.Clear();
6c5f2c01 sago007 2017-03-15 17:56 1629
        valid_ = true;
6c5f2c01 sago007 2017-03-15 17:56 1630
    }
6c5f2c01 sago007 2017-03-15 17:56 1631
6c5f2c01 sago007 2017-03-15 17:56 1632
    //! Checks whether the current state is valid.
6c5f2c01 sago007 2017-03-15 17:56 1633
    // Implementation of ISchemaValidator
6c5f2c01 sago007 2017-03-15 17:56 1634
    virtual bool IsValid() const { return valid_; }
6c5f2c01 sago007 2017-03-15 17:56 1635
6c5f2c01 sago007 2017-03-15 17:56 1636
    //! Gets the JSON pointer pointed to the invalid schema.
6c5f2c01 sago007 2017-03-15 17:56 1637
    PointerType GetInvalidSchemaPointer() const {
6c5f2c01 sago007 2017-03-15 17:56 1638
        return schemaStack_.Empty() ? PointerType() : schemaDocument_->GetPointer(&CurrentSchema());
6c5f2c01 sago007 2017-03-15 17:56 1639
    }
6c5f2c01 sago007 2017-03-15 17:56 1640
6c5f2c01 sago007 2017-03-15 17:56 1641
    //! Gets the keyword of invalid schema.
6c5f2c01 sago007 2017-03-15 17:56 1642
    const Ch* GetInvalidSchemaKeyword() const {
6c5f2c01 sago007 2017-03-15 17:56 1643
        return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
6c5f2c01 sago007 2017-03-15 17:56 1644
    }
6c5f2c01 sago007 2017-03-15 17:56 1645
6c5f2c01 sago007 2017-03-15 17:56 1646
    //! Gets the JSON pointer pointed to the invalid value.
6c5f2c01 sago007 2017-03-15 17:56 1647
    PointerType GetInvalidDocumentPointer() const {
6c5f2c01 sago007 2017-03-15 17:56 1648
        return documentStack_.Empty() ? PointerType() : PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
6c5f2c01 sago007 2017-03-15 17:56 1649
    }
6c5f2c01 sago007 2017-03-15 17:56 1650
6c5f2c01 sago007 2017-03-15 17:56 1651
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1652
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
6c5f2c01 sago007 2017-03-15 17:56 1653
CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN\
6c5f2c01 sago007 2017-03-15 17:56 1654
    *documentStack_.template Push<Ch>() = '\0';\
6c5f2c01 sago007 2017-03-15 17:56 1655
    documentStack_.template Pop<Ch>(1);\
6c5f2c01 sago007 2017-03-15 17:56 1656
    internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
6c5f2c01 sago007 2017-03-15 17:56 1657
CEREAL_RAPIDJSON_MULTILINEMACRO_END
6c5f2c01 sago007 2017-03-15 17:56 1658
#else
6c5f2c01 sago007 2017-03-15 17:56 1659
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
6c5f2c01 sago007 2017-03-15 17:56 1660
#endif
6c5f2c01 sago007 2017-03-15 17:56 1661
6c5f2c01 sago007 2017-03-15 17:56 1662
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
6c5f2c01 sago007 2017-03-15 17:56 1663
    if (!valid_) return false; \
6c5f2c01 sago007 2017-03-15 17:56 1664
    if (!BeginValue() || !CurrentSchema().method arg1) {\
6c5f2c01 sago007 2017-03-15 17:56 1665
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
6c5f2c01 sago007 2017-03-15 17:56 1666
        return valid_ = false;\
6c5f2c01 sago007 2017-03-15 17:56 1667
    }
6c5f2c01 sago007 2017-03-15 17:56 1668
6c5f2c01 sago007 2017-03-15 17:56 1669
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
6c5f2c01 sago007 2017-03-15 17:56 1670
    for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
6c5f2c01 sago007 2017-03-15 17:56 1671
        if (context->hasher)\
6c5f2c01 sago007 2017-03-15 17:56 1672
            static_cast<HasherType*>(context->hasher)->method arg2;\
6c5f2c01 sago007 2017-03-15 17:56 1673
        if (context->validators)\
6c5f2c01 sago007 2017-03-15 17:56 1674
            for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
6c5f2c01 sago007 2017-03-15 17:56 1675
                static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
6c5f2c01 sago007 2017-03-15 17:56 1676
        if (context->patternPropertiesValidators)\
6c5f2c01 sago007 2017-03-15 17:56 1677
            for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
6c5f2c01 sago007 2017-03-15 17:56 1678
                static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
6c5f2c01 sago007 2017-03-15 17:56 1679
    }
6c5f2c01 sago007 2017-03-15 17:56 1680
6c5f2c01 sago007 2017-03-15 17:56 1681
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
6c5f2c01 sago007 2017-03-15 17:56 1682
    return valid_ = EndValue() && outputHandler_.method arg2
6c5f2c01 sago007 2017-03-15 17:56 1683
6c5f2c01 sago007 2017-03-15 17:56 1684
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
6c5f2c01 sago007 2017-03-15 17:56 1685
    CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_   (method, arg1);\
6c5f2c01 sago007 2017-03-15 17:56 1686
    CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
6c5f2c01 sago007 2017-03-15 17:56 1687
    CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_     (method, arg2)
6c5f2c01 sago007 2017-03-15 17:56 1688
6c5f2c01 sago007 2017-03-15 17:56 1689
    bool Null()             { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null,   (CurrentContext()   ), ( )); }
6c5f2c01 sago007 2017-03-15 17:56 1690
    bool Bool(bool b)       { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool,   (CurrentContext(), b), (b)); }
6c5f2c01 sago007 2017-03-15 17:56 1691
    bool Int(int i)         { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int,    (CurrentContext(), i), (i)); }
6c5f2c01 sago007 2017-03-15 17:56 1692
    bool Uint(unsigned u)   { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint,   (CurrentContext(), u), (u)); }
6c5f2c01 sago007 2017-03-15 17:56 1693
    bool Int64(int64_t i)   { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64,  (CurrentContext(), i), (i)); }
6c5f2c01 sago007 2017-03-15 17:56 1694
    bool Uint64(uint64_t u) { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
6c5f2c01 sago007 2017-03-15 17:56 1695
    bool Double(double d)   { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
6c5f2c01 sago007 2017-03-15 17:56 1696
    bool RawNumber(const Ch* str, SizeType length, bool copy)
6c5f2c01 sago007 2017-03-15 17:56 1697
                                    { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
6c5f2c01 sago007 2017-03-15 17:56 1698
    bool String(const Ch* str, SizeType length, bool copy)
6c5f2c01 sago007 2017-03-15 17:56 1699
                                    { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
6c5f2c01 sago007 2017-03-15 17:56 1700
6c5f2c01 sago007 2017-03-15 17:56 1701
    bool StartObject() {
6c5f2c01 sago007 2017-03-15 17:56 1702
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
6c5f2c01 sago007 2017-03-15 17:56 1703
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartObject, ());
6c5f2c01 sago007 2017-03-15 17:56 1704
        return valid_ = outputHandler_.StartObject();
6c5f2c01 sago007 2017-03-15 17:56 1705
    }
6c5f2c01 sago007 2017-03-15 17:56 1706
    
6c5f2c01 sago007 2017-03-15 17:56 1707
    bool Key(const Ch* str, SizeType len, bool copy) {
6c5f2c01 sago007 2017-03-15 17:56 1708
        if (!valid_) return false;
6c5f2c01 sago007 2017-03-15 17:56 1709
        AppendToken(str, len);
6c5f2c01 sago007 2017-03-15 17:56 1710
        if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
6c5f2c01 sago007 2017-03-15 17:56 1711
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
6c5f2c01 sago007 2017-03-15 17:56 1712
        return valid_ = outputHandler_.Key(str, len, copy);
6c5f2c01 sago007 2017-03-15 17:56 1713
    }
6c5f2c01 sago007 2017-03-15 17:56 1714
    
6c5f2c01 sago007 2017-03-15 17:56 1715
    bool EndObject(SizeType memberCount) { 
6c5f2c01 sago007 2017-03-15 17:56 1716
        if (!valid_) return false;
6c5f2c01 sago007 2017-03-15 17:56 1717
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndObject, (memberCount));
6c5f2c01 sago007 2017-03-15 17:56 1718
        if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
6c5f2c01 sago007 2017-03-15 17:56 1719
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
6c5f2c01 sago007 2017-03-15 17:56 1720
    }
6c5f2c01 sago007 2017-03-15 17:56 1721
6c5f2c01 sago007 2017-03-15 17:56 1722
    bool StartArray() {
6c5f2c01 sago007 2017-03-15 17:56 1723
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
6c5f2c01 sago007 2017-03-15 17:56 1724
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(StartArray, ());
6c5f2c01 sago007 2017-03-15 17:56 1725
        return valid_ = outputHandler_.StartArray();
6c5f2c01 sago007 2017-03-15 17:56 1726
    }
6c5f2c01 sago007 2017-03-15 17:56 1727
    
6c5f2c01 sago007 2017-03-15 17:56 1728
    bool EndArray(SizeType elementCount) {
6c5f2c01 sago007 2017-03-15 17:56 1729
        if (!valid_) return false;
6c5f2c01 sago007 2017-03-15 17:56 1730
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(EndArray, (elementCount));
6c5f2c01 sago007 2017-03-15 17:56 1731
        if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
6c5f2c01 sago007 2017-03-15 17:56 1732
        CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
6c5f2c01 sago007 2017-03-15 17:56 1733
    }
6c5f2c01 sago007 2017-03-15 17:56 1734
6c5f2c01 sago007 2017-03-15 17:56 1735
#undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
6c5f2c01 sago007 2017-03-15 17:56 1736
#undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_
6c5f2c01 sago007 2017-03-15 17:56 1737
#undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
6c5f2c01 sago007 2017-03-15 17:56 1738
#undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_
6c5f2c01 sago007 2017-03-15 17:56 1739
6c5f2c01 sago007 2017-03-15 17:56 1740
    // Implementation of ISchemaStateFactory<SchemaType>
6c5f2c01 sago007 2017-03-15 17:56 1741
    virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
6c5f2c01 sago007 2017-03-15 17:56 1742
        return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root,
6c5f2c01 sago007 2017-03-15 17:56 1743
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1744
        depth_ + 1,
6c5f2c01 sago007 2017-03-15 17:56 1745
#endif
6c5f2c01 sago007 2017-03-15 17:56 1746
        &GetStateAllocator());
6c5f2c01 sago007 2017-03-15 17:56 1747
    }
6c5f2c01 sago007 2017-03-15 17:56 1748
6c5f2c01 sago007 2017-03-15 17:56 1749
    virtual void DestroySchemaValidator(ISchemaValidator* validator) {
6c5f2c01 sago007 2017-03-15 17:56 1750
        GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
6c5f2c01 sago007 2017-03-15 17:56 1751
        v->~GenericSchemaValidator();
6c5f2c01 sago007 2017-03-15 17:56 1752
        StateAllocator::Free(v);
6c5f2c01 sago007 2017-03-15 17:56 1753
    }
6c5f2c01 sago007 2017-03-15 17:56 1754
6c5f2c01 sago007 2017-03-15 17:56 1755
    virtual void* CreateHasher() {
6c5f2c01 sago007 2017-03-15 17:56 1756
        return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
6c5f2c01 sago007 2017-03-15 17:56 1757
    }
6c5f2c01 sago007 2017-03-15 17:56 1758
6c5f2c01 sago007 2017-03-15 17:56 1759
    virtual uint64_t GetHashCode(void* hasher) {
6c5f2c01 sago007 2017-03-15 17:56 1760
        return static_cast<HasherType*>(hasher)->GetHashCode();
6c5f2c01 sago007 2017-03-15 17:56 1761
    }
6c5f2c01 sago007 2017-03-15 17:56 1762
6c5f2c01 sago007 2017-03-15 17:56 1763
    virtual void DestroryHasher(void* hasher) {
6c5f2c01 sago007 2017-03-15 17:56 1764
        HasherType* h = static_cast<HasherType*>(hasher);
6c5f2c01 sago007 2017-03-15 17:56 1765
        h->~HasherType();
6c5f2c01 sago007 2017-03-15 17:56 1766
        StateAllocator::Free(h);
6c5f2c01 sago007 2017-03-15 17:56 1767
    }
6c5f2c01 sago007 2017-03-15 17:56 1768
6c5f2c01 sago007 2017-03-15 17:56 1769
    virtual void* MallocState(size_t size) {
6c5f2c01 sago007 2017-03-15 17:56 1770
        return GetStateAllocator().Malloc(size);
6c5f2c01 sago007 2017-03-15 17:56 1771
    }
6c5f2c01 sago007 2017-03-15 17:56 1772
6c5f2c01 sago007 2017-03-15 17:56 1773
    virtual void FreeState(void* p) {
6c5f2c01 sago007 2017-03-15 17:56 1774
        return StateAllocator::Free(p);
6c5f2c01 sago007 2017-03-15 17:56 1775
    }
6c5f2c01 sago007 2017-03-15 17:56 1776
6c5f2c01 sago007 2017-03-15 17:56 1777
private:
6c5f2c01 sago007 2017-03-15 17:56 1778
    typedef typename SchemaType::Context Context;
6c5f2c01 sago007 2017-03-15 17:56 1779
    typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
6c5f2c01 sago007 2017-03-15 17:56 1780
    typedef internal::Hasher<EncodingType, StateAllocator> HasherType;
6c5f2c01 sago007 2017-03-15 17:56 1781
6c5f2c01 sago007 2017-03-15 17:56 1782
    GenericSchemaValidator( 
6c5f2c01 sago007 2017-03-15 17:56 1783
        const SchemaDocumentType& schemaDocument,
6c5f2c01 sago007 2017-03-15 17:56 1784
        const SchemaType& root,
6c5f2c01 sago007 2017-03-15 17:56 1785
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1786
        unsigned depth,
6c5f2c01 sago007 2017-03-15 17:56 1787
#endif
6c5f2c01 sago007 2017-03-15 17:56 1788
        StateAllocator* allocator = 0,
6c5f2c01 sago007 2017-03-15 17:56 1789
        size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
6c5f2c01 sago007 2017-03-15 17:56 1790
        size_t documentStackCapacity = kDefaultDocumentStackCapacity)
6c5f2c01 sago007 2017-03-15 17:56 1791
        :
6c5f2c01 sago007 2017-03-15 17:56 1792
        schemaDocument_(&schemaDocument),
6c5f2c01 sago007 2017-03-15 17:56 1793
        root_(root),
6c5f2c01 sago007 2017-03-15 17:56 1794
        outputHandler_(GetNullHandler()),
6c5f2c01 sago007 2017-03-15 17:56 1795
        stateAllocator_(allocator),
6c5f2c01 sago007 2017-03-15 17:56 1796
        ownStateAllocator_(0),
6c5f2c01 sago007 2017-03-15 17:56 1797
        schemaStack_(allocator, schemaStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1798
        documentStack_(allocator, documentStackCapacity),
6c5f2c01 sago007 2017-03-15 17:56 1799
        valid_(true)
6c5f2c01 sago007 2017-03-15 17:56 1800
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1801
        , depth_(depth)
6c5f2c01 sago007 2017-03-15 17:56 1802
#endif
6c5f2c01 sago007 2017-03-15 17:56 1803
    {
6c5f2c01 sago007 2017-03-15 17:56 1804
    }
6c5f2c01 sago007 2017-03-15 17:56 1805
6c5f2c01 sago007 2017-03-15 17:56 1806
    StateAllocator& GetStateAllocator() {
6c5f2c01 sago007 2017-03-15 17:56 1807
        if (!stateAllocator_)
6c5f2c01 sago007 2017-03-15 17:56 1808
            stateAllocator_ = ownStateAllocator_ = CEREAL_RAPIDJSON_NEW(StateAllocator());
6c5f2c01 sago007 2017-03-15 17:56 1809
        return *stateAllocator_;
6c5f2c01 sago007 2017-03-15 17:56 1810
    }
6c5f2c01 sago007 2017-03-15 17:56 1811
6c5f2c01 sago007 2017-03-15 17:56 1812
    bool BeginValue() {
6c5f2c01 sago007 2017-03-15 17:56 1813
        if (schemaStack_.Empty())
6c5f2c01 sago007 2017-03-15 17:56 1814
            PushSchema(root_);
6c5f2c01 sago007 2017-03-15 17:56 1815
        else {
6c5f2c01 sago007 2017-03-15 17:56 1816
            if (CurrentContext().inArray)
6c5f2c01 sago007 2017-03-15 17:56 1817
                internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
6c5f2c01 sago007 2017-03-15 17:56 1818
6c5f2c01 sago007 2017-03-15 17:56 1819
            if (!CurrentSchema().BeginValue(CurrentContext()))
6c5f2c01 sago007 2017-03-15 17:56 1820
                return false;
6c5f2c01 sago007 2017-03-15 17:56 1821
6c5f2c01 sago007 2017-03-15 17:56 1822
            SizeType count = CurrentContext().patternPropertiesSchemaCount;
6c5f2c01 sago007 2017-03-15 17:56 1823
            const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
6c5f2c01 sago007 2017-03-15 17:56 1824
            typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
6c5f2c01 sago007 2017-03-15 17:56 1825
            bool valueUniqueness = CurrentContext().valueUniqueness;
6c5f2c01 sago007 2017-03-15 17:56 1826
            if (CurrentContext().valueSchema)
6c5f2c01 sago007 2017-03-15 17:56 1827
                PushSchema(*CurrentContext().valueSchema);
6c5f2c01 sago007 2017-03-15 17:56 1828
6c5f2c01 sago007 2017-03-15 17:56 1829
            if (count > 0) {
6c5f2c01 sago007 2017-03-15 17:56 1830
                CurrentContext().objectPatternValidatorType = patternValidatorType;
6c5f2c01 sago007 2017-03-15 17:56 1831
                ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
6c5f2c01 sago007 2017-03-15 17:56 1832
                SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
6c5f2c01 sago007 2017-03-15 17:56 1833
                va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
6c5f2c01 sago007 2017-03-15 17:56 1834
                for (SizeType i = 0; i < count; i++)
6c5f2c01 sago007 2017-03-15 17:56 1835
                    va[validatorCount++] = CreateSchemaValidator(*sa[i]);
6c5f2c01 sago007 2017-03-15 17:56 1836
            }
6c5f2c01 sago007 2017-03-15 17:56 1837
6c5f2c01 sago007 2017-03-15 17:56 1838
            CurrentContext().arrayUniqueness = valueUniqueness;
6c5f2c01 sago007 2017-03-15 17:56 1839
        }
6c5f2c01 sago007 2017-03-15 17:56 1840
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1841
    }
6c5f2c01 sago007 2017-03-15 17:56 1842
6c5f2c01 sago007 2017-03-15 17:56 1843
    bool EndValue() {
6c5f2c01 sago007 2017-03-15 17:56 1844
        if (!CurrentSchema().EndValue(CurrentContext()))
6c5f2c01 sago007 2017-03-15 17:56 1845
            return false;
6c5f2c01 sago007 2017-03-15 17:56 1846
6c5f2c01 sago007 2017-03-15 17:56 1847
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1848
        GenericStringBuffer<EncodingType> sb;
6c5f2c01 sago007 2017-03-15 17:56 1849
        schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
6c5f2c01 sago007 2017-03-15 17:56 1850
6c5f2c01 sago007 2017-03-15 17:56 1851
        *documentStack_.template Push<Ch>() = '\0';
6c5f2c01 sago007 2017-03-15 17:56 1852
        documentStack_.template Pop<Ch>(1);
6c5f2c01 sago007 2017-03-15 17:56 1853
        internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
6c5f2c01 sago007 2017-03-15 17:56 1854
#endif
6c5f2c01 sago007 2017-03-15 17:56 1855
6c5f2c01 sago007 2017-03-15 17:56 1856
        uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
6c5f2c01 sago007 2017-03-15 17:56 1857
        
6c5f2c01 sago007 2017-03-15 17:56 1858
        PopSchema();
6c5f2c01 sago007 2017-03-15 17:56 1859
6c5f2c01 sago007 2017-03-15 17:56 1860
        if (!schemaStack_.Empty()) {
6c5f2c01 sago007 2017-03-15 17:56 1861
            Context& context = CurrentContext();
6c5f2c01 sago007 2017-03-15 17:56 1862
            if (context.valueUniqueness) {
6c5f2c01 sago007 2017-03-15 17:56 1863
                HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
6c5f2c01 sago007 2017-03-15 17:56 1864
                if (!a)
6c5f2c01 sago007 2017-03-15 17:56 1865
                    CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
6c5f2c01 sago007 2017-03-15 17:56 1866
                for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
6c5f2c01 sago007 2017-03-15 17:56 1867
                    if (itr->GetUint64() == h)
6c5f2c01 sago007 2017-03-15 17:56 1868
                        CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
6c5f2c01 sago007 2017-03-15 17:56 1869
                a->PushBack(h, GetStateAllocator());
6c5f2c01 sago007 2017-03-15 17:56 1870
            }
6c5f2c01 sago007 2017-03-15 17:56 1871
        }
6c5f2c01 sago007 2017-03-15 17:56 1872
6c5f2c01 sago007 2017-03-15 17:56 1873
        // Remove the last token of document pointer
6c5f2c01 sago007 2017-03-15 17:56 1874
        while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
6c5f2c01 sago007 2017-03-15 17:56 1875
            ;
6c5f2c01 sago007 2017-03-15 17:56 1876
6c5f2c01 sago007 2017-03-15 17:56 1877
        return true;
6c5f2c01 sago007 2017-03-15 17:56 1878
    }
6c5f2c01 sago007 2017-03-15 17:56 1879
6c5f2c01 sago007 2017-03-15 17:56 1880
    void AppendToken(const Ch* str, SizeType len) {
6c5f2c01 sago007 2017-03-15 17:56 1881
        documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
6c5f2c01 sago007 2017-03-15 17:56 1882
        *documentStack_.template PushUnsafe<Ch>() = '/';
6c5f2c01 sago007 2017-03-15 17:56 1883
        for (SizeType i = 0; i < len; i++) {
6c5f2c01 sago007 2017-03-15 17:56 1884
            if (str[i] == '~') {
6c5f2c01 sago007 2017-03-15 17:56 1885
                *documentStack_.template PushUnsafe<Ch>() = '~';
6c5f2c01 sago007 2017-03-15 17:56 1886
                *documentStack_.template PushUnsafe<Ch>() = '0';
6c5f2c01 sago007 2017-03-15 17:56 1887
            }
6c5f2c01 sago007 2017-03-15 17:56 1888
            else if (str[i] == '/') {
6c5f2c01 sago007 2017-03-15 17:56 1889
                *documentStack_.template PushUnsafe<Ch>() = '~';
6c5f2c01 sago007 2017-03-15 17:56 1890
                *documentStack_.template PushUnsafe<Ch>() = '1';
6c5f2c01 sago007 2017-03-15 17:56 1891
            }
6c5f2c01 sago007 2017-03-15 17:56 1892
            else
6c5f2c01 sago007 2017-03-15 17:56 1893
                *documentStack_.template PushUnsafe<Ch>() = str[i];
6c5f2c01 sago007 2017-03-15 17:56 1894
        }
6c5f2c01 sago007 2017-03-15 17:56 1895
    }
6c5f2c01 sago007 2017-03-15 17:56 1896
6c5f2c01 sago007 2017-03-15 17:56 1897
    CEREAL_RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, &schema); }
6c5f2c01 sago007 2017-03-15 17:56 1898
    
6c5f2c01 sago007 2017-03-15 17:56 1899
    CEREAL_RAPIDJSON_FORCEINLINE void PopSchema() {
6c5f2c01 sago007 2017-03-15 17:56 1900
        Context* c = schemaStack_.template Pop<Context>(1);
6c5f2c01 sago007 2017-03-15 17:56 1901
        if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
6c5f2c01 sago007 2017-03-15 17:56 1902
            a->~HashCodeArray();
6c5f2c01 sago007 2017-03-15 17:56 1903
            StateAllocator::Free(a);
6c5f2c01 sago007 2017-03-15 17:56 1904
        }
6c5f2c01 sago007 2017-03-15 17:56 1905
        c->~Context();
6c5f2c01 sago007 2017-03-15 17:56 1906
    }
6c5f2c01 sago007 2017-03-15 17:56 1907
6c5f2c01 sago007 2017-03-15 17:56 1908
    const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
6c5f2c01 sago007 2017-03-15 17:56 1909
    Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
6c5f2c01 sago007 2017-03-15 17:56 1910
    const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
6c5f2c01 sago007 2017-03-15 17:56 1911
6c5f2c01 sago007 2017-03-15 17:56 1912
    static OutputHandler& GetNullHandler() {
6c5f2c01 sago007 2017-03-15 17:56 1913
        static OutputHandler nullHandler;
6c5f2c01 sago007 2017-03-15 17:56 1914
        return nullHandler;
6c5f2c01 sago007 2017-03-15 17:56 1915
    }
6c5f2c01 sago007 2017-03-15 17:56 1916
6c5f2c01 sago007 2017-03-15 17:56 1917
    static const size_t kDefaultSchemaStackCapacity = 1024;
6c5f2c01 sago007 2017-03-15 17:56 1918
    static const size_t kDefaultDocumentStackCapacity = 256;
6c5f2c01 sago007 2017-03-15 17:56 1919
    const SchemaDocumentType* schemaDocument_;
6c5f2c01 sago007 2017-03-15 17:56 1920
    const SchemaType& root_;
6c5f2c01 sago007 2017-03-15 17:56 1921
    OutputHandler& outputHandler_;
6c5f2c01 sago007 2017-03-15 17:56 1922
    StateAllocator* stateAllocator_;
6c5f2c01 sago007 2017-03-15 17:56 1923
    StateAllocator* ownStateAllocator_;
6c5f2c01 sago007 2017-03-15 17:56 1924
    internal::Stack<StateAllocator> schemaStack_;    //!< stack to store the current path of schema (BaseSchemaType *)
6c5f2c01 sago007 2017-03-15 17:56 1925
    internal::Stack<StateAllocator> documentStack_;  //!< stack to store the current path of validating document (Ch)
6c5f2c01 sago007 2017-03-15 17:56 1926
    bool valid_;
6c5f2c01 sago007 2017-03-15 17:56 1927
#if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
6c5f2c01 sago007 2017-03-15 17:56 1928
    unsigned depth_;
6c5f2c01 sago007 2017-03-15 17:56 1929
#endif
6c5f2c01 sago007 2017-03-15 17:56 1930
};
6c5f2c01 sago007 2017-03-15 17:56 1931
6c5f2c01 sago007 2017-03-15 17:56 1932
typedef GenericSchemaValidator<SchemaDocument> SchemaValidator;
6c5f2c01 sago007 2017-03-15 17:56 1933
6c5f2c01 sago007 2017-03-15 17:56 1934
///////////////////////////////////////////////////////////////////////////////
6c5f2c01 sago007 2017-03-15 17:56 1935
// SchemaValidatingReader
6c5f2c01 sago007 2017-03-15 17:56 1936
6c5f2c01 sago007 2017-03-15 17:56 1937
//! A helper class for parsing with validation.
6c5f2c01 sago007 2017-03-15 17:56 1938
/*!
6c5f2c01 sago007 2017-03-15 17:56 1939
    This helper class is a functor, designed as a parameter of \ref GenericDocument::Populate().
6c5f2c01 sago007 2017-03-15 17:56 1940
6c5f2c01 sago007 2017-03-15 17:56 1941
    \tparam parseFlags Combination of \ref ParseFlag.
6c5f2c01 sago007 2017-03-15 17:56 1942
    \tparam InputStream Type of input stream, implementing Stream concept.
6c5f2c01 sago007 2017-03-15 17:56 1943
    \tparam SourceEncoding Encoding of the input stream.
6c5f2c01 sago007 2017-03-15 17:56 1944
    \tparam SchemaDocumentType Type of schema document.
6c5f2c01 sago007 2017-03-15 17:56 1945
    \tparam StackAllocator Allocator type for stack.
6c5f2c01 sago007 2017-03-15 17:56 1946
*/
6c5f2c01 sago007 2017-03-15 17:56 1947
template <
6c5f2c01 sago007 2017-03-15 17:56 1948
    unsigned parseFlags,
6c5f2c01 sago007 2017-03-15 17:56 1949
    typename InputStream,
6c5f2c01 sago007 2017-03-15 17:56 1950
    typename SourceEncoding,
6c5f2c01 sago007 2017-03-15 17:56 1951
    typename SchemaDocumentType = SchemaDocument,
6c5f2c01 sago007 2017-03-15 17:56 1952
    typename StackAllocator = CrtAllocator>
6c5f2c01 sago007 2017-03-15 17:56 1953
class SchemaValidatingReader {
6c5f2c01 sago007 2017-03-15 17:56 1954
public:
6c5f2c01 sago007 2017-03-15 17:56 1955
    typedef typename SchemaDocumentType::PointerType PointerType;
6c5f2c01 sago007 2017-03-15 17:56 1956
    typedef typename InputStream::Ch Ch;
6c5f2c01 sago007 2017-03-15 17:56 1957
6c5f2c01 sago007 2017-03-15 17:56 1958
    //! Constructor
6c5f2c01 sago007 2017-03-15 17:56 1959
    /*!
6c5f2c01 sago007 2017-03-15 17:56 1960
        \param is Input stream.
6c5f2c01 sago007 2017-03-15 17:56 1961
        \param sd Schema document.
6c5f2c01 sago007 2017-03-15 17:56 1962
    */
6c5f2c01 sago007 2017-03-15 17:56 1963
    SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), isValid_(true) {}
6c5f2c01 sago007 2017-03-15 17:56 1964
6c5f2c01 sago007 2017-03-15 17:56 1965
    template <typename Handler>
6c5f2c01 sago007 2017-03-15 17:56 1966
    bool operator()(Handler& handler) {
6c5f2c01 sago007 2017-03-15 17:56 1967
        GenericReader<SourceEncoding, typename SchemaDocumentType::EncodingType, StackAllocator> reader;
6c5f2c01 sago007 2017-03-15 17:56 1968
        GenericSchemaValidator<SchemaDocumentType, Handler> validator(sd_, handler);
6c5f2c01 sago007 2017-03-15 17:56 1969
        parseResult_ = reader.template Parse<parseFlags>(is_, validator);
6c5f2c01 sago007 2017-03-15 17:56 1970
6c5f2c01 sago007 2017-03-15 17:56 1971
        isValid_ = validator.IsValid();
6c5f2c01 sago007 2017-03-15 17:56 1972
        if (isValid_) {
6c5f2c01 sago007 2017-03-15 17:56 1973
            invalidSchemaPointer_ = PointerType();
6c5f2c01 sago007 2017-03-15 17:56 1974
            invalidSchemaKeyword_ = 0;
6c5f2c01 sago007 2017-03-15 17:56 1975
            invalidDocumentPointer_ = PointerType();
6c5f2c01 sago007 2017-03-15 17:56 1976
        }
6c5f2c01 sago007 2017-03-15 17:56 1977
        else {
6c5f2c01 sago007 2017-03-15 17:56 1978
            invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
6c5f2c01 sago007 2017-03-15 17:56 1979
            invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
6c5f2c01 sago007 2017-03-15 17:56 1980
            invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
6c5f2c01 sago007 2017-03-15 17:56 1981
        }
6c5f2c01 sago007 2017-03-15 17:56 1982
6c5f2c01 sago007 2017-03-15 17:56 1983
        return parseResult_;
6c5f2c01 sago007 2017-03-15 17:56 1984
    }
6c5f2c01 sago007 2017-03-15 17:56 1985
6c5f2c01 sago007 2017-03-15 17:56 1986
    const ParseResult& GetParseResult() const { return parseResult_; }
6c5f2c01 sago007 2017-03-15 17:56 1987
    bool IsValid() const { return isValid_; }
6c5f2c01 sago007 2017-03-15 17:56 1988
    const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
6c5f2c01 sago007 2017-03-15 17:56 1989
    const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
6c5f2c01 sago007 2017-03-15 17:56 1990
    const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
6c5f2c01 sago007 2017-03-15 17:56 1991
6c5f2c01 sago007 2017-03-15 17:56 1992
private:
6c5f2c01 sago007 2017-03-15 17:56 1993
    InputStream& is_;
6c5f2c01 sago007 2017-03-15 17:56 1994
    const SchemaDocumentType& sd_;
6c5f2c01 sago007 2017-03-15 17:56 1995
6c5f2c01 sago007 2017-03-15 17:56 1996
    ParseResult parseResult_;
6c5f2c01 sago007 2017-03-15 17:56 1997
    PointerType invalidSchemaPointer_;
6c5f2c01 sago007 2017-03-15 17:56 1998
    const Ch* invalidSchemaKeyword_;
6c5f2c01 sago007 2017-03-15 17:56 1999
    PointerType invalidDocumentPointer_;
6c5f2c01 sago007 2017-03-15 17:56 2000
    bool isValid_;
6c5f2c01 sago007 2017-03-15 17:56 2001
};
6c5f2c01 sago007 2017-03-15 17:56 2002
6c5f2c01 sago007 2017-03-15 17:56 2003
CEREAL_RAPIDJSON_NAMESPACE_END
6c5f2c01 sago007 2017-03-15 17:56 2004
CEREAL_RAPIDJSON_DIAG_POP
6c5f2c01 sago007 2017-03-15 17:56 2005
6c5f2c01 sago007 2017-03-15 17:56 2006
#endif // CEREAL_RAPIDJSON_SCHEMA_H_
1970-01-01 00:00 2007