NDDEM
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 CEREAL_RAPIDJSON_SCHEMA_H_
16 #define CEREAL_RAPIDJSON_SCHEMA_H_
17 
18 #include "document.h"
19 #include "pointer.h"
20 #include "stringbuffer.h"
21 #include <cmath> // abs, floor
22 
23 #if !defined(CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX)
24 #define CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX 1
25 #else
26 #define CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX 0
27 #endif
28 
29 #if !CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX && defined(CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX) && (__cplusplus >=201103L || (defined(_MSC_VER) && _MSC_VER >= 1800))
30 #define CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX 1
31 #else
32 #define CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX 0
33 #endif
34 
35 #if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
36 #include "internal/regex.h"
37 #elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
38 #include <regex>
39 #endif
40 
41 #if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX || CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
42 #define CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX 1
43 #else
44 #define CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX 0
45 #endif
46 
47 #ifndef CEREAL_RAPIDJSON_SCHEMA_VERBOSE
48 #define CEREAL_RAPIDJSON_SCHEMA_VERBOSE 0
49 #endif
50 
51 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
52 #include "stringbuffer.h"
53 #endif
54 
55 CEREAL_RAPIDJSON_DIAG_PUSH
56 
57 #if defined(__GNUC__)
58 CEREAL_RAPIDJSON_DIAG_OFF(effc++)
59 #endif
60 
61 #ifdef __clang__
62 CEREAL_RAPIDJSON_DIAG_OFF(weak-vtables)
63 CEREAL_RAPIDJSON_DIAG_OFF(exit-time-destructors)
64 CEREAL_RAPIDJSON_DIAG_OFF(c++98-compat-pedantic)
65 CEREAL_RAPIDJSON_DIAG_OFF(variadic-macros)
66 #elif defined(_MSC_VER)
67 CEREAL_RAPIDJSON_DIAG_OFF(4512) // assignment operator could not be generated
68 #endif
69 
71 
73 // Verbose Utilities
74 
75 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
76 
77 namespace internal {
78 
79 inline void PrintInvalidKeyword(const char* keyword) {
80  printf("Fail keyword: %s\n", keyword);
81 }
82 
83 inline void PrintInvalidKeyword(const wchar_t* keyword) {
84  wprintf(L"Fail keyword: %ls\n", keyword);
85 }
86 
87 inline void PrintInvalidDocument(const char* document) {
88  printf("Fail document: %s\n\n", document);
89 }
90 
91 inline void PrintInvalidDocument(const wchar_t* document) {
92  wprintf(L"Fail document: %ls\n\n", document);
93 }
94 
95 inline void PrintValidatorPointers(unsigned depth, const char* s, const char* d) {
96  printf("S: %*s%s\nD: %*s%s\n\n", depth * 4, " ", s, depth * 4, " ", d);
97 }
98 
99 inline void PrintValidatorPointers(unsigned depth, const wchar_t* s, const wchar_t* d) {
100  wprintf(L"S: %*ls%ls\nD: %*ls%ls\n\n", depth * 4, L" ", s, depth * 4, L" ", d);
101 }
102 
103 } // namespace internal
104 
105 #endif // CEREAL_RAPIDJSON_SCHEMA_VERBOSE
106 
108 // CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN
109 
110 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
111 #define CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword) internal::PrintInvalidKeyword(keyword)
112 #else
113 #define CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword)
114 #endif
115 
116 #define CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)\
117 CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN\
118  context.invalidKeyword = keyword.GetString();\
119  CEREAL_RAPIDJSON_INVALID_KEYWORD_VERBOSE(keyword.GetString());\
120  return false;\
121 CEREAL_RAPIDJSON_MULTILINEMACRO_END
122 
124 // Forward declarations
125 
126 template <typename ValueType, typename Allocator>
128 
129 namespace internal {
130 
131 template <typename SchemaDocumentType>
132 class Schema;
133 
135 // ISchemaValidator
136 
138 public:
139  virtual ~ISchemaValidator() {}
140  virtual bool IsValid() const = 0;
141 };
142 
144 // ISchemaStateFactory
145 
146 template <typename SchemaType>
148 public:
149  virtual ~ISchemaStateFactory() {}
150  virtual ISchemaValidator* CreateSchemaValidator(const SchemaType&) = 0;
151  virtual void DestroySchemaValidator(ISchemaValidator* validator) = 0;
152  virtual void* CreateHasher() = 0;
153  virtual uint64_t GetHashCode(void* hasher) = 0;
154  virtual void DestroryHasher(void* hasher) = 0;
155  virtual void* MallocState(size_t size) = 0;
156  virtual void FreeState(void* p) = 0;
157 };
158 
160 // IValidationErrorHandler
161 
162 template <typename SchemaType>
164 public:
165  typedef typename SchemaType::Ch Ch;
166  typedef typename SchemaType::SValue SValue;
167 
169 
170  virtual void NotMultipleOf(int64_t actual, const SValue& expected) = 0;
171  virtual void NotMultipleOf(uint64_t actual, const SValue& expected) = 0;
172  virtual void NotMultipleOf(double actual, const SValue& expected) = 0;
173  virtual void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) = 0;
174  virtual void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
175  virtual void AboveMaximum(double actual, const SValue& expected, bool exclusive) = 0;
176  virtual void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) = 0;
177  virtual void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) = 0;
178  virtual void BelowMinimum(double actual, const SValue& expected, bool exclusive) = 0;
179 
180  virtual void TooLong(const Ch* str, SizeType length, SizeType expected) = 0;
181  virtual void TooShort(const Ch* str, SizeType length, SizeType expected) = 0;
182  virtual void DoesNotMatch(const Ch* str, SizeType length) = 0;
183 
184  virtual void DisallowedItem(SizeType index) = 0;
185  virtual void TooFewItems(SizeType actualCount, SizeType expectedCount) = 0;
186  virtual void TooManyItems(SizeType actualCount, SizeType expectedCount) = 0;
187  virtual void DuplicateItems(SizeType index1, SizeType index2) = 0;
188 
189  virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount) = 0;
190  virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount) = 0;
191  virtual void StartMissingProperties() = 0;
192  virtual void AddMissingProperty(const SValue& name) = 0;
193  virtual bool EndMissingProperties() = 0;
194  virtual void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) = 0;
195  virtual void DisallowedProperty(const Ch* name, SizeType length) = 0;
196 
197  virtual void StartDependencyErrors() = 0;
199  virtual void AddMissingDependentProperty(const SValue& targetName) = 0;
200  virtual void EndMissingDependentProperties(const SValue& sourceName) = 0;
201  virtual void AddDependencySchemaError(const SValue& souceName, ISchemaValidator* subvalidator) = 0;
202  virtual bool EndDependencyErrors() = 0;
203 
204  virtual void DisallowedValue() = 0;
205  virtual void StartDisallowedType() = 0;
206  virtual void AddExpectedType(const typename SchemaType::ValueType& expectedType) = 0;
207  virtual void EndDisallowedType(const typename SchemaType::ValueType& actualType) = 0;
208  virtual void NotAllOf(ISchemaValidator** subvalidators, SizeType count) = 0;
209  virtual void NoneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
210  virtual void NotOneOf(ISchemaValidator** subvalidators, SizeType count) = 0;
211  virtual void Disallowed() = 0;
212 };
213 
214 
216 // Hasher
217 
218 // For comparison of compound value
219 template<typename Encoding, typename Allocator>
220 class Hasher {
221 public:
222  typedef typename Encoding::Ch Ch;
223 
224  Hasher(Allocator* allocator = 0, size_t stackCapacity = kDefaultSize) : stack_(allocator, stackCapacity) {}
225 
226  bool Null() { return WriteType(kNullType); }
227  bool Bool(bool b) { return WriteType(b ? kTrueType : kFalseType); }
228  bool Int(int i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
229  bool Uint(unsigned u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
230  bool Int64(int64_t i) { Number n; n.u.i = i; n.d = static_cast<double>(i); return WriteNumber(n); }
231  bool Uint64(uint64_t u) { Number n; n.u.u = u; n.d = static_cast<double>(u); return WriteNumber(n); }
232  bool Double(double d) {
233  Number n;
234  if (d < 0) n.u.i = static_cast<int64_t>(d);
235  else n.u.u = static_cast<uint64_t>(d);
236  n.d = d;
237  return WriteNumber(n);
238  }
239 
240  bool RawNumber(const Ch* str, SizeType len, bool) {
241  WriteBuffer(kNumberType, str, len * sizeof(Ch));
242  return true;
243  }
244 
245  bool String(const Ch* str, SizeType len, bool) {
246  WriteBuffer(kStringType, str, len * sizeof(Ch));
247  return true;
248  }
249 
250  bool StartObject() { return true; }
251  bool Key(const Ch* str, SizeType len, bool copy) { return String(str, len, copy); }
252  bool EndObject(SizeType memberCount) {
253  uint64_t h = Hash(0, kObjectType);
254  uint64_t* kv = stack_.template Pop<uint64_t>(memberCount * 2);
255  for (SizeType i = 0; i < memberCount; i++)
256  h ^= Hash(kv[i * 2], kv[i * 2 + 1]); // Use xor to achieve member order insensitive
257  *stack_.template Push<uint64_t>() = h;
258  return true;
259  }
260 
261  bool StartArray() { return true; }
262  bool EndArray(SizeType elementCount) {
263  uint64_t h = Hash(0, kArrayType);
264  uint64_t* e = stack_.template Pop<uint64_t>(elementCount);
265  for (SizeType i = 0; i < elementCount; i++)
266  h = Hash(h, e[i]); // Use hash to achieve element order sensitive
267  *stack_.template Push<uint64_t>() = h;
268  return true;
269  }
270 
271  bool IsValid() const { return stack_.GetSize() == sizeof(uint64_t); }
272 
275  return *stack_.template Top<uint64_t>();
276  }
277 
278 private:
279  static const size_t kDefaultSize = 256;
280  struct Number {
281  union U {
284  }u;
285  double d;
286  };
287 
288  bool WriteType(Type type) { return WriteBuffer(type, 0, 0); }
289 
290  bool WriteNumber(const Number& n) { return WriteBuffer(kNumberType, &n, sizeof(n)); }
291 
292  bool WriteBuffer(Type type, const void* data, size_t len) {
293  // FNV-1a from http://isthe.com/chongo/tech/comp/fnv/
294  uint64_t h = Hash(CEREAL_RAPIDJSON_UINT64_C2(0x84222325, 0xcbf29ce4), type);
295  const unsigned char* d = static_cast<const unsigned char*>(data);
296  for (size_t i = 0; i < len; i++)
297  h = Hash(h, d[i]);
298  *stack_.template Push<uint64_t>() = h;
299  return true;
300  }
301 
303  static const uint64_t kPrime = CEREAL_RAPIDJSON_UINT64_C2(0x00000100, 0x000001b3);
304  h ^= d;
305  h *= kPrime;
306  return h;
307  }
308 
310 };
311 
313 // SchemaValidationContext
314 
315 template <typename SchemaDocumentType>
321  typedef typename ValueType::Ch Ch;
322 
327  };
328 
330  factory(f),
331  error_handler(eh),
332  schema(s),
333  valueSchema(),
334  invalidKeyword(),
335  hasher(),
337  validators(),
338  validatorCount(),
344  propertyExist(),
345  inArray(false),
346  valueUniqueness(false),
347  arrayUniqueness(false)
348  {
349  }
350 
352  if (hasher)
354  if (validators) {
355  for (SizeType i = 0; i < validatorCount; i++)
358  }
360  for (SizeType i = 0; i < patternPropertiesValidatorCount; i++)
363  }
366  if (propertyExist)
368  }
369 
375  void* hasher; // Only validator access
376  void* arrayElementHashCodes; // Only validator access this
387  bool inArray;
390 };
391 
393 // Schema
394 
395 template <typename SchemaDocumentType>
396 class Schema {
397 public:
398  typedef typename SchemaDocumentType::ValueType ValueType;
399  typedef typename SchemaDocumentType::AllocatorType AllocatorType;
400  typedef typename SchemaDocumentType::PointerType PointerType;
402  typedef typename EncodingType::Ch Ch;
408 
409  Schema(SchemaDocumentType* schemaDocument, const PointerType& p, const ValueType& value, const ValueType& document, AllocatorType* allocator) :
410  allocator_(allocator),
411  uri_(schemaDocument->GetURI(), *allocator),
412  pointer_(p, allocator),
413  typeless_(schemaDocument->GetTypeless()),
414  enum_(),
415  enumCount_(),
416  not_(),
417  type_((1 << kTotalSchemaType) - 1), // typeless
418  validatorCount_(),
420  properties_(),
424  propertyCount_(),
425  minProperties_(),
427  additionalProperties_(true),
429  hasRequired_(),
432  itemsList_(),
433  itemsTuple_(),
435  minItems_(),
436  maxItems_(SizeType(~0)),
437  additionalItems_(true),
438  uniqueItems_(false),
439  pattern_(),
440  minLength_(0),
441  maxLength_(~SizeType(0)),
442  exclusiveMinimum_(false),
443  exclusiveMaximum_(false),
445  {
446  typedef typename SchemaDocumentType::ValueType ValueType;
447  typedef typename ValueType::ConstValueIterator ConstValueIterator;
448  typedef typename ValueType::ConstMemberIterator ConstMemberIterator;
449 
450  if (!value.IsObject())
451  return;
452 
453  if (const ValueType* v = GetMember(value, GetTypeString())) {
454  type_ = 0;
455  if (v->IsString())
456  AddType(*v);
457  else if (v->IsArray())
458  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr)
459  AddType(*itr);
460  }
461 
462  if (const ValueType* v = GetMember(value, GetEnumString()))
463  if (v->IsArray() && v->Size() > 0) {
464  enum_ = static_cast<uint64_t*>(allocator_->Malloc(sizeof(uint64_t) * v->Size()));
465  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr) {
466  typedef Hasher<EncodingType, MemoryPoolAllocator<> > EnumHasherType;
467  char buffer[256u + 24];
468  MemoryPoolAllocator<> hasherAllocator(buffer, sizeof(buffer));
469  EnumHasherType h(&hasherAllocator, 256);
470  itr->Accept(h);
471  enum_[enumCount_++] = h.GetHashCode();
472  }
473  }
474 
475  if (schemaDocument) {
476  AssignIfExist(allOf_, *schemaDocument, p, value, GetAllOfString(), document);
477  AssignIfExist(anyOf_, *schemaDocument, p, value, GetAnyOfString(), document);
478  AssignIfExist(oneOf_, *schemaDocument, p, value, GetOneOfString(), document);
479  }
480 
481  if (const ValueType* v = GetMember(value, GetNotString())) {
482  schemaDocument->CreateSchema(&not_, p.Append(GetNotString(), allocator_), *v, document);
484  validatorCount_++;
485  }
486 
487  // Object
488 
489  const ValueType* properties = GetMember(value, GetPropertiesString());
490  const ValueType* required = GetMember(value, GetRequiredString());
491  const ValueType* dependencies = GetMember(value, GetDependenciesString());
492  {
493  // Gather properties from properties/required/dependencies
494  SValue allProperties(kArrayType);
495 
496  if (properties && properties->IsObject())
497  for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr)
498  AddUniqueElement(allProperties, itr->name);
499 
500  if (required && required->IsArray())
501  for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
502  if (itr->IsString())
503  AddUniqueElement(allProperties, *itr);
504 
505  if (dependencies && dependencies->IsObject())
506  for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
507  AddUniqueElement(allProperties, itr->name);
508  if (itr->value.IsArray())
509  for (ConstValueIterator i = itr->value.Begin(); i != itr->value.End(); ++i)
510  if (i->IsString())
511  AddUniqueElement(allProperties, *i);
512  }
513 
514  if (allProperties.Size() > 0) {
515  propertyCount_ = allProperties.Size();
516  properties_ = static_cast<Property*>(allocator_->Malloc(sizeof(Property) * propertyCount_));
517  for (SizeType i = 0; i < propertyCount_; i++) {
518  new (&properties_[i]) Property();
519  properties_[i].name = allProperties[i];
521  }
522  }
523  }
524 
525  if (properties && properties->IsObject()) {
526  PointerType q = p.Append(GetPropertiesString(), allocator_);
527  for (ConstMemberIterator itr = properties->MemberBegin(); itr != properties->MemberEnd(); ++itr) {
528  SizeType index;
529  if (FindPropertyIndex(itr->name, &index))
530  schemaDocument->CreateSchema(&properties_[index].schema, q.Append(itr->name, allocator_), itr->value, document);
531  }
532  }
533 
534  if (const ValueType* v = GetMember(value, GetPatternPropertiesString())) {
535  PointerType q = p.Append(GetPatternPropertiesString(), allocator_);
536  patternProperties_ = static_cast<PatternProperty*>(allocator_->Malloc(sizeof(PatternProperty) * v->MemberCount()));
538 
539  for (ConstMemberIterator itr = v->MemberBegin(); itr != v->MemberEnd(); ++itr) {
542  schemaDocument->CreateSchema(&patternProperties_[patternPropertyCount_].schema, q.Append(itr->name, allocator_), itr->value, document);
544  }
545  }
546 
547  if (required && required->IsArray())
548  for (ConstValueIterator itr = required->Begin(); itr != required->End(); ++itr)
549  if (itr->IsString()) {
550  SizeType index;
551  if (FindPropertyIndex(*itr, &index)) {
552  properties_[index].required = true;
553  hasRequired_ = true;
554  }
555  }
556 
557  if (dependencies && dependencies->IsObject()) {
558  PointerType q = p.Append(GetDependenciesString(), allocator_);
559  hasDependencies_ = true;
560  for (ConstMemberIterator itr = dependencies->MemberBegin(); itr != dependencies->MemberEnd(); ++itr) {
561  SizeType sourceIndex;
562  if (FindPropertyIndex(itr->name, &sourceIndex)) {
563  if (itr->value.IsArray()) {
564  properties_[sourceIndex].dependencies = static_cast<bool*>(allocator_->Malloc(sizeof(bool) * propertyCount_));
565  std::memset(properties_[sourceIndex].dependencies, 0, sizeof(bool)* propertyCount_);
566  for (ConstValueIterator targetItr = itr->value.Begin(); targetItr != itr->value.End(); ++targetItr) {
567  SizeType targetIndex;
568  if (FindPropertyIndex(*targetItr, &targetIndex))
569  properties_[sourceIndex].dependencies[targetIndex] = true;
570  }
571  }
572  else if (itr->value.IsObject()) {
573  hasSchemaDependencies_ = true;
574  schemaDocument->CreateSchema(&properties_[sourceIndex].dependenciesSchema, q.Append(itr->name, allocator_), itr->value, document);
576  validatorCount_++;
577  }
578  }
579  }
580  }
581 
582  if (const ValueType* v = GetMember(value, GetAdditionalPropertiesString())) {
583  if (v->IsBool())
584  additionalProperties_ = v->GetBool();
585  else if (v->IsObject())
586  schemaDocument->CreateSchema(&additionalPropertiesSchema_, p.Append(GetAdditionalPropertiesString(), allocator_), *v, document);
587  }
588 
589  AssignIfExist(minProperties_, value, GetMinPropertiesString());
590  AssignIfExist(maxProperties_, value, GetMaxPropertiesString());
591 
592  // Array
593  if (const ValueType* v = GetMember(value, GetItemsString())) {
594  PointerType q = p.Append(GetItemsString(), allocator_);
595  if (v->IsObject()) // List validation
596  schemaDocument->CreateSchema(&itemsList_, q, *v, document);
597  else if (v->IsArray()) { // Tuple validation
598  itemsTuple_ = static_cast<const Schema**>(allocator_->Malloc(sizeof(const Schema*) * v->Size()));
599  SizeType index = 0;
600  for (ConstValueIterator itr = v->Begin(); itr != v->End(); ++itr, index++)
601  schemaDocument->CreateSchema(&itemsTuple_[itemsTupleCount_++], q.Append(index, allocator_), *itr, document);
602  }
603  }
604 
605  AssignIfExist(minItems_, value, GetMinItemsString());
606  AssignIfExist(maxItems_, value, GetMaxItemsString());
607 
608  if (const ValueType* v = GetMember(value, GetAdditionalItemsString())) {
609  if (v->IsBool())
610  additionalItems_ = v->GetBool();
611  else if (v->IsObject())
612  schemaDocument->CreateSchema(&additionalItemsSchema_, p.Append(GetAdditionalItemsString(), allocator_), *v, document);
613  }
614 
615  AssignIfExist(uniqueItems_, value, GetUniqueItemsString());
616 
617  // String
618  AssignIfExist(minLength_, value, GetMinLengthString());
619  AssignIfExist(maxLength_, value, GetMaxLengthString());
620 
621  if (const ValueType* v = GetMember(value, GetPatternString()))
622  pattern_ = CreatePattern(*v);
623 
624  // Number
625  if (const ValueType* v = GetMember(value, GetMinimumString()))
626  if (v->IsNumber())
627  minimum_.CopyFrom(*v, *allocator_);
628 
629  if (const ValueType* v = GetMember(value, GetMaximumString()))
630  if (v->IsNumber())
631  maximum_.CopyFrom(*v, *allocator_);
632 
633  AssignIfExist(exclusiveMinimum_, value, GetExclusiveMinimumString());
634  AssignIfExist(exclusiveMaximum_, value, GetExclusiveMaximumString());
635 
636  if (const ValueType* v = GetMember(value, GetMultipleOfString()))
637  if (v->IsNumber() && v->GetDouble() > 0.0)
638  multipleOf_.CopyFrom(*v, *allocator_);
639 
640  // Default
641  if (const ValueType* v = GetMember(value, GetDefaultValueString()))
642  if (v->IsString())
643  defaultValueLength_ = v->GetStringLength();
644 
645  }
646 
648  AllocatorType::Free(enum_);
649  if (properties_) {
650  for (SizeType i = 0; i < propertyCount_; i++)
651  properties_[i].~Property();
652  AllocatorType::Free(properties_);
653  }
654  if (patternProperties_) {
655  for (SizeType i = 0; i < patternPropertyCount_; i++)
657  AllocatorType::Free(patternProperties_);
658  }
659  AllocatorType::Free(itemsTuple_);
660 #if CEREAL_RAPIDJSON_SCHEMA_HAS_REGEX
661  if (pattern_) {
662  pattern_->~RegexType();
663  AllocatorType::Free(pattern_);
664  }
665 #endif
666  }
667 
668  const SValue& GetURI() const {
669  return uri_;
670  }
671 
672  const PointerType& GetPointer() const {
673  return pointer_;
674  }
675 
676  bool BeginValue(Context& context) const {
677  if (context.inArray) {
678  if (uniqueItems_)
679  context.valueUniqueness = true;
680 
681  if (itemsList_)
682  context.valueSchema = itemsList_;
683  else if (itemsTuple_) {
684  if (context.arrayElementIndex < itemsTupleCount_)
685  context.valueSchema = itemsTuple_[context.arrayElementIndex];
686  else if (additionalItemsSchema_)
688  else if (additionalItems_)
689  context.valueSchema = typeless_;
690  else {
692  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetItemsString());
693  }
694  }
695  else
696  context.valueSchema = typeless_;
697 
698  context.arrayElementIndex++;
699  }
700  return true;
701  }
702 
703  CEREAL_RAPIDJSON_FORCEINLINE bool EndValue(Context& context) const {
704  if (context.patternPropertiesValidatorCount > 0) {
705  bool otherValid = false;
708  otherValid = context.patternPropertiesValidators[--count]->IsValid();
709 
710  bool patternValid = true;
711  for (SizeType i = 0; i < count; i++)
712  if (!context.patternPropertiesValidators[i]->IsValid()) {
713  patternValid = false;
714  break;
715  }
716 
718  if (!patternValid) {
720  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
721  }
722  }
724  if (!patternValid || !otherValid) {
726  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
727  }
728  }
729  else if (!patternValid && !otherValid) { // kPatternValidatorWithAdditionalProperty)
731  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternPropertiesString());
732  }
733  }
734 
735  if (enum_) {
736  const uint64_t h = context.factory.GetHashCode(context.hasher);
737  for (SizeType i = 0; i < enumCount_; i++)
738  if (enum_[i] == h)
739  goto foundEnum;
740  context.error_handler.DisallowedValue();
742  foundEnum:;
743  }
744 
745  if (allOf_.schemas)
746  for (SizeType i = allOf_.begin; i < allOf_.begin + allOf_.count; i++)
747  if (!context.validators[i]->IsValid()) {
749  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAllOfString());
750  }
751 
752  if (anyOf_.schemas) {
753  for (SizeType i = anyOf_.begin; i < anyOf_.begin + anyOf_.count; i++)
754  if (context.validators[i]->IsValid())
755  goto foundAny;
756  context.error_handler.NoneOf(&context.validators[anyOf_.begin], anyOf_.count);
757  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAnyOfString());
758  foundAny:;
759  }
760 
761  if (oneOf_.schemas) {
762  bool oneValid = false;
763  for (SizeType i = oneOf_.begin; i < oneOf_.begin + oneOf_.count; i++)
764  if (context.validators[i]->IsValid()) {
765  if (oneValid) {
767  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
768  } else
769  oneValid = true;
770  }
771  if (!oneValid) {
773  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetOneOfString());
774  }
775  }
776 
777  if (not_ && context.validators[notValidatorIndex_]->IsValid()) {
778  context.error_handler.Disallowed();
780  }
781 
782  return true;
783  }
784 
785  bool Null(Context& context) const {
786  if (!(type_ & (1 << kNullSchemaType))) {
787  DisallowedType(context, GetNullString());
789  }
790  return CreateParallelValidator(context);
791  }
792 
793  bool Bool(Context& context, bool) const {
794  if (!(type_ & (1 << kBooleanSchemaType))) {
795  DisallowedType(context, GetBooleanString());
797  }
798  return CreateParallelValidator(context);
799  }
800 
801  bool Int(Context& context, int i) const {
802  if (!CheckInt(context, i))
803  return false;
804  return CreateParallelValidator(context);
805  }
806 
807  bool Uint(Context& context, unsigned u) const {
808  if (!CheckUint(context, u))
809  return false;
810  return CreateParallelValidator(context);
811  }
812 
813  bool Int64(Context& context, int64_t i) const {
814  if (!CheckInt(context, i))
815  return false;
816  return CreateParallelValidator(context);
817  }
818 
819  bool Uint64(Context& context, uint64_t u) const {
820  if (!CheckUint(context, u))
821  return false;
822  return CreateParallelValidator(context);
823  }
824 
825  bool Double(Context& context, double d) const {
826  if (!(type_ & (1 << kNumberSchemaType))) {
827  DisallowedType(context, GetNumberString());
829  }
830 
831  if (!minimum_.IsNull() && !CheckDoubleMinimum(context, d))
832  return false;
833 
834  if (!maximum_.IsNull() && !CheckDoubleMaximum(context, d))
835  return false;
836 
837  if (!multipleOf_.IsNull() && !CheckDoubleMultipleOf(context, d))
838  return false;
839 
840  return CreateParallelValidator(context);
841  }
842 
843  bool String(Context& context, const Ch* str, SizeType length, bool) const {
844  if (!(type_ & (1 << kStringSchemaType))) {
845  DisallowedType(context, GetStringString());
847  }
848 
849  if (minLength_ != 0 || maxLength_ != SizeType(~0)) {
850  SizeType count;
851  if (internal::CountStringCodePoint<EncodingType>(str, length, &count)) {
852  if (count < minLength_) {
853  context.error_handler.TooShort(str, length, minLength_);
854  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinLengthString());
855  }
856  if (count > maxLength_) {
857  context.error_handler.TooLong(str, length, maxLength_);
858  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxLengthString());
859  }
860  }
861  }
862 
863  if (pattern_ && !IsPatternMatch(pattern_, str, length)) {
864  context.error_handler.DoesNotMatch(str, length);
865  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetPatternString());
866  }
867 
868  return CreateParallelValidator(context);
869  }
870 
871  bool StartObject(Context& context) const {
872  if (!(type_ & (1 << kObjectSchemaType))) {
873  DisallowedType(context, GetObjectString());
875  }
876 
878  context.propertyExist = static_cast<bool*>(context.factory.MallocState(sizeof(bool) * propertyCount_));
879  std::memset(context.propertyExist, 0, sizeof(bool) * propertyCount_);
880  }
881 
882  if (patternProperties_) { // pre-allocate schema array
883  SizeType count = patternPropertyCount_ + 1; // extra for valuePatternValidatorType
884  context.patternPropertiesSchemas = static_cast<const SchemaType**>(context.factory.MallocState(sizeof(const SchemaType*) * count));
885  context.patternPropertiesSchemaCount = 0;
886  std::memset(context.patternPropertiesSchemas, 0, sizeof(SchemaType*) * count);
887  }
888 
889  return CreateParallelValidator(context);
890  }
891 
892  bool Key(Context& context, const Ch* str, SizeType len, bool) const {
893  if (patternProperties_) {
894  context.patternPropertiesSchemaCount = 0;
895  for (SizeType i = 0; i < patternPropertyCount_; i++)
896  if (patternProperties_[i].pattern && IsPatternMatch(patternProperties_[i].pattern, str, len)) {
898  context.valueSchema = typeless_;
899  }
900  }
901 
902  SizeType index;
903  if (FindPropertyIndex(ValueType(str, len).Move(), &index)) {
904  if (context.patternPropertiesSchemaCount > 0) {
906  context.valueSchema = typeless_;
908  }
909  else
910  context.valueSchema = properties_[index].schema;
911 
912  if (context.propertyExist)
913  context.propertyExist[index] = true;
914 
915  return true;
916  }
917 
921  context.valueSchema = typeless_;
923  }
924  else
926  return true;
927  }
928  else if (additionalProperties_) {
929  context.valueSchema = typeless_;
930  return true;
931  }
932 
933  if (context.patternPropertiesSchemaCount == 0) { // patternProperties are not additional properties
934  context.error_handler.DisallowedProperty(str, len);
935  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetAdditionalPropertiesString());
936  }
937 
938  return true;
939  }
940 
941  bool EndObject(Context& context, SizeType memberCount) const {
942  if (hasRequired_) {
944  for (SizeType index = 0; index < propertyCount_; index++)
945  if (properties_[index].required && !context.propertyExist[index])
946  if (properties_[index].schema->defaultValueLength_ == 0 )
947  context.error_handler.AddMissingProperty(properties_[index].name);
948  if (context.error_handler.EndMissingProperties())
949  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetRequiredString());
950  }
951 
952  if (memberCount < minProperties_) {
953  context.error_handler.TooFewProperties(memberCount, minProperties_);
954  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinPropertiesString());
955  }
956 
957  if (memberCount > maxProperties_) {
958  context.error_handler.TooManyProperties(memberCount, maxProperties_);
959  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxPropertiesString());
960  }
961 
962  if (hasDependencies_) {
964  for (SizeType sourceIndex = 0; sourceIndex < propertyCount_; sourceIndex++) {
965  const Property& source = properties_[sourceIndex];
966  if (context.propertyExist[sourceIndex]) {
967  if (source.dependencies) {
969  for (SizeType targetIndex = 0; targetIndex < propertyCount_; targetIndex++)
970  if (source.dependencies[targetIndex] && !context.propertyExist[targetIndex])
971  context.error_handler.AddMissingDependentProperty(properties_[targetIndex].name);
973  }
974  else if (source.dependenciesSchema) {
975  ISchemaValidator* dependenciesValidator = context.validators[source.dependenciesValidatorIndex];
976  if (!dependenciesValidator->IsValid())
977  context.error_handler.AddDependencySchemaError(source.name, dependenciesValidator);
978  }
979  }
980  }
981  if (context.error_handler.EndDependencyErrors())
982  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetDependenciesString());
983  }
984 
985  return true;
986  }
987 
988  bool StartArray(Context& context) const {
989  if (!(type_ & (1 << kArraySchemaType))) {
990  DisallowedType(context, GetArrayString());
992  }
993 
994  context.arrayElementIndex = 0;
995  context.inArray = true;
996 
997  return CreateParallelValidator(context);
998  }
999 
1000  bool EndArray(Context& context, SizeType elementCount) const {
1001  context.inArray = false;
1002 
1003  if (elementCount < minItems_) {
1004  context.error_handler.TooFewItems(elementCount, minItems_);
1005  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinItemsString());
1006  }
1007 
1008  if (elementCount > maxItems_) {
1009  context.error_handler.TooManyItems(elementCount, maxItems_);
1010  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaxItemsString());
1011  }
1012 
1013  return true;
1014  }
1015 
1016  // Generate functions for string literal according to Ch
1017 #define CEREAL_RAPIDJSON_STRING_(name, ...) \
1018  static const ValueType& Get##name##String() {\
1019  static const Ch s[] = { __VA_ARGS__, '\0' };\
1020  static const ValueType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1));\
1021  return v;\
1022  }
1023 
1024  CEREAL_RAPIDJSON_STRING_(Null, 'n', 'u', 'l', 'l')
1025  CEREAL_RAPIDJSON_STRING_(Boolean, 'b', 'o', 'o', 'l', 'e', 'a', 'n')
1026  CEREAL_RAPIDJSON_STRING_(Object, 'o', 'b', 'j', 'e', 'c', 't')
1027  CEREAL_RAPIDJSON_STRING_(Array, 'a', 'r', 'r', 'a', 'y')
1028  CEREAL_RAPIDJSON_STRING_(String, 's', 't', 'r', 'i', 'n', 'g')
1029  CEREAL_RAPIDJSON_STRING_(Number, 'n', 'u', 'm', 'b', 'e', 'r')
1030  CEREAL_RAPIDJSON_STRING_(Integer, 'i', 'n', 't', 'e', 'g', 'e', 'r')
1031  CEREAL_RAPIDJSON_STRING_(Type, 't', 'y', 'p', 'e')
1032  CEREAL_RAPIDJSON_STRING_(Enum, 'e', 'n', 'u', 'm')
1033  CEREAL_RAPIDJSON_STRING_(AllOf, 'a', 'l', 'l', 'O', 'f')
1034  CEREAL_RAPIDJSON_STRING_(AnyOf, 'a', 'n', 'y', 'O', 'f')
1035  CEREAL_RAPIDJSON_STRING_(OneOf, 'o', 'n', 'e', 'O', 'f')
1036  CEREAL_RAPIDJSON_STRING_(Not, 'n', 'o', 't')
1037  CEREAL_RAPIDJSON_STRING_(Properties, 'p', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1038  CEREAL_RAPIDJSON_STRING_(Required, 'r', 'e', 'q', 'u', 'i', 'r', 'e', 'd')
1039  CEREAL_RAPIDJSON_STRING_(Dependencies, 'd', 'e', 'p', 'e', 'n', 'd', 'e', 'n', 'c', 'i', 'e', 's')
1040  CEREAL_RAPIDJSON_STRING_(PatternProperties, 'p', 'a', 't', 't', 'e', 'r', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1041  CEREAL_RAPIDJSON_STRING_(AdditionalProperties, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1042  CEREAL_RAPIDJSON_STRING_(MinProperties, 'm', 'i', 'n', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1043  CEREAL_RAPIDJSON_STRING_(MaxProperties, 'm', 'a', 'x', 'P', 'r', 'o', 'p', 'e', 'r', 't', 'i', 'e', 's')
1044  CEREAL_RAPIDJSON_STRING_(Items, 'i', 't', 'e', 'm', 's')
1045  CEREAL_RAPIDJSON_STRING_(MinItems, 'm', 'i', 'n', 'I', 't', 'e', 'm', 's')
1046  CEREAL_RAPIDJSON_STRING_(MaxItems, 'm', 'a', 'x', 'I', 't', 'e', 'm', 's')
1047  CEREAL_RAPIDJSON_STRING_(AdditionalItems, 'a', 'd', 'd', 'i', 't', 'i', 'o', 'n', 'a', 'l', 'I', 't', 'e', 'm', 's')
1048  CEREAL_RAPIDJSON_STRING_(UniqueItems, 'u', 'n', 'i', 'q', 'u', 'e', 'I', 't', 'e', 'm', 's')
1049  CEREAL_RAPIDJSON_STRING_(MinLength, 'm', 'i', 'n', 'L', 'e', 'n', 'g', 't', 'h')
1050  CEREAL_RAPIDJSON_STRING_(MaxLength, 'm', 'a', 'x', 'L', 'e', 'n', 'g', 't', 'h')
1051  CEREAL_RAPIDJSON_STRING_(Pattern, 'p', 'a', 't', 't', 'e', 'r', 'n')
1052  CEREAL_RAPIDJSON_STRING_(Minimum, 'm', 'i', 'n', 'i', 'm', 'u', 'm')
1053  CEREAL_RAPIDJSON_STRING_(Maximum, 'm', 'a', 'x', 'i', 'm', 'u', 'm')
1054  CEREAL_RAPIDJSON_STRING_(ExclusiveMinimum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'i', 'n', 'i', 'm', 'u', 'm')
1055  CEREAL_RAPIDJSON_STRING_(ExclusiveMaximum, 'e', 'x', 'c', 'l', 'u', 's', 'i', 'v', 'e', 'M', 'a', 'x', 'i', 'm', 'u', 'm')
1056  CEREAL_RAPIDJSON_STRING_(MultipleOf, 'm', 'u', 'l', 't', 'i', 'p', 'l', 'e', 'O', 'f')
1057  CEREAL_RAPIDJSON_STRING_(DefaultValue, 'd', 'e', 'f', 'a', 'u', 'l', 't')
1058 
1059 #undef CEREAL_RAPIDJSON_STRING_
1060 
1061 private:
1071  };
1072 
1073 #if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1075 #elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
1076  typedef std::basic_regex<Ch> RegexType;
1077 #else
1078  typedef char RegexType;
1079 #endif
1080 
1081  struct SchemaArray {
1083  ~SchemaArray() { AllocatorType::Free(schemas); }
1085  SizeType begin; // begin index of context.validators
1087  };
1088 
1089  template <typename V1, typename V2>
1090  void AddUniqueElement(V1& a, const V2& v) {
1091  for (typename V1::ConstValueIterator itr = a.Begin(); itr != a.End(); ++itr)
1092  if (*itr == v)
1093  return;
1094  V1 c(v, *allocator_);
1095  a.PushBack(c, *allocator_);
1096  }
1097 
1098  static const ValueType* GetMember(const ValueType& value, const ValueType& name) {
1099  typename ValueType::ConstMemberIterator itr = value.FindMember(name);
1100  return itr != value.MemberEnd() ? &(itr->value) : 0;
1101  }
1102 
1103  static void AssignIfExist(bool& out, const ValueType& value, const ValueType& name) {
1104  if (const ValueType* v = GetMember(value, name))
1105  if (v->IsBool())
1106  out = v->GetBool();
1107  }
1108 
1109  static void AssignIfExist(SizeType& out, const ValueType& value, const ValueType& name) {
1110  if (const ValueType* v = GetMember(value, name))
1111  if (v->IsUint64() && v->GetUint64() <= SizeType(~0))
1112  out = static_cast<SizeType>(v->GetUint64());
1113  }
1114 
1115  void AssignIfExist(SchemaArray& out, SchemaDocumentType& schemaDocument, const PointerType& p, const ValueType& value, const ValueType& name, const ValueType& document) {
1116  if (const ValueType* v = GetMember(value, name)) {
1117  if (v->IsArray() && v->Size() > 0) {
1118  PointerType q = p.Append(name, allocator_);
1119  out.count = v->Size();
1120  out.schemas = static_cast<const Schema**>(allocator_->Malloc(out.count * sizeof(const Schema*)));
1121  memset(out.schemas, 0, sizeof(Schema*)* out.count);
1122  for (SizeType i = 0; i < out.count; i++)
1123  schemaDocument.CreateSchema(&out.schemas[i], q.Append(i, allocator_), (*v)[i], document);
1124  out.begin = validatorCount_;
1125  validatorCount_ += out.count;
1126  }
1127  }
1128  }
1129 
1130 #if CEREAL_RAPIDJSON_SCHEMA_USE_INTERNALREGEX
1131  template <typename ValueType>
1133  if (value.IsString()) {
1134  RegexType* r = new (allocator_->Malloc(sizeof(RegexType))) RegexType(value.GetString(), allocator_);
1135  if (!r->IsValid()) {
1136  r->~RegexType();
1137  AllocatorType::Free(r);
1138  r = 0;
1139  }
1140  return r;
1141  }
1142  return 0;
1143  }
1144 
1145  static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType) {
1146  GenericRegexSearch<RegexType> rs(*pattern);
1147  return rs.Search(str);
1148  }
1149 #elif CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
1150  template <typename ValueType>
1151  RegexType* CreatePattern(const ValueType& value) {
1152  if (value.IsString()) {
1153  RegexType *r = static_cast<RegexType*>(allocator_->Malloc(sizeof(RegexType)));
1154  try {
1155  return new (r) RegexType(value.GetString(), std::size_t(value.GetStringLength()), std::regex_constants::ECMAScript);
1156  }
1157  catch (const std::regex_error&) {
1158  AllocatorType::Free(r);
1159  }
1160  }
1161  return 0;
1162  }
1163 
1164  static bool IsPatternMatch(const RegexType* pattern, const Ch *str, SizeType length) {
1165  std::match_results<const Ch*> r;
1166  return std::regex_search(str, str + length, r, *pattern);
1167  }
1168 #else
1169  template <typename ValueType>
1170  RegexType* CreatePattern(const ValueType&) { return 0; }
1171 
1172  static bool IsPatternMatch(const RegexType*, const Ch *, SizeType) { return true; }
1173 #endif // CEREAL_RAPIDJSON_SCHEMA_USE_STDREGEX
1174 
1175  void AddType(const ValueType& type) {
1176  if (type == GetNullString() ) type_ |= 1 << kNullSchemaType;
1177  else if (type == GetBooleanString()) type_ |= 1 << kBooleanSchemaType;
1178  else if (type == GetObjectString() ) type_ |= 1 << kObjectSchemaType;
1179  else if (type == GetArrayString() ) type_ |= 1 << kArraySchemaType;
1180  else if (type == GetStringString() ) type_ |= 1 << kStringSchemaType;
1181  else if (type == GetIntegerString()) type_ |= 1 << kIntegerSchemaType;
1182  else if (type == GetNumberString() ) type_ |= (1 << kNumberSchemaType) | (1 << kIntegerSchemaType);
1183  }
1184 
1185  bool CreateParallelValidator(Context& context) const {
1186  if (enum_ || context.arrayUniqueness)
1187  context.hasher = context.factory.CreateHasher();
1188 
1189  if (validatorCount_) {
1190  CEREAL_RAPIDJSON_ASSERT(context.validators == 0);
1191  context.validators = static_cast<ISchemaValidator**>(context.factory.MallocState(sizeof(ISchemaValidator*) * validatorCount_));
1192  context.validatorCount = validatorCount_;
1193 
1194  if (allOf_.schemas)
1195  CreateSchemaValidators(context, allOf_);
1196 
1197  if (anyOf_.schemas)
1198  CreateSchemaValidators(context, anyOf_);
1199 
1200  if (oneOf_.schemas)
1201  CreateSchemaValidators(context, oneOf_);
1202 
1203  if (not_)
1205 
1206  if (hasSchemaDependencies_) {
1207  for (SizeType i = 0; i < propertyCount_; i++)
1208  if (properties_[i].dependenciesSchema)
1209  context.validators[properties_[i].dependenciesValidatorIndex] = context.factory.CreateSchemaValidator(*properties_[i].dependenciesSchema);
1210  }
1211  }
1212 
1213  return true;
1214  }
1215 
1216  void CreateSchemaValidators(Context& context, const SchemaArray& schemas) const {
1217  for (SizeType i = 0; i < schemas.count; i++)
1218  context.validators[schemas.begin + i] = context.factory.CreateSchemaValidator(*schemas.schemas[i]);
1219  }
1220 
1221  // O(n)
1222  bool FindPropertyIndex(const ValueType& name, SizeType* outIndex) const {
1223  SizeType len = name.GetStringLength();
1224  const Ch* str = name.GetString();
1225  for (SizeType index = 0; index < propertyCount_; index++)
1226  if (properties_[index].name.GetStringLength() == len &&
1227  (std::memcmp(properties_[index].name.GetString(), str, sizeof(Ch) * len) == 0))
1228  {
1229  *outIndex = index;
1230  return true;
1231  }
1232  return false;
1233  }
1234 
1235  bool CheckInt(Context& context, int64_t i) const {
1236  if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1237  DisallowedType(context, GetIntegerString());
1238  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1239  }
1240 
1241  if (!minimum_.IsNull()) {
1242  if (minimum_.IsInt64()) {
1243  if (exclusiveMinimum_ ? i <= minimum_.GetInt64() : i < minimum_.GetInt64()) {
1245  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1246  }
1247  }
1248  else if (minimum_.IsUint64()) {
1250  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString()); // i <= max(int64_t) < minimum.GetUint64()
1251  }
1252  else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1253  return false;
1254  }
1255 
1256  if (!maximum_.IsNull()) {
1257  if (maximum_.IsInt64()) {
1258  if (exclusiveMaximum_ ? i >= maximum_.GetInt64() : i > maximum_.GetInt64()) {
1260  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1261  }
1262  }
1263  else if (maximum_.IsUint64()) { }
1264  /* do nothing */ // i <= max(int64_t) < maximum_.GetUint64()
1265  else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1266  return false;
1267  }
1268 
1269  if (!multipleOf_.IsNull()) {
1270  if (multipleOf_.IsUint64()) {
1271  if (static_cast<uint64_t>(i >= 0 ? i : -i) % multipleOf_.GetUint64() != 0) {
1273  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1274  }
1275  }
1276  else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1277  return false;
1278  }
1279 
1280  return true;
1281  }
1282 
1283  bool CheckUint(Context& context, uint64_t i) const {
1284  if (!(type_ & ((1 << kIntegerSchemaType) | (1 << kNumberSchemaType)))) {
1285  DisallowedType(context, GetIntegerString());
1286  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetTypeString());
1287  }
1288 
1289  if (!minimum_.IsNull()) {
1290  if (minimum_.IsUint64()) {
1291  if (exclusiveMinimum_ ? i <= minimum_.GetUint64() : i < minimum_.GetUint64()) {
1293  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1294  }
1295  }
1296  else if (minimum_.IsInt64())
1297  /* do nothing */; // i >= 0 > minimum.Getint64()
1298  else if (!CheckDoubleMinimum(context, static_cast<double>(i)))
1299  return false;
1300  }
1301 
1302  if (!maximum_.IsNull()) {
1303  if (maximum_.IsUint64()) {
1304  if (exclusiveMaximum_ ? i >= maximum_.GetUint64() : i > maximum_.GetUint64()) {
1306  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1307  }
1308  }
1309  else if (maximum_.IsInt64()) {
1311  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString()); // i >= 0 > maximum_
1312  }
1313  else if (!CheckDoubleMaximum(context, static_cast<double>(i)))
1314  return false;
1315  }
1316 
1317  if (!multipleOf_.IsNull()) {
1318  if (multipleOf_.IsUint64()) {
1319  if (i % multipleOf_.GetUint64() != 0) {
1321  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1322  }
1323  }
1324  else if (!CheckDoubleMultipleOf(context, static_cast<double>(i)))
1325  return false;
1326  }
1327 
1328  return true;
1329  }
1330 
1331  bool CheckDoubleMinimum(Context& context, double d) const {
1332  if (exclusiveMinimum_ ? d <= minimum_.GetDouble() : d < minimum_.GetDouble()) {
1334  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMinimumString());
1335  }
1336  return true;
1337  }
1338 
1339  bool CheckDoubleMaximum(Context& context, double d) const {
1340  if (exclusiveMaximum_ ? d >= maximum_.GetDouble() : d > maximum_.GetDouble()) {
1342  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMaximumString());
1343  }
1344  return true;
1345  }
1346 
1347  bool CheckDoubleMultipleOf(Context& context, double d) const {
1348  double a = std::abs(d), b = std::abs(multipleOf_.GetDouble());
1349  double q = std::floor(a / b);
1350  double r = a - q * b;
1351  if (r > 0.0) {
1353  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(GetMultipleOfString());
1354  }
1355  return true;
1356  }
1357 
1358  void DisallowedType(Context& context, const ValueType& actualType) const {
1359  ErrorHandler& eh = context.error_handler;
1360  eh.StartDisallowedType();
1361 
1362  if (type_ & (1 << kNullSchemaType)) eh.AddExpectedType(GetNullString());
1363  if (type_ & (1 << kBooleanSchemaType)) eh.AddExpectedType(GetBooleanString());
1364  if (type_ & (1 << kObjectSchemaType)) eh.AddExpectedType(GetObjectString());
1365  if (type_ & (1 << kArraySchemaType)) eh.AddExpectedType(GetArrayString());
1366  if (type_ & (1 << kStringSchemaType)) eh.AddExpectedType(GetStringString());
1367 
1368  if (type_ & (1 << kNumberSchemaType)) eh.AddExpectedType(GetNumberString());
1369  else if (type_ & (1 << kIntegerSchemaType)) eh.AddExpectedType(GetIntegerString());
1370 
1371  eh.EndDisallowedType(actualType);
1372  }
1373 
1374  struct Property {
1376  ~Property() { AllocatorType::Free(dependencies); }
1382  bool required;
1383  };
1384 
1388  if (pattern) {
1389  pattern->~RegexType();
1390  AllocatorType::Free(pattern);
1391  }
1392  }
1395  };
1396 
1407  unsigned type_; // bitmask of kSchemaType
1410 
1422 
1431 
1435 
1441 
1443 };
1444 
1445 template<typename Stack, typename Ch>
1446 struct TokenHelper {
1447  CEREAL_RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1448  *documentStack.template Push<Ch>() = '/';
1449  char buffer[21];
1450  size_t length = static_cast<size_t>((sizeof(SizeType) == 4 ? u32toa(index, buffer) : u64toa(index, buffer)) - buffer);
1451  for (size_t i = 0; i < length; i++)
1452  *documentStack.template Push<Ch>() = static_cast<Ch>(buffer[i]);
1453  }
1454 };
1455 
1456 // Partial specialized version for char to prevent buffer copying.
1457 template <typename Stack>
1458 struct TokenHelper<Stack, char> {
1459  CEREAL_RAPIDJSON_FORCEINLINE static void AppendIndexToken(Stack& documentStack, SizeType index) {
1460  if (sizeof(SizeType) == 4) {
1461  char *buffer = documentStack.template Push<char>(1 + 10); // '/' + uint
1462  *buffer++ = '/';
1463  const char* end = internal::u32toa(index, buffer);
1464  documentStack.template Pop<char>(static_cast<size_t>(10 - (end - buffer)));
1465  }
1466  else {
1467  char *buffer = documentStack.template Push<char>(1 + 20); // '/' + uint64
1468  *buffer++ = '/';
1469  const char* end = internal::u64toa(index, buffer);
1470  documentStack.template Pop<char>(static_cast<size_t>(20 - (end - buffer)));
1471  }
1472  }
1473 };
1474 
1475 } // namespace internal
1476 
1478 // IGenericRemoteSchemaDocumentProvider
1479 
1480 template <typename SchemaDocumentType>
1482 public:
1483  typedef typename SchemaDocumentType::Ch Ch;
1484 
1486  virtual const SchemaDocumentType* GetRemoteDocument(const Ch* uri, SizeType length) = 0;
1487 };
1488 
1490 // GenericSchemaDocument
1491 
1493 
1501 template <typename ValueT, typename Allocator = CrtAllocator>
1503 public:
1504  typedef ValueT ValueType;
1508  typedef typename EncodingType::Ch Ch;
1513  template <typename, typename, typename>
1515 
1517 
1526  explicit GenericSchemaDocument(const ValueType& document, const Ch* uri = 0, SizeType uriLength = 0,
1527  IRemoteSchemaDocumentProviderType* remoteProvider = 0, Allocator* allocator = 0) :
1528  remoteProvider_(remoteProvider),
1529  allocator_(allocator),
1530  ownAllocator_(),
1531  root_(),
1532  typeless_(),
1533  schemaMap_(allocator, kInitialSchemaMapSize),
1534  schemaRef_(allocator, kInitialSchemaRefSize)
1535  {
1536  if (!allocator_)
1538 
1539  Ch noUri[1] = {0};
1540  uri_.SetString(uri ? uri : noUri, uriLength, *allocator_);
1541 
1542  typeless_ = static_cast<SchemaType*>(allocator_->Malloc(sizeof(SchemaType)));
1544 
1545  // Generate root schema, it will call CreateSchema() to create sub-schemas,
1546  // And call AddRefSchema() if there are $ref.
1547  CreateSchemaRecursive(&root_, PointerType(), document, document);
1548 
1549  // Resolve $ref
1550  while (!schemaRef_.Empty()) {
1551  SchemaRefEntry* refEntry = schemaRef_.template Pop<SchemaRefEntry>(1);
1552  if (const SchemaType* s = GetSchema(refEntry->target)) {
1553  if (refEntry->schema)
1554  *refEntry->schema = s;
1555 
1556  // Create entry in map if not exist
1557  if (!GetSchema(refEntry->source)) {
1558  new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(refEntry->source, const_cast<SchemaType*>(s), false, allocator_);
1559  }
1560  }
1561  else if (refEntry->schema)
1562  *refEntry->schema = typeless_;
1563 
1564  refEntry->~SchemaRefEntry();
1565  }
1566 
1568 
1569  schemaRef_.ShrinkToFit(); // Deallocate all memory for ref
1570  }
1571 
1572 #if CEREAL_RAPIDJSON_HAS_CXX11_RVALUE_REFS
1574  GenericSchemaDocument(GenericSchemaDocument&& rhs) CEREAL_RAPIDJSON_NOEXCEPT :
1575  remoteProvider_(rhs.remoteProvider_),
1576  allocator_(rhs.allocator_),
1577  ownAllocator_(rhs.ownAllocator_),
1578  root_(rhs.root_),
1579  typeless_(rhs.typeless_),
1580  schemaMap_(std::move(rhs.schemaMap_)),
1581  schemaRef_(std::move(rhs.schemaRef_)),
1582  uri_(std::move(rhs.uri_))
1583  {
1584  rhs.remoteProvider_ = 0;
1585  rhs.allocator_ = 0;
1586  rhs.ownAllocator_ = 0;
1587  rhs.typeless_ = 0;
1588  }
1589 #endif
1590 
1593  while (!schemaMap_.Empty())
1594  schemaMap_.template Pop<SchemaEntry>(1)->~SchemaEntry();
1595 
1596  if (typeless_) {
1597  typeless_->~SchemaType();
1598  Allocator::Free(typeless_);
1599  }
1600 
1602  }
1603 
1604  const URIType& GetURI() const { return uri_; }
1605 
1607  const SchemaType& GetRoot() const { return *root_; }
1608 
1609 private:
1614 
1616  SchemaRefEntry(const PointerType& s, const PointerType& t, const SchemaType** outSchema, Allocator *allocator) : source(s, allocator), target(t, allocator), schema(outSchema) {}
1620  };
1621 
1622  struct SchemaEntry {
1623  SchemaEntry(const PointerType& p, SchemaType* s, bool o, Allocator* allocator) : pointer(p, allocator), schema(s), owned(o) {}
1625  if (owned) {
1626  schema->~SchemaType();
1627  Allocator::Free(schema);
1628  }
1629  }
1632  bool owned;
1633  };
1634 
1635  void CreateSchemaRecursive(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
1636  if (schema)
1637  *schema = typeless_;
1638 
1639  if (v.GetType() == kObjectType) {
1640  const SchemaType* s = GetSchema(pointer);
1641  if (!s)
1642  CreateSchema(schema, pointer, v, document);
1643 
1644  for (typename ValueType::ConstMemberIterator itr = v.MemberBegin(); itr != v.MemberEnd(); ++itr)
1645  CreateSchemaRecursive(0, pointer.Append(itr->name, allocator_), itr->value, document);
1646  }
1647  else if (v.GetType() == kArrayType)
1648  for (SizeType i = 0; i < v.Size(); i++)
1649  CreateSchemaRecursive(0, pointer.Append(i, allocator_), v[i], document);
1650  }
1651 
1652  void CreateSchema(const SchemaType** schema, const PointerType& pointer, const ValueType& v, const ValueType& document) {
1653  CEREAL_RAPIDJSON_ASSERT(pointer.IsValid());
1654  if (v.IsObject()) {
1655  if (!HandleRefSchema(pointer, schema, v, document)) {
1656  SchemaType* s = new (allocator_->Malloc(sizeof(SchemaType))) SchemaType(this, pointer, v, document, allocator_);
1657  new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(pointer, s, true, allocator_);
1658  if (schema)
1659  *schema = s;
1660  }
1661  }
1662  }
1663 
1664  bool HandleRefSchema(const PointerType& source, const SchemaType** schema, const ValueType& v, const ValueType& document) {
1665  static const Ch kRefString[] = { '$', 'r', 'e', 'f', '\0' };
1666  static const ValueType kRefValue(kRefString, 4);
1667 
1668  typename ValueType::ConstMemberIterator itr = v.FindMember(kRefValue);
1669  if (itr == v.MemberEnd())
1670  return false;
1671 
1672  if (itr->value.IsString()) {
1673  SizeType len = itr->value.GetStringLength();
1674  if (len > 0) {
1675  const Ch* s = itr->value.GetString();
1676  SizeType i = 0;
1677  while (i < len && s[i] != '#') // Find the first #
1678  i++;
1679 
1680  if (i > 0) { // Remote reference, resolve immediately
1681  if (remoteProvider_) {
1682  if (const GenericSchemaDocument* remoteDocument = remoteProvider_->GetRemoteDocument(s, i)) {
1683  PointerType pointer(&s[i], len - i, allocator_);
1684  if (pointer.IsValid()) {
1685  if (const SchemaType* sc = remoteDocument->GetSchema(pointer)) {
1686  if (schema)
1687  *schema = sc;
1688  new (schemaMap_.template Push<SchemaEntry>()) SchemaEntry(source, const_cast<SchemaType*>(sc), false, allocator_);
1689  return true;
1690  }
1691  }
1692  }
1693  }
1694  }
1695  else if (s[i] == '#') { // Local reference, defer resolution
1696  PointerType pointer(&s[i], len - i, allocator_);
1697  if (pointer.IsValid()) {
1698  if (const ValueType* nv = pointer.Get(document))
1699  if (HandleRefSchema(source, schema, *nv, document))
1700  return true;
1701 
1702  new (schemaRef_.template Push<SchemaRefEntry>()) SchemaRefEntry(source, pointer, schema, allocator_);
1703  return true;
1704  }
1705  }
1706  }
1707  }
1708  return false;
1709  }
1710 
1711  const SchemaType* GetSchema(const PointerType& pointer) const {
1712  for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1713  if (pointer == target->pointer)
1714  return target->schema;
1715  return 0;
1716  }
1717 
1718  PointerType GetPointer(const SchemaType* schema) const {
1719  for (const SchemaEntry* target = schemaMap_.template Bottom<SchemaEntry>(); target != schemaMap_.template End<SchemaEntry>(); ++target)
1720  if (schema == target->schema)
1721  return target->pointer;
1722  return PointerType();
1723  }
1724 
1725  const SchemaType* GetTypeless() const { return typeless_; }
1726 
1727  static const size_t kInitialSchemaMapSize = 64;
1728  static const size_t kInitialSchemaRefSize = 64;
1729 
1735  internal::Stack<Allocator> schemaMap_; // Stores created Pointer -> Schemas
1736  internal::Stack<Allocator> schemaRef_; // Stores Pointer from $ref and schema which holds the $ref
1738 };
1739 
1744 
1746 // GenericSchemaValidator
1747 
1749 
1760 template <
1761  typename SchemaDocumentType,
1763  typename StateAllocator = CrtAllocator>
1765  public internal::ISchemaStateFactory<typename SchemaDocumentType::SchemaType>,
1767  public internal::IValidationErrorHandler<typename SchemaDocumentType::SchemaType>
1768 {
1769 public:
1770  typedef typename SchemaDocumentType::SchemaType SchemaType;
1771  typedef typename SchemaDocumentType::PointerType PointerType;
1773  typedef typename SchemaType::SValue SValue;
1774  typedef typename EncodingType::Ch Ch;
1777 
1779 
1786  const SchemaDocumentType& schemaDocument,
1787  StateAllocator* allocator = 0,
1788  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1789  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1790  :
1791  schemaDocument_(&schemaDocument),
1792  root_(schemaDocument.GetRoot()),
1793  stateAllocator_(allocator),
1794  ownStateAllocator_(0),
1795  schemaStack_(allocator, schemaStackCapacity),
1796  documentStack_(allocator, documentStackCapacity),
1797  outputHandler_(0),
1799  currentError_(),
1801  valid_(true)
1803  , depth_(0)
1804 #endif
1805  {
1806  }
1807 
1809 
1816  const SchemaDocumentType& schemaDocument,
1817  OutputHandler& outputHandler,
1818  StateAllocator* allocator = 0,
1819  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
1820  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
1821  :
1822  schemaDocument_(&schemaDocument),
1823  root_(schemaDocument.GetRoot()),
1824  stateAllocator_(allocator),
1825  ownStateAllocator_(0),
1826  schemaStack_(allocator, schemaStackCapacity),
1827  documentStack_(allocator, documentStackCapacity),
1828  outputHandler_(&outputHandler),
1830  currentError_(),
1832  valid_(true)
1834  , depth_(0)
1835 #endif
1836  {
1837  }
1838 
1841  Reset();
1843  }
1844 
1846  void Reset() {
1847  while (!schemaStack_.Empty())
1848  PopSchema();
1849  documentStack_.Clear();
1850  error_.SetObject();
1851  currentError_.SetNull();
1852  missingDependents_.SetNull();
1853  valid_ = true;
1854  }
1855 
1857  // Implementation of ISchemaValidator
1858  virtual bool IsValid() const { return valid_; }
1859 
1861  ValueType& GetError() { return error_; }
1862  const ValueType& GetError() const { return error_; }
1863 
1866  return schemaStack_.Empty() ? PointerType() : CurrentSchema().GetPointer();
1867  }
1868 
1870  const Ch* GetInvalidSchemaKeyword() const {
1871  return schemaStack_.Empty() ? 0 : CurrentContext().invalidKeyword;
1872  }
1873 
1876  if (documentStack_.Empty()) {
1877  return PointerType();
1878  }
1879  else {
1880  return PointerType(documentStack_.template Bottom<Ch>(), documentStack_.GetSize() / sizeof(Ch));
1881  }
1882  }
1883 
1884  void NotMultipleOf(int64_t actual, const SValue& expected) {
1885  AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1886  }
1887  void NotMultipleOf(uint64_t actual, const SValue& expected) {
1888  AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1889  }
1890  void NotMultipleOf(double actual, const SValue& expected) {
1891  AddNumberError(SchemaType::GetMultipleOfString(), ValueType(actual).Move(), expected);
1892  }
1893  void AboveMaximum(int64_t actual, const SValue& expected, bool exclusive) {
1894  AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1895  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1896  }
1897  void AboveMaximum(uint64_t actual, const SValue& expected, bool exclusive) {
1898  AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1899  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1900  }
1901  void AboveMaximum(double actual, const SValue& expected, bool exclusive) {
1902  AddNumberError(SchemaType::GetMaximumString(), ValueType(actual).Move(), expected,
1903  exclusive ? &SchemaType::GetExclusiveMaximumString : 0);
1904  }
1905  void BelowMinimum(int64_t actual, const SValue& expected, bool exclusive) {
1906  AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1907  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1908  }
1909  void BelowMinimum(uint64_t actual, const SValue& expected, bool exclusive) {
1910  AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1911  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1912  }
1913  void BelowMinimum(double actual, const SValue& expected, bool exclusive) {
1914  AddNumberError(SchemaType::GetMinimumString(), ValueType(actual).Move(), expected,
1915  exclusive ? &SchemaType::GetExclusiveMinimumString : 0);
1916  }
1917 
1918  void TooLong(const Ch* str, SizeType length, SizeType expected) {
1919  AddNumberError(SchemaType::GetMaxLengthString(),
1920  ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1921  }
1922  void TooShort(const Ch* str, SizeType length, SizeType expected) {
1923  AddNumberError(SchemaType::GetMinLengthString(),
1924  ValueType(str, length, GetStateAllocator()).Move(), SValue(expected).Move());
1925  }
1926  void DoesNotMatch(const Ch* str, SizeType length) {
1927  currentError_.SetObject();
1928  currentError_.AddMember(GetActualString(), ValueType(str, length, GetStateAllocator()).Move(), GetStateAllocator());
1929  AddCurrentError(SchemaType::GetPatternString());
1930  }
1931 
1932  void DisallowedItem(SizeType index) {
1933  currentError_.SetObject();
1934  currentError_.AddMember(GetDisallowedString(), ValueType(index).Move(), GetStateAllocator());
1935  AddCurrentError(SchemaType::GetAdditionalItemsString(), true);
1936  }
1937  void TooFewItems(SizeType actualCount, SizeType expectedCount) {
1938  AddNumberError(SchemaType::GetMinItemsString(),
1939  ValueType(actualCount).Move(), SValue(expectedCount).Move());
1940  }
1941  void TooManyItems(SizeType actualCount, SizeType expectedCount) {
1942  AddNumberError(SchemaType::GetMaxItemsString(),
1943  ValueType(actualCount).Move(), SValue(expectedCount).Move());
1944  }
1945  void DuplicateItems(SizeType index1, SizeType index2) {
1946  ValueType duplicates(kArrayType);
1947  duplicates.PushBack(index1, GetStateAllocator());
1948  duplicates.PushBack(index2, GetStateAllocator());
1949  currentError_.SetObject();
1950  currentError_.AddMember(GetDuplicatesString(), duplicates, GetStateAllocator());
1951  AddCurrentError(SchemaType::GetUniqueItemsString(), true);
1952  }
1953 
1954  void TooManyProperties(SizeType actualCount, SizeType expectedCount) {
1955  AddNumberError(SchemaType::GetMaxPropertiesString(),
1956  ValueType(actualCount).Move(), SValue(expectedCount).Move());
1957  }
1958  void TooFewProperties(SizeType actualCount, SizeType expectedCount) {
1959  AddNumberError(SchemaType::GetMinPropertiesString(),
1960  ValueType(actualCount).Move(), SValue(expectedCount).Move());
1961  }
1963  currentError_.SetArray();
1964  }
1965  void AddMissingProperty(const SValue& name) {
1966  currentError_.PushBack(ValueType(name, GetStateAllocator()).Move(), GetStateAllocator());
1967  }
1969  if (currentError_.Empty())
1970  return false;
1971  ValueType error(kObjectType);
1972  error.AddMember(GetMissingString(), currentError_, GetStateAllocator());
1973  currentError_ = error;
1974  AddCurrentError(SchemaType::GetRequiredString());
1975  return true;
1976  }
1977  void PropertyViolations(ISchemaValidator** subvalidators, SizeType count) {
1978  for (SizeType i = 0; i < count; ++i)
1979  MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
1980  }
1981  void DisallowedProperty(const Ch* name, SizeType length) {
1982  currentError_.SetObject();
1983  currentError_.AddMember(GetDisallowedString(), ValueType(name, length, GetStateAllocator()).Move(), GetStateAllocator());
1984  AddCurrentError(SchemaType::GetAdditionalPropertiesString(), true);
1985  }
1986 
1988  currentError_.SetObject();
1989  }
1991  missingDependents_.SetArray();
1992  }
1993  void AddMissingDependentProperty(const SValue& targetName) {
1994  missingDependents_.PushBack(ValueType(targetName, GetStateAllocator()).Move(), GetStateAllocator());
1995  }
1996  void EndMissingDependentProperties(const SValue& sourceName) {
1997  if (!missingDependents_.Empty())
1998  currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2000  }
2001  void AddDependencySchemaError(const SValue& sourceName, ISchemaValidator* subvalidator) {
2002  currentError_.AddMember(ValueType(sourceName, GetStateAllocator()).Move(),
2003  static_cast<GenericSchemaValidator*>(subvalidator)->GetError(), GetStateAllocator());
2004  }
2006  if (currentError_.ObjectEmpty())
2007  return false;
2008  ValueType error(kObjectType);
2009  error.AddMember(GetErrorsString(), currentError_, GetStateAllocator());
2010  currentError_ = error;
2011  AddCurrentError(SchemaType::GetDependenciesString());
2012  return true;
2013  }
2014 
2016  currentError_.SetObject();
2017  AddCurrentError(SchemaType::GetEnumString());
2018  }
2020  currentError_.SetArray();
2021  }
2022  void AddExpectedType(const typename SchemaType::ValueType& expectedType) {
2023  currentError_.PushBack(ValueType(expectedType, GetStateAllocator()).Move(), GetStateAllocator());
2024  }
2025  void EndDisallowedType(const typename SchemaType::ValueType& actualType) {
2026  ValueType error(kObjectType);
2027  error.AddMember(GetExpectedString(), currentError_, GetStateAllocator());
2028  error.AddMember(GetActualString(), ValueType(actualType, GetStateAllocator()).Move(), GetStateAllocator());
2029  currentError_ = error;
2030  AddCurrentError(SchemaType::GetTypeString());
2031  }
2032  void NotAllOf(ISchemaValidator** subvalidators, SizeType count) {
2033  for (SizeType i = 0; i < count; ++i) {
2034  MergeError(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError());
2035  }
2036  }
2037  void NoneOf(ISchemaValidator** subvalidators, SizeType count) {
2038  AddErrorArray(SchemaType::GetAnyOfString(), subvalidators, count);
2039  }
2040  void NotOneOf(ISchemaValidator** subvalidators, SizeType count) {
2041  AddErrorArray(SchemaType::GetOneOfString(), subvalidators, count);
2042  }
2043  void Disallowed() {
2044  currentError_.SetObject();
2045  AddCurrentError(SchemaType::GetNotString());
2046  }
2047 
2048 #define CEREAL_RAPIDJSON_STRING_(name, ...) \
2049  static const StringRefType& Get##name##String() {\
2050  static const Ch s[] = { __VA_ARGS__, '\0' };\
2051  static const StringRefType v(s, static_cast<SizeType>(sizeof(s) / sizeof(Ch) - 1)); \
2052  return v;\
2053  }
2054 
2055  CEREAL_RAPIDJSON_STRING_(InstanceRef, 'i', 'n', 's', 't', 'a', 'n', 'c', 'e', 'R', 'e', 'f')
2056  CEREAL_RAPIDJSON_STRING_(SchemaRef, 's', 'c', 'h', 'e', 'm', 'a', 'R', 'e', 'f')
2057  CEREAL_RAPIDJSON_STRING_(Expected, 'e', 'x', 'p', 'e', 'c', 't', 'e', 'd')
2058  CEREAL_RAPIDJSON_STRING_(Actual, 'a', 'c', 't', 'u', 'a', 'l')
2059  CEREAL_RAPIDJSON_STRING_(Disallowed, 'd', 'i', 's', 'a', 'l', 'l', 'o', 'w', 'e', 'd')
2060  CEREAL_RAPIDJSON_STRING_(Missing, 'm', 'i', 's', 's', 'i', 'n', 'g')
2061  CEREAL_RAPIDJSON_STRING_(Errors, 'e', 'r', 'r', 'o', 'r', 's')
2062  CEREAL_RAPIDJSON_STRING_(Duplicates, 'd', 'u', 'p', 'l', 'i', 'c', 'a', 't', 'e', 's')
2063 
2064 #undef CEREAL_RAPIDJSON_STRING_
2065 
2066 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
2067 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_() \
2068 CEREAL_RAPIDJSON_MULTILINEMACRO_BEGIN\
2069  *documentStack_.template Push<Ch>() = '\0';\
2070  documentStack_.template Pop<Ch>(1);\
2071  internal::PrintInvalidDocument(documentStack_.template Bottom<Ch>());\
2072 CEREAL_RAPIDJSON_MULTILINEMACRO_END
2073 #else
2074 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_()
2075 #endif
2076 
2077 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)\
2078  if (!valid_) return false; \
2079  if (!BeginValue() || !CurrentSchema().method arg1) {\
2080  CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_();\
2081  return valid_ = false;\
2082  }
2083 
2084 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)\
2085  for (Context* context = schemaStack_.template Bottom<Context>(); context != schemaStack_.template End<Context>(); context++) {\
2086  if (context->hasher)\
2087  static_cast<HasherType*>(context->hasher)->method arg2;\
2088  if (context->validators)\
2089  for (SizeType i_ = 0; i_ < context->validatorCount; i_++)\
2090  static_cast<GenericSchemaValidator*>(context->validators[i_])->method arg2;\
2091  if (context->patternPropertiesValidators)\
2092  for (SizeType i_ = 0; i_ < context->patternPropertiesValidatorCount; i_++)\
2093  static_cast<GenericSchemaValidator*>(context->patternPropertiesValidators[i_])->method arg2;\
2094  }
2095 
2096 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)\
2097  return valid_ = EndValue() && (!outputHandler_ || outputHandler_->method arg2)
2098 
2099 #define CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2) \
2100  CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_ (method, arg1);\
2101  CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2);\
2102  CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_ (method, arg2)
2103 
2111  bool RawNumber(const Ch* str, SizeType length, bool copy)
2112  { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2113  bool String(const Ch* str, SizeType length, bool copy)
2114  { CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(String, (CurrentContext(), str, length, copy), (str, length, copy)); }
2115 
2116  bool StartObject() {
2119  return valid_ = !outputHandler_ || outputHandler_->StartObject();
2120  }
2121 
2122  bool Key(const Ch* str, SizeType len, bool copy) {
2123  if (!valid_) return false;
2124  AppendToken(str, len);
2125  if (!CurrentSchema().Key(CurrentContext(), str, len, copy)) return valid_ = false;
2126  CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(Key, (str, len, copy));
2127  return valid_ = !outputHandler_ || outputHandler_->Key(str, len, copy);
2128  }
2129 
2130  bool EndObject(SizeType memberCount) {
2131  if (!valid_) return false;
2133  if (!CurrentSchema().EndObject(CurrentContext(), memberCount)) return valid_ = false;
2135  }
2136 
2137  bool StartArray() {
2140  return valid_ = !outputHandler_ || outputHandler_->StartArray();
2141  }
2142 
2143  bool EndArray(SizeType elementCount) {
2144  if (!valid_) return false;
2146  if (!CurrentSchema().EndArray(CurrentContext(), elementCount)) return valid_ = false;
2148  }
2149 
2150 #undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_VERBOSE_
2151 #undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_
2152 #undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_
2153 #undef CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_
2154 
2155  // Implementation of ISchemaStateFactory<SchemaType>
2156  virtual ISchemaValidator* CreateSchemaValidator(const SchemaType& root) {
2157  return new (GetStateAllocator().Malloc(sizeof(GenericSchemaValidator))) GenericSchemaValidator(*schemaDocument_, root, documentStack_.template Bottom<char>(), documentStack_.GetSize(),
2158 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
2159  depth_ + 1,
2160 #endif
2161  &GetStateAllocator());
2162  }
2163 
2164  virtual void DestroySchemaValidator(ISchemaValidator* validator) {
2165  GenericSchemaValidator* v = static_cast<GenericSchemaValidator*>(validator);
2167  StateAllocator::Free(v);
2168  }
2169 
2170  virtual void* CreateHasher() {
2171  return new (GetStateAllocator().Malloc(sizeof(HasherType))) HasherType(&GetStateAllocator());
2172  }
2173 
2174  virtual uint64_t GetHashCode(void* hasher) {
2175  return static_cast<HasherType*>(hasher)->GetHashCode();
2176  }
2177 
2178  virtual void DestroryHasher(void* hasher) {
2179  HasherType* h = static_cast<HasherType*>(hasher);
2180  h->~HasherType();
2181  StateAllocator::Free(h);
2182  }
2183 
2184  virtual void* MallocState(size_t size) {
2185  return GetStateAllocator().Malloc(size);
2186  }
2187 
2188  virtual void FreeState(void* p) {
2189  StateAllocator::Free(p);
2190  }
2191 
2192 private:
2193  typedef typename SchemaType::Context Context;
2194  typedef GenericValue<UTF8<>, StateAllocator> HashCodeArray;
2196 
2198  const SchemaDocumentType& schemaDocument,
2199  const SchemaType& root,
2200  const char* basePath, size_t basePathSize,
2202  unsigned depth,
2203 #endif
2204  StateAllocator* allocator = 0,
2205  size_t schemaStackCapacity = kDefaultSchemaStackCapacity,
2206  size_t documentStackCapacity = kDefaultDocumentStackCapacity)
2207  :
2208  schemaDocument_(&schemaDocument),
2209  root_(root),
2210  stateAllocator_(allocator),
2211  ownStateAllocator_(0),
2212  schemaStack_(allocator, schemaStackCapacity),
2213  documentStack_(allocator, documentStackCapacity),
2214  outputHandler_(0),
2216  currentError_(),
2218  valid_(true)
2220  , depth_(depth)
2221 #endif
2222  {
2223  if (basePath && basePathSize)
2224  memcpy(documentStack_.template Push<char>(basePathSize), basePath, basePathSize);
2225  }
2226 
2227  StateAllocator& GetStateAllocator() {
2228  if (!stateAllocator_)
2230  return *stateAllocator_;
2231  }
2232 
2233  bool BeginValue() {
2234  if (schemaStack_.Empty())
2235  PushSchema(root_);
2236  else {
2237  if (CurrentContext().inArray)
2239 
2241  return false;
2242 
2243  SizeType count = CurrentContext().patternPropertiesSchemaCount;
2244  const SchemaType** sa = CurrentContext().patternPropertiesSchemas;
2245  typename Context::PatternValidatorType patternValidatorType = CurrentContext().valuePatternValidatorType;
2246  bool valueUniqueness = CurrentContext().valueUniqueness;
2247  CEREAL_RAPIDJSON_ASSERT(CurrentContext().valueSchema);
2248  PushSchema(*CurrentContext().valueSchema);
2249 
2250  if (count > 0) {
2251  CurrentContext().objectPatternValidatorType = patternValidatorType;
2252  ISchemaValidator**& va = CurrentContext().patternPropertiesValidators;
2253  SizeType& validatorCount = CurrentContext().patternPropertiesValidatorCount;
2254  va = static_cast<ISchemaValidator**>(MallocState(sizeof(ISchemaValidator*) * count));
2255  for (SizeType i = 0; i < count; i++)
2256  va[validatorCount++] = CreateSchemaValidator(*sa[i]);
2257  }
2258 
2259  CurrentContext().arrayUniqueness = valueUniqueness;
2260  }
2261  return true;
2262  }
2263 
2264  bool EndValue() {
2266  return false;
2267 
2268 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
2270  schemaDocument_->GetPointer(&CurrentSchema()).Stringify(sb);
2271 
2272  *documentStack_.template Push<Ch>() = '\0';
2273  documentStack_.template Pop<Ch>(1);
2274  internal::PrintValidatorPointers(depth_, sb.GetString(), documentStack_.template Bottom<Ch>());
2275 #endif
2276 
2277  uint64_t h = CurrentContext().arrayUniqueness ? static_cast<HasherType*>(CurrentContext().hasher)->GetHashCode() : 0;
2278 
2279  PopSchema();
2280 
2281  if (!schemaStack_.Empty()) {
2282  Context& context = CurrentContext();
2283  if (context.valueUniqueness) {
2284  HashCodeArray* a = static_cast<HashCodeArray*>(context.arrayElementHashCodes);
2285  if (!a)
2286  CurrentContext().arrayElementHashCodes = a = new (GetStateAllocator().Malloc(sizeof(HashCodeArray))) HashCodeArray(kArrayType);
2287  for (typename HashCodeArray::ConstValueIterator itr = a->Begin(); itr != a->End(); ++itr)
2288  if (itr->GetUint64() == h) {
2289  DuplicateItems(static_cast<SizeType>(itr - a->Begin()), a->Size());
2290  CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(SchemaType::GetUniqueItemsString());
2291  }
2292  a->PushBack(h, GetStateAllocator());
2293  }
2294  }
2295 
2296  // Remove the last token of document pointer
2297  while (!documentStack_.Empty() && *documentStack_.template Pop<Ch>(1) != '/')
2298  ;
2299 
2300  return true;
2301  }
2302 
2303  void AppendToken(const Ch* str, SizeType len) {
2304  documentStack_.template Reserve<Ch>(1 + len * 2); // worst case all characters are escaped as two characters
2305  *documentStack_.template PushUnsafe<Ch>() = '/';
2306  for (SizeType i = 0; i < len; i++) {
2307  if (str[i] == '~') {
2308  *documentStack_.template PushUnsafe<Ch>() = '~';
2309  *documentStack_.template PushUnsafe<Ch>() = '0';
2310  }
2311  else if (str[i] == '/') {
2312  *documentStack_.template PushUnsafe<Ch>() = '~';
2313  *documentStack_.template PushUnsafe<Ch>() = '1';
2314  }
2315  else
2316  *documentStack_.template PushUnsafe<Ch>() = str[i];
2317  }
2318  }
2319 
2320  CEREAL_RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType& schema) { new (schemaStack_.template Push<Context>()) Context(*this, *this, &schema); }
2321 
2322  CEREAL_RAPIDJSON_FORCEINLINE void PopSchema() {
2323  Context* c = schemaStack_.template Pop<Context>(1);
2324  if (HashCodeArray* a = static_cast<HashCodeArray*>(c->arrayElementHashCodes)) {
2325  a->~HashCodeArray();
2326  StateAllocator::Free(a);
2327  }
2328  c->~Context();
2329  }
2330 
2331  void AddErrorLocation(ValueType& result, bool parent) {
2333  PointerType instancePointer = GetInvalidDocumentPointer();
2334  ((parent && instancePointer.GetTokenCount() > 0)
2335  ? PointerType(instancePointer.GetTokens(), instancePointer.GetTokenCount() - 1)
2336  : instancePointer).StringifyUriFragment(sb);
2337  ValueType instanceRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2338  GetStateAllocator());
2339  result.AddMember(GetInstanceRefString(), instanceRef, GetStateAllocator());
2340  sb.Clear();
2341  memcpy(sb.Push(CurrentSchema().GetURI().GetStringLength()),
2342  CurrentSchema().GetURI().GetString(),
2343  CurrentSchema().GetURI().GetStringLength() * sizeof(Ch));
2344  GetInvalidSchemaPointer().StringifyUriFragment(sb);
2345  ValueType schemaRef(sb.GetString(), static_cast<SizeType>(sb.GetSize() / sizeof(Ch)),
2346  GetStateAllocator());
2347  result.AddMember(GetSchemaRefString(), schemaRef, GetStateAllocator());
2348  }
2349 
2350  void AddError(ValueType& keyword, ValueType& error) {
2351  typename ValueType::MemberIterator member = error_.FindMember(keyword);
2352  if (member == error_.MemberEnd())
2353  error_.AddMember(keyword, error, GetStateAllocator());
2354  else {
2355  if (member->value.IsObject()) {
2356  ValueType errors(kArrayType);
2357  errors.PushBack(member->value, GetStateAllocator());
2358  member->value = errors;
2359  }
2360  member->value.PushBack(error, GetStateAllocator());
2361  }
2362  }
2363 
2364  void AddCurrentError(const typename SchemaType::ValueType& keyword, bool parent = false) {
2366  AddError(ValueType(keyword, GetStateAllocator(), false).Move(), currentError_);
2367  }
2368 
2369  void MergeError(ValueType& other) {
2370  for (typename ValueType::MemberIterator it = other.MemberBegin(), end = other.MemberEnd(); it != end; ++it) {
2371  AddError(it->name, it->value);
2372  }
2373  }
2374 
2375  void AddNumberError(const typename SchemaType::ValueType& keyword, ValueType& actual, const SValue& expected,
2376  const typename SchemaType::ValueType& (*exclusive)() = 0) {
2377  currentError_.SetObject();
2378  currentError_.AddMember(GetActualString(), actual, GetStateAllocator());
2379  currentError_.AddMember(GetExpectedString(), ValueType(expected, GetStateAllocator()).Move(), GetStateAllocator());
2380  if (exclusive)
2381  currentError_.AddMember(ValueType(exclusive(), GetStateAllocator()).Move(), true, GetStateAllocator());
2382  AddCurrentError(keyword);
2383  }
2384 
2385  void AddErrorArray(const typename SchemaType::ValueType& keyword,
2386  ISchemaValidator** subvalidators, SizeType count) {
2387  ValueType errors(kArrayType);
2388  for (SizeType i = 0; i < count; ++i)
2389  errors.PushBack(static_cast<GenericSchemaValidator*>(subvalidators[i])->GetError(), GetStateAllocator());
2390  currentError_.SetObject();
2391  currentError_.AddMember(GetErrorsString(), errors, GetStateAllocator());
2392  AddCurrentError(keyword);
2393  }
2394 
2395  const SchemaType& CurrentSchema() const { return *schemaStack_.template Top<Context>()->schema; }
2396  Context& CurrentContext() { return *schemaStack_.template Top<Context>(); }
2397  const Context& CurrentContext() const { return *schemaStack_.template Top<Context>(); }
2398 
2399  static const size_t kDefaultSchemaStackCapacity = 1024;
2400  static const size_t kDefaultDocumentStackCapacity = 256;
2401  const SchemaDocumentType* schemaDocument_;
2403  StateAllocator* stateAllocator_;
2404  StateAllocator* ownStateAllocator_;
2407  OutputHandler* outputHandler_;
2411  bool valid_;
2412 #if CEREAL_RAPIDJSON_SCHEMA_VERBOSE
2413  unsigned depth_;
2414 #endif
2415 };
2416 
2418 
2420 // SchemaValidatingReader
2421 
2423 
2432 template <
2433  unsigned parseFlags,
2434  typename InputStream,
2435  typename SourceEncoding,
2436  typename SchemaDocumentType = SchemaDocument,
2437  typename StackAllocator = CrtAllocator>
2439 public:
2440  typedef typename SchemaDocumentType::PointerType PointerType;
2441  typedef typename InputStream::Ch Ch;
2443 
2445 
2449  SchemaValidatingReader(InputStream& is, const SchemaDocumentType& sd) : is_(is), sd_(sd), invalidSchemaKeyword_(), error_(kObjectType), isValid_(true) {}
2450 
2451  template <typename Handler>
2452  bool operator()(Handler& handler) {
2455  parseResult_ = reader.template Parse<parseFlags>(is_, validator);
2456 
2457  isValid_ = validator.IsValid();
2458  if (isValid_) {
2462  error_.SetObject();
2463  }
2464  else {
2468  error_.CopyFrom(validator.GetError(), allocator_);
2469  }
2470 
2471  return parseResult_;
2472  }
2473 
2474  const ParseResult& GetParseResult() const { return parseResult_; }
2475  bool IsValid() const { return isValid_; }
2479  const ValueType& GetError() const { return error_; }
2480 
2481 private:
2482  InputStream& is_;
2483  const SchemaDocumentType& sd_;
2484 
2489  StackAllocator allocator_;
2491  bool isValid_;
2492 };
2493 
2495 CEREAL_RAPIDJSON_DIAG_POP
2496 
2497 #endif // CEREAL_RAPIDJSON_SCHEMA_H_
#define CEREAL_RAPIDJSON_ASSERT(x)
Definition: json.hpp:50
EncodingType
Definition: Xml.h:26
C-runtime library allocator.
Definition: allocators.h:75
(Constant) member iterator for a JSON object value
Definition: document.h:105
SAX-style JSON parser. Use Reader for UTF8 encoding and default allocator.
Definition: reader.h:537
JSON schema document.
Definition: schema.h:1502
const SchemaType * GetTypeless() const
Definition: schema.h:1725
internal::Stack< Allocator > schemaRef_
Definition: schema.h:1736
bool HandleRefSchema(const PointerType &source, const SchemaType **schema, const ValueType &v, const ValueType &document)
Definition: schema.h:1664
void CreateSchemaRecursive(const SchemaType **schema, const PointerType &pointer, const ValueType &v, const ValueType &document)
Definition: schema.h:1635
static const size_t kInitialSchemaMapSize
Definition: schema.h:1727
const SchemaType & GetRoot() const
Get the root schema.
Definition: schema.h:1607
const SchemaType * root_
Root schema.
Definition: schema.h:1733
static const size_t kInitialSchemaRefSize
Definition: schema.h:1728
GenericSchemaDocument & operator=(const GenericSchemaDocument &)
Prohibit assignment.
const SchemaType * GetSchema(const PointerType &pointer) const
Definition: schema.h:1711
~GenericSchemaDocument()
Destructor.
Definition: schema.h:1592
URIType uri_
Definition: schema.h:1737
SchemaType * typeless_
Definition: schema.h:1734
internal::Stack< Allocator > schemaMap_
Definition: schema.h:1735
Allocator * allocator_
Definition: schema.h:1731
Allocator * ownAllocator_
Definition: schema.h:1732
IGenericRemoteSchemaDocumentProvider< GenericSchemaDocument > IRemoteSchemaDocumentProviderType
Definition: schema.h:1505
void CreateSchema(const SchemaType **schema, const PointerType &pointer, const ValueType &v, const ValueType &document)
Definition: schema.h:1652
EncodingType::Ch Ch
Definition: schema.h:1508
Allocator AllocatorType
Definition: schema.h:1506
GenericValue< EncodingType, Allocator > URIType
Definition: schema.h:1511
internal::Schema< GenericSchemaDocument > SchemaType
Definition: schema.h:1509
ValueType::EncodingType EncodingType
Definition: schema.h:1507
PointerType GetPointer(const SchemaType *schema) const
Definition: schema.h:1718
ValueT ValueType
Definition: schema.h:1504
GenericSchemaDocument(const GenericSchemaDocument &)
Prohibit copying.
IRemoteSchemaDocumentProviderType * remoteProvider_
Definition: schema.h:1730
GenericSchemaDocument(const ValueType &document, const Ch *uri=0, SizeType uriLength=0, IRemoteSchemaDocumentProviderType *remoteProvider=0, Allocator *allocator=0)
Constructor.
Definition: schema.h:1526
GenericPointer< ValueType, Allocator > PointerType
Definition: schema.h:1510
const URIType & GetURI() const
Definition: schema.h:1604
JSON Schema Validator.
Definition: schema.h:1768
static const size_t kDefaultDocumentStackCapacity
Definition: schema.h:2400
virtual void DestroryHasher(void *hasher)
Definition: schema.h:2178
Context & CurrentContext()
Definition: schema.h:2396
ValueType missingDependents_
Definition: schema.h:2410
void AddError(ValueType &keyword, ValueType &error)
Definition: schema.h:2350
void BelowMinimum(int64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:1905
const ValueType & GetError() const
Definition: schema.h:1862
CEREAL_RAPIDJSON_FORCEINLINE void PushSchema(const SchemaType &schema)
Definition: schema.h:2320
StateAllocator * ownStateAllocator_
Definition: schema.h:2404
StateAllocator * stateAllocator_
Definition: schema.h:2403
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor without output handler.
Definition: schema.h:1785
void DisallowedValue()
Definition: schema.h:2015
void AddCurrentError(const typename SchemaType::ValueType &keyword, bool parent=false)
Definition: schema.h:2364
void TooLong(const Ch *str, SizeType length, SizeType expected)
Definition: schema.h:1918
void AddDependencySchemaError(const SValue &sourceName, ISchemaValidator *subvalidator)
Definition: schema.h:2001
void PropertyViolations(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:1977
void DisallowedItem(SizeType index)
Definition: schema.h:1932
CEREAL_RAPIDJSON_FORCEINLINE void PopSchema()
Definition: schema.h:2322
bool String(const Ch *str, SizeType length, bool copy)
Definition: schema.h:2113
bool BeginValue()
Definition: schema.h:2233
SchemaType::SValue SValue
Definition: schema.h:1773
~GenericSchemaValidator()
Destructor.
Definition: schema.h:1840
void StartMissingProperties()
Definition: schema.h:1962
void NotAllOf(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2032
const SchemaDocumentType * schemaDocument_
Definition: schema.h:2401
GenericValue< EncodingType, StateAllocator > ValueType
Definition: schema.h:1776
void DisallowedProperty(const Ch *name, SizeType length)
Definition: schema.h:1981
void Reset()
Reset the internal states.
Definition: schema.h:1846
void AboveMaximum(int64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:1893
virtual void FreeState(void *p)
Definition: schema.h:2188
bool EndMissingProperties()
Definition: schema.h:1968
void MergeError(ValueType &other)
Definition: schema.h:2369
bool StartObject()
Definition: schema.h:2116
PointerType GetInvalidSchemaPointer() const
Gets the JSON pointer pointed to the invalid schema.
Definition: schema.h:1865
void NotMultipleOf(uint64_t actual, const SValue &expected)
Definition: schema.h:1887
GenericStringRef< Ch > StringRefType
Definition: schema.h:1775
bool valid_
Definition: schema.h:2411
bool EndArray(SizeType elementCount)
Definition: schema.h:2143
void AddExpectedType(const typename SchemaType::ValueType &expectedType)
Definition: schema.h:2022
bool Key(const Ch *str, SizeType len, bool copy)
Definition: schema.h:2122
bool Null()
Definition: schema.h:2104
const SchemaType & root_
Definition: schema.h:2402
void StartDependencyErrors()
Definition: schema.h:1987
void TooShort(const Ch *str, SizeType length, SizeType expected)
Definition: schema.h:1922
void TooManyItems(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:1941
ValueType & GetError()
Gets the error object.
Definition: schema.h:1861
virtual void * MallocState(size_t size)
Definition: schema.h:2184
void DuplicateItems(SizeType index1, SizeType index2)
Definition: schema.h:1945
StateAllocator & GetStateAllocator()
Definition: schema.h:2227
void AddMissingDependentProperty(const SValue &targetName)
Definition: schema.h:1993
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, const SchemaType &root, const char *basePath, size_t basePathSize, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Definition: schema.h:2197
EncodingType::Ch Ch
Definition: schema.h:1774
void AddMissingProperty(const SValue &name)
Definition: schema.h:1965
virtual bool IsValid() const
Checks whether the current state is valid.
Definition: schema.h:1858
const Context & CurrentContext() const
Definition: schema.h:2397
void AboveMaximum(uint64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:1897
internal::Stack< StateAllocator > documentStack_
stack to store the current path of validating document (Ch)
Definition: schema.h:2406
void StartDisallowedType()
Definition: schema.h:2019
ValueType error_
Definition: schema.h:2408
bool Bool(bool b)
Definition: schema.h:2105
bool Uint(unsigned u)
Definition: schema.h:2107
bool EndObject(SizeType memberCount)
Definition: schema.h:2130
void AddNumberError(const typename SchemaType::ValueType &keyword, ValueType &actual, const SValue &expected, const typename SchemaType::ValueType &(*exclusive)()=0)
Definition: schema.h:2375
static const size_t kDefaultSchemaStackCapacity
Definition: schema.h:2399
void NoneOf(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2037
void TooFewProperties(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:1958
void NotMultipleOf(int64_t actual, const SValue &expected)
Definition: schema.h:1884
bool EndDependencyErrors()
Definition: schema.h:2005
const Ch * GetInvalidSchemaKeyword() const
Gets the keyword of invalid schema.
Definition: schema.h:1870
internal::Hasher< EncodingType, StateAllocator > HasherType
Definition: schema.h:2195
bool StartArray()
Definition: schema.h:2137
virtual void * CreateHasher()
Definition: schema.h:2170
void AboveMaximum(double actual, const SValue &expected, bool exclusive)
Definition: schema.h:1901
bool Uint64(uint64_t u)
Definition: schema.h:2109
virtual uint64_t GetHashCode(void *hasher)
Definition: schema.h:2174
OutputHandler * outputHandler_
Definition: schema.h:2407
PointerType GetInvalidDocumentPointer() const
Gets the JSON pointer pointed to the invalid value.
Definition: schema.h:1875
GenericSchemaValidator(const SchemaDocumentType &schemaDocument, OutputHandler &outputHandler, StateAllocator *allocator=0, size_t schemaStackCapacity=kDefaultSchemaStackCapacity, size_t documentStackCapacity=kDefaultDocumentStackCapacity)
Constructor with output handler.
Definition: schema.h:1815
void StartMissingDependentProperties()
Definition: schema.h:1990
bool Int64(int64_t i)
Definition: schema.h:2108
SchemaType::Context Context
Definition: schema.h:2193
SchemaDocumentType::SchemaType SchemaType
Definition: schema.h:1770
void Disallowed()
Definition: schema.h:2043
SchemaType::EncodingType EncodingType
Definition: schema.h:1772
void AppendToken(const Ch *str, SizeType len)
Definition: schema.h:2303
const SchemaType & CurrentSchema() const
Definition: schema.h:2395
void BelowMinimum(uint64_t actual, const SValue &expected, bool exclusive)
Definition: schema.h:1909
void NotOneOf(ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2040
void TooManyProperties(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:1954
bool Int(int i)
Definition: schema.h:2106
SchemaDocumentType::PointerType PointerType
Definition: schema.h:1771
void EndDisallowedType(const typename SchemaType::ValueType &actualType)
Definition: schema.h:2025
GenericValue< UTF8<>, StateAllocator > HashCodeArray
Definition: schema.h:2194
virtual void DestroySchemaValidator(ISchemaValidator *validator)
Definition: schema.h:2164
bool RawNumber(const Ch *str, SizeType length, bool copy)
Definition: schema.h:2111
internal::Stack< StateAllocator > schemaStack_
stack to store the current path of schema (BaseSchemaType *)
Definition: schema.h:2405
void NotMultipleOf(double actual, const SValue &expected)
Definition: schema.h:1890
bool EndValue()
Definition: schema.h:2264
bool Double(double d)
Definition: schema.h:2110
virtual ISchemaValidator * CreateSchemaValidator(const SchemaType &root)
Definition: schema.h:2156
void DoesNotMatch(const Ch *str, SizeType length)
Definition: schema.h:1926
void TooFewItems(SizeType actualCount, SizeType expectedCount)
Definition: schema.h:1937
void AddErrorArray(const typename SchemaType::ValueType &keyword, ISchemaValidator **subvalidators, SizeType count)
Definition: schema.h:2385
void AddErrorLocation(ValueType &result, bool parent)
Definition: schema.h:2331
ValueType currentError_
Definition: schema.h:2409
void EndMissingDependentProperties(const SValue &sourceName)
Definition: schema.h:1996
void BelowMinimum(double actual, const SValue &expected, bool exclusive)
Definition: schema.h:1913
Represents an in-memory output stream.
Definition: stringbuffer.h:41
void Clear()
Definition: stringbuffer.h:60
Ch * Push(size_t count)
Definition: stringbuffer.h:69
size_t GetSize() const
Get the size of string in bytes in the string buffer.
Definition: stringbuffer.h:82
const Ch * GetString() const
Definition: stringbuffer.h:73
Definition: schema.h:1481
virtual ~IGenericRemoteSchemaDocumentProvider()
Definition: schema.h:1485
virtual const SchemaDocumentType * GetRemoteDocument(const Ch *uri, SizeType length)=0
SchemaDocumentType::Ch Ch
Definition: schema.h:1483
Default memory allocator used by the parser and DOM.
Definition: allocators.h:115
A helper class for parsing with validation.
Definition: schema.h:2438
ValueType error_
Definition: schema.h:2490
PointerType invalidSchemaPointer_
Definition: schema.h:2486
SchemaDocumentType::PointerType PointerType
Definition: schema.h:2440
const Ch * invalidSchemaKeyword_
Definition: schema.h:2487
bool IsValid() const
Definition: schema.h:2475
bool isValid_
Definition: schema.h:2491
const PointerType & GetInvalidDocumentPointer() const
Definition: schema.h:2478
InputStream::Ch Ch
Definition: schema.h:2441
bool operator()(Handler &handler)
Definition: schema.h:2452
const ValueType & GetError() const
Definition: schema.h:2479
StackAllocator allocator_
Definition: schema.h:2489
ParseResult parseResult_
Definition: schema.h:2485
const SchemaDocumentType & sd_
Definition: schema.h:2483
const PointerType & GetInvalidSchemaPointer() const
Definition: schema.h:2476
const Ch * GetInvalidSchemaKeyword() const
Definition: schema.h:2477
PointerType invalidDocumentPointer_
Definition: schema.h:2488
const ParseResult & GetParseResult() const
Definition: schema.h:2474
SchemaValidatingReader(InputStream &is, const SchemaDocumentType &sd)
Constructor.
Definition: schema.h:2449
GenericValue< SourceEncoding, StackAllocator > ValueType
Definition: schema.h:2442
InputStream & is_
Definition: schema.h:2482
Definition: regex.h:607
bool Search(InputStream &is)
Definition: regex.h:640
Regular expression engine with subset of ECMAscript grammar.
Definition: regex.h:114
bool IsValid() const
Definition: regex.h:135
Definition: schema.h:220
bool WriteBuffer(Type type, const void *data, size_t len)
Definition: schema.h:292
static const size_t kDefaultSize
Definition: schema.h:279
bool Bool(bool b)
Definition: schema.h:227
bool Uint64(uint64_t u)
Definition: schema.h:231
bool StartObject()
Definition: schema.h:250
bool Key(const Ch *str, SizeType len, bool copy)
Definition: schema.h:251
bool StartArray()
Definition: schema.h:261
Encoding::Ch Ch
Definition: schema.h:222
bool Uint(unsigned u)
Definition: schema.h:229
bool Null()
Definition: schema.h:226
bool EndObject(SizeType memberCount)
Definition: schema.h:252
Hasher(Allocator *allocator=0, size_t stackCapacity=kDefaultSize)
Definition: schema.h:224
bool Double(double d)
Definition: schema.h:232
bool String(const Ch *str, SizeType len, bool)
Definition: schema.h:245
bool Int(int i)
Definition: schema.h:228
bool WriteNumber(const Number &n)
Definition: schema.h:290
uint64_t GetHashCode() const
Definition: schema.h:273
static uint64_t Hash(uint64_t h, uint64_t d)
Definition: schema.h:302
bool EndArray(SizeType elementCount)
Definition: schema.h:262
bool Int64(int64_t i)
Definition: schema.h:230
bool IsValid() const
Definition: schema.h:271
bool RawNumber(const Ch *str, SizeType len, bool)
Definition: schema.h:240
Stack< Allocator > stack_
Definition: schema.h:309
bool WriteType(Type type)
Definition: schema.h:288
Definition: schema.h:147
virtual void DestroySchemaValidator(ISchemaValidator *validator)=0
virtual void FreeState(void *p)=0
virtual void * CreateHasher()=0
virtual void DestroryHasher(void *hasher)=0
virtual void * MallocState(size_t size)=0
virtual uint64_t GetHashCode(void *hasher)=0
virtual ~ISchemaStateFactory()
Definition: schema.h:149
virtual ISchemaValidator * CreateSchemaValidator(const SchemaType &)=0
Definition: schema.h:137
virtual bool IsValid() const =0
virtual ~ISchemaValidator()
Definition: schema.h:139
Definition: schema.h:163
virtual void EndMissingDependentProperties(const SValue &sourceName)=0
virtual void DisallowedItem(SizeType index)=0
virtual void NotMultipleOf(int64_t actual, const SValue &expected)=0
SchemaType::Ch Ch
Definition: schema.h:165
SchemaType::SValue SValue
Definition: schema.h:166
virtual void AddMissingDependentProperty(const SValue &targetName)=0
virtual void TooManyProperties(SizeType actualCount, SizeType expectedCount)=0
virtual bool EndMissingProperties()=0
virtual void DuplicateItems(SizeType index1, SizeType index2)=0
virtual void AddMissingProperty(const SValue &name)=0
virtual void NotAllOf(ISchemaValidator **subvalidators, SizeType count)=0
virtual void AddDependencySchemaError(const SValue &souceName, ISchemaValidator *subvalidator)=0
virtual void TooShort(const Ch *str, SizeType length, SizeType expected)=0
virtual void BelowMinimum(int64_t actual, const SValue &expected, bool exclusive)=0
virtual void AboveMaximum(double actual, const SValue &expected, bool exclusive)=0
virtual void AddExpectedType(const typename SchemaType::ValueType &expectedType)=0
virtual void DisallowedProperty(const Ch *name, SizeType length)=0
virtual void NoneOf(ISchemaValidator **subvalidators, SizeType count)=0
virtual void NotOneOf(ISchemaValidator **subvalidators, SizeType count)=0
virtual void AboveMaximum(uint64_t actual, const SValue &expected, bool exclusive)=0
virtual ~IValidationErrorHandler()
Definition: schema.h:168
virtual void AboveMaximum(int64_t actual, const SValue &expected, bool exclusive)=0
virtual bool EndDependencyErrors()=0
virtual void BelowMinimum(double actual, const SValue &expected, bool exclusive)=0
virtual void TooManyItems(SizeType actualCount, SizeType expectedCount)=0
virtual void DoesNotMatch(const Ch *str, SizeType length)=0
virtual void StartDisallowedType()=0
virtual void BelowMinimum(uint64_t actual, const SValue &expected, bool exclusive)=0
virtual void StartDependencyErrors()=0
virtual void PropertyViolations(ISchemaValidator **subvalidators, SizeType count)=0
virtual void StartMissingProperties()=0
virtual void EndDisallowedType(const typename SchemaType::ValueType &actualType)=0
virtual void NotMultipleOf(uint64_t actual, const SValue &expected)=0
virtual void NotMultipleOf(double actual, const SValue &expected)=0
virtual void TooFewProperties(SizeType actualCount, SizeType expectedCount)=0
virtual void TooLong(const Ch *str, SizeType length, SizeType expected)=0
virtual void StartMissingDependentProperties()=0
virtual void TooFewItems(SizeType actualCount, SizeType expectedCount)=0
Definition: schema.h:396
bool Int64(Context &context, int64_t i) const
Definition: schema.h:813
void CreateSchemaValidators(Context &context, const SchemaArray &schemas) const
Definition: schema.h:1216
bool exclusiveMaximum_
Definition: schema.h:1440
SizeType notValidatorIndex_
Definition: schema.h:1409
bool StartArray(Context &context) const
Definition: schema.h:988
bool CheckUint(Context &context, uint64_t i) const
Definition: schema.h:1283
bool StartObject(Context &context) const
Definition: schema.h:871
SchemaDocumentType::PointerType PointerType
Definition: schema.h:400
bool additionalProperties_
Definition: schema.h:1418
bool exclusiveMinimum_
Definition: schema.h:1439
bool Int(Context &context, int i) const
Definition: schema.h:801
bool Uint64(Context &context, uint64_t u) const
Definition: schema.h:819
bool uniqueItems_
Definition: schema.h:1430
SizeType maxLength_
Definition: schema.h:1434
bool FindPropertyIndex(const ValueType &name, SizeType *outIndex) const
Definition: schema.h:1222
AllocatorType * allocator_
Definition: schema.h:1397
static void AssignIfExist(SizeType &out, const ValueType &value, const ValueType &name)
Definition: schema.h:1109
IValidationErrorHandler< Schema > ErrorHandler
Definition: schema.h:406
Schema(SchemaDocumentType *schemaDocument, const PointerType &p, const ValueType &value, const ValueType &document, AllocatorType *allocator)
Definition: schema.h:409
SizeType validatorCount_
Definition: schema.h:1408
SValue maximum_
Definition: schema.h:1437
bool CheckDoubleMultipleOf(Context &context, double d) const
Definition: schema.h:1347
const PointerType & GetPointer() const
Definition: schema.h:672
SchemaArray oneOf_
Definition: schema.h:1405
SizeType minItems_
Definition: schema.h:1427
~Schema()
Definition: schema.h:647
static void AssignIfExist(bool &out, const ValueType &value, const ValueType &name)
Definition: schema.h:1103
void AddType(const ValueType &type)
Definition: schema.h:1175
bool additionalItems_
Definition: schema.h:1429
bool CheckDoubleMinimum(Context &context, double d) const
Definition: schema.h:1331
bool EndObject(Context &context, SizeType memberCount) const
Definition: schema.h:941
static bool IsPatternMatch(const RegexType *pattern, const Ch *str, SizeType)
Definition: schema.h:1145
SizeType maxProperties_
Definition: schema.h:1417
Property * properties_
Definition: schema.h:1411
void DisallowedType(Context &context, const ValueType &actualType) const
Definition: schema.h:1358
bool CheckInt(Context &context, int64_t i) const
Definition: schema.h:1235
const SchemaType * typeless_
Definition: schema.h:1400
internal::GenericRegex< EncodingType, AllocatorType > RegexType
Definition: schema.h:1074
SchemaDocumentType::AllocatorType AllocatorType
Definition: schema.h:399
bool EndArray(Context &context, SizeType elementCount) const
Definition: schema.h:1000
const SchemaType * additionalPropertiesSchema_
Definition: schema.h:1412
SizeType defaultValueLength_
Definition: schema.h:1442
bool Double(Context &context, double d) const
Definition: schema.h:825
bool CreateParallelValidator(Context &context) const
Definition: schema.h:1185
SchemaDocumentType::ValueType ValueType
Definition: schema.h:398
const SchemaType * additionalItemsSchema_
Definition: schema.h:1423
const SValue & GetURI() const
Definition: schema.h:668
RegexType * CreatePattern(const ValueType &value)
Definition: schema.h:1132
unsigned type_
Definition: schema.h:1407
bool String(Context &context, const Ch *str, SizeType length, bool) const
Definition: schema.h:843
bool CheckDoubleMaximum(Context &context, double d) const
Definition: schema.h:1339
void AddUniqueElement(V1 &a, const V2 &v)
Definition: schema.h:1090
SizeType enumCount_
Definition: schema.h:1402
EncodingType::Ch Ch
Definition: schema.h:402
SValue minimum_
Definition: schema.h:1436
PatternProperty * patternProperties_
Definition: schema.h:1413
ValueType::EncodingType EncodingType
Definition: schema.h:401
SchemaArray allOf_
Definition: schema.h:1403
SizeType minProperties_
Definition: schema.h:1416
bool hasSchemaDependencies_
Definition: schema.h:1421
GenericValue< EncodingType, AllocatorType > SValue
Definition: schema.h:405
bool Bool(Context &context, bool) const
Definition: schema.h:793
const SchemaType ** itemsTuple_
Definition: schema.h:1425
const SchemaType * not_
Definition: schema.h:1406
SizeType minLength_
Definition: schema.h:1433
bool Uint(Context &context, unsigned u) const
Definition: schema.h:807
bool Key(Context &context, const Ch *str, SizeType len, bool) const
Definition: schema.h:892
PointerType pointer_
Definition: schema.h:1399
SizeType maxItems_
Definition: schema.h:1428
Schema< SchemaDocumentType > SchemaType
Definition: schema.h:404
SchemaValidationContext< SchemaDocumentType > Context
Definition: schema.h:403
SValue uri_
Definition: schema.h:1398
bool Null(Context &context) const
Definition: schema.h:785
SizeType itemsTupleCount_
Definition: schema.h:1426
SizeType patternPropertyCount_
Definition: schema.h:1414
bool hasRequired_
Definition: schema.h:1420
CEREAL_RAPIDJSON_FORCEINLINE bool EndValue(Context &context) const
Definition: schema.h:703
SizeType propertyCount_
Definition: schema.h:1415
RegexType * pattern_
Definition: schema.h:1432
bool hasDependencies_
Definition: schema.h:1419
bool BeginValue(Context &context) const
Definition: schema.h:676
uint64_t * enum_
Definition: schema.h:1401
static const ValueType * GetMember(const ValueType &value, const ValueType &name)
Definition: schema.h:1098
void AssignIfExist(SchemaArray &out, SchemaDocumentType &schemaDocument, const PointerType &p, const ValueType &value, const ValueType &name, const ValueType &document)
Definition: schema.h:1115
SValue multipleOf_
Definition: schema.h:1438
SchemaValueType
Definition: schema.h:1062
@ kArraySchemaType
Definition: schema.h:1066
@ kNumberSchemaType
Definition: schema.h:1068
@ kStringSchemaType
Definition: schema.h:1067
@ kNullSchemaType
Definition: schema.h:1063
@ kObjectSchemaType
Definition: schema.h:1065
@ kIntegerSchemaType
Definition: schema.h:1069
@ kBooleanSchemaType
Definition: schema.h:1064
@ kTotalSchemaType
Definition: schema.h:1070
const SchemaType * itemsList_
Definition: schema.h:1424
SchemaArray anyOf_
Definition: schema.h:1404
A type-unsafe stack for storing different types of data.
Definition: stack.h:37
Concept for allocating, resizing and freeing memory block.
Concept for receiving events from GenericReader upon parsing. The functions return true if no error o...
#define CEREAL_RAPIDJSON_NAMESPACE_BEGIN
provide custom rapidjson namespace (opening expression)
Definition: rapidjson.h:121
#define CEREAL_RAPIDJSON_NAMESPACE_END
provide custom rapidjson namespace (closing expression)
Definition: rapidjson.h:124
uint d
type
The type the bitset is encoded with.
Definition: bitset.hpp:44
Definition: document.h:416
char * u32toa(uint32_t value, char *buffer)
Definition: itoa.h:39
char * u64toa(uint64_t value, char *buffer)
Definition: itoa.h:126
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1282
const GenericPointer< typename T::ValueType > & pointer
Definition: pointer.h:1181
const CharType(& source)[N]
Definition: pointer.h:1204
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1181
Type
Type of JSON value.
Definition: rapidjson.h:644
@ kFalseType
false
Definition: rapidjson.h:646
@ kObjectType
object
Definition: rapidjson.h:648
@ kTrueType
true
Definition: rapidjson.h:647
@ kStringType
string
Definition: rapidjson.h:650
@ kNullType
null
Definition: rapidjson.h:645
@ kArrayType
array
Definition: rapidjson.h:649
@ kNumberType
number
Definition: rapidjson.h:651
#define CEREAL_RAPIDJSON_DELETE(x)
! customization point for global delete
Definition: rapidjson.h:631
#define CEREAL_RAPIDJSON_UINT64_C2(high32, low32)
Construct a 64-bit literal by a pair of 32-bit integer.
Definition: rapidjson.h:289
#define CEREAL_RAPIDJSON_NEW(TypeName)
! customization point for global new
Definition: rapidjson.h:627
CEREAL_RAPIDJSON_NAMESPACE_BEGIN typedef unsigned SizeType
Size type (for string lengths, array sizes, etc.)
Definition: rapidjson.h:384
GenericSchemaValidator< SchemaDocument > SchemaValidator
Definition: schema.h:2417
#define CEREAL_RAPIDJSON_SCHEMA_VERBOSE
Definition: schema.h:48
#define CEREAL_RAPIDJSON_INVALID_KEYWORD_RETURN(keyword)
Definition: schema.h:116
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_BEGIN_(method, arg1)
Definition: schema.h:2077
#define CEREAL_RAPIDJSON_STRING_(name,...)
Definition: schema.h:2048
GenericSchemaDocument< Value > SchemaDocument
GenericSchemaDocument using Value type.
Definition: schema.h:1741
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_PARALLEL_(method, arg2)
Definition: schema.h:2084
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_END_(method, arg2)
Definition: schema.h:2096
#define CEREAL_RAPIDJSON_SCHEMA_HANDLE_VALUE_(method, arg1, arg2)
Definition: schema.h:2099
IGenericRemoteSchemaDocumentProvider< SchemaDocument > IRemoteSchemaDocumentProvider
IGenericRemoteSchemaDocumentProvider using SchemaDocument.
Definition: schema.h:1743
signed __int64 int64_t
Definition: stdint.h:135
unsigned __int64 uint64_t
Definition: stdint.h:136
Definition: schema.h:1622
bool owned
Definition: schema.h:1632
~SchemaEntry()
Definition: schema.h:1624
PointerType pointer
Definition: schema.h:1630
SchemaType * schema
Definition: schema.h:1631
SchemaEntry(const PointerType &p, SchemaType *s, bool o, Allocator *allocator)
Definition: schema.h:1623
Definition: schema.h:1615
SchemaRefEntry(const PointerType &s, const PointerType &t, const SchemaType **outSchema, Allocator *allocator)
Definition: schema.h:1616
PointerType target
Definition: schema.h:1618
const SchemaType ** schema
Definition: schema.h:1619
PointerType source
Definition: schema.h:1617
Reference to a constant string (not taking a copy)
Definition: document.h:263
Result of parsing (wraps ParseErrorCode)
Definition: error.h:106
Definition: schema.h:280
double d
Definition: schema.h:285
union internal::Hasher::Number::U u
Definition: schema.h:316
bool arrayUniqueness
Definition: schema.h:389
SizeType validatorCount
Definition: schema.h:378
const SchemaType ** patternPropertiesSchemas
Definition: schema.h:381
ISchemaValidator ** validators
Definition: schema.h:377
SizeType arrayElementIndex
Definition: schema.h:385
bool valueUniqueness
Definition: schema.h:388
SizeType patternPropertiesValidatorCount
Definition: schema.h:380
ISchemaStateFactory< SchemaType > SchemaValidatorFactoryType
Definition: schema.h:318
const SchemaType * valueSchema
Definition: schema.h:373
bool * propertyExist
Definition: schema.h:386
void * hasher
Definition: schema.h:375
IValidationErrorHandler< SchemaType > ErrorHandlerType
Definition: schema.h:319
PatternValidatorType
Definition: schema.h:323
@ kPatternValidatorWithProperty
Definition: schema.h:325
@ kPatternValidatorWithAdditionalProperty
Definition: schema.h:326
@ kPatternValidatorOnly
Definition: schema.h:324
void * arrayElementHashCodes
Definition: schema.h:376
ISchemaValidator ** patternPropertiesValidators
Definition: schema.h:379
SizeType patternPropertiesSchemaCount
Definition: schema.h:382
Schema< SchemaDocumentType > SchemaType
Definition: schema.h:317
const Ch * invalidKeyword
Definition: schema.h:374
~SchemaValidationContext()
Definition: schema.h:351
ValueType::Ch Ch
Definition: schema.h:321
SchemaType::ValueType ValueType
Definition: schema.h:320
PatternValidatorType valuePatternValidatorType
Definition: schema.h:383
SchemaValidationContext(SchemaValidatorFactoryType &f, ErrorHandlerType &eh, const SchemaType *s)
Definition: schema.h:329
ErrorHandlerType & error_handler
Definition: schema.h:371
PatternValidatorType objectPatternValidatorType
Definition: schema.h:384
SchemaValidatorFactoryType & factory
Definition: schema.h:370
bool inArray
Definition: schema.h:387
const SchemaType * schema
Definition: schema.h:372
Definition: schema.h:1385
~PatternProperty()
Definition: schema.h:1387
RegexType * pattern
Definition: schema.h:1394
const SchemaType * schema
Definition: schema.h:1393
PatternProperty()
Definition: schema.h:1386
Definition: schema.h:1374
const SchemaType * dependenciesSchema
Definition: schema.h:1379
bool required
Definition: schema.h:1382
~Property()
Definition: schema.h:1376
const SchemaType * schema
Definition: schema.h:1378
SizeType dependenciesValidatorIndex
Definition: schema.h:1380
bool * dependencies
Definition: schema.h:1381
SValue name
Definition: schema.h:1377
Property()
Definition: schema.h:1375
Definition: schema.h:1081
SchemaArray()
Definition: schema.h:1082
const SchemaType ** schemas
Definition: schema.h:1084
~SchemaArray()
Definition: schema.h:1083
SizeType count
Definition: schema.h:1086
SizeType begin
Definition: schema.h:1085
static CEREAL_RAPIDJSON_FORCEINLINE void AppendIndexToken(Stack &documentStack, SizeType index)
Definition: schema.h:1459
Definition: schema.h:1446
static CEREAL_RAPIDJSON_FORCEINLINE void AppendIndexToken(Stack &documentStack, SizeType index)
Definition: schema.h:1447
Definition: schema.h:281
int64_t i
Definition: schema.h:283
uint64_t u
Definition: schema.h:282