Elaztek Developer Hub
Blamite Game Engine - blam!  00398.09.22.23.2015.blamite
The core library for the Blamite Game Engine.
schema.h
Go to the documentation of this file.
1 // Tencent is pleased to support the open source community by making RapidJSON available->
2 //
3 // Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip-> All rights reserved->
4 //
5 // Licensed under the MIT License (the "License"); you may not use this file except
6 // in compliance with the License-> You may obtain a copy of the License at
7 //
8 // http://opensource->org/licenses/MIT
9 //
10 // Unless required by applicable law or agreed to in writing, software distributed
11 // under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12 // CONDITIONS OF ANY KIND, either express or implied-> See the License for the
13 // specific language governing permissions and limitations under the License->
14 
15 #ifndef RAPIDJSON_SCHEMA_H_
16 #define RAPIDJSON_SCHEMA_H_
17 
18 #include "document.h"
19 #include "pointer.h"
20 #include "stringbuffer.h"
21 #include "error/en.h"
22 #include "uri.h"
23 #include <cmath> // abs, floor
24 
25 #if !defined(RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
26 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
27 #else
28 #define RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
29 #endif
30 
31 #if !RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
32 #define RAPIDJSON_SCHEMA_USE_STDREGEX 1
33 #else
34 #define RAPIDJSON_SCHEMA_USE_STDREGEX 0
35 #endif
36 
37 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
38 #include "internal/regex.h"
39 #elif RAPIDJSON_SCHEMA_USE_STDREGEX
40 #include <regex>
41 #endif
42 
43 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX || RAPIDJSON_SCHEMA_USE_STDREGEX
44 #define RAPIDJSON_SCHEMA_HAS_REGEX 1
45 #else
46 #define RAPIDJSON_SCHEMA_HAS_REGEX 0
47 #endif
48 
49 #ifndef RAPIDJSON_SCHEMA_VERBOSE
50 #define RAPIDJSON_SCHEMA_VERBOSE 0
51 #endif
52 
53 #if RAPIDJSON_SCHEMA_VERBOSE
54 #include "stringbuffer.h"
55 #endif
56 
57 RAPIDJSON_DIAG_PUSH
58 
59 #if defined(__GNUC__)
60 RAPIDJSON_DIAG_OFF(effc++)
61 #endif
62 
63 #ifdef __clang__
64 RAPIDJSON_DIAG_OFF(weak-vtables)
65 RAPIDJSON_DIAG_OFF(exit-time-destructors)
66 RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
67 RAPIDJSON_DIAG_OFF(variadic-macros)
68 #elif defined(_MSC_VER)
69 RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
70 #endif
71 
73 
75 // Verbose Utilities
76 
77 #if RAPIDJSON_SCHEMA_VERBOSE
78 
79 namespace internal {
80 
81 inline void PrintInvalidKeyword(const char* keyword) {
82  printf("Fail keyword: %s\n", keyword);
83 }
84 
85 inline void PrintInvalidKeyword(const wchar_t* keyword) {
86  wprintf(L"Fail keyword: %ls\n", keyword);
87 }
88 
89 inline void PrintInvalidDocument(const char* document) {
90  printf("Fail document: %s\n\n", document);
91 }
92 
93 inline void PrintInvalidDocument(const wchar_t* document) {
94  wprintf(L"Fail document: %ls\n\n", document);
95 }
96 
97 inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
98  printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
99 }
100 
101 inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
102  wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
103 }
104 
105 } // namespace internal
106 
107 #endif // RAPIDJSON_SCHEMA_VERBOSE
108 
110 // RAPIDJSON_INVALID_KEYWORD_RETURN
111 
112 #if RAPIDJSON_SCHEMA_VERBOSE
113 #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
114 #else
115 #define RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
116 #endif
117 
118 #define RAPIDJSON_INVALID_KEYWORD_RETURN(code)\
119 RAPIDJSON_MULTILINEMACRO_BEGIN\
120  context.invalidCode = code;\
121  context.invalidKeyword = SchemaType::GetValidateErrorKeyword(code).GetString();\
122  RAPIDJSON_INVALID_KEYWORD_VERBOSE(context.invalidKeyword);\
123  return false;\
124 RAPIDJSON_MULTILINEMACRO_END
125 
127 // ValidateFlag
128 
135 #ifndef RAPIDJSON_VALIDATE_DEFAULT_FLAGS
136 #define RAPIDJSON_VALIDATE_DEFAULT_FLAGS kValidateNoFlags
137 #endif
138 
140 
146 };
147 
149 // Forward declarations
150 
151 template <typename ValueType, typename Allocator>
153 
154 namespace internal {
155 
156 template <typename SchemaDocumentType>
157 class Schema;
158 
160 // ISchemaValidator
161 
163 public:
164  virtual ~ISchemaValidator() {}
165  virtual bool IsValid() const = 0;
166  virtual void SetValidateFlags(unsigned flags) = 0;
167  virtual unsigned GetValidateFlags() const = 0;
168 };
169 
171 // ISchemaStateFactory
172 
173 template <typename SchemaType>
175 public:
176  virtual ~ISchemaStateFactory() {}
177  virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&, const bool inheritContinueOnErrors) = 0;
178  virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
179  virtual void* CreateHasher() = 0;
180  virtual uint64_t GetHashCode(void* hasher) = 0;
181  virtual void DestroryHasher(void* hasher) = 0;
182  virtual void* MallocState(size_t size) = 0;
183  virtual void FreeState(void* p) = 0;
184 };
185 
187 // IValidationErrorHandler
188 
189 template <typename SchemaType>
191 public:
192  typedef typename SchemaType::Ch Ch;
193  typedef typename SchemaType::SValue SValue;
194 
196 
197  virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0;
198  virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0;
199  virtual void NotMultipleOf(double actual, const SValue& expected) = 0;
200  virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0;
201  virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
202  virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0;
203  virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0;
204  virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
205  virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0;
206 
207  virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0;
208  virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0;
209  virtual void DoesNotMatch(const Ch* str, SizeType length) = 0;
210 
211  virtual void DisallowedItem(SizeType index) = 0;
212  virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;
213  virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;
214  virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;
215 
216  virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;
217  virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;
218  virtual void StartMissingProperties() = 0;
219  virtual void AddMissingProperty(const SValue& name) = 0;
220  virtual bool EndMissingProperties() = 0;
221  virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0;
222  virtual void DisallowedProperty(const Ch* name, SizeType length) = 0;
223 
224  virtual void StartDependencyErrors() = 0;
225  virtual void StartMissingDependentProperties() = 0;
226  virtual void AddMissingDependentProperty(const SValue& targetName) = 0;
227  virtual void EndMissingDependentProperties(const SValue& sourceName) = 0;
228  virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0;
229  virtual bool EndDependencyErrors() = 0;
230 
231  virtual void DisallowedValue(const ValidateErrorCode code) = 0;
232  virtual void StartDisallowedType() = 0;
233  virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0;
234  virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0;
235  virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0;
236  virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
237  virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched) = 0;
238  virtual void Disallowed() = 0;
239 };
240 
241 
243 // Hasher
244 
245 // For comparison of compound value
246 template<typename Encoding, typename Allocator>
247 class Hasher {
248 public:
249  typedef typename Encoding::Ch Ch;
250 
251  Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
252 
253  bool Null() { return WriteType(kNullType); }
254  bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
255  bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
256  bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
257  bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
258  bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
259  bool Double(double d) {
260  Number n;
261  if (d < 0) n.u.i = static_cast<int64_t>(d);
262  else n.u.u = static_cast<uint64_t>(d);
263  n.d = d;
264  return WriteNumber(n);
265  }
266 
267  bool RawNumber(const Ch* str, SizeType len, bool) {
268  WriteBuffer(kNumberType, str, len * sizeof(Ch));
269  return true;
270  }
271 
272  bool String(const Ch* str, SizeType len, bool) {
273  WriteBuffer(kStringType, str, len * sizeof(Ch));
274  return true;
275  }
276 
277  bool StartObject() { return true; }
278  bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
279  bool EndObject(SizeType memberCount) {
280  uint64_t h = Hash(0, kObjectType);
281  uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
282  for (SizeType i = 0; i < memberCount; i++)
283  h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
284  *stack_.template Push<uint64_t>() = h;
285  return true;
286  }
287 
288  bool StartArray() { return true; }
289  bool EndArray(SizeType elementCount) {
290  uint64_t h = Hash(0, kArrayType);
291  uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
292  for (SizeType i = 0; i < elementCount; i++)
293  h = Hash(h, e[i]); // Use hash to achieve element order sensitive
294  *stack_.template Push<uint64_t>() = h;
295  return true;
296  }
297 
298  bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
299 
302  return *stack_.template Top<uint64_t>();
303  }
304 
305 private:
306  static const size_t kDefaultSize = 256;
307  struct Number {
308  union U {
311  }u;
312  double d;
313  };
314 
315  bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
316 
317  bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
318 
319  bool WriteBuffer(Type type, const void* data, size_t len) {
320  // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
321  uint64_t h = Hash(RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
322  const unsigned char* d = static_cast<const unsigned char*>(data);
323  for (size_t i = 0; i < len; i++)
324  h = Hash(h, d[i]);
325  *stack_.template Push<uint64_t>() = h;
326  return true;
327  }
328 
329  static uint64_t Hash(uint64_t h, uint64_t d) {
330  static const uint64_t kPrime = RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
331  h ^= d;
332  h *= kPrime;
333  return h;
334  }
335 
336  Stack<Allocator> stack_;
337 };
338 
340 // SchemaValidationContext
341 
342 template <typename SchemaDocumentType>
348  typedef typename ValueType::Ch Ch;
349 
354  };
355 
357  factory(f),
358  error_handler(eh),
359  schema(s),
360  valueSchema(),
361  invalidKeyword(),
362  invalidCode(),
363  hasher(),
365  validators(),
366  validatorCount(),
372  propertyExist(),
373  inArray(false),
374  valueUniqueness(false),
375  arrayUniqueness(false)
376  {
377  }
378 
380  if (hasher)
382  if (validators) {
383  for (SizeType i = 0; i < validatorCount; i++)
386  }
388  for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
391  }
394  if (propertyExist)
396  }
397 
404  void* hasher; // Only validator access
405  void* arrayElementHashCodes; // Only validator access this
416  bool inArray;
419 };
420 
422 // Schema
423 
424 template <typename SchemaDocumentType>
425 class Schema {
426 public:
427  typedef typename SchemaDocumentType::ValueType ValueType;
428  typedef typename SchemaDocumentType::AllocatorType AllocatorType;
429  typedef typename SchemaDocumentType::PointerType PointerType;
430  typedef typename ValueType::EncodingType EncodingType;
431  typedef typename EncodingType::Ch Ch;
438 
439  Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator, const UriType& id = UriType()) :
440  allocator_(allocator),
441  uri_(schemaDocument->GetURI(), *allocator),
442  id_(id),
443  pointer_(p, allocator),
444  typeless_(schemaDocument->GetTypeless()),
445  enum_(),
446  enumCount_(),
447  not_(),
448  type_((1 << kTotalSchemaType) - 1), // typeless
449  validatorCount_(),
450  notValidatorIndex_(),
451  properties_(),
452  additionalPropertiesSchema_(),
453  patternProperties_(),
454  patternPropertyCount_(),
455  propertyCount_(),
456  minProperties_(),
457  maxProperties_(SizeType(~0)),
458  additionalProperties_(true),
459  hasDependencies_(),
460  hasRequired_(),
461  hasSchemaDependencies_(),
462  additionalItemsSchema_(),
463  itemsList_(),
464  itemsTuple_(),
465  itemsTupleCount_(),
466  minItems_(),
467  maxItems_(SizeType(~0)),
468  additionalItems_(true),
469  uniqueItems_(false),
470  pattern_(),
471  minLength_(0),
472  maxLength_(~SizeType(0)),
473  exclusiveMinimum_(false),
474  exclusiveMaximum_(false),
475  defaultValueLength_(0)
476  {
477  typedef typename ValueType::ConstValueIterator ConstValueIterator;
478  typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
479 
480  // PR #1393
481  // Early add this Schema and its $ref(s) in schemaDocument's map to avoid infinite
482  // recursion (with recursive schemas), since schemaDocument->getSchema() is always
483  // checked before creating a new one. Don't cache typeless_, though.
484  if (this != typeless_) {
485  typedef typename SchemaDocumentType::SchemaEntry SchemaEntry;
486  SchemaEntry *entry = schemaDocument->schemaMap_.template Push<SchemaEntry>();
487  new (entry) SchemaEntry(pointer_, this, true, allocator_);
488  schemaDocument->AddSchemaRefs(this);
489  }
490 
491  if (!value.IsObject())
492  return;
493 
494  // If we have an id property, resolve it with the in-scope id
495  if (const ValueType* v = GetMember(value, GetIdString())) {
496  if (v->IsString()) {
497  UriType local(*v, allocator);
498  id_ = local.Resolve(id_, allocator);
499  }
500  }
501 
502  if (const ValueType* v = GetMember(value, GetTypeString())) {
503  type_ = 0;
504  if (v->IsString())
505  AddType(*v);
506  else if (v->IsArray())
507  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
508  AddType(*itr);
509  }
510 
511  if (const ValueType* v = GetMember(value, GetEnumString())) {
512  if (v->IsArray() && v->Size() > 0) {
513  enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
514  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
515  typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
516  char buffer[256u + 24];
517  MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
518  EnumHasherType h(&hasherAllocator, 256);
519  itr->Accept(h);
520  enum_[enumCount_++] = h.GetHashCode();
521  }
522  }
523  }
524 
525  if (schemaDocument) {
526  AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
527  AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
528  AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
529 
530  if (const ValueType* v = GetMember(value, GetNotString())) {
531  schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document, id_);
532  notValidatorIndex_ = validatorCount_;
533  validatorCount_++;
534  }
535  }
536 
537  // Object
538 
539  const ValueType* properties = GetMember(value, GetPropertiesString());
540  const ValueType* required = GetMember(value, GetRequiredString());
541  const ValueType* dependencies = GetMember(value, GetDependenciesString());
542  {
543  // Gather properties from properties/required/dependencies
544  SValue allProperties(kArrayType);
545 
546  if (properties && properties->IsObject())
547  for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
548  AddUniqueElement(allProperties, itr->name);
549 
550  if (required && required->IsArray())
551  for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
552  if (itr->IsString())
553  AddUniqueElement(allProperties, *itr);
554 
555  if (dependencies && dependencies->IsObject())
556  for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
557  AddUniqueElement(allProperties, itr->name);
558  if (itr->value.IsArray())
559  for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
560  if (i->IsString())
561  AddUniqueElement(allProperties, *i);
562  }
563 
564  if (allProperties.Size() > 0) {
565  propertyCount_ = allProperties.Size();
566  properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
567  for (SizeType i = 0; i < propertyCount_; i++) {
568  new (&properties_[i]) Property();
569  properties_[i].name = allProperties[i];
570  properties_[i].schema = typeless_;
571  }
572  }
573  }
574 
575  if (properties && properties->IsObject()) {
576  PointerType q = p.Append(GetPropertiesString(), allocator_);
577  for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
578  SizeType index;
579  if (FindPropertyIndex(itr->name, &index))
580  schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
581  }
582  }
583 
584  if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
585  PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
586  patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
587  patternPropertyCount_ = 0;
588 
589  for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
590  new (&patternProperties_[patternPropertyCount_]) PatternProperty();
591  patternProperties_[patternPropertyCount_].pattern = CreatePattern(itr->name);
592  schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document, id_);
593  patternPropertyCount_++;
594  }
595  }
596 
597  if (required && required->IsArray())
598  for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
599  if (itr->IsString()) {
600  SizeType index;
601  if (FindPropertyIndex(*itr, &index)) {
602  properties_[index].required = true;
603  hasRequired_ = true;
604  }
605  }
606 
607  if (dependencies && dependencies->IsObject()) {
608  PointerType q = p.Append(GetDependenciesString(), allocator_);
609  hasDependencies_ = true;
610  for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
611  SizeType sourceIndex;
612  if (FindPropertyIndex(itr->name, &sourceIndex)) {
613  if (itr->value.IsArray()) {
614  properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
615  std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
616  for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
617  SizeType targetIndex;
618  if (FindPropertyIndex(*targetItr, &targetIndex))
619  properties_[sourceIndex].dependencies[targetIndex] = true;
620  }
621  }
622  else if (itr->value.IsObject()) {
623  hasSchemaDependencies_ = true;
624  schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document, id_);
625  properties_[sourceIndex].dependenciesValidatorIndex = validatorCount_;
626  validatorCount_++;
627  }
628  }
629  }
630  }
631 
632  if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
633  if (v->IsBool())
634  additionalProperties_ = v->GetBool();
635  else if (v->IsObject())
636  schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document, id_);
637  }
638 
639  AssignIfExist(minProperties_, value, GetMinPropertiesString());
640  AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
641 
642  // Array
643  if (const ValueType* v = GetMember(value, GetItemsString())) {
644  PointerType q = p.Append(GetItemsString(), allocator_);
645  if (v->IsObject()) // List validation
646  schemaDocument->CreateSchema(&itemsList_, q, *v, document, id_);
647  else if (v->IsArray()) { // Tuple validation
648  itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
649  SizeType index = 0;
650  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
651  schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document, id_);
652  }
653  }
654 
655  AssignIfExist(minItems_, value, GetMinItemsString());
656  AssignIfExist(maxItems_, value, GetMaxItemsString());
657 
658  if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
659  if (v->IsBool())
660  additionalItems_ = v->GetBool();
661  else if (v->IsObject())
662  schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document, id_);
663  }
664 
665  AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
666 
667  // String
668  AssignIfExist(minLength_, value, GetMinLengthString());
669  AssignIfExist(maxLength_, value, GetMaxLengthString());
670 
671  if (const ValueType* v = GetMember(value, GetPatternString()))
672  pattern_ = CreatePattern(*v);
673 
674  // Number
675  if (const ValueType* v = GetMember(value, GetMinimumString()))
676  if (v->IsNumber())
677  minimum_.CopyFrom(*v, *allocator_);
678 
679  if (const ValueType* v = GetMember(value, GetMaximumString()))
680  if (v->IsNumber())
681  maximum_.CopyFrom(*v, *allocator_);
682 
683  AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
684  AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
685 
686  if (const ValueType* v = GetMember(value, GetMultipleOfString()))
687  if (v->IsNumber() && v->GetDouble() > 0.0)
688  multipleOf_.CopyFrom(*v, *allocator_);
689 
690  // Default
691  if (const ValueType* v = GetMember(value, GetDefaultValueString()))
692  if (v->IsString())
693  defaultValueLength_ = v->GetStringLength();
694 
695  }
696 
698  AllocatorType::Free(enum_);
699  if (properties_) {
700  for (SizeType i = 0; i < propertyCount_; i++)
701  properties_[i].~Property();
702  AllocatorType::Free(properties_);
703  }
704  if (patternProperties_) {
705  for (SizeType i = 0; i < patternPropertyCount_; i++)
706  patternProperties_[i].~PatternProperty();
707  AllocatorType::Free(patternProperties_);
708  }
709  AllocatorType::Free(itemsTuple_);
710 #if RAPIDJSON_SCHEMA_HAS_REGEX
711  if (pattern_) {
712  pattern_->~RegexType();
713  AllocatorType::Free(pattern_);
714  }
715 #endif
716  }
717 
718  const SValue& GetURI() const {
719  return uri_;
720  }
721 
722  const UriType& GetId() const {
723  return id_;
724  }
725 
726  const PointerType& GetPointer() const {
727  return pointer_;
728  }
729 
730  bool BeginValue(Context& context) const {
731  if (context.inArray) {
732  if (uniqueItems_)
733  context.valueUniqueness = true;
734 
735  if (itemsList_)
736  context.valueSchema = itemsList_;
737  else if (itemsTuple_) {
738  if (context.arrayElementIndex < itemsTupleCount_)
739  context.valueSchema = itemsTuple_[context.arrayElementIndex];
740  else if (additionalItemsSchema_)
741  context.valueSchema = additionalItemsSchema_;
742  else if (additionalItems_)
743  context.valueSchema = typeless_;
744  else {
746  // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error
747  context.valueSchema = typeless_;
748  // Must bump arrayElementIndex for when kValidateContinueOnErrorFlag is set
749  context.arrayElementIndex++;
751  }
752  }
753  else
754  context.valueSchema = typeless_;
755 
756  context.arrayElementIndex++;
757  }
758  return true;
759  }
760 
761  RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
762  // Only check pattern properties if we have validators
763  if (context.patternPropertiesValidatorCount > 0) {
764  bool otherValid = false;
767  otherValid = context.patternPropertiesValidators[--count]->IsValid();
768 
769  bool patternValid = true;
770  for (SizeType i = 0; i < count; i++)
771  if (!context.patternPropertiesValidators[i]->IsValid()) {
772  patternValid = false;
773  break;
774  }
775 
777  if (!patternValid) {
780  }
781  }
783  if (!patternValid || !otherValid) {
786  }
787  }
788  else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty)
791  }
792  }
793 
794  // For enums only check if we have a hasher
795  if (enum_ && context.hasher) {
796  const uint64_t h = context.factory.GetHashCode(context.hasher);
797  for (SizeType i = 0; i < enumCount_; i++)
798  if (enum_[i] == h)
799  goto foundEnum;
802  foundEnum:;
803  }
804 
805  // Only check allOf etc if we have validators
806  if (context.validatorCount > 0) {
807  if (allOf_.schemas)
808  for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
809  if (!context.validators[i]->IsValid()) {
810  context.error_handler.NotAllOf(&context.validators[allOf_.begin], allOf_.count);
812  }
813 
814  if (anyOf_.schemas) {
815  for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
816  if (context.validators[i]->IsValid())
817  goto foundAny;
818  context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
820  foundAny:;
821  }
822 
823  if (oneOf_.schemas) {
824  bool oneValid = false;
825  for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
826  if (context.validators[i]->IsValid()) {
827  if (oneValid) {
828  context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, true);
830  } else
831  oneValid = true;
832  }
833  if (!oneValid) {
834  context.error_handler.NotOneOf(&context.validators[oneOf_.begin], oneOf_.count, false);
836  }
837  }
838 
839  if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
840  context.error_handler.Disallowed();
842  }
843  }
844 
845  return true;
846  }
847 
848  bool Null(Context& context) const {
849  if (!(type_ & (1 << kNullSchemaType))) {
850  DisallowedType(context, GetNullString());
852  }
853  return CreateParallelValidator(context);
854  }
855 
856  bool Bool(Context& context, bool) const {
857  if (!(type_ & (1 << kBooleanSchemaType))) {
858  DisallowedType(context, GetBooleanString());
860  }
861  return CreateParallelValidator(context);
862  }
863 
864  bool Int(Context& context, int i) const {
865  if (!CheckInt(context, i))
866  return false;
867  return CreateParallelValidator(context);
868  }
869 
870  bool Uint(Context& context, unsigned u) const {
871  if (!CheckUint(context, u))
872  return false;
873  return CreateParallelValidator(context);
874  }
875 
876  bool Int64(Context& context, int64_t i) const {
877  if (!CheckInt(context, i))
878  return false;
879  return CreateParallelValidator(context);
880  }
881 
882  bool Uint64(Context& context, uint64_t u) const {
883  if (!CheckUint(context, u))
884  return false;
885  return CreateParallelValidator(context);
886  }
887 
888  bool Double(Context& context, double d) const {
889  if (!(type_ & (1 << kNumberSchemaType))) {
890  DisallowedType(context, GetNumberString());
892  }
893 
894  if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
895  return false;
896 
897  if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
898  return false;
899 
900  if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
901  return false;
902 
903  return CreateParallelValidator(context);
904  }
905 
906  bool String(Context& context, const Ch* str, SizeType length, bool) const {
907  if (!(type_ & (1 << kStringSchemaType))) {
908  DisallowedType(context, GetStringString());
910  }
911 
912  if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
913  SizeType count;
914  if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
915  if (count < minLength_) {
916  context.error_handler.TooShort(str, length, minLength_);
918  }
919  if (count > maxLength_) {
920  context.error_handler.TooLong(str, length, maxLength_);
922  }
923  }
924  }
925 
926  if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
927  context.error_handler.DoesNotMatch(str, length);
929  }
930 
931  return CreateParallelValidator(context);
932  }
933 
934  bool StartObject(Context& context) const {
935  if (!(type_ & (1 << kObjectSchemaType))) {
936  DisallowedType(context, GetObjectString());
938  }
939 
940  if (hasDependencies_ || hasRequired_) {
941  context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
942  std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
943  }
944 
945  if (patternProperties_) { // pre-allocate schema array
946  SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
947  context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
948  context.patternPropertiesSchemaCount = 0;
949  std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
950  }
951 
952  return CreateParallelValidator(context);
953  }
954 
955  bool Key(Context& context, const Ch* str, SizeType len, bool) const {
956  if (patternProperties_) {
957  context.patternPropertiesSchemaCount = 0;
958  for (SizeType i = 0; i < patternPropertyCount_; i++)
959  if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
960  context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = patternProperties_[i].schema;
961  context.valueSchema = typeless_;
962  }
963  }
964 
965  SizeType index = 0;
966  if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
967  if (context.patternPropertiesSchemaCount > 0) {
968  context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = properties_[index].schema;
969  context.valueSchema = typeless_;
971  }
972  else
973  context.valueSchema = properties_[index].schema;
974 
975  if (context.propertyExist)
976  context.propertyExist[index] = true;
977 
978  return true;
979  }
980 
981  if (additionalPropertiesSchema_) {
982  if (context.patternPropertiesSchemaCount > 0) {
983  context.patternPropertiesSchemas[context.patternPropertiesSchemaCount++] = additionalPropertiesSchema_;
984  context.valueSchema = typeless_;
986  }
987  else
988  context.valueSchema = additionalPropertiesSchema_;
989  return true;
990  }
991  else if (additionalProperties_) {
992  context.valueSchema = typeless_;
993  return true;
994  }
995 
996  if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties
997  // Must set valueSchema for when kValidateContinueOnErrorFlag is set, else reports spurious type error
998  context.valueSchema = typeless_;
999  context.error_handler.DisallowedProperty(str, len);
1001  }
1002 
1003  return true;
1004  }
1005 
1006  bool EndObject(Context& context, SizeType memberCount) const {
1007  if (hasRequired_) {
1009  for (SizeType index = 0; index < propertyCount_; index++)
1010  if (properties_[index].required && !context.propertyExist[index])
1011  if (properties_[index].schema->defaultValueLength_ == 0 )
1012  context.error_handler.AddMissingProperty(properties_[index].name);
1013  if (context.error_handler.EndMissingProperties())
1015  }
1016 
1017  if (memberCount < minProperties_) {
1018  context.error_handler.TooFewProperties(memberCount, minProperties_);
1020  }
1021 
1022  if (memberCount > maxProperties_) {
1023  context.error_handler.TooManyProperties(memberCount, maxProperties_);
1025  }
1026 
1027  if (hasDependencies_) {
1029  for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
1030  const Property& source = properties_[sourceIndex];
1031  if (context.propertyExist[sourceIndex]) {
1032  if (source.dependencies) {
1034  for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
1035  if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
1036  context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
1038  }
1039  else if (source.dependenciesSchema) {
1040  ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
1041  if (!dependenciesValidator->IsValid())
1042  context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
1043  }
1044  }
1045  }
1046  if (context.error_handler.EndDependencyErrors())
1048  }
1049 
1050  return true;
1051  }
1052 
1053  bool StartArray(Context& context) const {
1054  context.arrayElementIndex = 0;
1055  context.inArray = true; // Ensure we note that we are in an array
1056 
1057  if (!(type_ & (1 << kArraySchemaType))) {
1058  DisallowedType(context, GetArrayString());
1060  }
1061 
1062  return CreateParallelValidator(context);
1063  }
1064 
1065  bool EndArray(Context& context, SizeType elementCount) const {
1066  context.inArray = false;
1067 
1068  if (elementCount < minItems_) {
1069  context.error_handler.TooFewItems(elementCount, minItems_);
1071  }
1072 
1073  if (elementCount > maxItems_) {
1074  context.error_handler.TooManyItems(elementCount, maxItems_);
1076  }
1077 
1078  return true;
1079  }
1080 
1081  static const ValueType& GetValidateErrorKeyword(ValidateErrorCode validateErrorCode) {
1082  switch (validateErrorCode) {
1083  case kValidateErrorMultipleOf: return GetMultipleOfString();
1084  case kValidateErrorMaximum: return GetMaximumString();
1085  case kValidateErrorExclusiveMaximum: return GetMaximumString(); // Same
1086  case kValidateErrorMinimum: return GetMinimumString();
1087  case kValidateErrorExclusiveMinimum: return GetMinimumString(); // Same
1088 
1089  case kValidateErrorMaxLength: return GetMaxLengthString();
1090  case kValidateErrorMinLength: return GetMinLengthString();
1091  case kValidateErrorPattern: return GetPatternString();
1092 
1093  case kValidateErrorMaxItems: return GetMaxItemsString();
1094  case kValidateErrorMinItems: return GetMinItemsString();
1095  case kValidateErrorUniqueItems: return GetUniqueItemsString();
1096  case kValidateErrorAdditionalItems: return GetAdditionalItemsString();
1097 
1098  case kValidateErrorMaxProperties: return GetMaxPropertiesString();
1099  case kValidateErrorMinProperties: return GetMinPropertiesString();
1100  case kValidateErrorRequired: return GetRequiredString();
1101  case kValidateErrorAdditionalProperties: return GetAdditionalPropertiesString();
1102  case kValidateErrorPatternProperties: return GetPatternPropertiesString();
1103  case kValidateErrorDependencies: return GetDependenciesString();
1104 
1105  case kValidateErrorEnum: return GetEnumString();
1106  case kValidateErrorType: return GetTypeString();
1107 
1108  case kValidateErrorOneOf: return GetOneOfString();
1109  case kValidateErrorOneOfMatch: return GetOneOfString(); // Same
1110  case kValidateErrorAllOf: return GetAllOfString();
1111  case kValidateErrorAnyOf: return GetAnyOfString();
1112  case kValidateErrorNot: return GetNotString();
1113 
1114  default: return GetNullString();
1115  }
1116  }
1117 
1118 
1119  // Generate functions for string literal according to Ch
1120 #define RAPIDJSON_STRING_(name, ...) \
1121  static const ValueType& Get##name##String() {\
1122  static const Ch s[] = { __VA_ARGS__, '\0' };\
1123  static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
1124  return v;\
1125  }
1126 
1127  RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
1128  RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
1129  RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
1130  RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
1131  RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
1132  RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
1133  RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
1134  RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
1135  RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
1136  RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
1137  RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
1138  RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
1139  RAPIDJSON_STRING_(Not, 'n', 'o', 't')
1140  RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1141  RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
1142  RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
1143  RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1144  RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1145  RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1146  RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1147  RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
1148  RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
1149  RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
1150  RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
1151  RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
1152  RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
1153  RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
1154  RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
1155  RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
1156  RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
1157  RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
1158  RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
1159  RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
1160  RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't')
1161  RAPIDJSON_STRING_(Ref, '$', 'r', 'e', 'f')
1162  RAPIDJSON_STRING_(Id, 'i', 'd')
1163 
1164  RAPIDJSON_STRING_(SchemeEnd, ':')
1165  RAPIDJSON_STRING_(AuthStart, '/', '/')
1166  RAPIDJSON_STRING_(QueryStart, '?')
1167  RAPIDJSON_STRING_(FragStart, '#')
1168  RAPIDJSON_STRING_(Slash, '/')
1169  RAPIDJSON_STRING_(Dot, '.')
1170 
1171 #undef RAPIDJSON_STRING_
1172 
1173 private:
1174  enum SchemaValueType {
1175  kNullSchemaType,
1176  kBooleanSchemaType,
1177  kObjectSchemaType,
1178  kArraySchemaType,
1179  kStringSchemaType,
1180  kNumberSchemaType,
1181  kIntegerSchemaType,
1182  kTotalSchemaType
1183  };
1184 
1185 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1187 #elif RAPIDJSON_SCHEMA_USE_STDREGEX
1188  typedef std::basic_regex<Ch> RegexType;
1189 #else
1190  typedef char RegexType;
1191 #endif
1192 
1193  struct SchemaArray {
1194  SchemaArray() : schemas(), count() {}
1195  ~SchemaArray() { AllocatorType::Free(schemas); }
1196  const SchemaType** schemas;
1197  SizeType begin; // begin index of context.validators
1198  SizeType count;
1199  };
1200 
1201  template <typename V1, typename V2>
1202  void AddUniqueElement(V1& a, const V2& v) {
1203  for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1204  if (*itr == v)
1205  return;
1206  V1 c(v, *allocator_);
1207  a.PushBack(c, *allocator_);
1208  }
1209 
1210  static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
1211  typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1212  return itr != value.MemberEnd() ? &(itr->value) : 0;
1213  }
1214 
1215  static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
1216  if (const ValueType* v = GetMember(value, name))
1217  if (v->IsBool())
1218  out = v->GetBool();
1219  }
1220 
1221  static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
1222  if (const ValueType* v = GetMember(value, name))
1223  if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
1224  out = static_cast<SizeType>(v->GetUint64());
1225  }
1226 
1227  void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
1228  if (const ValueType* v = GetMember(value, name)) {
1229  if (v->IsArray() && v->Size() > 0) {
1230  PointerType q = p.Append(name, allocator_);
1231  out.count = v->Size();
1232  out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
1233  memset(out.schemas, 0, sizeof(Schema*)* out.count);
1234  for (SizeType i = 0; i < out.count; i++)
1235  schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document, id_);
1236  out.begin = validatorCount_;
1237  validatorCount_ += out.count;
1238  }
1239  }
1240  }
1241 
1242 #if RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1243  template <typename ValueType>
1244  RegexType* CreatePattern(const ValueType& value) {
1245  if (value.IsString()) {
1246  RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1247  if (!r->IsValid()) {
1248  r->~RegexType();
1250  r = 0;
1251  }
1252  return r;
1253  }
1254  return 0;
1255  }
1256 
1257  static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
1258  GenericRegexSearch<RegexType> rs(*pattern);
1259  return rs.Search(str);
1260  }
1261 #elif RAPIDJSON_SCHEMA_USE_STDREGEX
1262  template <typename ValueType>
1263  RegexType* CreatePattern(const ValueType& value) {
1264  if (value.IsString()) {
1265  RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
1266  try {
1267  return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1268  }
1269  catch (const std::regex_error&) {
1271  }
1272  }
1273  return 0;
1274  }
1275 
1276  static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
1277  std::match_results<const Ch*> r;
1278  return std::regex_search(str, str + length, r, *pattern);
1279  }
1280 #else
1281  template <typename ValueType>
1282  RegexType* CreatePattern(const ValueType&) { return 0; }
1283 
1284  static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
1285 #endif // RAPIDJSON_SCHEMA_USE_STDREGEX
1286 
1287  void AddType(const ValueType& type) {
1288  if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1289  else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1290  else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1291  else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1292  else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1293  else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1294  else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1295  }
1296 
1297  bool CreateParallelValidator(Context& context) const {
1298  if (enum_ || context.arrayUniqueness)
1299  context.hasher = context.factory.CreateHasher();
1300 
1301  if (validatorCount_) {
1302  RAPIDJSON_ASSERT(context.validators == 0);
1303  context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
1304  context.validatorCount = validatorCount_;
1305 
1306  // Always return after first failure for these sub-validators
1307  if (allOf_.schemas)
1308  CreateSchemaValidators(context, allOf_, false);
1309 
1310  if (anyOf_.schemas)
1311  CreateSchemaValidators(context, anyOf_, false);
1312 
1313  if (oneOf_.schemas)
1314  CreateSchemaValidators(context, oneOf_, false);
1315 
1316  if (not_)
1317  context.validators[notValidatorIndex_] = context.factory.CreateSchemaValidator(*not_, false);
1318 
1319  if (hasSchemaDependencies_) {
1320  for (SizeType i = 0; i < propertyCount_; i++)
1321  if (properties_[i].dependenciesSchema)
1322  context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema, false);
1323  }
1324  }
1325 
1326  return true;
1327  }
1328 
1329  void CreateSchemaValidators(Context& context, const SchemaArray& schemas, const bool inheritContinueOnErrors) const {
1330  for (SizeType i = 0; i < schemas.count; i++)
1331  context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i], inheritContinueOnErrors);
1332  }
1333 
1334  // O(n)
1335  bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
1336  SizeType len = name.GetStringLength();
1337  const Ch* str = name.GetString();
1338  for (SizeType index = 0; index < propertyCount_; index++)
1339  if (properties_[index].name.GetStringLength() == len &&
1340  (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
1341  {
1342  *outIndex = index;
1343  return true;
1344  }
1345  return false;
1346  }
1347 
1348  bool CheckInt(Context& context, int64_t i) const {
1349  if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1350  DisallowedType(context, GetIntegerString());
1352  }
1353 
1354  if (!minimum_.IsNull()) {
1355  if (minimum_.IsInt64()) {
1356  if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1357  context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1359  }
1360  }
1361  else if (minimum_.IsUint64()) {
1362  context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1363  RAPIDJSON_INVALID_KEYWORD_RETURN(exclusiveMinimum_ ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum); // i <= max(int64_t) < minimum.GetUint64()
1364  }
1365  else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1366  return false;
1367  }
1368 
1369  if (!maximum_.IsNull()) {
1370  if (maximum_.IsInt64()) {
1371  if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1372  context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1374  }
1375  }
1376  else if (maximum_.IsUint64()) { }
1377  /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
1378  else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1379  return false;
1380  }
1381 
1382  if (!multipleOf_.IsNull()) {
1383  if (multipleOf_.IsUint64()) {
1384  if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1385  context.error_handler.NotMultipleOf(i, multipleOf_);
1387  }
1388  }
1389  else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1390  return false;
1391  }
1392 
1393  return true;
1394  }
1395 
1396  bool CheckUint(Context& context, uint64_t i) const {
1397  if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1398  DisallowedType(context, GetIntegerString());
1400  }
1401 
1402  if (!minimum_.IsNull()) {
1403  if (minimum_.IsUint64()) {
1404  if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1405  context.error_handler.BelowMinimum(i, minimum_, exclusiveMinimum_);
1407  }
1408  }
1409  else if (minimum_.IsInt64())
1410  /* do nothing */; // i >= 0 > minimum.Getint64()
1411  else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1412  return false;
1413  }
1414 
1415  if (!maximum_.IsNull()) {
1416  if (maximum_.IsUint64()) {
1417  if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1418  context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1420  }
1421  }
1422  else if (maximum_.IsInt64()) {
1423  context.error_handler.AboveMaximum(i, maximum_, exclusiveMaximum_);
1425  }
1426  else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1427  return false;
1428  }
1429 
1430  if (!multipleOf_.IsNull()) {
1431  if (multipleOf_.IsUint64()) {
1432  if (i % multipleOf_.GetUint64() != 0) {
1433  context.error_handler.NotMultipleOf(i, multipleOf_);
1435  }
1436  }
1437  else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1438  return false;
1439  }
1440 
1441  return true;
1442  }
1443 
1444  bool CheckDoubleMinimum(Context& context, double d) const {
1445  if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1446  context.error_handler.BelowMinimum(d, minimum_, exclusiveMinimum_);
1448  }
1449  return true;
1450  }
1451 
1452  bool CheckDoubleMaximum(Context& context, double d) const {
1453  if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1454  context.error_handler.AboveMaximum(d, maximum_, exclusiveMaximum_);
1456  }
1457  return true;
1458  }
1459 
1460  bool CheckDoubleMultipleOf(Context& context, double d) const {
1461  double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1462  double q = std::floor(a / b);
1463  double r = a - q * b;
1464  if (r > 0.0) {
1465  context.error_handler.NotMultipleOf(d, multipleOf_);
1467  }
1468  return true;
1469  }
1470 
1471  void DisallowedType(Context& context, const ValueType& actualType) const {
1472  ErrorHandler& eh = context.error_handler;
1473  eh.StartDisallowedType();
1474 
1475  if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1476  if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1477  if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1478  if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1479  if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1480 
1481  if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1482  else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1483 
1484  eh.EndDisallowedType(actualType);
1485  }
1486 
1487  struct Property {
1488  Property() : schema(), dependenciesSchema(), dependenciesValidatorIndex(), dependencies(), required(false) {}
1489  ~Property() { AllocatorType::Free(dependencies); }
1490  SValue name;
1491  const SchemaType* schema;
1492  const SchemaType* dependenciesSchema;
1493  SizeType dependenciesValidatorIndex;
1494  bool* dependencies;
1495  bool required;
1496  };
1497 
1498  struct PatternProperty {
1499  PatternProperty() : schema(), pattern() {}
1500  ~PatternProperty() {
1501  if (pattern) {
1502  pattern->~RegexType();
1503  AllocatorType::Free(pattern);
1504  }
1505  }
1506  const SchemaType* schema;
1507  RegexType* pattern;
1508  };
1509 
1510  AllocatorType* allocator_;
1511  SValue uri_;
1512  UriType id_;
1513  PointerType pointer_;
1514  const SchemaType* typeless_;
1515  uint64_t* enum_;
1516  SizeType enumCount_;
1517  SchemaArray allOf_;
1518  SchemaArray anyOf_;
1519  SchemaArray oneOf_;
1520  const SchemaType* not_;
1521  unsigned type_; // bitmask of kSchemaType
1522  SizeType validatorCount_;
1523  SizeType notValidatorIndex_;
1524 
1525  Property* properties_;
1526  const SchemaType* additionalPropertiesSchema_;
1527  PatternProperty* patternProperties_;
1528  SizeType patternPropertyCount_;
1529  SizeType propertyCount_;
1530  SizeType minProperties_;
1531  SizeType maxProperties_;
1532  bool additionalProperties_;
1533  bool hasDependencies_;
1534  bool hasRequired_;
1535  bool hasSchemaDependencies_;
1536 
1537  const SchemaType* additionalItemsSchema_;
1538  const SchemaType* itemsList_;
1539  const SchemaType** itemsTuple_;
1540  SizeType itemsTupleCount_;
1541  SizeType minItems_;
1542  SizeType maxItems_;
1543  bool additionalItems_;
1544  bool uniqueItems_;
1545 
1546  RegexType* pattern_;
1547  SizeType minLength_;
1548  SizeType maxLength_;
1549 
1550  SValue minimum_;
1551  SValue maximum_;
1552  SValue multipleOf_;
1553  bool exclusiveMinimum_;
1554  bool exclusiveMaximum_;
1555 
1556  SizeType defaultValueLength_;
1557 };
1558 
1559 template<typename Stack, typename Ch>
1560 struct TokenHelper {
1561  RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1562  *documentStack.template Push<Ch>() = '/';
1563  char buffer[21];
1564  size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
1565  for (size_t i = 0; i < length; i++)
1566  *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
1567  }
1568 };
1569 
1570 // Partial specialized version for char to prevent buffer copying.
1571 template <typename Stack>
1572 struct TokenHelper<Stack, char> {
1573  RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1574  if (sizeof(SizeType) == 4) {
1575  char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
1576  *buffer++ = '/';
1577  const char* end = internal::u32toa(index, buffer);
1578  documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
1579  }
1580  else {
1581  char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
1582  *buffer++ = '/';
1583  const char* end = internal::u64toa(index, buffer);
1584  documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
1585  }
1586  }
1587 };
1588 
1589 } // namespace internal
1590 
1592 // IGenericRemoteSchemaDocumentProvider
1593 
1594 template <typename SchemaDocumentType>
1596 public:
1597  typedef typename SchemaDocumentType::Ch Ch;
1598  typedef typename SchemaDocumentType::ValueType ValueType;
1599  typedef typename SchemaDocumentType::AllocatorType AllocatorType;
1600 
1602  virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
1603  virtual const SchemaDocumentType* GetRemoteDocument(GenericUri<ValueType, AllocatorType> uri) { return GetRemoteDocument(uri.GetBaseString(), uri.GetBaseStringLength()); }
1604 };
1605 
1607 // GenericSchemaDocument
1608 
1610 
1618 template <typename ValueT, typename Allocator = CrtAllocator>
1619 class GenericSchemaDocument {
1620 public:
1621  typedef ValueT ValueType;
1624  typedef typename ValueType::EncodingType EncodingType;
1625  typedef typename EncodingType::Ch Ch;
1631  template <typename, typename, typename>
1633 
1635 
1645  explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
1646  IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0,
1647  const PointerType& pointer = PointerType()) : // PR #1393
1648  remoteProvider_(remoteProvider),
1649  allocator_(allocator),
1650  ownAllocator_(),
1651  root_(),
1652  typeless_(),
1653  schemaMap_(allocator, kInitialSchemaMapSize),
1654  schemaRef_(allocator, kInitialSchemaRefSize)
1655  {
1656  if (!allocator_)
1657  ownAllocator_ = allocator_ = RAPIDJSON_NEW(Allocator)();
1658 
1659  Ch noUri[1] = {0};
1660  uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
1661  docId_ = UriType(uri_, allocator_);
1662 
1663  typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
1664  new (typeless_) SchemaType(this, PointerType(), ValueType(kObjectType).Move(), ValueType(kObjectType).Move(), allocator_, docId_);
1665 
1666  // Generate root schema, it will call CreateSchema() to create sub-schemas,
1667  // And call HandleRefSchema() if there are $ref.
1668  // PR #1393 use input pointer if supplied
1669  root_ = typeless_;
1670  if (pointer.GetTokenCount() == 0) {
1671  CreateSchemaRecursive(&root_, pointer, document, document, docId_);
1672  }
1673  else if (const ValueType* v = pointer.Get(document)) {
1674  CreateSchema(&root_, pointer, *v, document, docId_);
1675  }
1676 
1677  RAPIDJSON_ASSERT(root_ != 0);
1678 
1679  schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
1680  }
1681 
1682 #if RAPIDJSON_HAS_CXX11_RVALUE_REFS
1683  GenericSchemaDocument(GenericSchemaDocument&& rhs) RAPIDJSON_NOEXCEPT :
1685  remoteProvider_(rhs.remoteProvider_),
1686  allocator_(rhs.allocator_),
1687  ownAllocator_(rhs.ownAllocator_),
1688  root_(rhs.root_),
1689  typeless_(rhs.typeless_),
1690  schemaMap_(std::move(rhs.schemaMap_)),
1691  schemaRef_(std::move(rhs.schemaRef_)),
1692  uri_(std::move(rhs.uri_)),
1693  docId_(rhs.docId_)
1694  {
1695  rhs.remoteProvider_ = 0;
1696  rhs.allocator_ = 0;
1697  rhs.ownAllocator_ = 0;
1698  rhs.typeless_ = 0;
1699  }
1700 #endif
1701 
1704  while (!schemaMap_.Empty())
1705  schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
1706 
1707  if (typeless_) {
1708  typeless_->~SchemaType();
1709  Allocator::Free(typeless_);
1710  }
1711 
1712  RAPIDJSON_DELETE(ownAllocator_);
1713  }
1714 
1715  const SValue& GetURI() const { return uri_; }
1716 
1718  const SchemaType& GetRoot() const { return *root_; }
1719 
1720 private:
1724  GenericSchemaDocument& operator=(const GenericSchemaDocument&);
1725 
1726  typedef const PointerType* SchemaRefPtr; // PR #1393
1727 
1728  struct SchemaEntry {
1729  SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
1730  ~SchemaEntry() {
1731  if (owned) {
1732  schema->~SchemaType();
1733  Allocator::Free(schema);
1734  }
1735  }
1737  SchemaType* schema;
1738  bool owned;
1739  };
1740 
1741  // Changed by PR #1393
1742  void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) {
1743  if (v.GetType() == kObjectType) {
1744  UriType newid = UriType(CreateSchema(schema, pointer, v, document, id), allocator_);
1745 
1746  for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
1747  CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document, newid);
1748  }
1749  else if (v.GetType() == kArrayType)
1750  for (SizeType i = 0; i < v.Size(); i++)
1751  CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document, id);
1752  }
1753 
1754  // Changed by PR #1393
1755  const UriType& CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document, const UriType& id) {
1756  RAPIDJSON_ASSERT(pointer.IsValid());
1757  if (v.IsObject()) {
1758  if (const SchemaType* sc = GetSchema(pointer)) {
1759  if (schema)
1760  *schema = sc;
1761  AddSchemaRefs(const_cast<SchemaType*>(sc));
1762  }
1763  else if (!HandleRefSchema(pointer, schema, v, document, id)) {
1764  // The new schema constructor adds itself and its $ref(s) to schemaMap_
1765  SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_, id);
1766  if (schema)
1767  *schema = s;
1768  return s->GetId();
1769  }
1770  }
1771  else {
1772  if (schema)
1773  *schema = typeless_;
1774  AddSchemaRefs(typeless_);
1775  }
1776  return id;
1777  }
1778 
1779  // Changed by PR #1393
1780  // TODO should this return a UriType& ?
1781  bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document, const UriType& id) {
1782  typename ValueType::ConstMemberIterator itr = v.FindMember(SchemaType::GetRefString());
1783  if (itr == v.MemberEnd())
1784  return false;
1785 
1786  // Resolve the source pointer to the $ref'ed schema (finally)
1787  new (schemaRef_.template Push<SchemaRefPtr>()) SchemaRefPtr(&source);
1788 
1789  if (itr->value.IsString()) {
1790  SizeType len = itr->value.GetStringLength();
1791  if (len > 0) {
1792  // First resolve $ref against the in-scope id
1793  UriType scopeId = UriType(id, allocator_);
1794  UriType ref = UriType(itr->value, allocator_).Resolve(scopeId, allocator_);
1795  // See if the resolved $ref minus the fragment matches a resolved id in this document
1796  // Search from the root. Returns the subschema in the document and its absolute JSON pointer.
1797  PointerType basePointer = PointerType();
1798  const ValueType *base = FindId(document, ref, basePointer, docId_, false);
1799  if (!base) {
1800  // Remote reference - call the remote document provider
1801  if (remoteProvider_) {
1802  if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(ref)) {
1803  const Ch* s = ref.GetFragString();
1804  len = ref.GetFragStringLength();
1805  if (len <= 1 || s[1] == '/') {
1806  // JSON pointer fragment, absolute in the remote schema
1807  const PointerType pointer(s, len, allocator_);
1808  if (pointer.IsValid()) {
1809  // Get the subschema
1810  if (const SchemaType *sc = remoteDocument->GetSchema(pointer)) {
1811  if (schema)
1812  *schema = sc;
1813  AddSchemaRefs(const_cast<SchemaType *>(sc));
1814  return true;
1815  }
1816  }
1817  } else {
1818  // Plain name fragment, not allowed
1819  }
1820  }
1821  }
1822  }
1823  else { // Local reference
1824  const Ch* s = ref.GetFragString();
1825  len = ref.GetFragStringLength();
1826  if (len <= 1 || s[1] == '/') {
1827  // JSON pointer fragment, relative to the resolved URI
1828  const PointerType relPointer(s, len, allocator_);
1829  if (relPointer.IsValid()) {
1830  // Get the subschema
1831  if (const ValueType *pv = relPointer.Get(*base)) {
1832  // Now get the absolute JSON pointer by adding relative to base
1833  PointerType pointer(basePointer);
1834  for (SizeType i = 0; i < relPointer.GetTokenCount(); i++)
1835  pointer = pointer.Append(relPointer.GetTokens()[i], allocator_);
1836  //GenericStringBuffer<EncodingType> sb;
1837  //pointer.StringifyUriFragment(sb);
1838  if (pointer.IsValid() && !IsCyclicRef(pointer)) {
1839  // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
1840  // TODO: cache pointer <-> id mapping
1841  size_t unresolvedTokenIndex;
1842  scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1843  CreateSchema(schema, pointer, *pv, document, scopeId);
1844  return true;
1845  }
1846  }
1847  }
1848  } else {
1849  // Plain name fragment, relative to the resolved URI
1850  // See if the fragment matches an id in this document.
1851  // Search from the base we just established. Returns the subschema in the document and its absolute JSON pointer.
1853  if (const ValueType *pv = FindId(*base, ref, pointer, UriType(ref.GetBaseString(), ref.GetBaseStringLength(), allocator_), true, basePointer)) {
1854  if (!IsCyclicRef(pointer)) {
1855  //GenericStringBuffer<EncodingType> sb;
1856  //pointer.StringifyUriFragment(sb);
1857  // Call CreateSchema recursively, but first compute the in-scope id for the $ref target as we have jumped there
1858  // TODO: cache pointer <-> id mapping
1859  size_t unresolvedTokenIndex;
1860  scopeId = pointer.GetUri(document, docId_, &unresolvedTokenIndex, allocator_);
1861  CreateSchema(schema, pointer, *pv, document, scopeId);
1862  return true;
1863  }
1864  }
1865  }
1866  }
1867  }
1868  }
1869 
1870  // Invalid/Unknown $ref
1871  if (schema)
1872  *schema = typeless_;
1873  AddSchemaRefs(typeless_);
1874  return true;
1875  }
1876 
1878  // If full specified use all URI else ignore fragment.
1879  // If found, return a pointer to the subschema and its JSON pointer.
1880  // TODO cache pointer <-> id mapping
1881  ValueType* FindId(const ValueType& doc, const UriType& finduri, PointerType& resptr, const UriType& baseuri, bool full, const PointerType& here = PointerType()) const {
1882  SizeType i = 0;
1883  ValueType* resval = 0;
1884  UriType tempuri = UriType(finduri, allocator_);
1885  UriType localuri = UriType(baseuri, allocator_);
1886  if (doc.GetType() == kObjectType) {
1887  // Establish the base URI of this object
1888  typename ValueType::ConstMemberIterator m = doc.FindMember(SchemaType::GetIdString());
1889  if (m != doc.MemberEnd() && m->value.GetType() == kStringType) {
1890  localuri = UriType(m->value, allocator_).Resolve(baseuri, allocator_);
1891  }
1892  // See if it matches
1893  if (localuri.Match(finduri, full)) {
1894  resval = const_cast<ValueType *>(&doc);
1895  resptr = here;
1896  return resval;
1897  }
1898  // No match, continue looking
1899  for (m = doc.MemberBegin(); m != doc.MemberEnd(); ++m) {
1900  if (m->value.GetType() == kObjectType || m->value.GetType() == kArrayType) {
1901  resval = FindId(m->value, finduri, resptr, localuri, full, here.Append(m->name.GetString(), m->name.GetStringLength(), allocator_));
1902  }
1903  if (resval) break;
1904  }
1905  } else if (doc.GetType() == kArrayType) {
1906  // Continue looking
1907  for (typename ValueType::ConstValueIterator v = doc.Begin(); v != doc.End(); ++v) {
1908  if (v->GetType() == kObjectType || v->GetType() == kArrayType) {
1909  resval = FindId(*v, finduri, resptr, localuri, full, here.Append(i, allocator_));
1910  }
1911  if (resval) break;
1912  i++;
1913  }
1914  }
1915  return resval;
1916  }
1917 
1918  // Added by PR #1393
1919  void AddSchemaRefs(SchemaType* schema) {
1920  while (!schemaRef_.Empty()) {
1921  SchemaRefPtr *ref = schemaRef_.template Pop<SchemaRefPtr>(1);
1922  SchemaEntry *entry = schemaMap_.template Push<SchemaEntry>();
1923  new (entry) SchemaEntry(**ref, schema, false, allocator_);
1924  }
1925  }
1926 
1927  // Added by PR #1393
1928  bool IsCyclicRef(const PointerType& pointer) const {
1929  for (const SchemaRefPtr* ref = schemaRef_.template Bottom<SchemaRefPtr>(); ref != schemaRef_.template End<SchemaRefPtr>(); ++ref)
1930  if (pointer == **ref)
1931  return true;
1932  return false;
1933  }
1934 
1935  const SchemaType* GetSchema(const PointerType& pointer) const {
1936  for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1937  if (pointer == target->pointer)
1938  return target->schema;
1939  return 0;
1940  }
1941 
1942  PointerType GetPointer(const SchemaType* schema) const {
1943  for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1944  if (schema == target->schema)
1945  return target->pointer;
1946  return PointerType();
1947  }
1948 
1949  const SchemaType* GetTypeless() const { return typeless_; }
1950 
1951  static const size_t kInitialSchemaMapSize = 64;
1952  static const size_t kInitialSchemaRefSize = 64;
1953 
1954  IRemoteSchemaDocumentProviderType* remoteProvider_;
1955  Allocator *allocator_;
1956  Allocator *ownAllocator_;
1957  const SchemaType* root_;
1958  SchemaType* typeless_;
1959  internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
1960  internal::Stack<Allocator> schemaRef_; // Stores Pointer(s) from $ref(s) until resolved
1961  SValue uri_; // Schema document URI
1962  UriType docId_;
1963 };
1964 
1969 
1971 // GenericSchemaValidator
1972 
1974 
1985 template <
1986  typename SchemaDocumentType,
1988  typename StateAllocator = CrtAllocator>
1989 class GenericSchemaValidator :
1990  public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
1992  public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType> {
1993 public:
1994  typedef typename SchemaDocumentType::SchemaType SchemaType;
1995  typedef typename SchemaDocumentType::PointerType PointerType;
1996  typedef typename SchemaType::EncodingType EncodingType;
1997  typedef typename SchemaType::SValue SValue;
1998  typedef typename EncodingType::Ch Ch;
2001 
2003 
2010  const SchemaDocumentType& schemaDocument,
2011  StateAllocator* allocator = 0,
2012  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2013  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2014  :
2015  schemaDocument_(&schemaDocument),
2016  root_(schemaDocument.GetRoot()),
2017  stateAllocator_(allocator),
2018  ownStateAllocator_(0),
2019  schemaStack_(allocator, schemaStackCapacity),
2020  documentStack_(allocator, documentStackCapacity),
2021  outputHandler_(0),
2022  error_(kObjectType),
2023  currentError_(),
2024  missingDependents_(),
2025  valid_(true),
2026  flags_(kValidateDefaultFlags)
2028  , depth_(0)
2029 #endif
2030  {
2031  }
2032 
2034 
2041  const SchemaDocumentType& schemaDocument,
2042  OutputHandler& outputHandler,
2043  StateAllocator* allocator = 0,
2044  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2045  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2046  :
2047  schemaDocument_(&schemaDocument),
2048  root_(schemaDocument.GetRoot()),
2049  stateAllocator_(allocator),
2050  ownStateAllocator_(0),
2051  schemaStack_(allocator, schemaStackCapacity),
2052  documentStack_(allocator, documentStackCapacity),
2053  outputHandler_(&outputHandler),
2054  error_(kObjectType),
2055  currentError_(),
2056  missingDependents_(),
2057  valid_(true),
2058  flags_(kValidateDefaultFlags)
2060  , depth_(0)
2061 #endif
2062  {
2063  }
2064 
2067  Reset();
2068  RAPIDJSON_DELETE(ownStateAllocator_);
2069  }
2070 
2072  void Reset() {
2073  while (!schemaStack_.Empty())
2074  PopSchema();
2075  documentStack_.Clear();
2076  ResetError();
2077  }
2078 
2080  void ResetError() {
2081  error_.SetObject();
2082  currentError_.SetNull();
2083  missingDependents_.SetNull();
2084  valid_ = true;
2085  }
2086 
2088  void SetValidateFlags(unsigned flags) {
2089  flags_ = flags;
2090  }
2091  virtual unsigned GetValidateFlags() const {
2092  return flags_;
2093  }
2094 
2096  // Implementation of ISchemaValidator
2097  virtual bool IsValid() const {
2098  if (!valid_) return false;
2099  if (GetContinueOnErrors() && !error_.ObjectEmpty()) return false;
2100  return true;
2101  }
2102 
2104  ValueType& GetError() { return error_; }
2105  const ValueType& GetError() const { return error_; }
2106 
2108  // If reporting all errors, the stack will be empty.
2110  return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
2111  }
2112 
2114  // If reporting all errors, the stack will be empty, so return "errors".
2115  const Ch* GetInvalidSchemaKeyword() const {
2116  if (!schemaStack_.Empty()) return CurrentContext().invalidKeyword;
2117  if (GetContinueOnErrors() && !error_.ObjectEmpty()) return (const Ch*)GetErrorsString();
2118  return 0;
2119  }
2120 
2122  // If reporting all errors, the stack will be empty, so return kValidateErrors.
2124  if (!schemaStack_.Empty()) return CurrentContext().invalidCode;
2125  if (GetContinueOnErrors() && !error_.ObjectEmpty()) return kValidateErrors;
2126  return kValidateErrorNone;
2127  }
2128 
2130  // If reporting all errors, the stack will be empty.
2132  if (documentStack_.Empty()) {
2133  return PointerType();
2134  }
2135  else {
2136  return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
2137  }
2138  }
2139 
2140  void NotMultipleOf(int64_t actual, const SValue& expected) {
2141  AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
2142  }
2143  void NotMultipleOf(uint64_t actual, const SValue& expected) {
2144  AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
2145  }
2146  void NotMultipleOf(double actual, const SValue& expected) {
2147  AddNumberError(kValidateErrorMultipleOf, ValueType(actual).Move(), expected);
2148  }
2149  void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) {
2150  AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
2151  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2152  }
2153  void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) {
2154  AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
2155  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2156  }
2157  void AboveMaximum(double actual, const SValue& expected, bool exclusive) {
2158  AddNumberError(exclusive ? kValidateErrorExclusiveMaximum : kValidateErrorMaximum, ValueType(actual).Move(), expected,
2159  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
2160  }
2161  void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) {
2162  AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
2163  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2164  }
2165  void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) {
2166  AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
2167  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2168  }
2169  void BelowMinimum(double actual, const SValue& expected, bool exclusive) {
2170  AddNumberError(exclusive ? kValidateErrorExclusiveMinimum : kValidateErrorMinimum, ValueType(actual).Move(), expected,
2171  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
2172  }
2173 
2174  void TooLong(const Ch* str, SizeType length, SizeType expected) {
2175  AddNumberError(kValidateErrorMaxLength,
2176  ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2177  }
2178  void TooShort(const Ch* str, SizeType length, SizeType expected) {
2179  AddNumberError(kValidateErrorMinLength,
2180  ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
2181  }
2182  void DoesNotMatch(const Ch* str, SizeType length) {
2183  currentError_.SetObject();
2184  currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
2185  AddCurrentError(kValidateErrorPattern);
2186  }
2187 
2188  void DisallowedItem(SizeType index) {
2189  currentError_.SetObject();
2190  currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
2191  AddCurrentError(kValidateErrorAdditionalItems, true);
2192  }
2193  void TooFewItems(SizeType actualCount, SizeType expectedCount) {
2194  AddNumberError(kValidateErrorMinItems,
2195  ValueType(actualCount).Move(), SValue(expectedCount).Move());
2196  }
2197  void TooManyItems(SizeType actualCount, SizeType expectedCount) {
2198  AddNumberError(kValidateErrorMaxItems,
2199  ValueType(actualCount).Move(), SValue(expectedCount).Move());
2200  }
2201  void DuplicateItems(SizeType index1, SizeType index2) {
2202  ValueType duplicates(kArrayType);
2203  duplicates.PushBack(index1, GetStateAllocator());
2204  duplicates.PushBack(index2, GetStateAllocator());
2205  currentError_.SetObject();
2206  currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
2207  AddCurrentError(kValidateErrorUniqueItems, true);
2208  }
2209 
2210  void TooManyProperties(SizeType actualCount, SizeType expectedCount) {
2211  AddNumberError(kValidateErrorMaxProperties,
2212  ValueType(actualCount).Move(), SValue(expectedCount).Move());
2213  }
2214  void TooFewProperties(SizeType actualCount, SizeType expectedCount) {
2215  AddNumberError(kValidateErrorMinProperties,
2216  ValueType(actualCount).Move(), SValue(expectedCount).Move());
2217  }
2219  currentError_.SetArray();
2220  }
2222  currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
2223  }
2225  if (currentError_.Empty())
2226  return false;
2227  ValueType error(kObjectType);
2228  error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
2229  currentError_ = error;
2230  AddCurrentError(kValidateErrorRequired);
2231  return true;
2232  }
2233  void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {
2234  for (SizeType i = 0; i < count; ++i)
2235  MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2236  }
2237  void DisallowedProperty(const Ch* name, SizeType length) {
2238  currentError_.SetObject();
2239  currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
2240  AddCurrentError(kValidateErrorAdditionalProperties, true);
2241  }
2242 
2244  currentError_.SetObject();
2245  }
2247  missingDependents_.SetArray();
2248  }
2249  void AddMissingDependentProperty(const SValue& targetName) {
2250  missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
2251  }
2252  void EndMissingDependentProperties(const SValue& sourceName) {
2253  if (!missingDependents_.Empty()) {
2254  // Create equivalent 'required' error
2255  ValueType error(kObjectType);
2257  error.AddMember(GetMissingString(), missingDependents_.Move(), GetStateAllocator());
2258  AddErrorCode(error, code);
2259  AddErrorInstanceLocation(error, false);
2260  // When appending to a pointer ensure its allocator is used
2261  PointerType schemaRef = GetInvalidSchemaPointer().Append(SchemaType::GetValidateErrorKeyword(kValidateErrorDependencies), &GetInvalidSchemaPointer().GetAllocator());
2262  AddErrorSchemaLocation(error, schemaRef.Append(sourceName.GetString(), sourceName.GetStringLength(), &GetInvalidSchemaPointer().GetAllocator()));
2263  ValueType wrapper(kObjectType);
2264  wrapper.AddMember(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator()).Move(), error, GetStateAllocator());
2265  currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(), wrapper, GetStateAllocator());
2266  }
2267  }
2268  void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) {
2269  currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2270  static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
2271  }
2273  if (currentError_.ObjectEmpty())
2274  return false;
2275  ValueType error(kObjectType);
2276  error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
2277  currentError_ = error;
2278  AddCurrentError(kValidateErrorDependencies);
2279  return true;
2280  }
2281 
2283  currentError_.SetObject();
2284  AddCurrentError(code);
2285  }
2287  currentError_.SetArray();
2288  }
2289  void AddExpectedType(const typename SchemaType::ValueType& expectedType) {
2290  currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2291  }
2292  void EndDisallowedType(const typename SchemaType::ValueType& actualType) {
2293  ValueType error(kObjectType);
2294  error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2295  error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2296  currentError_ = error;
2297  AddCurrentError(kValidateErrorType);
2298  }
2299  void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {
2300  // Treat allOf like oneOf and anyOf to match https://rapidjson.org/md_doc_schema.html#allOf-anyOf-oneOf
2301  AddErrorArray(kValidateErrorAllOf, subvalidators, count);
2302  //for (SizeType i = 0; i < count; ++i) {
2303  // MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2304  //}
2305  }
2306  void NoneOf(ISchemaValidator** subvalidators, SizeType count) {
2307  AddErrorArray(kValidateErrorAnyOf, subvalidators, count);
2308  }
2309  void NotOneOf(ISchemaValidator** subvalidators, SizeType count, bool matched = false) {
2310  AddErrorArray(matched ? kValidateErrorOneOfMatch : kValidateErrorOneOf, subvalidators, count);
2311  }
2312  void Disallowed() {
2313  currentError_.SetObject();
2314  AddCurrentError(kValidateErrorNot);
2315  }
2316 
2317 #define RAPIDJSON_STRING_(name, ...) \
2318  static const StringRefType& Get##name##String() {\
2319  static const Ch s[] = { __VA_ARGS__, '\0' };\
2320  static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
2321  return v;\
2322  }
2323 
2324  RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
2325  RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
2326  RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
2327  RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
2328  RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
2329  RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
2330  RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
2331  RAPIDJSON_STRING_(ErrorCode, 'e', 'r', 'r', 'o', 'r', 'C', 'o', 'd', 'e')
2332  RAPIDJSON_STRING_(ErrorMessage, 'e', 'r', 'r', 'o', 'r', 'M', 'e', 's', 's', 'a', 'g', 'e')
2333  RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
2334 
2335 #undef RAPIDJSON_STRING_
2336 
2337 #if RAPIDJSON_SCHEMA_VERBOSE
2338 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
2339 RAPIDJSON_MULTILINEMACRO_BEGIN\
2340  *documentStack_.template Push<Ch>() = '\0';\
2341  documentStack_.template Pop<Ch>(1);\
2342  internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
2343 RAPIDJSON_MULTILINEMACRO_END
2344 #else
2345 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
2346 #endif
2347 
2348 #define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
2349  if (!valid_) return false; \
2350  if ((!BeginValue() && !GetContinueOnErrors()) || (!CurrentSchema().method arg1 && !GetContinueOnErrors())) {\
2351  RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
2352  return valid_ = false;\
2353  }
2354 
2355 #define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
2356  for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
2357  if (context->hasher)\
2358  static_cast<HasherType*>(context->hasher)->method arg2;\
2359  if (context->validators)\
2360  for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
2361  static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
2362  if (context->patternPropertiesValidators)\
2363  for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
2364  static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
2365  }
2366 
2367 #define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
2368  valid_ = (EndValue() || GetContinueOnErrors()) && (!outputHandler_ || outputHandler_->method arg2);\
2369  return valid_;
2370 
2371 #define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
2372  RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
2373  RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
2374  RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
2375 
2376  bool Null() { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Null, (CurrentContext()), ( )); }
2377  bool Bool(bool b) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Bool, (CurrentContext(), b), (b)); }
2378  bool Int(int i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int, (CurrentContext(), i), (i)); }
2379  bool Uint(unsigned u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint, (CurrentContext(), u), (u)); }
2380  bool Int64(int64_t i) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Int64, (CurrentContext(), i), (i)); }
2381  bool Uint64(uint64_t u) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Uint64, (CurrentContext(), u), (u)); }
2382  bool Double(double d) { RAPIDJSON_SCHEMA_HANDLE_VALUE_(Double, (CurrentContext(), d), (d)); }
2383  bool RawNumber(const Ch* str, SizeType length, bool copy)
2384  { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2385  bool String(const Ch* str, SizeType length, bool copy)
2386  { RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2387 
2388  bool StartObject() {
2389  RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartObject, (CurrentContext()));
2391  return valid_ = !outputHandler_ || outputHandler_->StartObject();
2392  }
2393 
2394  bool Key(const Ch* str, SizeType len, bool copy) {
2395  if (!valid_) return false;
2396  AppendToken(str, len);
2397  if (!CurrentSchema().Key(CurrentContext(), str, len, copy) && !GetContinueOnErrors()) return valid_ = false;
2399  return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2400  }
2401 
2402  bool EndObject(SizeType memberCount) {
2403  if (!valid_) return false;
2405  if (!CurrentSchema().EndObject(CurrentContext(), memberCount) && !GetContinueOnErrors()) return valid_ = false;
2406  RAPIDJSON_SCHEMA_HANDLE_END_(EndObject, (memberCount));
2407  }
2408 
2409  bool StartArray() {
2410  RAPIDJSON_SCHEMA_HANDLE_BEGIN_(StartArray, (CurrentContext()));
2412  return valid_ = !outputHandler_ || outputHandler_->StartArray();
2413  }
2414 
2415  bool EndArray(SizeType elementCount) {
2416  if (!valid_) return false;
2418  if (!CurrentSchema().EndArray(CurrentContext(), elementCount) && !GetContinueOnErrors()) return valid_ = false;
2419  RAPIDJSON_SCHEMA_HANDLE_END_(EndArray, (elementCount));
2420  }
2421 
2422 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
2423 #undef RAPIDJSON_SCHEMA_HANDLE_BEGIN_
2424 #undef RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
2425 #undef RAPIDJSON_SCHEMA_HANDLE_VALUE_
2426 
2427  // Implementation of ISchemaStateFactory<SchemaType>
2428  virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root, const bool inheritContinueOnErrors) {
2429  ISchemaValidator* sv = new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),
2430 #if RAPIDJSON_SCHEMA_VERBOSE
2431  depth_ + 1,
2432 #endif
2433  &GetStateAllocator());
2434  sv->SetValidateFlags(inheritContinueOnErrors ? GetValidateFlags() : GetValidateFlags() & ~(unsigned)kValidateContinueOnErrorFlag);
2435  return sv;
2436  }
2437 
2438  virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2439  GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
2442  }
2443 
2444  virtual void* CreateHasher() {
2445  return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
2446  }
2447 
2448  virtual uint64_t GetHashCode(void* hasher) {
2449  return static_cast<HasherType*>(hasher)->GetHashCode();
2450  }
2451 
2452  virtual void DestroryHasher(void* hasher) {
2453  HasherType* h = static_cast<HasherType*>(hasher);
2454  h->~HasherType();
2456  }
2457 
2458  virtual void* MallocState(size_t size) {
2459  return GetStateAllocator().Malloc(size);
2460  }
2461 
2462  virtual void FreeState(void* p) {
2464  }
2465 
2466 private:
2467  typedef typename SchemaType::Context Context;
2468  typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
2470 
2472  const SchemaDocumentType& schemaDocument,
2473  const SchemaType& root,
2474  const char* basePath, size_t basePathSize,
2476  unsigned depth,
2477 #endif
2478  StateAllocator* allocator = 0,
2479  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2480  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2481  :
2482  schemaDocument_(&schemaDocument),
2483  root_(root),
2484  stateAllocator_(allocator),
2485  ownStateAllocator_(0),
2486  schemaStack_(allocator, schemaStackCapacity),
2487  documentStack_(allocator, documentStackCapacity),
2488  outputHandler_(0),
2489  error_(kObjectType),
2490  currentError_(),
2491  missingDependents_(),
2492  valid_(true),
2493  flags_(kValidateDefaultFlags)
2495  , depth_(depth)
2496 #endif
2497  {
2498  if (basePath && basePathSize)
2499  memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2500  }
2501 
2502  StateAllocator& GetStateAllocator() {
2503  if (!stateAllocator_)
2504  stateAllocator_ = ownStateAllocator_ = RAPIDJSON_NEW(StateAllocator)();
2505  return *stateAllocator_;
2506  }
2507 
2508  bool GetContinueOnErrors() const {
2509  return flags_ & kValidateContinueOnErrorFlag;
2510  }
2511 
2512  bool BeginValue() {
2513  if (schemaStack_.Empty())
2514  PushSchema(root_);
2515  else {
2516  if (CurrentContext().inArray)
2517  internal::TokenHelper<internal::Stack<StateAllocator>, Ch>::AppendIndexToken(documentStack_, CurrentContext().arrayElementIndex);
2518 
2519  if (!CurrentSchema().BeginValue(CurrentContext()) && !GetContinueOnErrors())
2520  return false;
2521 
2522  SizeType count = CurrentContext().patternPropertiesSchemaCount;
2523  const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2524  typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2525  bool valueUniqueness = CurrentContext().valueUniqueness;
2526  RAPIDJSON_ASSERT(CurrentContext().valueSchema);
2527  PushSchema(*CurrentContext().valueSchema);
2528 
2529  if (count > 0) {
2530  CurrentContext().objectPatternValidatorType = patternValidatorType;
2531  ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2532  SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2533  va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
2534  for (SizeType i = 0; i < count; i++)
2535  va[validatorCount++] = CreateSchemaValidator(*sa[i], true); // Inherit continueOnError
2536  }
2537 
2538  CurrentContext().arrayUniqueness = valueUniqueness;
2539  }
2540  return true;
2541  }
2542 
2543  bool EndValue() {
2544  if (!CurrentSchema().EndValue(CurrentContext()) && !GetContinueOnErrors())
2545  return false;
2546 
2547 #if RAPIDJSON_SCHEMA_VERBOSE
2549  schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2550 
2551  *documentStack_.template Push<Ch>() = '\0';
2552  documentStack_.template Pop<Ch>(1);
2553  internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
2554 #endif
2555  void* hasher = CurrentContext().hasher;
2556  uint64_t h = hasher && CurrentContext().arrayUniqueness ? static_cast<HasherType*>(hasher)->GetHashCode() : 0;
2557 
2558  PopSchema();
2559 
2560  if (!schemaStack_.Empty()) {
2561  Context& context = CurrentContext();
2562  // Only check uniqueness if there is a hasher
2563  if (hasher && context.valueUniqueness) {
2564  HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
2565  if (!a)
2566  CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
2567  for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
2568  if (itr->GetUint64() == h) {
2569  DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
2570  // Cleanup before returning if continuing
2571  if (GetContinueOnErrors()) {
2572  a->PushBack(h, GetStateAllocator());
2573  while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/');
2574  }
2576  }
2577  a->PushBack(h, GetStateAllocator());
2578  }
2579  }
2580 
2581  // Remove the last token of document pointer
2582  while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
2583  ;
2584 
2585  return true;
2586  }
2587 
2588  void AppendToken(const Ch* str, SizeType len) {
2589  documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
2590  *documentStack_.template PushUnsafe<Ch>() = '/';
2591  for (SizeType i = 0; i < len; i++) {
2592  if (str[i] == '~') {
2593  *documentStack_.template PushUnsafe<Ch>() = '~';
2594  *documentStack_.template PushUnsafe<Ch>() = '0';
2595  }
2596  else if (str[i] == '/') {
2597  *documentStack_.template PushUnsafe<Ch>() = '~';
2598  *documentStack_.template PushUnsafe<Ch>() = '1';
2599  }
2600  else
2601  *documentStack_.template PushUnsafe<Ch>() = str[i];
2602  }
2603  }
2604 
2605  RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema); }
2606 
2607  RAPIDJSON_FORCEINLINE void PopSchema() {
2608  Context* c = schemaStack_.template Pop<Context>(1);
2609  if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
2610  a->~HashCodeArray();
2612  }
2613  c->~Context();
2614  }
2615 
2616  void AddErrorInstanceLocation(ValueType& result, bool parent) {
2618  PointerType instancePointer = GetInvalidDocumentPointer();
2619  ((parent && instancePointer.GetTokenCount() > 0)
2620  ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2621  : instancePointer).StringifyUriFragment(sb);
2622  ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2623  GetStateAllocator());
2624  result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2625  }
2626 
2627  void AddErrorSchemaLocation(ValueType& result, PointerType schema = PointerType()) {
2629  SizeType len = CurrentSchema().GetURI().GetStringLength();
2630  if (len) memcpy(sb.Push(len), CurrentSchema().GetURI().GetString(), len * sizeof(Ch));
2631  if (schema.GetTokenCount()) schema.StringifyUriFragment(sb);
2632  else GetInvalidSchemaPointer().StringifyUriFragment(sb);
2633  ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2634  GetStateAllocator());
2635  result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2636  }
2637 
2638  void AddErrorCode(ValueType& result, const ValidateErrorCode code) {
2639  result.AddMember(GetErrorCodeString(), code, GetStateAllocator());
2640  }
2641 
2642  void AddError(ValueType& keyword, ValueType& error) {
2643  typename ValueType::MemberIterator member = error_.FindMember(keyword);
2644  if (member == error_.MemberEnd())
2645  error_.AddMember(keyword, error, GetStateAllocator());
2646  else {
2647  if (member->value.IsObject()) {
2648  ValueType errors(kArrayType);
2649  errors.PushBack(member->value, GetStateAllocator());
2650  member->value = errors;
2651  }
2652  member->value.PushBack(error, GetStateAllocator());
2653  }
2654  }
2655 
2656  void AddCurrentError(const ValidateErrorCode code, bool parent = false) {
2657  AddErrorCode(currentError_, code);
2658  AddErrorInstanceLocation(currentError_, parent);
2659  AddErrorSchemaLocation(currentError_);
2660  AddError(ValueType(SchemaType::GetValidateErrorKeyword(code), GetStateAllocator(), false).Move(), currentError_);
2661  }
2662 
2663  void MergeError(ValueType& other) {
2664  for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {
2665  AddError(it->name, it->value);
2666  }
2667  }
2668 
2669  void AddNumberError(const ValidateErrorCode code, ValueType& actual, const SValue& expected,
2670  const typename SchemaType::ValueType& (*exclusive)() = 0) {
2671  currentError_.SetObject();
2672  currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2673  currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2674  if (exclusive)
2675  currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator());
2676  AddCurrentError(code);
2677  }
2678 
2679  void AddErrorArray(const ValidateErrorCode code,
2680  ISchemaValidator** subvalidators, SizeType count) {
2681  ValueType errors(kArrayType);
2682  for (SizeType i = 0; i < count; ++i)
2683  errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
2684  currentError_.SetObject();
2685  currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2686  AddCurrentError(code);
2687  }
2688 
2689  const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
2690  Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
2691  const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
2692 
2693  static const size_t kDefaultSchemaStackCapacity = 1024;
2694  static const size_t kDefaultDocumentStackCapacity = 256;
2695  const SchemaDocumentType* schemaDocument_;
2696  const SchemaType& root_;
2697  StateAllocator* stateAllocator_;
2698  StateAllocator* ownStateAllocator_;
2699  internal::Stack<StateAllocator> schemaStack_;
2700  internal::Stack<StateAllocator> documentStack_;
2701  OutputHandler* outputHandler_;
2702  ValueType error_;
2703  ValueType currentError_;
2704  ValueType missingDependents_;
2705  bool valid_;
2706  unsigned flags_;
2707 #if RAPIDJSON_SCHEMA_VERBOSE
2708  unsigned depth_;
2709 #endif
2710 };
2711 
2713 
2715 // SchemaValidatingReader
2716 
2718 
2727 template <
2728  unsigned parseFlags,
2729  typename InputStream,
2730  typename SourceEncoding,
2731  typename SchemaDocumentType = SchemaDocument,
2732  typename StackAllocator = CrtAllocator>
2734 public:
2735  typedef typename SchemaDocumentType::PointerType PointerType;
2736  typedef typename InputStream::Ch Ch;
2738 
2740 
2744  SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), invalidSchemaCode_(kValidateErrorNone), error_(kObjectType), isValid_(true) {}
2745 
2746  template <typename Handler>
2747  bool operator()(Handler& handler) {
2750  parseResult_ = reader.template Parse<parseFlags>(is_, validator);
2751 
2752  isValid_ = validator.IsValid();
2753  if (isValid_) {
2754  invalidSchemaPointer_ = PointerType();
2755  invalidSchemaKeyword_ = 0;
2756  invalidDocumentPointer_ = PointerType();
2757  error_.SetObject();
2758  }
2759  else {
2760  invalidSchemaPointer_ = validator.GetInvalidSchemaPointer();
2761  invalidSchemaKeyword_ = validator.GetInvalidSchemaKeyword();
2762  invalidSchemaCode_ = validator.GetInvalidSchemaCode();
2763  invalidDocumentPointer_ = validator.GetInvalidDocumentPointer();
2764  error_.CopyFrom(validator.GetError(), allocator_);
2765  }
2766 
2767  return parseResult_;
2768  }
2769 
2770  const ParseResult& GetParseResult() const { return parseResult_; }
2771  bool IsValid() const { return isValid_; }
2772  const PointerType& GetInvalidSchemaPointer() const { return invalidSchemaPointer_; }
2773  const Ch* GetInvalidSchemaKeyword() const { return invalidSchemaKeyword_; }
2774  const PointerType& GetInvalidDocumentPointer() const { return invalidDocumentPointer_; }
2775  const ValueType& GetError() const { return error_; }
2776  ValidateErrorCode GetInvalidSchemaCode() const { return invalidSchemaCode_; }
2777 
2778 private:
2779  InputStream& is_;
2780  const SchemaDocumentType& sd_;
2781 
2782  ParseResult parseResult_;
2783  PointerType invalidSchemaPointer_;
2784  const Ch* invalidSchemaKeyword_;
2785  PointerType invalidDocumentPointer_;
2786  ValidateErrorCode invalidSchemaCode_;
2787  StackAllocator allocator_;
2788  ValueType error_;
2789  bool isValid_;
2790 };
2791 
2793 RAPIDJSON_DIAG_POP
2794 
2795 #endif // RAPIDJSON_SCHEMA_H_
GenericValue::MemberIterator
GenericMemberIterator< false, Encoding, Allocator >::Iterator MemberIterator
Member iterator for iterating in object.
Definition: document.h:676
kValidateErrorAllOf
@ kValidateErrorAllOf
Property did not match all of the sub-schemas specified by 'allOf'.
Definition: error.h:193
GenericSchemaValidator::TooManyProperties
void TooManyProperties(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:2210
internal::IValidationErrorHandler::StartDisallowedType
virtual void StartDisallowedType()=0
GenericPointer
Represents a JSON Pointer. Use Pointer for UTF8 encoding and default allocator.
Definition: fwd.h:126
internal::SchemaValidationContext::patternPropertiesValidatorCount
SizeType patternPropertiesValidatorCount
Definition: schema.h:409
GenericSchemaValidator::TooFewItems
void TooFewItems(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:2193
GenericSchemaValidator::TooShort
void TooShort(const Ch *str, SizeType length, SizeType expected)
Definition: schema.h:2178
internal::IValidationErrorHandler::BelowMinimum
virtual void BelowMinimum(int64_t actual, const SValue &expected, bool exclusive)=0
RAPIDJSON_NAMESPACE_END
#define RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
kValidateErrors
@ kValidateErrors
Top level error code when kValidateContinueOnErrorsFlag set.
Definition: error.h:163
internal::Schema::Key
bool Key(Context &context, const Ch *str, SizeType len, bool) const
Definition: schema.h:955
IGenericRemoteSchemaDocumentProvider::ValueType
SchemaDocumentType::ValueType ValueType
Definition: schema.h:1598
kNullType
@ kNullType
null
Definition: rapidjson.h:730
kValidateNoFlags
@ kValidateNoFlags
No flags are set.
Definition: schema.h:143
internal::IValidationErrorHandler::AddExpectedType
virtual void AddExpectedType(const typename SchemaType::ValueType &expectedType)=0
uri.h
RAPIDJSON_NAMESPACE_BEGIN
#define RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
internal::IValidationErrorHandler::EndMissingProperties
virtual bool EndMissingProperties()=0
kValidateErrorMaxProperties
@ kValidateErrorMaxProperties
Object has more members than 'maxProperties' value.
Definition: error.h:181
GenericSchemaDocument::~GenericSchemaDocument
~GenericSchemaDocument()
Destructor.
Definition: schema.h:1703
RAPIDJSON_SCHEMA_HANDLE_VALUE_
#define RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2)
Definition: schema.h:2371
GenericSchemaValidator::RawNumber
bool RawNumber(const Ch *str, SizeType length, bool copy)
Definition: schema.h:2383
internal::IValidationErrorHandler::TooLong
virtual void TooLong(const Ch *str, SizeType length, SizeType expected)=0
internal::SchemaValidationContext::hasher
void * hasher
Definition: schema.h:404
kValidateErrorMaxLength
@ kValidateErrorMaxLength
String is longer than the 'maxLength' value.
Definition: error.h:172
internal::Schema::ErrorHandler
IValidationErrorHandler< Schema > ErrorHandler
Definition: schema.h:435
internal::Hasher::GetHashCode
uint64_t GetHashCode() const
Definition: schema.h:300
internal::SchemaValidationContext::patternPropertiesSchemas
const SchemaType ** patternPropertiesSchemas
Definition: schema.h:410
SchemaValidatingReader::operator()
bool operator()(Handler &handler)
Definition: schema.h:2747
GenericSchemaDocument::ValueType
ValueT ValueType
Definition: schema.h:1621
kFalseType
@ kFalseType
false
Definition: rapidjson.h:731
internal::SchemaValidationContext::kPatternValidatorWithProperty
@ kPatternValidatorWithProperty
Definition: schema.h:352
GenericSchemaValidator::GetHashCode
virtual uint64_t GetHashCode(void *hasher)
Definition: schema.h:2448
Allocator
Concept for allocating, resizing and freeing memory block.
internal::Hasher::StartObject
bool StartObject()
Definition: schema.h:277
internal::IValidationErrorHandler::AddMissingDependentProperty
virtual void AddMissingDependentProperty(const SValue &targetName)=0
internal::Hasher::Number::U
Definition: schema.h:308
kArrayType
@ kArrayType
array
Definition: rapidjson.h:734
internal::SchemaValidationContext::valueUniqueness
bool valueUniqueness
Definition: schema.h:417
GenericValue::ConstValueIterator
const typedef GenericValue * ConstValueIterator
Constant value iterator for iterating in array.
Definition: document.h:679
internal::Schema::GetPointer
const PointerType & GetPointer() const
Definition: schema.h:726
kValidateErrorOneOf
@ kValidateErrorOneOf
Property did not match any of the sub-schemas specified by 'oneOf'.
Definition: error.h:191
kValidateContinueOnErrorFlag
@ kValidateContinueOnErrorFlag
Don't stop after first validation error.
Definition: schema.h:144
internal::Schema::GetValidateErrorKeyword
static const ValueType & GetValidateErrorKeyword(ValidateErrorCode validateErrorCode)
Definition: schema.h:1081
internal::SchemaValidationContext::ValueType
SchemaType::ValueType ValueType
Definition: schema.h:347
GenericSchemaValidator::EndDependencyErrors
bool EndDependencyErrors()
Definition: schema.h:2272
kValidateErrorExclusiveMaximum
@ kValidateErrorExclusiveMaximum
Number is greater than or equal to the 'maximum' value.
Definition: error.h:168
SchemaValidatingReader::GetParseResult
const ParseResult & GetParseResult() const
Definition: schema.h:2770
internal::ISchemaValidator
Definition: schema.h:162
GenericSchemaValidator::Uint
bool Uint(unsigned u)
Definition: schema.h:2379
internal::SchemaValidationContext::SchemaValidatorFactoryType
ISchemaStateFactory< SchemaType > SchemaValidatorFactoryType
Definition: schema.h:345
GenericSchemaValidator::EndMissingDependentProperties
void EndMissingDependentProperties(const SValue &sourceName)
Definition: schema.h:2252
GenericSchemaValidator::DuplicateItems
void DuplicateItems(SizeType index1, SizeType index2)
Definition: schema.h:2201
GenericSchemaValidator::Disallowed
void Disallowed()
Definition: schema.h:2312
Type
Type
Type of JSON value.
Definition: rapidjson.h:729
GenericSchemaValidator::GetInvalidDocumentPointer
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
Definition: schema.h:2131
internal::Hasher::String
bool String(const Ch *str, SizeType len, bool)
Definition: schema.h:272
GenericSchemaValidator::NotAllOf
void NotAllOf(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2299
internal::Hasher::Number::U::u
uint64_t u
Definition: schema.h:309
kValidateDefaultFlags
@ kValidateDefaultFlags
Default validate flags. Can be customized by defining RAPIDJSON_VALIDATE_DEFAULT_FLAGS.
Definition: schema.h:145
GenericSchemaValidator::EndObject
bool EndObject(SizeType memberCount)
Definition: schema.h:2402
GenericSchemaValidator::StartDependencyErrors
void StartDependencyErrors()
Definition: schema.h:2243
internal::Hasher::Bool
bool Bool(bool b)
Definition: schema.h:254
IGenericRemoteSchemaDocumentProvider::~IGenericRemoteSchemaDocumentProvider
virtual ~IGenericRemoteSchemaDocumentProvider()
Definition: schema.h:1601
internal::SchemaValidationContext::validators
ISchemaValidator ** validators
Definition: schema.h:406
document.h
internal::SchemaValidationContext::error_handler
ErrorHandlerType & error_handler
Definition: schema.h:399
GenericSchemaValidator::StartDisallowedType
void StartDisallowedType()
Definition: schema.h:2286
RAPIDJSON_SCHEMA_HANDLE_END_
#define RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)
Definition: schema.h:2367
internal::Hasher::Uint
bool Uint(unsigned u)
Definition: schema.h:256
internal::IValidationErrorHandler::NotOneOf
virtual void NotOneOf(ISchemaValidator **subvalidators, SizeType count, bool matched)=0
GenericSchemaValidator::AddExpectedType
void AddExpectedType(const typename SchemaType::ValueType &expectedType)
Definition: schema.h:2289
internal::Hasher::EndObject
bool EndObject(SizeType memberCount)
Definition: schema.h:279
SchemaValidatingReader::ValueType
GenericValue< SourceEncoding, StackAllocator > ValueType
Definition: schema.h:2737
kObjectType
@ kObjectType
object
Definition: rapidjson.h:733
GenericSchemaValidator::SValue
SchemaType::SValue SValue
Definition: schema.h:1997
internal::Hasher::EndArray
bool EndArray(SizeType elementCount)
Definition: schema.h:289
internal::Hasher::RawNumber
bool RawNumber(const Ch *str, SizeType len, bool)
Definition: schema.h:267
parent
HWND parent
Definition: error_notice.cpp:21
exclusive
The original diffuse textures are from the NVIDIA texture with other maps generated from them by Steve Streeting The following license applies to all textures Single Product or Project Use of NVSDK Art Imagery THIS IS A LEGAL immediately delete the NVSDK Art Imagery from your hard disk If you proceed to use any of the you thereby signify that you have agreed to all of the terms and conditions set forth below You may not modify or distribute the Images except in strict accordance with this License Agreement Company hereby grants to you the following non exclusive
Definition: TextureUsageAgreement.txt:6
internal::IValidationErrorHandler::DisallowedItem
virtual void DisallowedItem(SizeType index)=0
IGenericRemoteSchemaDocumentProvider
Definition: fwd.h:133
kValidateErrorEnum
@ kValidateErrorEnum
Property has a value that is not one of its allowed enumerated values.
Definition: error.h:188
internal::Schema::StartArray
bool StartArray(Context &context) const
Definition: schema.h:1053
copy
ARPHIC PUBLIC LICENSE Ltd Yung Chi Taiwan All rights reserved except as specified below Everyone is permitted to copy and distribute verbatim copies of this license but changing it is forbidden Preamble The licenses for most software are designed to take away your freedom to share and change it By the ARPHIC PUBLIC LICENSE specifically permits and encourages you to use this provided that you give the recipients all the rights that we gave you and make sure they can get the modifications of this software Legal Terms Font means the TrueType fonts AR PL Mingti2L AR PL KaitiM AR PL KaitiM and the derivatives of those fonts created through any modification including modifying reordering converting changing font or adding deleting some characters in from glyph table PL means Public License Copyright Holder means whoever is named in the copyright or copyrights for the Font You means the or person redistributing or modifying the Font Freely Available means that you have the freedom to copy or modify the Font as well as redistribute copies of the Font under the same conditions you not price If you you can charge for this service Copying &Distribution You may copy and distribute verbatim copies of this Font in any without provided that you retain this license including modifying reordering converting changing font or adding deleting some characters in from glyph and copy and distribute such modifications under the terms of Section provided that the following conditions are such as by offering access to copy the modifications from a designated or distributing the modifications on a medium customarily used for software interchange c If the modified fonts normally reads commands interactively when you must cause when started running for such interactive use in the most ordinary to print or display an announcement including an appropriate copyright notice and a notice that there is no and telling the user how to view a copy of this License These requirements apply to the modified work as a whole If identifiable sections of that work are not derived from the and can be reasonably considered independent and separate works in then this License and its do not apply to those sections when you distribute them as separate works mere aggregation of another work not based on the Font with the Font on a volume of a storage or distribution medium does not bring the other work under the scope of this License Condition Subsequent You may not copy
Definition: ARPHICPL.TXT:41
GenericSchemaValidator::Key
bool Key(const Ch *str, SizeType len, bool copy)
Definition: schema.h:2394
internal::ISchemaValidator::~ISchemaValidator
virtual ~ISchemaValidator()
Definition: schema.h:164
GenericStringBuffer::Push
Ch * Push(size_t count)
Definition: stringbuffer.h:69
internal::Hasher::Int
bool Int(int i)
Definition: schema.h:255
GenericSchemaValidator::AboveMaximum
void AboveMaximum(double actual, const SValue &expected, bool exclusive)
Definition: schema.h:2157
GenericStringBuffer
Represents an in-memory output stream.
Definition: fwd.h:59
RAPIDJSON_VALIDATE_DEFAULT_FLAGS
#define RAPIDJSON_VALIDATE_DEFAULT_FLAGS
User-defined kValidateDefaultFlags definition.
Definition: schema.h:136
GenericUri::GetBaseStringLength
SizeType GetBaseStringLength() const
Definition: uri.h:106
internal::IValidationErrorHandler::EndMissingDependentProperties
virtual void EndMissingDependentProperties(const SValue &sourceName)=0
internal::Hasher::Key
bool Key(const Ch *str, SizeType len, bool copy)
Definition: schema.h:278
GenericSchemaValidator::NotOneOf
void NotOneOf(ISchemaValidator **subvalidators, SizeType count, bool matched=false)
Definition: schema.h:2309
GenericSchemaValidator::AboveMaximum
void AboveMaximum(uint64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:2153
internal::ISchemaStateFactory::CreateSchemaValidator
virtual ISchemaValidator * CreateSchemaValidator(const SchemaType &, const bool inheritContinueOnErrors)=0
internal::SchemaValidationContext::arrayElementIndex
SizeType arrayElementIndex
Definition: schema.h:414
GenericSchemaValidator::EndMissingProperties
bool EndMissingProperties()
Definition: schema.h:2224
GenericSchemaValidator::Int64
bool Int64(int64_t i)
Definition: schema.h:2380
GenericSchemaValidator::StringRefType
GenericStringRef< Ch > StringRefType
Definition: schema.h:1999
y
font DisplayOffset y
Definition: README.txt:68
kValidateErrorNone
@ kValidateErrorNone
No error.
Definition: error.h:164
internal::IValidationErrorHandler::StartMissingDependentProperties
virtual void StartMissingDependentProperties()=0
SizeType
RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:415
kValidateErrorType
@ kValidateErrorType
Property has a type that is not allowed by the schema..
Definition: error.h:189
GenericSchemaValidator::Null
bool Null()
Definition: schema.h:2376
GenericSchemaValidator::BelowMinimum
void BelowMinimum(double actual, const SValue &expected, bool exclusive)
Definition: schema.h:2169
GenericSchemaValidator::IsValid
virtual bool IsValid() const
Checks whether the current state is valid.
Definition: schema.h:2097
internal::GenericRegex
Regular expression engine with subset of ECMAscript grammar.
Definition: regex.h:110
internal::ISchemaStateFactory::CreateHasher
virtual void * CreateHasher()=0
internal::Hasher::Ch
Encoding::Ch Ch
Definition: schema.h:249
internal::IValidationErrorHandler::TooShort
virtual void TooShort(const Ch *str, SizeType length, SizeType expected)=0
stringbuffer.h
allocator
Blam::LinearAllocator allocator
– TO BE FILLED IN BY VERTIGO –
Definition: main.cpp:76
kValidateErrorMinItems
@ kValidateErrorMinItems
Array is shorter than the 'minItems' value.
Definition: error.h:177
internal::Hasher::Number::U::i
int64_t i
Definition: schema.h:310
SchemaValidatingReader::GetError
const ValueType & GetError() const
Definition: schema.h:2775
GenericSchemaValidator::DoesNotMatch
void DoesNotMatch(const Ch *str, SizeType length)
Definition: schema.h:2182
GenericSchemaValidator::SetValidateFlags
void SetValidateFlags(unsigned flags)
Implementation of ISchemaValidator.
Definition: schema.h:2088
kStringType
@ kStringType
string
Definition: rapidjson.h:735
internal::IValidationErrorHandler::StartDependencyErrors
virtual void StartDependencyErrors()=0
uint64_t
unsigned long long uint64_t
Definition: stdint.h:18
internal::IValidationErrorHandler::Ch
SchemaType::Ch Ch
Definition: schema.h:192
internal::Schema::Schema
Schema(SchemaDocumentType *schemaDocument, const PointerType &p, const ValueType &value, const ValueType &document, AllocatorType *allocator, const UriType &id=UriType())
Definition: schema.h:439
internal::Schema::EndObject
bool EndObject(Context &context, SizeType memberCount) const
Definition: schema.h:1006
internal::Hasher::Double
bool Double(double d)
Definition: schema.h:259
internal::ISchemaValidator::GetValidateFlags
virtual unsigned GetValidateFlags() const =0
internal::IValidationErrorHandler::NotMultipleOf
virtual void NotMultipleOf(int64_t actual, const SValue &expected)=0
GenericSchemaValidator::TooManyItems
void TooManyItems(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:2197
GenericSchemaValidator::StartMissingDependentProperties
void StartMissingDependentProperties()
Definition: schema.h:2246
GenericSchemaValidator::~GenericSchemaValidator
~GenericSchemaValidator()
Destructor.
Definition: schema.h:2066
RAPIDJSON_ASSERT
#define RAPIDJSON_ASSERT(x)
Assertion.
Definition: rapidjson.h:437
internal::IValidationErrorHandler::TooFewItems
virtual void TooFewItems(SizeType actualCount, SizeType expectedCount)=0
SchemaValidatingReader::GetInvalidSchemaKeyword
const Ch * GetInvalidSchemaKeyword() const
Definition: schema.h:2773
GenericStringBuffer::GetString
const Ch * GetString() const
Definition: stringbuffer.h:73
internal::ISchemaStateFactory::MallocState
virtual void * MallocState(size_t size)=0
GenericSchemaValidator::SchemaType
SchemaDocumentType::SchemaType SchemaType
Definition: schema.h:1994
internal::IValidationErrorHandler::NotAllOf
virtual void NotAllOf(ISchemaValidator **subvalidators, SizeType count)=0
GenericSchemaValidator::TooFewProperties
void TooFewProperties(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:2214
internal::Schema
Definition: schema.h:157
ValidateFlag
ValidateFlag
Combination of validate flags.
Definition: schema.h:142
internal::IValidationErrorHandler::TooFewProperties
virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount)=0
GenericSchemaValidator::GetInvalidSchemaPointer
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
Definition: schema.h:2109
kValidateErrorOneOfMatch
@ kValidateErrorOneOfMatch
Property matched more than one of the sub-schemas specified by 'oneOf'.
Definition: error.h:192
GenericSchemaValidator::GetError
const ValueType & GetError() const
Definition: schema.h:2105
internal::Schema::Null
bool Null(Context &context) const
Definition: schema.h:848
GenericSchemaValidator::StartObject
bool StartObject()
Definition: schema.h:2388
GenericSchemaValidator::BelowMinimum
void BelowMinimum(int64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:2161
internal::Schema::UriType
GenericUri< ValueType, AllocatorType > UriType
Definition: schema.h:436
internal::IValidationErrorHandler::EndDependencyErrors
virtual bool EndDependencyErrors()=0
IGenericRemoteSchemaDocumentProvider::Ch
SchemaDocumentType::Ch Ch
Definition: schema.h:1597
RAPIDJSON_SCHEMA_HANDLE_BEGIN_
#define RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)
Definition: schema.h:2348
GenericSchemaValidator::PropertyViolations
void PropertyViolations(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2233
internal::Schema::EndArray
bool EndArray(Context &context, SizeType elementCount) const
Definition: schema.h:1065
GenericSchemaValidator::GenericSchemaValidator
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor without output handler.
Definition: schema.h:2009
internal::IValidationErrorHandler::PropertyViolations
virtual void PropertyViolations(ISchemaValidator **subvalidators, SizeType count)=0
internal::Schema::StartObject
bool StartObject(Context &context) const
Definition: schema.h:934
a
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1249
pointer.h
SchemaValidatingReader::GetInvalidSchemaPointer
const PointerType & GetInvalidSchemaPointer() const
Definition: schema.h:2772
GenericSchemaValidator::AddDependencySchemaError
void AddDependencySchemaError(const SValue &sourceName, ISchemaValidator *subvalidator)
Definition: schema.h:2268
kNumberType
@ kNumberType
number
Definition: rapidjson.h:736
internal::SchemaValidationContext::SchemaValidationContext
SchemaValidationContext(SchemaValidatorFactoryType &f, ErrorHandlerType &eh, const SchemaType *s)
Definition: schema.h:356
internal::Schema::GetURI
const SValue & GetURI() const
Definition: schema.h:718
GenericSchemaValidator::EndArray
bool EndArray(SizeType elementCount)
Definition: schema.h:2415
SchemaValidatingReader::GetInvalidSchemaCode
ValidateErrorCode GetInvalidSchemaCode() const
Definition: schema.h:2776
GenericSchemaValidator::AddMissingProperty
void AddMissingProperty(const SValue &name)
Definition: schema.h:2221
kValidateErrorUniqueItems
@ kValidateErrorUniqueItems
Array has duplicate items but 'uniqueItems' is true.
Definition: error.h:178
document
ARPHIC PUBLIC LICENSE Ltd Yung Chi Taiwan All rights reserved except as specified below Everyone is permitted to copy and distribute verbatim copies of this license document
Definition: ARPHICPL.TXT:7
GenericSchemaValidator::GenericSchemaValidator
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, OutputHandler &outputHandler, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor with output handler.
Definition: schema.h:2040
internal::Schema::SValue
GenericValue< EncodingType, AllocatorType > SValue
Definition: schema.h:434
internal::IValidationErrorHandler::TooManyItems
virtual void TooManyItems(SizeType actualCount, SizeType expectedCount)=0
SchemaValidatingReader
A helper class for parsing with validation.
Definition: schema.h:2733
SchemaValidatingReader::SchemaValidatingReader
SchemaValidatingReader(InputStream &is, const SchemaDocumentType &sd)
Constructor.
Definition: schema.h:2744
GenericSchemaDocument::UriType
GenericUri< ValueType, Allocator > UriType
Definition: schema.h:1629
GenericSchemaValidator::Ch
EncodingType::Ch Ch
Definition: schema.h:1998
SchemaValidatingReader::GetInvalidDocumentPointer
const PointerType & GetInvalidDocumentPointer() const
Definition: schema.h:2774
GenericSchemaValidator::FreeState
virtual void FreeState(void *p)
Definition: schema.h:2462
MemoryPoolAllocator
Default memory allocator used by the parser and DOM.
Definition: allocators.h:129
ParseResult
Result of parsing (wraps ParseErrorCode)
Definition: error.h:106
RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
#define RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)
Definition: schema.h:2355
internal::Schema::ValueType
SchemaDocumentType::ValueType ValueType
Definition: schema.h:427
internal::IValidationErrorHandler::~IValidationErrorHandler
virtual ~IValidationErrorHandler()
Definition: schema.h:195
int64_t
long long int64_t
Definition: stdint.h:14
GenericSchemaValidator::CreateSchemaValidator
virtual ISchemaValidator * CreateSchemaValidator(const SchemaType &root, const bool inheritContinueOnErrors)
Definition: schema.h:2428
GenericSchemaValidator::CreateHasher
virtual void * CreateHasher()
Definition: schema.h:2444
internal::Schema::GetId
const UriType & GetId() const
Definition: schema.h:722
BaseReaderHandler< typename SchemaDocumentType::SchemaType::EncodingType >
GenericSchemaValidator::DisallowedValue
void DisallowedValue(const ValidateErrorCode code=kValidateErrorEnum)
Definition: schema.h:2282
GenericSchemaValidator::StartArray
bool StartArray()
Definition: schema.h:2409
internal::Hasher::StartArray
bool StartArray()
Definition: schema.h:288
internal::ISchemaStateFactory
Definition: schema.h:174
internal::IValidationErrorHandler::DuplicateItems
virtual void DuplicateItems(SizeType index1, SizeType index2)=0
GenericSchemaValidator::TooLong
void TooLong(const Ch *str, SizeType length, SizeType expected)
Definition: schema.h:2174
GenericSchemaValidator::DisallowedProperty
void DisallowedProperty(const Ch *name, SizeType length)
Definition: schema.h:2237
internal::Schema::Uint64
bool Uint64(Context &context, uint64_t u) const
Definition: schema.h:882
GenericSchemaValidator::GetError
ValueType & GetError()
Gets the error object.
Definition: schema.h:2104
GenericSchemaValidator::DestroySchemaValidator
virtual void DestroySchemaValidator(ISchemaValidator *validator)
Definition: schema.h:2438
kValidateErrorPatternProperties
@ kValidateErrorPatternProperties
See other errors.
Definition: error.h:185
BlamTagFieldType::Boolean
@ Boolean
Indicates that the field is a boolean.
RAPIDJSON_INVALID_KEYWORD_RETURN
#define RAPIDJSON_INVALID_KEYWORD_RETURN(code)
Definition: schema.h:118
GenericStringBuffer::GetSize
size_t GetSize() const
Get the size of string in bytes in the string buffer.
Definition: stringbuffer.h:82
it
ARPHIC PUBLIC LICENSE Ltd Yung Chi Taiwan All rights reserved except as specified below Everyone is permitted to copy and distribute verbatim copies of this license but changing it is forbidden Preamble The licenses for most software are designed to take away your freedom to share and change it By the ARPHIC PUBLIC LICENSE specifically permits and encourages you to use this provided that you give the recipients all the rights that we gave you and make sure they can get the modifications of this software Legal Terms Font means the TrueType fonts AR PL Mingti2L AR PL KaitiM AR PL KaitiM and the derivatives of those fonts created through any modification including modifying reordering converting changing font or adding deleting some characters in from glyph table PL means Public License Copyright Holder means whoever is named in the copyright or copyrights for the Font You means the or person redistributing or modifying the Font Freely Available means that you have the freedom to copy or modify the Font as well as redistribute copies of the Font under the same conditions you not price If you you can charge for this service Copying &Distribution You may copy and distribute verbatim copies of this Font in any without provided that you retain this license including modifying reordering converting changing font or adding deleting some characters in from glyph and copy and distribute such modifications under the terms of Section provided that the following conditions are such as by offering access to copy the modifications from a designated or distributing the modifications on a medium customarily used for software interchange c If the modified fonts normally reads commands interactively when you must cause it
Definition: ARPHICPL.TXT:36
internal::SchemaValidationContext::kPatternValidatorOnly
@ kPatternValidatorOnly
Definition: schema.h:351
Blam::Globals::Object
@ Object
Unknown. Referenced within the hs_doc from Halo 2 Sapien.
Definition: globals.h:47
internal::Schema::PointerType
SchemaDocumentType::PointerType PointerType
Definition: schema.h:429
GenericSchemaValidator::GetInvalidSchemaKeyword
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
Definition: schema.h:2115
regex.h
GenericSchemaDocument::PointerType
GenericPointer< ValueType, Allocator > PointerType
Definition: schema.h:1627
GenericSchemaValidator::Double
bool Double(double d)
Definition: schema.h:2382
kValidateErrorMinLength
@ kValidateErrorMinLength
String is longer than the 'maxLength' value.
Definition: error.h:173
GenericSchemaValidator::PointerType
SchemaDocumentType::PointerType PointerType
Definition: schema.h:1995
internal::IValidationErrorHandler::StartMissingProperties
virtual void StartMissingProperties()=0
RAPIDJSON_STRING_
#define RAPIDJSON_STRING_(name,...)
Definition: schema.h:2317
GenericSchemaValidator::NotMultipleOf
void NotMultipleOf(uint64_t actual, const SValue &expected)
Definition: schema.h:2143
GenericSchemaDocument::AllocatorType
Allocator AllocatorType
Definition: schema.h:1623
internal::Hasher::Uint64
bool Uint64(uint64_t u)
Definition: schema.h:258
IGenericRemoteSchemaDocumentProvider::AllocatorType
SchemaDocumentType::AllocatorType AllocatorType
Definition: schema.h:1599
Free
void Free(A &a, T *p, size_t n=1)
Definition: allocators.h:447
internal::Schema::EncodingType
ValueType::EncodingType EncodingType
Definition: schema.h:430
internal::Hasher
Definition: schema.h:247
GenericSchemaValidator::EndDisallowedType
void EndDisallowedType(const typename SchemaType::ValueType &actualType)
Definition: schema.h:2292
RAPIDJSON_NEW
#define RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:712
RAPIDJSON_DELETE
#define RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:716
GenericReader
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: fwd.h:88
internal::SchemaValidationContext::patternPropertiesSchemaCount
SizeType patternPropertiesSchemaCount
Definition: schema.h:411
internal::SchemaValidationContext
Definition: schema.h:343
internal::Stack
A type-unsafe stack for storing different types of data.
Definition: stack.h:37
GenericSchemaValidator::String
bool String(const Ch *str, SizeType length, bool copy)
Definition: schema.h:2385
GenericSchemaDocument::GetURI
const SValue & GetURI() const
Definition: schema.h:1715
GenericSchemaDocument::IRemoteSchemaDocumentProviderType
IGenericRemoteSchemaDocumentProvider< GenericSchemaDocument > IRemoteSchemaDocumentProviderType
Definition: schema.h:1622
internal::SchemaValidationContext::validatorCount
SizeType validatorCount
Definition: schema.h:407
SchemaValidatingReader::PointerType
SchemaDocumentType::PointerType PointerType
Definition: schema.h:2735
GenericValue< EncodingType, AllocatorType >
internal::ISchemaStateFactory::DestroySchemaValidator
virtual void DestroySchemaValidator(ISchemaValidator *validator)=0
internal::IValidationErrorHandler::DisallowedValue
virtual void DisallowedValue(const ValidateErrorCode code)=0
internal::Hasher::Int64
bool Int64(int64_t i)
Definition: schema.h:257
GenericSchemaDocument::EncodingType
ValueType::EncodingType EncodingType
Definition: schema.h:1624
internal::SchemaValidationContext::arrayUniqueness
bool arrayUniqueness
Definition: schema.h:418
kValidateErrorAdditionalItems
@ kValidateErrorAdditionalItems
Array has additional items that are not allowed by the schema.
Definition: error.h:179
internal::ISchemaStateFactory::DestroryHasher
virtual void DestroryHasher(void *hasher)=0
kValidateErrorDependencies
@ kValidateErrorDependencies
Object has missing property or schema dependencies.
Definition: error.h:186
kValidateErrorAdditionalProperties
@ kValidateErrorAdditionalProperties
Object has additional members that are not allowed by the schema.
Definition: error.h:184
x
config GlyphExtraSpacing x
Definition: README.txt:30
internal::Schema::String
bool String(Context &context, const Ch *str, SizeType length, bool) const
Definition: schema.h:906
IRemoteSchemaDocumentProvider
IGenericRemoteSchemaDocumentProvider< SchemaDocument > IRemoteSchemaDocumentProvider
IGenericRemoteSchemaDocumentProvider using SchemaDocument.
Definition: schema.h:1968
kValidateErrorPattern
@ kValidateErrorPattern
String does not match the 'pattern' regular expression.
Definition: error.h:174
pointer
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1249
GenericSchemaDocument::SValue
GenericValue< EncodingType, AllocatorType > SValue
Definition: schema.h:1628
internal::IValidationErrorHandler::NoneOf
virtual void NoneOf(ISchemaValidator **subvalidators, SizeType count)=0
GenericSchemaValidator::GetInvalidSchemaCode
ValidateErrorCode GetInvalidSchemaCode() const
Gets the error code of invalid schema.
Definition: schema.h:2123
SchemaValidatingReader::IsValid
bool IsValid() const
Definition: schema.h:2771
GenericSchemaValidator::AboveMaximum
void AboveMaximum(int64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:2149
kValidateErrorMaximum
@ kValidateErrorMaximum
Number is greater than the 'maximum' value.
Definition: error.h:167
kTrueType
@ kTrueType
true
Definition: rapidjson.h:732
internal::SchemaValidationContext::Ch
ValueType::Ch Ch
Definition: schema.h:348
internal::IValidationErrorHandler
Definition: schema.h:190
GenericUri::GetBaseString
const Ch * GetBaseString() const
Definition: uri.h:105
value
Offset font vertically by altering the io Font DisplayOffset value
Definition: README.txt:67
GenericSchemaValidator::Bool
bool Bool(bool b)
Definition: schema.h:2377
internal::Hasher::Null
bool Null()
Definition: schema.h:253
kValidateErrorMaxItems
@ kValidateErrorMaxItems
Array is longer than the 'maxItems' value.
Definition: error.h:176
internal::Schema::Uint
bool Uint(Context &context, unsigned u) const
Definition: schema.h:870
GenericSchemaValidator::DisallowedItem
void DisallowedItem(SizeType index)
Definition: schema.h:2188
internal::Schema::EndValue
RAPIDJSON_FORCEINLINE bool EndValue(Context &context) const
Definition: schema.h:761
internal::SchemaValidationContext::arrayElementHashCodes
void * arrayElementHashCodes
Definition: schema.h:405
internal::IValidationErrorHandler::DoesNotMatch
virtual void DoesNotMatch(const Ch *str, SizeType length)=0
internal::Schema::Bool
bool Bool(Context &context, bool) const
Definition: schema.h:856
GenericSchemaValidator::GetValidateFlags
virtual unsigned GetValidateFlags() const
Definition: schema.h:2091
internal::Schema::BeginValue
bool BeginValue(Context &context) const
Definition: schema.h:730
GenericStringRef
Reference to a constant string (not taking a copy)
Definition: document.h:346
internal::TokenHelper
Definition: schema.h:1560
internal::Hasher::Hasher
Hasher(Allocator *allocator=0, size_t stackCapacity=kDefaultSize)
Definition: schema.h:251
GenericSchemaValidator::StartMissingProperties
void StartMissingProperties()
Definition: schema.h:2218
internal::Schema::Int64
bool Int64(Context &context, int64_t i) const
Definition: schema.h:876
en.h
ValidateErrorCode
ValidateErrorCode
Error codes when validating.
Definition: error.h:162
SchemaDocument
GenericSchemaDocument< Value > SchemaDocument
GenericSchemaDocument using Value type.
Definition: schema.h:1966
SchemaValidatingReader::Ch
InputStream::Ch Ch
Definition: schema.h:2736
GenericSchemaValidator::ResetError
void ResetError()
Reset the error state.
Definition: schema.h:2080
internal::SchemaValidationContext::ErrorHandlerType
IValidationErrorHandler< SchemaType > ErrorHandlerType
Definition: schema.h:346
CrtAllocator
C-runtime library allocator.
Definition: allocators.h:82
internal::Schema::~Schema
~Schema()
Definition: schema.h:697
GenericSchemaValidator
JSON Schema Validator.
Definition: fwd.h:145
kValidateErrorMinProperties
@ kValidateErrorMinProperties
Object has less members than 'minProperties' value.
Definition: error.h:182
GenericSchemaValidator::AddMissingDependentProperty
void AddMissingDependentProperty(const SValue &targetName)
Definition: schema.h:2249
internal::u64toa
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:126
internal::IValidationErrorHandler::AboveMaximum
virtual void AboveMaximum(int64_t actual, const SValue &expected, bool exclusive)=0
GenericSchemaValidator::EncodingType
SchemaType::EncodingType EncodingType
Definition: schema.h:1996
GenericSchemaValidator::Reset
void Reset()
Reset the internal states.
Definition: schema.h:2072
internal::Hasher::IsValid
bool IsValid() const
Definition: schema.h:298
internal::Schema::Double
bool Double(Context &context, double d) const
Definition: schema.h:888
internal::SchemaValidationContext::~SchemaValidationContext
~SchemaValidationContext()
Definition: schema.h:379
internal::IValidationErrorHandler::SValue
SchemaType::SValue SValue
Definition: schema.h:193
internal::IValidationErrorHandler::Disallowed
virtual void Disallowed()=0
GenericSchemaDocument
JSON schema document.
Definition: fwd.h:136
internal::IValidationErrorHandler::EndDisallowedType
virtual void EndDisallowedType(const typename SchemaType::ValueType &actualType)=0
internal
Definition: allocators.h:422
RAPIDJSON_SCHEMA_VERBOSE
#define RAPIDJSON_SCHEMA_VERBOSE
Definition: schema.h:50
internal::ISchemaStateFactory::FreeState
virtual void FreeState(void *p)=0
GenericSchemaDocument::GenericSchemaDocument
GenericSchemaDocument(const ValueType &document, const Ch *uri=0, SizeType uriLength=0, IRemoteSchemaDocumentProviderType *remoteProvider=0, Allocator *allocator=0, const PointerType &pointer=PointerType())
Constructor.
Definition: schema.h:1645
internal::u32toa
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
internal::SchemaValidationContext::schema
const SchemaType * schema
Definition: schema.h:400
kValidateErrorAnyOf
@ kValidateErrorAnyOf
Property did not match any of the sub-schemas specified by 'anyOf'.
Definition: error.h:194
internal::Schema::SchemaType
Schema< SchemaDocumentType > SchemaType
Definition: schema.h:433
SchemaValidator
GenericSchemaValidator< SchemaDocument > SchemaValidator
Definition: schema.h:2712
GenericSchemaValidator::ValueType
GenericValue< EncodingType, StateAllocator > ValueType
Definition: schema.h:2000
internal::SchemaValidationContext::propertyExist
bool * propertyExist
Definition: schema.h:415
internal::ISchemaValidator::IsValid
virtual bool IsValid() const =0
GenericSchemaValidator::DestroryHasher
virtual void DestroryHasher(void *hasher)
Definition: schema.h:2452
GenericSchemaValidator::NoneOf
void NoneOf(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2306
internal::SchemaValidationContext::patternPropertiesValidators
ISchemaValidator ** patternPropertiesValidators
Definition: schema.h:408
GenericUri< ValueType, AllocatorType >
internal::Schema::AllocatorType
SchemaDocumentType::AllocatorType AllocatorType
Definition: schema.h:428
internal::TokenHelper< Stack, char >::AppendIndexToken
static RAPIDJSON_FORCEINLINE void AppendIndexToken(Stack &documentStack, SizeType index)
Definition: schema.h:1573
internal::SchemaValidationContext::inArray
bool inArray
Definition: schema.h:416
internal::Schema::Context
SchemaValidationContext< SchemaDocumentType > Context
Definition: schema.h:432
internal::SchemaValidationContext::valuePatternValidatorType
PatternValidatorType valuePatternValidatorType
Definition: schema.h:412
GenericSchemaValidator::Uint64
bool Uint64(uint64_t u)
Definition: schema.h:2381
GenericSchemaValidator::NotMultipleOf
void NotMultipleOf(double actual, const SValue &expected)
Definition: schema.h:2146
IGenericRemoteSchemaDocumentProvider::GetRemoteDocument
virtual const SchemaDocumentType * GetRemoteDocument(GenericUri< ValueType, AllocatorType > uri)
Definition: schema.h:1603
internal::SchemaValidationContext::SchemaType
Schema< SchemaDocumentType > SchemaType
Definition: schema.h:344
GenericUri::Resolve
GenericUri Resolve(const GenericUri &baseuri, Allocator *allocator=0)
Resolve this URI against another (base) URI in accordance with URI resolution rules.
Definition: uri.h:156
internal::ISchemaValidator::SetValidateFlags
virtual void SetValidateFlags(unsigned flags)=0
kValidateErrorRequired
@ kValidateErrorRequired
Object is missing one or more members required by the schema.
Definition: error.h:183
internal::ISchemaStateFactory::GetHashCode
virtual uint64_t GetHashCode(void *hasher)=0
kValidateErrorMinimum
@ kValidateErrorMinimum
Number is less than the 'minimum' value.
Definition: error.h:169
GenericSchemaValidator::MallocState
virtual void * MallocState(size_t size)
Definition: schema.h:2458
GenericSchemaValidator::NotMultipleOf
void NotMultipleOf(int64_t actual, const SValue &expected)
Definition: schema.h:2140
internal::IValidationErrorHandler::AddMissingProperty
virtual void AddMissingProperty(const SValue &name)=0
IGenericRemoteSchemaDocumentProvider::GetRemoteDocument
virtual const SchemaDocumentType * GetRemoteDocument(const Ch *uri, SizeType length)=0
GenericSchemaDocument::Ch
EncodingType::Ch Ch
Definition: schema.h:1625
internal::SchemaValidationContext::valueSchema
const SchemaType * valueSchema
Definition: schema.h:401
internal::SchemaValidationContext::factory
SchemaValidatorFactoryType & factory
Definition: schema.h:398
GenericSchemaDocument::GetRoot
const SchemaType & GetRoot() const
Get the root schema.
Definition: schema.h:1718
internal::SchemaValidationContext::kPatternValidatorWithAdditionalProperty
@ kPatternValidatorWithAdditionalProperty
Definition: schema.h:353
internal::IValidationErrorHandler::DisallowedProperty
virtual void DisallowedProperty(const Ch *name, SizeType length)=0
internal::SchemaValidationContext::invalidKeyword
const Ch * invalidKeyword
Definition: schema.h:402
GenericSchemaValidator::BelowMinimum
void BelowMinimum(uint64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:2165
GenericSchemaValidator::Int
bool Int(int i)
Definition: schema.h:2378
internal::TokenHelper::AppendIndexToken
static RAPIDJSON_FORCEINLINE void AppendIndexToken(Stack &documentStack, SizeType index)
Definition: schema.h:1561
name
ARPHIC PUBLIC LICENSE Ltd Yung Chi Taiwan All rights reserved except as specified below Everyone is permitted to copy and distribute verbatim copies of this license but changing it is forbidden Preamble The licenses for most software are designed to take away your freedom to share and change it By the ARPHIC PUBLIC LICENSE specifically permits and encourages you to use this provided that you give the recipients all the rights that we gave you and make sure they can get the modifications of this software Legal Terms Font means the TrueType fonts AR PL Mingti2L AR PL KaitiM AR PL KaitiM and the derivatives of those fonts created through any modification including modifying reordering converting changing font name
Definition: ARPHICPL.TXT:16
kValidateErrorMultipleOf
@ kValidateErrorMultipleOf
Number is not a multiple of the 'multipleOf' value.
Definition: error.h:166
RAPIDJSON_UINT64_C2
#define RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:320
internal::IValidationErrorHandler::AddDependencySchemaError
virtual void AddDependencySchemaError(const SValue &souceName, ISchemaValidator *subvalidator)=0
internal::SchemaValidationContext::invalidCode
ValidateErrorCode invalidCode
Definition: schema.h:403
internal::Schema::Ch
EncodingType::Ch Ch
Definition: schema.h:431
kValidateErrorNot
@ kValidateErrorNot
Property matched the sub-schema specified by 'not'.
Definition: error.h:195
internal::SchemaValidationContext::PatternValidatorType
PatternValidatorType
Definition: schema.h:350
internal::SchemaValidationContext::objectPatternValidatorType
PatternValidatorType objectPatternValidatorType
Definition: schema.h:413
GenericSchemaDocument::SchemaType
internal::Schema< GenericSchemaDocument > SchemaType
Definition: schema.h:1626
Handler
Concept for receiving events from GenericReader upon parsing. The functions return true if no error o...
internal::ISchemaStateFactory::~ISchemaStateFactory
virtual ~ISchemaStateFactory()
Definition: schema.h:176
source
const CharType(& source)[N]
Definition: pointer.h:1272
internal::IValidationErrorHandler::TooManyProperties
virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount)=0
internal::Schema::Int
bool Int(Context &context, int i) const
Definition: schema.h:864
kValidateErrorExclusiveMinimum
@ kValidateErrorExclusiveMinimum
Number is less than or equal to the 'minimum' value.
Definition: error.h:170