Coverage Report

Created: 2026-05-30 06:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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