NCBI C++ ToolKit
schema.h
Go to the documentation of this file.

Go to the SVN repository for this file.

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