/src/valijson/include/valijson/constraints/concrete_constraints.hpp
Line | Count | Source |
1 | | /** |
2 | | * @file |
3 | | * |
4 | | * @brief Class definitions to support JSON Schema constraints |
5 | | * |
6 | | * This file contains class definitions for all of the constraints required to |
7 | | * support JSON Schema. These classes all inherit from the BasicConstraint |
8 | | * template class, which implements the common parts of the Constraint |
9 | | * interface. |
10 | | * |
11 | | * @see BasicConstraint |
12 | | * @see Constraint |
13 | | */ |
14 | | |
15 | | #pragma once |
16 | | |
17 | | #include <limits> |
18 | | #include <map> |
19 | | #include <set> |
20 | | #include <string> |
21 | | #include <vector> |
22 | | #include <cmath> |
23 | | |
24 | | #include <valijson/constraints/basic_constraint.hpp> |
25 | | #include <valijson/internal/custom_allocator.hpp> |
26 | | #include <valijson/internal/frozen_value.hpp> |
27 | | #include <valijson/schema.hpp> |
28 | | #include <valijson/exceptions.hpp> |
29 | | #include <valijson/validation_results.hpp> |
30 | | |
31 | | #ifdef _MSC_VER |
32 | | #pragma warning( push ) |
33 | | #pragma warning( disable : 4702 ) |
34 | | #endif |
35 | | |
36 | | namespace valijson { |
37 | | |
38 | | class ValidationResults; |
39 | | |
40 | | namespace constraints { |
41 | | |
42 | | /** |
43 | | * @brief Represents an 'allOf' constraint. |
44 | | * |
45 | | * An allOf constraint provides a collection of sub-schemas that a value must |
46 | | * validate against. If a value fails to validate against any of these sub- |
47 | | * schemas, then validation fails. |
48 | | */ |
49 | | class AllOfConstraint: public BasicConstraint<AllOfConstraint> |
50 | | { |
51 | | public: |
52 | | AllOfConstraint() |
53 | 53.6k | : m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
54 | | |
55 | | AllOfConstraint(CustomAlloc allocFn, CustomFree freeFn) |
56 | | : BasicConstraint(allocFn, freeFn), |
57 | 0 | m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
58 | | |
59 | | void addSubschema(const Subschema *subschema) |
60 | 66.4k | { |
61 | 66.4k | m_subschemas.push_back(subschema); |
62 | 66.4k | } |
63 | | |
64 | | template<typename FunctorType> |
65 | | void applyToSubschemas(const FunctorType &fn) const |
66 | 176k | { |
67 | 176k | unsigned int index = 0; |
68 | 176k | for (const Subschema *subschema : m_subschemas) { |
69 | 164k | if (!fn(index, subschema)) { |
70 | 5.20k | return; |
71 | 5.20k | } |
72 | | |
73 | 159k | index++; |
74 | 159k | } |
75 | 176k | } void valijson::constraints::AllOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 66 | 175k | { | 67 | 175k | unsigned int index = 0; | 68 | 175k | for (const Subschema *subschema : m_subschemas) { | 69 | 164k | if (!fn(index, subschema)) { | 70 | 5.20k | return; | 71 | 5.20k | } | 72 | | | 73 | 159k | index++; | 74 | 159k | } | 75 | 175k | } |
void valijson::constraints::AllOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 66 | 563 | { | 67 | 563 | unsigned int index = 0; | 68 | 563 | for (const Subschema *subschema : m_subschemas) { | 69 | 502 | if (!fn(index, subschema)) { | 70 | 0 | return; | 71 | 0 | } | 72 | | | 73 | 502 | index++; | 74 | 502 | } | 75 | 563 | } |
|
76 | | |
77 | | private: |
78 | | typedef std::vector<const Subschema *, internal::CustomAllocator<const Subschema *>> Subschemas; |
79 | | |
80 | | /// Collection of sub-schemas, all of which must be satisfied |
81 | | Subschemas m_subschemas; |
82 | | }; |
83 | | |
84 | | /** |
85 | | * @brief Represents an 'anyOf' constraint |
86 | | * |
87 | | * An anyOf constraint provides a collection of sub-schemas that a value can |
88 | | * validate against. If a value validates against one of these sub-schemas, |
89 | | * then the validation passes. |
90 | | */ |
91 | | class AnyOfConstraint: public BasicConstraint<AnyOfConstraint> |
92 | | { |
93 | | public: |
94 | | AnyOfConstraint() |
95 | 37.7k | : m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
96 | | |
97 | | AnyOfConstraint(CustomAlloc allocFn, CustomFree freeFn) |
98 | | : BasicConstraint(allocFn, freeFn), |
99 | 0 | m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
100 | | |
101 | | void addSubschema(const Subschema *subschema) |
102 | 49.2k | { |
103 | 49.2k | m_subschemas.push_back(subschema); |
104 | 49.2k | } |
105 | | |
106 | | template<typename FunctorType> |
107 | | void applyToSubschemas(const FunctorType &fn) const |
108 | 212k | { |
109 | 212k | unsigned int index = 0; |
110 | 220k | for (const Subschema *subschema : m_subschemas) { |
111 | 220k | if (!fn(index, subschema)) { |
112 | 205k | return; |
113 | 205k | } |
114 | | |
115 | 14.8k | index++; |
116 | 14.8k | } |
117 | 212k | } void valijson::constraints::AnyOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 108 | 212k | { | 109 | 212k | unsigned int index = 0; | 110 | 220k | for (const Subschema *subschema : m_subschemas) { | 111 | 220k | if (!fn(index, subschema)) { | 112 | 205k | return; | 113 | 205k | } | 114 | | | 115 | 14.8k | index++; | 116 | 14.8k | } | 117 | 212k | } |
void valijson::constraints::AnyOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 108 | 118 | { | 109 | 118 | unsigned int index = 0; | 110 | 118 | for (const Subschema *subschema : m_subschemas) { | 111 | 38 | if (!fn(index, subschema)) { | 112 | 38 | return; | 113 | 38 | } | 114 | | | 115 | 0 | index++; | 116 | 0 | } | 117 | 118 | } |
|
118 | | |
119 | | private: |
120 | | typedef std::vector<const Subschema *, internal::CustomAllocator<const Subschema *>> Subschemas; |
121 | | |
122 | | /// Collection of sub-schemas, at least one of which must be satisfied |
123 | | Subschemas m_subschemas; |
124 | | }; |
125 | | |
126 | | /** |
127 | | * @brief Represents a combination 'if', 'then' and 'else' constraints |
128 | | * |
129 | | * The schema provided by an 'if' constraint is used as the expression for a conditional. When the |
130 | | * target validates against that schema, the 'then' subschema will be also be tested. Otherwise, |
131 | | * the 'else' subschema will be tested. |
132 | | */ |
133 | | class ConditionalConstraint: public BasicConstraint<ConditionalConstraint> |
134 | | { |
135 | | public: |
136 | | ConditionalConstraint() |
137 | 12.2k | : m_ifSubschema(nullptr), |
138 | 12.2k | m_thenSubschema(nullptr), |
139 | 12.2k | m_elseSubschema(nullptr) { } |
140 | | |
141 | | ConditionalConstraint(CustomAlloc allocFn, CustomFree freeFn) |
142 | | : BasicConstraint(allocFn, freeFn), |
143 | | m_ifSubschema(nullptr), |
144 | | m_thenSubschema(nullptr), |
145 | 0 | m_elseSubschema(nullptr) { } |
146 | | |
147 | | const Subschema * getIfSubschema() const |
148 | 206k | { |
149 | 206k | return m_ifSubschema; |
150 | 206k | } |
151 | | |
152 | | const Subschema * getThenSubschema() const |
153 | 174k | { |
154 | 174k | return m_thenSubschema; |
155 | 174k | } |
156 | | |
157 | | const Subschema * getElseSubschema() const |
158 | 31.4k | { |
159 | 31.4k | return m_elseSubschema; |
160 | 31.4k | } |
161 | | |
162 | | void setIfSubschema(const Subschema *subschema) |
163 | 11.3k | { |
164 | 11.3k | m_ifSubschema = subschema; |
165 | 11.3k | } |
166 | | |
167 | | void setThenSubschema(const Subschema *subschema) |
168 | 2.73k | { |
169 | 2.73k | m_thenSubschema = subschema; |
170 | 2.73k | } |
171 | | |
172 | | void setElseSubschema(const Subschema *subschema) |
173 | 3.59k | { |
174 | 3.59k | m_elseSubschema = subschema; |
175 | 3.59k | } |
176 | | |
177 | | private: |
178 | | const Subschema *m_ifSubschema; |
179 | | const Subschema *m_thenSubschema; |
180 | | const Subschema *m_elseSubschema; |
181 | | }; |
182 | | |
183 | | class ConstConstraint: public BasicConstraint<ConstConstraint> |
184 | | { |
185 | | public: |
186 | | ConstConstraint() |
187 | 14.5k | : m_value(nullptr) { } |
188 | | |
189 | | ConstConstraint(CustomAlloc allocFn, CustomFree freeFn) |
190 | | : BasicConstraint(allocFn, freeFn), |
191 | 0 | m_value(nullptr) { } |
192 | | |
193 | | ConstConstraint(const ConstConstraint &other) |
194 | 14.5k | : BasicConstraint(other), |
195 | 14.5k | m_value(other.m_value->clone()) { } |
196 | | |
197 | | adapters::FrozenValue * getValue() const |
198 | 19.9k | { |
199 | 19.9k | return m_value.get(); |
200 | 19.9k | } |
201 | | |
202 | | void setValue(const adapters::Adapter &value) |
203 | 14.5k | { |
204 | 14.5k | m_value = std::unique_ptr<adapters::FrozenValue>(value.freeze()); |
205 | 14.5k | } |
206 | | |
207 | | private: |
208 | | std::unique_ptr<adapters::FrozenValue> m_value; |
209 | | }; |
210 | | |
211 | | /** |
212 | | * @brief Represents a 'contains' constraint |
213 | | * |
214 | | * A 'contains' constraint specifies a schema that must be satisfied by at least one |
215 | | * of the values in an array. |
216 | | */ |
217 | | class ContainsConstraint: public BasicConstraint<ContainsConstraint> |
218 | | { |
219 | | public: |
220 | | ContainsConstraint() |
221 | 24.1k | : m_subschema(nullptr) { } |
222 | | |
223 | | ContainsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
224 | | : BasicConstraint(allocFn, freeFn), |
225 | 0 | m_subschema(nullptr) { } |
226 | | |
227 | | const Subschema * getSubschema() const |
228 | 2.52k | { |
229 | 2.52k | return m_subschema; |
230 | 2.52k | } |
231 | | |
232 | | void setSubschema(const Subschema *subschema) |
233 | 23.4k | { |
234 | 23.4k | m_subschema = subschema; |
235 | 23.4k | } |
236 | | |
237 | | private: |
238 | | const Subschema *m_subschema; |
239 | | }; |
240 | | |
241 | | /** |
242 | | * @brief Represents a 'dependencies' constraint. |
243 | | * |
244 | | * A dependency constraint ensures that a given property is valid only if the |
245 | | * properties that it depends on are present. |
246 | | */ |
247 | | class DependenciesConstraint: public BasicConstraint<DependenciesConstraint> |
248 | | { |
249 | | public: |
250 | | DependenciesConstraint() |
251 | 40.9k | : m_propertyDependencies(std::less<String>(), m_allocator), |
252 | 40.9k | m_schemaDependencies(std::less<String>(), m_allocator) |
253 | 40.9k | { } |
254 | | |
255 | | DependenciesConstraint(CustomAlloc allocFn, CustomFree freeFn) |
256 | | : BasicConstraint(allocFn, freeFn), |
257 | | m_propertyDependencies(std::less<String>(), m_allocator), |
258 | | m_schemaDependencies(std::less<String>(), m_allocator) |
259 | 0 | { } |
260 | | |
261 | | template<typename StringType> |
262 | | DependenciesConstraint & addPropertyDependency( |
263 | | const StringType &propertyName, |
264 | | const StringType &dependencyName) |
265 | 0 | { |
266 | 0 | const String key(propertyName.c_str(), m_allocator); |
267 | 0 | auto itr = m_propertyDependencies.find(key); |
268 | 0 | if (itr == m_propertyDependencies.end()) { |
269 | 0 | itr = m_propertyDependencies.insert(PropertyDependencies::value_type( |
270 | 0 | key, PropertySet(std::less<String>(), m_allocator))).first; |
271 | 0 | } |
272 | |
|
273 | 0 | itr->second.insert(String(dependencyName.c_str(), m_allocator)); |
274 | |
|
275 | 0 | return *this; |
276 | 0 | } |
277 | | |
278 | | template<typename StringType, typename ContainerType> |
279 | | DependenciesConstraint & addPropertyDependencies( |
280 | | const StringType &propertyName, |
281 | | const ContainerType &dependencyNames) |
282 | 82.6k | { |
283 | 82.6k | const String key(propertyName.c_str(), m_allocator); |
284 | 82.6k | auto itr = m_propertyDependencies.find(key); |
285 | 82.6k | if (itr == m_propertyDependencies.end()) { |
286 | 71.3k | itr = m_propertyDependencies.insert(PropertyDependencies::value_type( |
287 | 71.3k | key, PropertySet(std::less<String>(), m_allocator))).first; |
288 | 71.3k | } |
289 | | |
290 | 82.6k | typedef typename ContainerType::value_type ValueType; |
291 | 82.6k | for (const ValueType &dependencyName : dependencyNames) { |
292 | 30.0k | itr->second.insert(String(dependencyName.c_str(), m_allocator)); |
293 | 30.0k | } |
294 | | |
295 | 82.6k | return *this; |
296 | 82.6k | } |
297 | | |
298 | | template<typename StringType> |
299 | | DependenciesConstraint & addSchemaDependency(const StringType &propertyName, const Subschema *schemaDependency) |
300 | 58.9k | { |
301 | 58.9k | if (m_schemaDependencies.insert(SchemaDependencies::value_type( |
302 | 58.9k | String(propertyName.c_str(), m_allocator), |
303 | 58.9k | schemaDependency)).second) { |
304 | 58.7k | return *this; |
305 | 58.7k | } |
306 | | |
307 | 221 | throwRuntimeError("Dependencies constraint already contains a dependent " |
308 | 221 | "schema for the property '" + propertyName + "'"); |
309 | 221 | } |
310 | | |
311 | | template<typename FunctorType> |
312 | | void applyToPropertyDependencies(const FunctorType &fn) const |
313 | 31.3k | { |
314 | 49.2k | for (const PropertyDependencies::value_type &v : m_propertyDependencies) { |
315 | 49.2k | if (!fn(v.first, v.second)) { |
316 | 374 | return; |
317 | 374 | } |
318 | 49.2k | } |
319 | 31.3k | } void valijson::constraints::DependenciesConstraint::applyToPropertyDependencies<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePropertyDependencies>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePropertyDependencies const&) const Line | Count | Source | 313 | 31.3k | { | 314 | 49.2k | for (const PropertyDependencies::value_type &v : m_propertyDependencies) { | 315 | 49.2k | if (!fn(v.first, v.second)) { | 316 | 374 | return; | 317 | 374 | } | 318 | 49.2k | } | 319 | 31.3k | } |
Unexecuted instantiation: void valijson::constraints::DependenciesConstraint::applyToPropertyDependencies<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePropertyDependencies>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePropertyDependencies const&) const |
320 | | |
321 | | template<typename FunctorType> |
322 | | void applyToSchemaDependencies(const FunctorType &fn) const |
323 | 30.9k | { |
324 | 45.5k | for (const SchemaDependencies::value_type &v : m_schemaDependencies) { |
325 | 45.5k | if (!fn(v.first, v.second)) { |
326 | 1 | return; |
327 | 1 | } |
328 | 45.5k | } |
329 | 30.9k | } void valijson::constraints::DependenciesConstraint::applyToSchemaDependencies<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSchemaDependencies>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSchemaDependencies const&) const Line | Count | Source | 323 | 30.9k | { | 324 | 45.5k | for (const SchemaDependencies::value_type &v : m_schemaDependencies) { | 325 | 45.5k | if (!fn(v.first, v.second)) { | 326 | 1 | return; | 327 | 1 | } | 328 | 45.5k | } | 329 | 30.9k | } |
Unexecuted instantiation: void valijson::constraints::DependenciesConstraint::applyToSchemaDependencies<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSchemaDependencies>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSchemaDependencies const&) const |
330 | | |
331 | | private: |
332 | | typedef std::set<String, std::less<String>, internal::CustomAllocator<String>> PropertySet; |
333 | | |
334 | | typedef std::map<String, PropertySet, std::less<String>, |
335 | | internal::CustomAllocator<std::pair<const String, PropertySet>>> PropertyDependencies; |
336 | | |
337 | | typedef std::map<String, const Subschema *, std::less<String>, |
338 | | internal::CustomAllocator<std::pair<const String, const Subschema *>>> SchemaDependencies; |
339 | | |
340 | | /// Mapping from property names to their property-based dependencies |
341 | | PropertyDependencies m_propertyDependencies; |
342 | | |
343 | | /// Mapping from property names to their schema-based dependencies |
344 | | SchemaDependencies m_schemaDependencies; |
345 | | }; |
346 | | |
347 | | /** |
348 | | * @brief Represents an 'enum' constraint |
349 | | * |
350 | | * An enum constraint provides a collection of permissible values for a JSON |
351 | | * node. The node will only validate against this constraint if it matches one |
352 | | * or more of the values in the collection. |
353 | | */ |
354 | | class EnumConstraint: public BasicConstraint<EnumConstraint> |
355 | | { |
356 | | public: |
357 | | EnumConstraint() |
358 | 6.47k | : m_enumValues(Allocator::rebind<const EnumValue *>::other(m_allocator)) { } |
359 | | |
360 | | EnumConstraint(CustomAlloc allocFn, CustomFree freeFn) |
361 | | : BasicConstraint(allocFn, freeFn), |
362 | 0 | m_enumValues(Allocator::rebind<const EnumValue *>::other(m_allocator)) { } |
363 | | |
364 | | EnumConstraint(const EnumConstraint &other) |
365 | 6.02k | : BasicConstraint(other), |
366 | 6.02k | m_enumValues(Allocator::rebind<const EnumValue *>::other(m_allocator)) |
367 | 6.02k | { |
368 | 6.02k | #if VALIJSON_USE_EXCEPTIONS |
369 | 6.02k | try { |
370 | 6.02k | #endif |
371 | | // Clone individual enum values |
372 | 34.9k | for (const EnumValue *otherValue : other.m_enumValues) { |
373 | 34.9k | const EnumValue *value = otherValue->clone(); |
374 | 34.9k | #if VALIJSON_USE_EXCEPTIONS |
375 | 34.9k | try { |
376 | 34.9k | #endif |
377 | 34.9k | m_enumValues.push_back(value); |
378 | 34.9k | #if VALIJSON_USE_EXCEPTIONS |
379 | 34.9k | } catch (...) { |
380 | 0 | delete value; |
381 | 0 | value = nullptr; |
382 | 0 | throw; |
383 | 0 | } |
384 | 34.9k | } |
385 | 6.02k | } catch (...) { |
386 | | // Delete values already added to constraint |
387 | 0 | for (const EnumValue *value : m_enumValues) { |
388 | 0 | delete value; |
389 | 0 | } |
390 | 0 | throw; |
391 | 0 | #endif |
392 | 0 | } |
393 | 6.02k | } |
394 | | |
395 | | ~EnumConstraint() override |
396 | 12.5k | { |
397 | 69.9k | for (const EnumValue *value : m_enumValues) { |
398 | 69.9k | delete value; |
399 | 69.9k | } |
400 | 12.5k | } |
401 | | |
402 | | void addValue(const adapters::Adapter &value) |
403 | 34.9k | { |
404 | | // TODO: Freeze value using custom alloc/free functions |
405 | 34.9k | m_enumValues.push_back(value.freeze()); |
406 | 34.9k | } |
407 | | |
408 | | void addValue(const adapters::FrozenValue &value) |
409 | 0 | { |
410 | 0 | // TODO: Clone using custom alloc/free functions |
411 | 0 | m_enumValues.push_back(value.clone()); |
412 | 0 | } |
413 | | |
414 | | template<typename FunctorType> |
415 | | void applyToValues(const FunctorType &fn) const |
416 | 2.65k | { |
417 | 14.0k | for (const EnumValue *value : m_enumValues) { |
418 | 14.0k | if (!fn(*value)) { |
419 | 60 | return; |
420 | 60 | } |
421 | 14.0k | } |
422 | 2.65k | } void valijson::constraints::EnumConstraint::applyToValues<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateEquality>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateEquality const&) const Line | Count | Source | 416 | 2.65k | { | 417 | 14.0k | for (const EnumValue *value : m_enumValues) { | 418 | 14.0k | if (!fn(*value)) { | 419 | 60 | return; | 420 | 60 | } | 421 | 14.0k | } | 422 | 2.65k | } |
Unexecuted instantiation: void valijson::constraints::EnumConstraint::applyToValues<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateEquality>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateEquality const&) const |
423 | | |
424 | | private: |
425 | | typedef adapters::FrozenValue EnumValue; |
426 | | |
427 | | typedef std::vector<const EnumValue *, internal::CustomAllocator<const EnumValue *>> EnumValues; |
428 | | |
429 | | EnumValues m_enumValues; |
430 | | }; |
431 | | |
432 | | /** |
433 | | * @brief Represent a 'format' constraint |
434 | | * |
435 | | * A format constraint restricts the content of string values, as defined by a set of commonly used formats. |
436 | | * |
437 | | * As this is an optional feature in JSON Schema, unrecognised formats will be treated as valid for any string value. |
438 | | */ |
439 | | class FormatConstraint: public BasicConstraint<FormatConstraint> |
440 | | { |
441 | | public: |
442 | | FormatConstraint() |
443 | 6.13k | : m_format() { } |
444 | | |
445 | | const std::string & getFormat() const |
446 | 14.3k | { |
447 | 14.3k | return m_format; |
448 | 14.3k | } |
449 | | |
450 | | void setFormat(const std::string & format) |
451 | 6.13k | { |
452 | 6.13k | m_format = format; |
453 | 6.13k | } |
454 | | |
455 | | private: |
456 | | std::string m_format; |
457 | | }; |
458 | | |
459 | | /** |
460 | | * @brief Represents non-singular 'items' and 'additionalItems' constraints |
461 | | * |
462 | | * Unlike the SingularItemsConstraint class, this class represents an 'items' |
463 | | * constraint that specifies an array of sub-schemas, which should be used to |
464 | | * validate each item in an array, in sequence. It also represents an optional |
465 | | * 'additionalItems' sub-schema that should be used when an array contains |
466 | | * more values than there are sub-schemas in the 'items' constraint. |
467 | | * |
468 | | * The prefix 'Linear' comes from the fact that this class contains a list of |
469 | | * sub-schemas that corresponding array items must be validated against, and |
470 | | * this validation is performed linearly (i.e. in sequence). |
471 | | */ |
472 | | class LinearItemsConstraint: public BasicConstraint<LinearItemsConstraint> |
473 | | { |
474 | | public: |
475 | | LinearItemsConstraint() |
476 | 39.9k | : m_itemSubschemas(Allocator::rebind<const Subschema *>::other(m_allocator)), |
477 | 39.9k | m_additionalItemsSubschema(nullptr) { } |
478 | | |
479 | | LinearItemsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
480 | | : BasicConstraint(allocFn, freeFn), |
481 | | m_itemSubschemas(Allocator::rebind<const Subschema *>::other(m_allocator)), |
482 | 0 | m_additionalItemsSubschema(nullptr) { } |
483 | | |
484 | | void addItemSubschema(const Subschema *subschema) |
485 | 61.1k | { |
486 | 61.1k | m_itemSubschemas.push_back(subschema); |
487 | 61.1k | } |
488 | | |
489 | | template<typename FunctorType> |
490 | | void applyToItemSubschemas(const FunctorType &fn) const |
491 | 15.7k | { |
492 | 15.7k | unsigned int index = 0; |
493 | 15.9k | for (const Subschema *subschema : m_itemSubschemas) { |
494 | 15.9k | if (!fn(index, subschema)) { |
495 | 8.41k | return; |
496 | 8.41k | } |
497 | | |
498 | 7.48k | index++; |
499 | 7.48k | } |
500 | 15.7k | } void valijson::constraints::LinearItemsConstraint::applyToItemSubschemas<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateItems>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateItems const&) const Line | Count | Source | 491 | 15.7k | { | 492 | 15.7k | unsigned int index = 0; | 493 | 15.9k | for (const Subschema *subschema : m_itemSubschemas) { | 494 | 15.9k | if (!fn(index, subschema)) { | 495 | 8.41k | return; | 496 | 8.41k | } | 497 | | | 498 | 7.48k | index++; | 499 | 7.48k | } | 500 | 15.7k | } |
Unexecuted instantiation: void valijson::constraints::LinearItemsConstraint::applyToItemSubschemas<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateItems>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateItems const&) const |
501 | | |
502 | | const Subschema * getAdditionalItemsSubschema() const |
503 | 16.6k | { |
504 | 16.6k | return m_additionalItemsSubschema; |
505 | 16.6k | } |
506 | | |
507 | | size_t getItemSubschemaCount() const |
508 | 16.6k | { |
509 | 16.6k | return m_itemSubschemas.size(); |
510 | 16.6k | } |
511 | | |
512 | | void setAdditionalItemsSubschema(const Subschema *subschema) |
513 | 39.4k | { |
514 | 39.4k | m_additionalItemsSubschema = subschema; |
515 | 39.4k | } |
516 | | |
517 | | private: |
518 | | typedef std::vector<const Subschema *, internal::CustomAllocator<const Subschema *>> Subschemas; |
519 | | |
520 | | Subschemas m_itemSubschemas; |
521 | | |
522 | | const Subschema* m_additionalItemsSubschema; |
523 | | }; |
524 | | |
525 | | /** |
526 | | * @brief Represents 'maximum' and 'exclusiveMaximum' constraints |
527 | | */ |
528 | | class MaximumConstraint: public BasicConstraint<MaximumConstraint> |
529 | | { |
530 | | public: |
531 | | MaximumConstraint() |
532 | 14.0k | : m_maximum(std::numeric_limits<double>::infinity()), |
533 | 14.0k | m_exclusiveMaximum(false) { } |
534 | | |
535 | | MaximumConstraint(CustomAlloc allocFn, CustomFree freeFn) |
536 | | : BasicConstraint(allocFn, freeFn), |
537 | | m_maximum(std::numeric_limits<double>::infinity()), |
538 | 0 | m_exclusiveMaximum(false) { } |
539 | | |
540 | | bool getExclusiveMaximum() const |
541 | 5.34k | { |
542 | 5.34k | return m_exclusiveMaximum; |
543 | 5.34k | } |
544 | | |
545 | | void setExclusiveMaximum(bool newExclusiveMaximum) |
546 | 7.40k | { |
547 | 7.40k | m_exclusiveMaximum = newExclusiveMaximum; |
548 | 7.40k | } |
549 | | |
550 | | double getMaximum() const |
551 | 5.34k | { |
552 | 5.34k | return m_maximum; |
553 | 5.34k | } |
554 | | |
555 | | void setMaximum(double newMaximum) |
556 | 14.0k | { |
557 | 14.0k | m_maximum = newMaximum; |
558 | 14.0k | } |
559 | | |
560 | | private: |
561 | | double m_maximum; |
562 | | bool m_exclusiveMaximum; |
563 | | }; |
564 | | |
565 | | /** |
566 | | * @brief Represents a 'maxItems' constraint |
567 | | */ |
568 | | class MaxItemsConstraint: public BasicConstraint<MaxItemsConstraint> |
569 | | { |
570 | | public: |
571 | | MaxItemsConstraint() |
572 | 9.50k | : m_maxItems(std::numeric_limits<uint64_t>::max()) { } |
573 | | |
574 | | MaxItemsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
575 | | : BasicConstraint(allocFn, freeFn), |
576 | 0 | m_maxItems(std::numeric_limits<uint64_t>::max()) { } |
577 | | |
578 | | uint64_t getMaxItems() const |
579 | 5.25k | { |
580 | 5.25k | return m_maxItems; |
581 | 5.25k | } |
582 | | |
583 | | void setMaxItems(uint64_t newMaxItems) |
584 | 9.50k | { |
585 | 9.50k | m_maxItems = newMaxItems; |
586 | 9.50k | } |
587 | | |
588 | | private: |
589 | | uint64_t m_maxItems; |
590 | | }; |
591 | | |
592 | | /** |
593 | | * @brief Represents a 'maxLength' constraint |
594 | | */ |
595 | | class MaxLengthConstraint: public BasicConstraint<MaxLengthConstraint> |
596 | | { |
597 | | public: |
598 | | MaxLengthConstraint() |
599 | 7.27k | : m_maxLength(std::numeric_limits<uint64_t>::max()) { } |
600 | | |
601 | | MaxLengthConstraint(CustomAlloc allocFn, CustomFree freeFn) |
602 | | : BasicConstraint(allocFn, freeFn), |
603 | 0 | m_maxLength(std::numeric_limits<uint64_t>::max()) { } |
604 | | |
605 | | uint64_t getMaxLength() const |
606 | 3.94k | { |
607 | 3.94k | return m_maxLength; |
608 | 3.94k | } |
609 | | |
610 | | void setMaxLength(uint64_t newMaxLength) |
611 | 7.27k | { |
612 | 7.27k | m_maxLength = newMaxLength; |
613 | 7.27k | } |
614 | | |
615 | | private: |
616 | | uint64_t m_maxLength; |
617 | | }; |
618 | | |
619 | | /** |
620 | | * @brief Represents a 'maxProperties' constraint |
621 | | */ |
622 | | class MaxPropertiesConstraint: public BasicConstraint<MaxPropertiesConstraint> |
623 | | { |
624 | | public: |
625 | | MaxPropertiesConstraint() |
626 | 2.96k | : m_maxProperties(std::numeric_limits<uint64_t>::max()) { } |
627 | | |
628 | | MaxPropertiesConstraint(CustomAlloc allocFn, CustomFree freeFn) |
629 | | : BasicConstraint(allocFn, freeFn), |
630 | 0 | m_maxProperties(std::numeric_limits<uint64_t>::max()) { } |
631 | | |
632 | | uint64_t getMaxProperties() const |
633 | 1.34k | { |
634 | 1.34k | return m_maxProperties; |
635 | 1.34k | } |
636 | | |
637 | | void setMaxProperties(uint64_t newMaxProperties) |
638 | 2.96k | { |
639 | 2.96k | m_maxProperties = newMaxProperties; |
640 | 2.96k | } |
641 | | |
642 | | private: |
643 | | uint64_t m_maxProperties; |
644 | | }; |
645 | | |
646 | | /** |
647 | | * @brief Represents 'minimum' and 'exclusiveMinimum' constraints |
648 | | */ |
649 | | class MinimumConstraint: public BasicConstraint<MinimumConstraint> |
650 | | { |
651 | | public: |
652 | | MinimumConstraint() |
653 | 10.1k | : m_minimum(-std::numeric_limits<double>::infinity()), |
654 | 10.1k | m_exclusiveMinimum(false) { } |
655 | | |
656 | | MinimumConstraint(CustomAlloc allocFn, CustomFree freeFn) |
657 | | : BasicConstraint(allocFn, freeFn), |
658 | | m_minimum(-std::numeric_limits<double>::infinity()), |
659 | 0 | m_exclusiveMinimum(false) { } |
660 | | |
661 | | bool getExclusiveMinimum() const |
662 | 3.58k | { |
663 | 3.58k | return m_exclusiveMinimum; |
664 | 3.58k | } |
665 | | |
666 | | void setExclusiveMinimum(bool newExclusiveMinimum) |
667 | 421 | { |
668 | 421 | m_exclusiveMinimum = newExclusiveMinimum; |
669 | 421 | } |
670 | | |
671 | | double getMinimum() const |
672 | 3.58k | { |
673 | 3.58k | return m_minimum; |
674 | 3.58k | } |
675 | | |
676 | | void setMinimum(double newMinimum) |
677 | 10.1k | { |
678 | 10.1k | m_minimum = newMinimum; |
679 | 10.1k | } |
680 | | |
681 | | private: |
682 | | double m_minimum; |
683 | | bool m_exclusiveMinimum; |
684 | | }; |
685 | | |
686 | | /** |
687 | | * @brief Represents a 'minItems' constraint |
688 | | */ |
689 | | class MinItemsConstraint: public BasicConstraint<MinItemsConstraint> |
690 | | { |
691 | | public: |
692 | | MinItemsConstraint() |
693 | 3.86k | : m_minItems(0) { } |
694 | | |
695 | | MinItemsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
696 | | : BasicConstraint(allocFn, freeFn), |
697 | 0 | m_minItems(0) { } |
698 | | |
699 | | uint64_t getMinItems() const |
700 | 2.93k | { |
701 | 2.93k | return m_minItems; |
702 | 2.93k | } |
703 | | |
704 | | void setMinItems(uint64_t newMinItems) |
705 | 3.86k | { |
706 | 3.86k | m_minItems = newMinItems; |
707 | 3.86k | } |
708 | | |
709 | | private: |
710 | | uint64_t m_minItems; |
711 | | }; |
712 | | |
713 | | /** |
714 | | * @brief Represents a 'minLength' constraint |
715 | | */ |
716 | | class MinLengthConstraint: public BasicConstraint<MinLengthConstraint> |
717 | | { |
718 | | public: |
719 | | MinLengthConstraint() |
720 | 4.09k | : m_minLength(0) { } |
721 | | |
722 | | MinLengthConstraint(CustomAlloc allocFn, CustomFree freeFn) |
723 | | : BasicConstraint(allocFn, freeFn), |
724 | 0 | m_minLength(0) { } |
725 | | |
726 | | uint64_t getMinLength() const |
727 | 9.54k | { |
728 | 9.54k | return m_minLength; |
729 | 9.54k | } |
730 | | |
731 | | void setMinLength(uint64_t newMinLength) |
732 | 4.09k | { |
733 | 4.09k | m_minLength = newMinLength; |
734 | 4.09k | } |
735 | | |
736 | | private: |
737 | | uint64_t m_minLength; |
738 | | }; |
739 | | |
740 | | /** |
741 | | * @brief Represents a 'minProperties' constraint |
742 | | */ |
743 | | class MinPropertiesConstraint: public BasicConstraint<MinPropertiesConstraint> |
744 | | { |
745 | | public: |
746 | | MinPropertiesConstraint() |
747 | 2.27k | : m_minProperties(0) { } |
748 | | |
749 | | MinPropertiesConstraint(CustomAlloc allocFn, CustomFree freeFn) |
750 | | : BasicConstraint(allocFn, freeFn), |
751 | 0 | m_minProperties(0) { } |
752 | | |
753 | | uint64_t getMinProperties() const |
754 | 7.52k | { |
755 | 7.52k | return m_minProperties; |
756 | 7.52k | } |
757 | | |
758 | | void setMinProperties(uint64_t newMinProperties) |
759 | 2.27k | { |
760 | 2.27k | m_minProperties = newMinProperties; |
761 | 2.27k | } |
762 | | |
763 | | private: |
764 | | uint64_t m_minProperties; |
765 | | }; |
766 | | |
767 | | /** |
768 | | * @brief Represents either 'multipleOf' or 'divisibleBy' constraints where |
769 | | * the divisor is a floating point number |
770 | | */ |
771 | | class MultipleOfDoubleConstraint: |
772 | | public BasicConstraint<MultipleOfDoubleConstraint> |
773 | | { |
774 | | public: |
775 | | MultipleOfDoubleConstraint() |
776 | 1.21k | : m_value(1.) { } |
777 | | |
778 | | MultipleOfDoubleConstraint(CustomAlloc allocFn, CustomFree freeFn) |
779 | | : BasicConstraint(allocFn, freeFn), |
780 | 0 | m_value(1.) { } |
781 | | |
782 | | double getDivisor() const |
783 | 10.7k | { |
784 | 10.7k | return m_value; |
785 | 10.7k | } |
786 | | |
787 | | void setDivisor(double newValue) |
788 | 1.21k | { |
789 | 1.21k | if (!std::isfinite(newValue) || newValue <= 0.0) { |
790 | 4 | throwRuntimeError( |
791 | 4 | "Divisor for 'multipleOf' or 'divisibleBy' must be positive"); |
792 | 4 | } |
793 | | |
794 | 1.21k | m_value = newValue; |
795 | 1.21k | } |
796 | | |
797 | | private: |
798 | | double m_value; |
799 | | }; |
800 | | |
801 | | /** |
802 | | * @brief Represents either 'multipleOf' or 'divisibleBy' constraints where |
803 | | * the divisor is of integer type |
804 | | */ |
805 | | class MultipleOfIntConstraint: |
806 | | public BasicConstraint<MultipleOfIntConstraint> |
807 | | { |
808 | | public: |
809 | | MultipleOfIntConstraint() |
810 | 14.2k | : m_value(1) { } |
811 | | |
812 | | MultipleOfIntConstraint(CustomAlloc allocFn, CustomFree freeFn) |
813 | | : BasicConstraint(allocFn, freeFn), |
814 | 0 | m_value(1) { } |
815 | | |
816 | | int64_t getDivisor() const |
817 | 18.4k | { |
818 | 18.4k | return m_value; |
819 | 18.4k | } |
820 | | |
821 | | void setDivisor(int64_t newValue) |
822 | 14.2k | { |
823 | 14.2k | if (newValue <= 0) { |
824 | 592 | throwRuntimeError( |
825 | 592 | "Divisor for 'multipleOf' or 'divisibleBy' must be positive"); |
826 | 592 | } |
827 | | |
828 | 14.2k | m_value = newValue; |
829 | 14.2k | } |
830 | | |
831 | | private: |
832 | | int64_t m_value; |
833 | | }; |
834 | | |
835 | | /** |
836 | | * @brief Represents a 'not' constraint |
837 | | */ |
838 | | class NotConstraint: public BasicConstraint<NotConstraint> |
839 | | { |
840 | | public: |
841 | | NotConstraint() |
842 | 5.95k | : m_subschema(nullptr) { } |
843 | | |
844 | | NotConstraint(CustomAlloc allocFn, CustomFree freeFn) |
845 | | : BasicConstraint(allocFn, freeFn), |
846 | 0 | m_subschema(nullptr) { } |
847 | | |
848 | | const Subschema * getSubschema() const |
849 | 9.49k | { |
850 | 9.49k | return m_subschema; |
851 | 9.49k | } |
852 | | |
853 | | void setSubschema(const Subschema *subschema) |
854 | 5.95k | { |
855 | 5.95k | m_subschema = subschema; |
856 | 5.95k | } |
857 | | |
858 | | private: |
859 | | const Subschema *m_subschema; |
860 | | }; |
861 | | |
862 | | /** |
863 | | * @brief Represents a 'oneOf' constraint. |
864 | | */ |
865 | | class OneOfConstraint: public BasicConstraint<OneOfConstraint> |
866 | | { |
867 | | public: |
868 | | OneOfConstraint() |
869 | 23.8k | : m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
870 | | |
871 | | OneOfConstraint(CustomAlloc allocFn, CustomFree freeFn) |
872 | | : BasicConstraint(allocFn, freeFn), |
873 | 0 | m_subschemas(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
874 | | |
875 | | void addSubschema(const Subschema *subschema) |
876 | 56.8k | { |
877 | 56.8k | m_subschemas.push_back(subschema); |
878 | 56.8k | } |
879 | | |
880 | | template<typename FunctorType> |
881 | | void applyToSubschemas(const FunctorType &fn) const |
882 | 113k | { |
883 | 113k | unsigned int index = 0; |
884 | 122k | for (const Subschema *subschema : m_subschemas) { |
885 | 122k | if (!fn(index, subschema)) { |
886 | 0 | return; |
887 | 0 | } |
888 | | |
889 | 122k | index++; |
890 | 122k | } |
891 | 113k | } void valijson::constraints::OneOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 882 | 113k | { | 883 | 113k | unsigned int index = 0; | 884 | 122k | for (const Subschema *subschema : m_subschemas) { | 885 | 122k | if (!fn(index, subschema)) { | 886 | 0 | return; | 887 | 0 | } | 888 | | | 889 | 122k | index++; | 890 | 122k | } | 891 | 113k | } |
void valijson::constraints::OneOfConstraint::applyToSubschemas<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 882 | 236 | { | 883 | 236 | unsigned int index = 0; | 884 | 242 | for (const Subschema *subschema : m_subschemas) { | 885 | 242 | if (!fn(index, subschema)) { | 886 | 0 | return; | 887 | 0 | } | 888 | | | 889 | 242 | index++; | 890 | 242 | } | 891 | 236 | } |
|
892 | | |
893 | | private: |
894 | | typedef std::vector<const Subschema *, internal::CustomAllocator<const Subschema *>> Subschemas; |
895 | | |
896 | | /// Collection of sub-schemas, exactly one of which must be satisfied |
897 | | Subschemas m_subschemas; |
898 | | }; |
899 | | |
900 | | /** |
901 | | * @brief Represents a 'pattern' constraint |
902 | | */ |
903 | | class PatternConstraint: public BasicConstraint<PatternConstraint> |
904 | | { |
905 | | public: |
906 | | PatternConstraint() |
907 | 14.6k | : m_pattern(Allocator::rebind<char>::other(m_allocator)) { } |
908 | | |
909 | | PatternConstraint(CustomAlloc allocFn, CustomFree freeFn) |
910 | | : BasicConstraint(allocFn, freeFn), |
911 | 0 | m_pattern(Allocator::rebind<char>::other(m_allocator)) { } |
912 | | |
913 | | template<typename AllocatorType> |
914 | | bool getPattern(std::basic_string<char, std::char_traits<char>, AllocatorType> &result) const |
915 | | { |
916 | | result.assign(m_pattern.c_str()); |
917 | | return true; |
918 | | } |
919 | | |
920 | | template<typename AllocatorType> |
921 | | std::basic_string<char, std::char_traits<char>, AllocatorType> getPattern( |
922 | | const AllocatorType &alloc = AllocatorType()) const |
923 | 24.0k | { |
924 | 24.0k | return std::basic_string<char, std::char_traits<char>, AllocatorType>(m_pattern.c_str(), alloc); |
925 | 24.0k | } |
926 | | |
927 | | template<typename AllocatorType> |
928 | | void setPattern(const std::basic_string<char, std::char_traits<char>, AllocatorType> &pattern) |
929 | 14.4k | { |
930 | 14.4k | m_pattern.assign(pattern.c_str()); |
931 | 14.4k | } |
932 | | |
933 | | private: |
934 | | String m_pattern; |
935 | | }; |
936 | | |
937 | | class PolyConstraint : public Constraint |
938 | | { |
939 | | public: |
940 | | bool accept(ConstraintVisitor &visitor) const override |
941 | 0 | { |
942 | 0 | return visitor.visit(*static_cast<const PolyConstraint*>(this)); |
943 | 0 | } |
944 | | |
945 | | OwningPointer clone(CustomAlloc allocFn, CustomFree freeFn) const override |
946 | 0 | { |
947 | 0 | // smart pointer to automatically free raw memory on exception |
948 | 0 | typedef std::unique_ptr<Constraint, CustomFree> RawOwningPointer; |
949 | 0 | auto ptr = RawOwningPointer(static_cast<Constraint*>(allocFn(sizeOf())), freeFn); |
950 | 0 | if (!ptr) { |
951 | 0 | throwRuntimeError("Failed to allocate memory for cloned constraint"); |
952 | 0 | } |
953 | 0 |
|
954 | 0 | // constructor might throw but the memory will be taken care of anyways |
955 | 0 | (void)cloneInto(ptr.get()); |
956 | 0 |
|
957 | 0 | // implicitly convert to smart pointer that will also destroy object instance |
958 | 0 | return ptr; |
959 | 0 | } |
960 | | |
961 | | virtual bool validate(const adapters::Adapter &target, |
962 | | const valijson::ValidationResults::Path &path, |
963 | | valijson::ValidationResults *results) const = 0; |
964 | | |
965 | | private: |
966 | | virtual Constraint * cloneInto(void *) const = 0; |
967 | | |
968 | | virtual size_t sizeOf() const = 0; |
969 | | }; |
970 | | |
971 | | /** |
972 | | * @brief Represents a combination of 'properties', 'patternProperties' and |
973 | | * 'additionalProperties' constraints |
974 | | */ |
975 | | class PropertiesConstraint: public BasicConstraint<PropertiesConstraint> |
976 | | { |
977 | | public: |
978 | | PropertiesConstraint() |
979 | 56.8k | : m_properties(std::less<String>(), m_allocator), |
980 | 56.8k | m_patternProperties(std::less<String>(), m_allocator), |
981 | 56.8k | m_additionalProperties(nullptr) { } |
982 | | |
983 | | PropertiesConstraint(CustomAlloc allocFn, CustomFree freeFn) |
984 | | : BasicConstraint(allocFn, freeFn), |
985 | | m_properties(std::less<String>(), m_allocator), |
986 | | m_patternProperties(std::less<String>(), m_allocator), |
987 | 0 | m_additionalProperties(nullptr) { } |
988 | | |
989 | | bool addPatternPropertySubschema(const char *patternProperty, const Subschema *subschema) |
990 | 315k | { |
991 | 315k | return m_patternProperties.insert(PropertySchemaMap::value_type( |
992 | 315k | String(patternProperty, m_allocator), subschema)).second; |
993 | 315k | } |
994 | | |
995 | | template<typename AllocatorType> |
996 | | bool addPatternPropertySubschema(const std::basic_string<char, |
997 | | std::char_traits<char>, AllocatorType> &patternProperty, |
998 | | const Subschema *subschema) |
999 | 315k | { |
1000 | 315k | return addPatternPropertySubschema(patternProperty.c_str(), subschema); |
1001 | 315k | } |
1002 | | |
1003 | | bool addPropertySubschema(const char *propertyName, |
1004 | | const Subschema *subschema) |
1005 | 95.1k | { |
1006 | 95.1k | return m_properties.insert(PropertySchemaMap::value_type( |
1007 | 95.1k | String(propertyName, m_allocator), subschema)).second; |
1008 | 95.1k | } |
1009 | | |
1010 | | template<typename AllocatorType> |
1011 | | bool addPropertySubschema(const std::basic_string<char, |
1012 | | std::char_traits<char>, AllocatorType> &propertyName, |
1013 | | const Subschema *subschema) |
1014 | 95.1k | { |
1015 | 95.1k | return addPropertySubschema(propertyName.c_str(), subschema); |
1016 | 95.1k | } |
1017 | | |
1018 | | template<typename FunctorType> |
1019 | | void applyToPatternProperties(const FunctorType &fn) const |
1020 | 214k | { |
1021 | 214k | typedef typename PropertySchemaMap::value_type ValueType; |
1022 | 1.71M | for (const ValueType &value : m_patternProperties) { |
1023 | 1.71M | if (!fn(value.first, value.second)) { |
1024 | 24.4k | return; |
1025 | 24.4k | } |
1026 | 1.71M | } |
1027 | 214k | } void valijson::constraints::PropertiesConstraint::applyToPatternProperties<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePatternPropertySubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePatternPropertySubschemas const&) const Line | Count | Source | 1020 | 214k | { | 1021 | 214k | typedef typename PropertySchemaMap::value_type ValueType; | 1022 | 1.71M | for (const ValueType &value : m_patternProperties) { | 1023 | 1.71M | if (!fn(value.first, value.second)) { | 1024 | 24.4k | return; | 1025 | 24.4k | } | 1026 | 1.71M | } | 1027 | 214k | } |
Unexecuted instantiation: void valijson::constraints::PropertiesConstraint::applyToPatternProperties<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePatternPropertySubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePatternPropertySubschemas const&) const |
1028 | | |
1029 | | template<typename FunctorType> |
1030 | | void applyToProperties(const FunctorType &fn) const |
1031 | 214k | { |
1032 | 214k | typedef typename PropertySchemaMap::value_type ValueType; |
1033 | 214k | for (const ValueType &value : m_properties) { |
1034 | 89.6k | if (!fn(value.first, value.second)) { |
1035 | 4 | return; |
1036 | 4 | } |
1037 | 89.6k | } |
1038 | 214k | } void valijson::constraints::PropertiesConstraint::applyToProperties<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePropertySubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidatePropertySubschemas const&) const Line | Count | Source | 1031 | 214k | { | 1032 | 214k | typedef typename PropertySchemaMap::value_type ValueType; | 1033 | 214k | for (const ValueType &value : m_properties) { | 1034 | 89.6k | if (!fn(value.first, value.second)) { | 1035 | 4 | return; | 1036 | 4 | } | 1037 | 89.6k | } | 1038 | 214k | } |
Unexecuted instantiation: void valijson::constraints::PropertiesConstraint::applyToProperties<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePropertySubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidatePropertySubschemas const&) const |
1039 | | |
1040 | | const Subschema * getAdditionalPropertiesSubschema() const |
1041 | 197k | { |
1042 | 197k | return m_additionalProperties; |
1043 | 197k | } |
1044 | | |
1045 | | void setAdditionalPropertiesSubschema(const Subschema *subschema) |
1046 | 44.5k | { |
1047 | 44.5k | m_additionalProperties = subschema; |
1048 | 44.5k | } |
1049 | | |
1050 | | private: |
1051 | | typedef std::map< |
1052 | | String, |
1053 | | const Subschema *, |
1054 | | std::less<String>, |
1055 | | internal::CustomAllocator<std::pair<const String, const Subschema *>> |
1056 | | > PropertySchemaMap; |
1057 | | |
1058 | | PropertySchemaMap m_properties; |
1059 | | PropertySchemaMap m_patternProperties; |
1060 | | |
1061 | | const Subschema *m_additionalProperties; |
1062 | | }; |
1063 | | |
1064 | | class PropertyNamesConstraint: public BasicConstraint<PropertyNamesConstraint> |
1065 | | { |
1066 | | public: |
1067 | | PropertyNamesConstraint() |
1068 | 4.61k | : m_subschema(nullptr) { } |
1069 | | |
1070 | | PropertyNamesConstraint(CustomAlloc allocFn, CustomFree freeFn) |
1071 | | : BasicConstraint(allocFn, freeFn), |
1072 | 0 | m_subschema(nullptr) { } |
1073 | | |
1074 | | const Subschema * getSubschema() const |
1075 | 21.6k | { |
1076 | 21.6k | return m_subschema; |
1077 | 21.6k | } |
1078 | | |
1079 | | void setSubschema(const Subschema *subschema) |
1080 | 4.61k | { |
1081 | 4.61k | m_subschema = subschema; |
1082 | 4.61k | } |
1083 | | |
1084 | | private: |
1085 | | const Subschema *m_subschema; |
1086 | | }; |
1087 | | |
1088 | | /** |
1089 | | * @brief Represents a 'required' constraint |
1090 | | */ |
1091 | | class RequiredConstraint: public BasicConstraint<RequiredConstraint> |
1092 | | { |
1093 | | public: |
1094 | | RequiredConstraint() |
1095 | 8.59k | : m_requiredProperties(std::less<String>(), m_allocator) { } |
1096 | | |
1097 | | RequiredConstraint(CustomAlloc allocFn, CustomFree freeFn) |
1098 | | : BasicConstraint(allocFn, freeFn), |
1099 | 0 | m_requiredProperties(std::less<String>(), m_allocator) { } |
1100 | | |
1101 | | bool addRequiredProperty(const char *propertyName) |
1102 | 40.3k | { |
1103 | 40.3k | return m_requiredProperties.insert(String(propertyName, |
1104 | 40.3k | Allocator::rebind<char>::other(m_allocator))).second; |
1105 | 40.3k | } |
1106 | | |
1107 | | template<typename AllocatorType> |
1108 | | bool addRequiredProperty(const std::basic_string<char, std::char_traits<char>, AllocatorType> &propertyName) |
1109 | 40.3k | { |
1110 | 40.3k | return addRequiredProperty(propertyName.c_str()); |
1111 | 40.3k | } |
1112 | | |
1113 | | template<typename FunctorType> |
1114 | | void applyToRequiredProperties(const FunctorType &fn) const |
1115 | 13.1k | { |
1116 | 118k | for (const String &propertyName : m_requiredProperties) { |
1117 | 118k | if (!fn(propertyName)) { |
1118 | 78 | return; |
1119 | 78 | } |
1120 | 118k | } |
1121 | 13.1k | } Unexecuted instantiation: void valijson::constraints::RequiredConstraint::applyToRequiredProperties<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateProperties>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateProperties const&) const void valijson::constraints::RequiredConstraint::applyToRequiredProperties<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateProperties>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateProperties const&) const Line | Count | Source | 1115 | 13.1k | { | 1116 | 118k | for (const String &propertyName : m_requiredProperties) { | 1117 | 118k | if (!fn(propertyName)) { | 1118 | 78 | return; | 1119 | 78 | } | 1120 | 118k | } | 1121 | 13.1k | } |
|
1122 | | |
1123 | | private: |
1124 | | typedef std::set<String, std::less<String>, |
1125 | | internal::CustomAllocator<String>> RequiredProperties; |
1126 | | |
1127 | | RequiredProperties m_requiredProperties; |
1128 | | }; |
1129 | | |
1130 | | /** |
1131 | | * @brief Represents an 'items' constraint that specifies one sub-schema |
1132 | | * |
1133 | | * A value is considered valid against this constraint if it is an array, and |
1134 | | * each item in the array validates against the sub-schema specified by this |
1135 | | * constraint. |
1136 | | * |
1137 | | * The prefix 'Singular' comes from the fact that array items must validate |
1138 | | * against exactly one sub-schema. |
1139 | | */ |
1140 | | class SingularItemsConstraint: public BasicConstraint<SingularItemsConstraint> |
1141 | | { |
1142 | | public: |
1143 | | SingularItemsConstraint() |
1144 | 11.8k | : m_itemsSubschema(nullptr) { } |
1145 | | |
1146 | | SingularItemsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
1147 | | : BasicConstraint(allocFn, freeFn), |
1148 | 0 | m_itemsSubschema(nullptr) { } |
1149 | | |
1150 | | const Subschema * getItemsSubschema() const |
1151 | 1.78k | { |
1152 | 1.78k | return m_itemsSubschema; |
1153 | 1.78k | } |
1154 | | |
1155 | | void setItemsSubschema(const Subschema *subschema) |
1156 | 7.30k | { |
1157 | 7.30k | m_itemsSubschema = subschema; |
1158 | 7.30k | } |
1159 | | |
1160 | | private: |
1161 | | const Subschema *m_itemsSubschema; |
1162 | | }; |
1163 | | |
1164 | | /** |
1165 | | * @brief Represents a 'type' constraint. |
1166 | | */ |
1167 | | class TypeConstraint: public BasicConstraint<TypeConstraint> |
1168 | | { |
1169 | | public: |
1170 | | enum JsonType { |
1171 | | kAny, |
1172 | | kArray, |
1173 | | kBoolean, |
1174 | | kInteger, |
1175 | | kNull, |
1176 | | kNumber, |
1177 | | kObject, |
1178 | | kString |
1179 | | }; |
1180 | | |
1181 | | TypeConstraint() |
1182 | 33.8k | : m_namedTypes(std::less<JsonType>(), m_allocator), |
1183 | 33.8k | m_schemaTypes(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
1184 | | |
1185 | | TypeConstraint(CustomAlloc allocFn, CustomFree freeFn) |
1186 | | : BasicConstraint(allocFn, freeFn), |
1187 | | m_namedTypes(std::less<JsonType>(), m_allocator), |
1188 | 0 | m_schemaTypes(Allocator::rebind<const Subschema *>::other(m_allocator)) { } |
1189 | | |
1190 | | void addNamedType(JsonType type) |
1191 | 31.5k | { |
1192 | 31.5k | m_namedTypes.insert(type); |
1193 | 31.5k | } |
1194 | | |
1195 | | void addSchemaType(const Subschema *subschema) |
1196 | 0 | { |
1197 | 0 | m_schemaTypes.push_back(subschema); |
1198 | 0 | } |
1199 | | |
1200 | | template<typename FunctorType> |
1201 | | void applyToNamedTypes(const FunctorType &fn) const |
1202 | 35.4k | { |
1203 | 36.5k | for (const JsonType namedType : m_namedTypes) { |
1204 | 36.5k | if (!fn(namedType)) { |
1205 | 0 | return; |
1206 | 0 | } |
1207 | 36.5k | } |
1208 | 35.4k | } void valijson::constraints::TypeConstraint::applyToNamedTypes<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateNamedTypes>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateNamedTypes const&) const Line | Count | Source | 1202 | 1.70k | { | 1203 | 1.70k | for (const JsonType namedType : m_namedTypes) { | 1204 | 1.70k | if (!fn(namedType)) { | 1205 | 0 | return; | 1206 | 0 | } | 1207 | 1.70k | } | 1208 | 1.70k | } |
void valijson::constraints::TypeConstraint::applyToNamedTypes<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateNamedTypes>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateNamedTypes const&) const Line | Count | Source | 1202 | 33.7k | { | 1203 | 34.7k | for (const JsonType namedType : m_namedTypes) { | 1204 | 34.7k | if (!fn(namedType)) { | 1205 | 0 | return; | 1206 | 0 | } | 1207 | 34.7k | } | 1208 | 33.7k | } |
|
1209 | | |
1210 | | template<typename FunctorType> |
1211 | | void applyToSchemaTypes(const FunctorType &fn) const |
1212 | 11.5k | { |
1213 | 11.5k | unsigned int index = 0; |
1214 | 11.5k | for (const Subschema *subschema : m_schemaTypes) { |
1215 | 0 | if (!fn(index, subschema)) { |
1216 | 0 | return; |
1217 | 0 | } |
1218 | | |
1219 | 0 | index++; |
1220 | 0 | } |
1221 | 11.5k | } void valijson::constraints::TypeConstraint::applyToSchemaTypes<valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::StdStringAdapter, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 1212 | 1.54k | { | 1213 | 1.54k | unsigned int index = 0; | 1214 | 1.54k | for (const Subschema *subschema : m_schemaTypes) { | 1215 | 0 | if (!fn(index, subschema)) { | 1216 | 0 | return; | 1217 | 0 | } | 1218 | | | 1219 | 0 | index++; | 1220 | 0 | } | 1221 | 1.54k | } |
void valijson::constraints::TypeConstraint::applyToSchemaTypes<valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas>(valijson::ValidationVisitor<valijson::adapters::GenericRapidJsonAdapter<rapidjson::GenericValue<rapidjson::UTF8<char>, rapidjson::MemoryPoolAllocator<rapidjson::CrtAllocator> > >, valijson::DefaultRegexEngine>::ValidateSubschemas const&) const Line | Count | Source | 1212 | 10.0k | { | 1213 | 10.0k | unsigned int index = 0; | 1214 | 10.0k | for (const Subschema *subschema : m_schemaTypes) { | 1215 | 0 | if (!fn(index, subschema)) { | 1216 | 0 | return; | 1217 | 0 | } | 1218 | | | 1219 | 0 | index++; | 1220 | 0 | } | 1221 | 10.0k | } |
|
1222 | | |
1223 | | template<typename AllocatorType> |
1224 | | static JsonType jsonTypeFromString(const std::basic_string<char, |
1225 | | std::char_traits<char>, AllocatorType> &typeName) |
1226 | 33.9k | { |
1227 | 33.9k | if (typeName.compare("any") == 0) { |
1228 | 3.46k | return kAny; |
1229 | 30.4k | } else if (typeName.compare("array") == 0) { |
1230 | 301 | return kArray; |
1231 | 30.1k | } else if (typeName.compare("boolean") == 0) { |
1232 | 923 | return kBoolean; |
1233 | 29.2k | } else if (typeName.compare("integer") == 0) { |
1234 | 21.5k | return kInteger; |
1235 | 21.5k | } else if (typeName.compare("null") == 0) { |
1236 | 75 | return kNull; |
1237 | 7.56k | } else if (typeName.compare("number") == 0) { |
1238 | 1.81k | return kNumber; |
1239 | 5.74k | } else if (typeName.compare("object") == 0) { |
1240 | 1.66k | return kObject; |
1241 | 4.08k | } else if (typeName.compare("string") == 0) { |
1242 | 2.33k | return kString; |
1243 | 2.33k | } |
1244 | | |
1245 | 1.74k | throwRuntimeError("Unrecognised JSON type name '" + |
1246 | 1.74k | std::string(typeName.c_str()) + "'"); |
1247 | 1.74k | abort(); |
1248 | 33.9k | } |
1249 | | |
1250 | | private: |
1251 | | typedef std::set<JsonType, std::less<JsonType>, internal::CustomAllocator<JsonType>> NamedTypes; |
1252 | | |
1253 | | typedef std::vector<const Subschema *, |
1254 | | Allocator::rebind<const Subschema *>::other> SchemaTypes; |
1255 | | |
1256 | | /// Set of named JSON types that serve as valid types |
1257 | | NamedTypes m_namedTypes; |
1258 | | |
1259 | | /// Set of sub-schemas that serve as valid types |
1260 | | SchemaTypes m_schemaTypes; |
1261 | | }; |
1262 | | |
1263 | | /** |
1264 | | * @brief Represents a 'uniqueItems' constraint |
1265 | | */ |
1266 | | class UniqueItemsConstraint: public BasicConstraint<UniqueItemsConstraint> |
1267 | | { |
1268 | | public: |
1269 | 2.79k | UniqueItemsConstraint() = default; |
1270 | | |
1271 | | UniqueItemsConstraint(CustomAlloc allocFn, CustomFree freeFn) |
1272 | 0 | : BasicConstraint(allocFn, freeFn) { } |
1273 | | }; |
1274 | | |
1275 | | } // namespace constraints |
1276 | | } // namespace valijson |
1277 | | |
1278 | | #ifdef _MSC_VER |
1279 | | #pragma warning( pop ) |
1280 | | #endif |