• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OpenLightingProject / ola / 20179851591

12 Dec 2025 09:05PM UTC coverage: 45.048% (-0.7%) from 45.72%
20179851591

Pull #2027

github

web-flow
Bump actions/upload-artifact from 4 to 6

Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #2027: Bump actions/upload-artifact from 4 to 6

8554 of 19812 branches covered (43.18%)

22094 of 49046 relevant lines covered (45.05%)

50.63 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.91
/common/web/JsonSchema.cpp
1
/*
2
 * This library is free software; you can redistribute it and/or
3
 * modify it under the terms of the GNU Lesser General Public
4
 * License as published by the Free Software Foundation; either
5
 * version 2.1 of the License, or (at your option) any later version.
6
 *
7
 * This library is distributed in the hope that it will be useful,
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
10
 * Lesser General Public License for more details.
11
 *
12
 * You should have received a copy of the GNU Lesser General Public
13
 * License along with this library; if not, write to the Free Software
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15
 *
16
 * JsonSchema.cpp
17
 * Json Schema validation.
18
 * See http://www.json-schema.org/
19
 * Copyright (C) 2014 Simon Newton
20
 */
21

22
#include <math.h>
23
#include <algorithm>
24
#include <set>
25
#include <string>
26
#include <vector>
27

28
#include "ola/Logging.h"
29
#include "common/web/SchemaParser.h"
30
#include "ola/stl/STLUtils.h"
31
#include "ola/web/JsonLexer.h"
32
#include "ola/web/JsonSchema.h"
33
#include "ola/web/JsonTypes.h"
34

35
namespace ola {
36
namespace web {
37

38
using std::auto_ptr;
39
using std::set;
40
using std::string;
41
using std::vector;
42

43
// BaseValidator
44
// -----------------------------------------------------------------------------
45
BaseValidator::~BaseValidator() {
264✔
46
  STLDeleteElements(&m_enums);
264✔
47
}
272✔
48

49
JsonObject* BaseValidator::GetSchema() const {
165✔
50
  JsonObject *schema = new JsonObject();
165✔
51
  if (!m_schema.empty()) {
165✔
52
    schema->Add("$schema", m_schema);
18✔
53
  }
54
  if (!m_id.empty()) {
165✔
55
    schema->Add("id", m_id);
18✔
56
  }
57
  if (!m_title.empty()) {
165✔
58
    schema->Add("title", m_title);
18✔
59
  }
60
  if (!m_description.empty()) {
165✔
61
    schema->Add("description", m_description);
20✔
62
  }
63
  const string type = JsonTypeToString(m_type);
165✔
64
  if (!type.empty()) {
165✔
65
    schema->Add("type", type);
228✔
66
  }
67

68
  if (m_default_value.get()) {
165✔
69
    schema->AddValue("default", m_default_value.get()->Clone());
48✔
70
  }
71

72
  if (!m_enums.empty()) {
165✔
73
    JsonArray *enum_array = schema->AddArray("enum");
6✔
74
    vector<const JsonValue*>::const_iterator iter = m_enums.begin();
6✔
75
    for (; iter != m_enums.end(); ++iter) {
30✔
76
      enum_array->AppendValue((*iter)->Clone());
48✔
77
    }
78
  }
79
  ExtendSchema(schema);
165✔
80
  return schema;
165✔
81
}
165✔
82

83
void BaseValidator::SetSchema(const string &schema) {
9✔
84
  m_schema = schema;
9✔
85
}
9✔
86

87
void BaseValidator::SetId(const string &id) {
9✔
88
  m_id = id;
9✔
89
}
9✔
90

91
void BaseValidator::SetTitle(const string &title) {
9✔
92
  m_title = title;
9✔
93
}
9✔
94

95
void BaseValidator::SetDescription(const string &description) {
10✔
96
  m_description = description;
10✔
97
}
10✔
98

99
void BaseValidator::SetDefaultValue(const JsonValue *value) {
24✔
100
  m_default_value.reset(value);
24✔
101
}
24✔
102

103
const JsonValue *BaseValidator::GetDefaultValue() const {
×
104
  return m_default_value.get();
×
105
}
106

107
void BaseValidator::AddEnumValue(const JsonValue *value) {
29✔
108
  m_enums.push_back(value);
29✔
109
}
29✔
110

111
bool BaseValidator::CheckEnums(const JsonValue &value) {
82✔
112
  if (m_enums.empty()) {
82✔
113
    return true;
114
  }
115
  vector<const JsonValue*>::const_iterator iter = m_enums.begin();
116
  for (; iter != m_enums.end(); ++iter) {
28✔
117
    if (**iter == value) {
23✔
118
      return true;
119
    }
120
  }
121
  return false;
122
}
123

124
// ReferenceValidator
125
// -----------------------------------------------------------------------------
126
ReferenceValidator::ReferenceValidator(const SchemaDefinitions *definitions,
28✔
127
                                       const string &schema)
28✔
128
    : m_definitions(definitions),
28✔
129
      m_schema(schema),
28✔
130
      m_validator(NULL) {
28✔
131
}
28✔
132

133
bool ReferenceValidator::IsValid() const {
8✔
134
  return m_validator ? m_validator->IsValid() : false;
8✔
135
}
136

137
void ReferenceValidator::Visit(const JsonString &value) {
1✔
138
  Validate(value);
1✔
139
}
1✔
140

141
void ReferenceValidator::Visit(const JsonBool &value) {
1✔
142
  Validate(value);
1✔
143
}
1✔
144

145
void ReferenceValidator::Visit(const JsonNull &value) {
1✔
146
  Validate(value);
1✔
147
}
1✔
148

149
void ReferenceValidator::Visit(const JsonRawValue &value) {
×
150
  Validate(value);
×
151
}
×
152

153
void ReferenceValidator::Visit(const JsonObject &value) {
1✔
154
  Validate(value);
1✔
155
}
1✔
156

157
void ReferenceValidator::Visit(const JsonArray &value) {
1✔
158
  Validate(value);
1✔
159
}
1✔
160

161
void ReferenceValidator::Visit(const JsonUInt &value) {
1✔
162
  Validate(value);
1✔
163
}
1✔
164

165
void ReferenceValidator::Visit(const JsonUInt64 &value) {
×
166
  Validate(value);
×
167
}
×
168

169
void ReferenceValidator::Visit(const JsonInt &value) {
1✔
170
  Validate(value);
1✔
171
}
1✔
172

173
void ReferenceValidator::Visit(const JsonInt64 &value) {
×
174
  Validate(value);
×
175
}
×
176

177
void ReferenceValidator::Visit(const JsonDouble &value) {
1✔
178
  Validate(value);
1✔
179
}
1✔
180

181
JsonObject* ReferenceValidator::GetSchema() const {
27✔
182
  JsonObject *schema = new JsonObject();
27✔
183
  schema->Add("$ref", m_schema);
27✔
184
  return schema;
27✔
185
}
186

187
void ReferenceValidator::SetSchema(const std::string&) {}
×
188
void ReferenceValidator::SetId(const std::string &) {}
×
189
void ReferenceValidator::SetTitle(const std::string &) {}
×
190
void ReferenceValidator::SetDescription(const std::string &) {}
×
191
void ReferenceValidator::SetDefaultValue(const JsonValue *) {}
×
192
const JsonValue *ReferenceValidator::GetDefaultValue() const { return NULL; }
×
193

194
template <typename T>
195
void ReferenceValidator::Validate(const T &value) {
1✔
196
  if (!m_validator) {
1!
197
    m_validator = m_definitions->Lookup(m_schema);
×
198
  }
199

200
  if (m_validator) {
1!
201
    value.Accept(m_validator);
1✔
202
  }
203
}
1✔
204

205
// StringValidator
206
// -----------------------------------------------------------------------------
207
void StringValidator::Visit(const JsonString &str) {
12✔
208
  const std::string& value = str.Value();
12✔
209
  size_t str_size = value.size();
12✔
210
  if (str_size < m_options.min_length) {
12✔
211
    m_is_valid = false;
1✔
212
    return;
1✔
213
  }
214

215
  if (m_options.max_length >= 0 &&
11✔
216
      str_size > static_cast<size_t>(m_options.max_length)) {
2✔
217
    m_is_valid = false;
1✔
218
    return;
1✔
219
  }
220

221
  m_is_valid = CheckEnums(str);
10✔
222
}
223

224
void StringValidator::ExtendSchema(JsonObject *schema) const {
22✔
225
  if (m_options.min_length > 0) {
22✔
226
    schema->Add("minLength", m_options.min_length);
4✔
227
  }
228

229
  if (m_options.max_length >= 0) {
22✔
230
    schema->Add("maxLength", m_options.max_length);
6✔
231
  }
232

233
  // TODO(simon): Add pattern here?
234
  // TODO(simon): Add format here?
235
}
22✔
236

237
// IntegerValidator
238
// -----------------------------------------------------------------------------
239
IntegerValidator::~IntegerValidator() {
49✔
240
  STLDeleteElements(&m_constraints);
49✔
241
}
71✔
242

243
void IntegerValidator::AddConstraint(NumberConstraint *constraint) {
28✔
244
  m_constraints.push_back(constraint);
28✔
245
}
28✔
246

247
void IntegerValidator::Visit(const JsonUInt &value) {
37✔
248
  CheckValue(value);
37✔
249
}
37✔
250

251
void IntegerValidator::Visit(const JsonInt &value) {
42✔
252
  CheckValue(value);
42✔
253
}
42✔
254

255
void IntegerValidator::Visit(const JsonUInt64 &value) {
×
256
  CheckValue(value);
×
257
}
×
258

259
void IntegerValidator::Visit(const JsonInt64 &value) {
×
260
  CheckValue(value);
×
261
}
×
262

263
void IntegerValidator::Visit(const JsonDouble &value) {
5✔
264
  BaseValidator::Visit(value);
5✔
265
}
5✔
266

267
void IntegerValidator::ExtendSchema(JsonObject *schema) const {
26✔
268
  vector<NumberConstraint*>::const_iterator iter = m_constraints.begin();
26✔
269
  for (; iter != m_constraints.end(); ++iter) {
41✔
270
    (*iter)->ExtendSchema(schema);
15✔
271
  }
272
}
26✔
273

274
void IntegerValidator::CheckValue(const JsonNumber &value) {
80✔
275
  vector<NumberConstraint*>::const_iterator iter = m_constraints.begin();
80✔
276
  for (; iter != m_constraints.end(); ++iter) {
118✔
277
    if (!(*iter)->IsValid(value)) {
52✔
278
      m_is_valid = false;
14✔
279
      return;
14✔
280
    }
281
  }
282
  m_is_valid = CheckEnums(value);
66✔
283
}
284

285
void NumberValidator::Visit(const JsonDouble &value) {
1✔
286
  CheckValue(value);
1✔
287
}
1✔
288

289
// ObjectValidator
290
// -----------------------------------------------------------------------------
291
ObjectValidator::ObjectValidator(const Options &options)
35✔
292
    : BaseValidator(JSON_OBJECT),
293
      m_options(options) {
35✔
294
}
35✔
295

296
ObjectValidator::~ObjectValidator() {
70✔
297
  STLDeleteValues(&m_property_validators);
35✔
298
  STLDeleteValues(&m_schema_dependencies);
35✔
299
}
35✔
300

301
void ObjectValidator::AddValidator(const std::string &property,
43✔
302
                                   ValidatorInterface *validator) {
303
  STLReplaceAndDelete(&m_property_validators, property, validator);
43✔
304
}
43✔
305

306
void ObjectValidator::SetAdditionalValidator(ValidatorInterface *validator) {
7✔
307
  m_additional_property_validator.reset(validator);
7✔
308
}
7✔
309

310
void ObjectValidator::AddSchemaDependency(const string &property,
3✔
311
                                          ValidatorInterface *validator) {
312
  STLReplaceAndDelete(&m_schema_dependencies, property, validator);
3✔
313
}
3✔
314

315
void ObjectValidator::AddPropertyDependency(const string &property,
5✔
316
                                            const StringSet &properties) {
317
  m_property_dependencies[property] = properties;
5✔
318
}
5✔
319

320
void ObjectValidator::Visit(const JsonObject &obj) {
44✔
321
  m_is_valid = true;
44✔
322

323
  if (obj.Size() < m_options.min_properties) {
44✔
324
    m_is_valid = false;
2✔
325
    return;
3✔
326
  }
327

328
  if (m_options.max_properties > 0 &&
42✔
329
      obj.Size() > static_cast<size_t>(m_options.max_properties)) {
3✔
330
    m_is_valid = false;
1✔
331
    return;
1✔
332
  }
333

334
  m_seen_properties.clear();
41✔
335
  obj.VisitProperties(this);
41✔
336

337
  StringSet missing_properties;
41✔
338
  std::set_difference(m_options.required_properties.begin(),
41✔
339
                      m_options.required_properties.end(),
340
                      m_seen_properties.begin(),
341
                      m_seen_properties.end(),
342
                      std::inserter(missing_properties,
343
                                    missing_properties.end()));
344
  if (!missing_properties.empty()) {
41✔
345
    m_is_valid = false;
3✔
346
  }
347

348
  // Check PropertyDependencies
349
  PropertyDependencies::const_iterator prop_iter =
41✔
350
    m_property_dependencies.begin();
41✔
351
  for (; prop_iter != m_property_dependencies.end() && m_is_valid;
45✔
352
       ++prop_iter) {
4✔
353
    if (!STLContains(m_seen_properties, prop_iter->first)) {
4✔
354
      continue;
2✔
355
    }
356

357
    StringSet::const_iterator iter = prop_iter->second.begin();
2✔
358
    for (; iter != prop_iter->second.end(); ++iter) {
3✔
359
      if (!STLContains(m_seen_properties, *iter)) {
2✔
360
        m_is_valid = false;
1✔
361
        break;
1✔
362
      }
363
    }
364
  }
365

366
  // Check Schema Dependencies
367
  SchemaDependencies::const_iterator schema_iter =
41✔
368
    m_schema_dependencies.begin();
41✔
369
  for (; schema_iter != m_schema_dependencies.end() && m_is_valid;
45✔
370
       ++schema_iter) {
4✔
371
    if (STLContains(m_seen_properties, schema_iter->first)) {
5✔
372
      obj.Accept(schema_iter->second);
2✔
373
      if (!schema_iter->second->IsValid()) {
2✔
374
        m_is_valid = false;
1✔
375
        break;
1✔
376
      }
377
    }
378
  }
379
}
41✔
380

381
void ObjectValidator::VisitProperty(const std::string &property,
72✔
382
                                    const JsonValue &value) {
383
  m_seen_properties.insert(property);
72✔
384

385
  // The algorithm is described in section 8.3.3
386
  ValidatorInterface *validator = STLFindOrNull(
72✔
387
      m_property_validators, property);
72✔
388

389
  // patternProperties would be added here if supported
390

391
  if (!validator) {
72✔
392
    // try the additional validator
393
    validator = m_additional_property_validator.get();
44✔
394
  }
395

396
  if (validator) {
44✔
397
    value.Accept(validator);
31✔
398
    m_is_valid &= validator->IsValid();
31✔
399
  } else {
400
    // No validator found
401
    if (m_options.has_allow_additional_properties &&
41✔
402
        !m_options.allow_additional_properties) {
4✔
403
      m_is_valid &= false;
2✔
404
    }
405
  }
406
}
72✔
407

408
void ObjectValidator::ExtendSchema(JsonObject *schema) const {
24✔
409
  if (m_options.min_properties > 0) {
24✔
410
    schema->Add("minProperties", m_options.min_properties);
4✔
411
  }
412

413
  if (m_options.max_properties >= 0) {
24✔
414
    schema->Add("maxProperties", m_options.max_properties);
6✔
415
  }
416

417
  if (m_options.has_required_properties) {
24✔
418
    JsonArray *required_properties = schema->AddArray("required");
2✔
419
    StringSet::const_iterator iter = m_options.required_properties.begin();
2✔
420
    for (; iter != m_options.required_properties.end(); ++iter) {
3✔
421
      required_properties->Append(*iter);
1✔
422
    }
423
  }
424

425
  if (!m_property_validators.empty()) {
24✔
426
    JsonObject *properties = schema->AddObject("properties");
3✔
427
    PropertyValidators::const_iterator iter = m_property_validators.begin();
3✔
428
    for (; iter != m_property_validators.end(); iter++) {
38✔
429
      JsonObject *child_schema = iter->second->GetSchema();
35✔
430
      properties->AddValue(iter->first, child_schema);
35✔
431
    }
432
  }
433

434
  if (m_options.has_allow_additional_properties) {
24✔
435
    schema->Add("additionalProperties", m_options.allow_additional_properties);
4✔
436
  } else if (m_additional_property_validator.get()) {
22✔
437
    schema->AddValue("additionalProperties",
12✔
438
                     m_additional_property_validator->GetSchema());
6✔
439
  }
440

441
  if (!(m_property_dependencies.empty() && m_schema_dependencies.empty())) {
24✔
442
    JsonObject *dependencies = schema->AddObject("dependencies");
5✔
443
    PropertyDependencies::const_iterator prop_iter =
5✔
444
      m_property_dependencies.begin();
5✔
445
    for (; prop_iter != m_property_dependencies.end(); ++prop_iter) {
9✔
446
      JsonArray *properties = dependencies->AddArray(prop_iter->first);
4✔
447
      StringSet::const_iterator iter = prop_iter->second.begin();
4✔
448
      for (; iter != prop_iter->second.end(); ++iter) {
9✔
449
        properties->Append(*iter);
5✔
450
      }
451
    }
452

453
    SchemaDependencies::const_iterator schema_iter =
5✔
454
      m_schema_dependencies.begin();
5✔
455
    for (; schema_iter != m_schema_dependencies.end(); ++schema_iter) {
7✔
456
      dependencies->AddValue(schema_iter->first,
2✔
457
          schema_iter->second->GetSchema());
2✔
458
    }
459
  }
460
}
24✔
461

462
// ArrayValidator
463
// -----------------------------------------------------------------------------
464
ArrayValidator::ArrayValidator(Items *items, AdditionalItems *additional_items,
34✔
465
                               const Options &options)
34✔
466
  : BaseValidator(JSON_ARRAY),
467
    m_items(items),
34✔
468
    m_additional_items(additional_items),
34✔
469
    m_options(options),
34✔
470
    m_wildcard_validator(new WildcardValidator()) {
34✔
471
}
34✔
472

473
ArrayValidator::~ArrayValidator() {}
34✔
474

475
// items: array or schema (object)
476
// additionalItems : schema (object) or bool
477
//
478
// items = object
479
// items = array, additional = bool
480
// items = array, additional = schema
481
void ArrayValidator::Visit(const JsonArray &array) {
14✔
482
  if (array.Size() < m_options.min_items) {
14✔
483
    m_is_valid = false;
2✔
484
    return;
4✔
485
  }
486

487
  if (m_options.max_items > 0 &&
12✔
488
      array.Size() > static_cast<size_t>(m_options.max_items)) {
4✔
489
    m_is_valid = false;
1✔
490
    return;
1✔
491
  }
492

493

494
  auto_ptr<ArrayElementValidator> element_validator(
11✔
495
      ConstructElementValidator());
11✔
496

497
  for (unsigned int i = 0; i < array.Size(); i++) {
28✔
498
    array.ElementAt(i)->Accept(element_validator.get());
17✔
499
    if (!element_validator->IsValid()) {
17✔
500
      break;
501
    }
502
  }
503
  m_is_valid = element_validator->IsValid();
11✔
504
  if (!m_is_valid) {
11✔
505
    return;
506
  }
507

508
  if (m_options.unique_items) {
11✔
509
    for (unsigned int i = 0; i < array.Size(); i++) {
13✔
510
      for (unsigned int j = 0; j < i; j++) {
14✔
511
        if (*(array.ElementAt(i)) == *(array.ElementAt(j))) {
6✔
512
          m_is_valid = false;
1✔
513
          return;
1✔
514
        }
515
      }
516
    }
517
  }
518
}
11✔
519

520
void ArrayValidator::ExtendSchema(JsonObject *schema) const {
30✔
521
  if (m_options.min_items > 0) {
30✔
522
    schema->Add("minItems", m_options.min_items);
16✔
523
  }
524

525
  if (m_options.max_items >= 0) {
30✔
526
    schema->Add("maxItems", m_options.max_items);
4✔
527
  }
528

529
  if (m_options.unique_items) {
30✔
530
    schema->Add("uniqueItems", m_options.unique_items);
10✔
531
  }
532

533
  if (m_items.get()) {
30✔
534
    // items exists
535
    if (m_items->Validator()) {
22✔
536
      // items is an object
537
      JsonObject *child_schema = m_items->Validator()->GetSchema();
15✔
538
      schema->AddValue("items", child_schema);
30✔
539
    } else {
540
      // items is an array
541
      const ValidatorList &validators = m_items->Validators();
7✔
542
      JsonArray *items = schema->AddArray("items");
7✔
543
      ValidatorList::const_iterator iter = validators.begin();
7✔
544
      for (; iter != validators.end(); iter++) {
16✔
545
        JsonObject *child_schema = (*iter)->GetSchema();
9✔
546
        items->Append(child_schema);
9✔
547
      }
548
    }
549
  }
550

551
  if (m_additional_items.get()) {
30✔
552
    // additionalItems exists
553
    if (m_additional_items->Validator()) {
11✔
554
      // additionalItems is an object
555
      JsonObject *child_schema = m_additional_items->Validator()->GetSchema();
4✔
556
      schema->AddValue("additionalItems", child_schema);
8✔
557
    } else {
558
      // additionalItems is a bool
559
      schema->Add("additionalItems", m_additional_items->AllowAdditional());
14✔
560
    }
561
  }
562
}
30✔
563

564
// TODO(simon): do this once at construction, rather than on every visit?
565
ArrayValidator::ArrayElementValidator*
566
    ArrayValidator::ConstructElementValidator() const {
11✔
567
  if (m_items.get()) {
11✔
568
    if (m_items->Validator()) {
×
569
      // 8.2.3.1, items is an object.
570
      ValidatorList empty_validators;
×
571
      return new ArrayElementValidator(empty_validators, m_items->Validator());
×
572
    } else {
×
573
      // 8.2.3.3, items is an array.
574
      const ValidatorList &validators = m_items->Validators();
×
575
      ValidatorInterface *default_validator = NULL;
×
576

577
      // Check to see if additionalItems it defined.
578
      if (m_additional_items.get()) {
×
579
        if (m_additional_items->Validator()) {
×
580
          // additionalItems is an object
581
          default_validator = m_additional_items->Validator();
582
        } else if (m_additional_items->AllowAdditional()) {
×
583
          // additionalItems is a bool, and true
584
          default_validator = m_wildcard_validator.get();
×
585
        }
586
      } else {
587
        // additionalItems not provided, so it defaults to the empty schema
588
        // (wildcard).
589
        default_validator = m_wildcard_validator.get();
×
590
      }
591
      return new ArrayElementValidator(validators, default_validator);
×
592
    }
593
  } else {
594
    // no items, therefore it defaults to the empty (wildcard) schema.
595
    ValidatorList empty_validators;
11✔
596
    return new ArrayElementValidator(
11✔
597
        empty_validators, m_wildcard_validator.get());
11✔
598
  }
11✔
599
}
600

601
// ArrayValidator::ArrayElementValidator
602
// -----------------------------------------------------------------------------
603
ArrayValidator::ArrayElementValidator::ArrayElementValidator(
11✔
604
    const ValidatorList &validators,
605
    ValidatorInterface *default_validator)
11✔
606
    : BaseValidator(JSON_UNDEFINED),
607
      m_item_validators(validators.begin(), validators.end()),
22✔
608
      m_default_validator(default_validator) {
11✔
609
}
11✔
610

611
void ArrayValidator::ArrayElementValidator::Visit(
×
612
    const JsonString &value) {
613
  ValidateItem(value);
×
614
}
×
615

616
void ArrayValidator::ArrayElementValidator::Visit(const JsonBool &value) {
×
617
  ValidateItem(value);
×
618
}
×
619

620
void ArrayValidator::ArrayElementValidator::Visit(const JsonNull &value) {
×
621
  ValidateItem(value);
×
622
}
×
623

624
void ArrayValidator::ArrayElementValidator::Visit(const JsonRawValue &value) {
×
625
  ValidateItem(value);
×
626
}
×
627

628
void ArrayValidator::ArrayElementValidator::Visit(const JsonObject &value) {
×
629
  ValidateItem(value);
×
630
}
×
631

632
void ArrayValidator::ArrayElementValidator::Visit(const JsonArray &value) {
×
633
  ValidateItem(value);
×
634
}
×
635

636
void ArrayValidator::ArrayElementValidator::Visit(const JsonUInt &value) {
17✔
637
  ValidateItem(value);
17✔
638
}
17✔
639

640
void ArrayValidator::ArrayElementValidator::Visit(
×
641
    const JsonUInt64 &value) {
642
  ValidateItem(value);
×
643
}
×
644

645
void ArrayValidator::ArrayElementValidator::Visit(const JsonInt &value) {
×
646
  ValidateItem(value);
×
647
}
×
648

649
void ArrayValidator::ArrayElementValidator::Visit(const JsonInt64 &value) {
×
650
  ValidateItem(value);
×
651
}
×
652

653
void ArrayValidator::ArrayElementValidator::Visit(
×
654
    const JsonDouble &value) {
655
  ValidateItem(value);
×
656
}
×
657

658
template <typename T>
659
void ArrayValidator::ArrayElementValidator::ValidateItem(const T &item) {
×
660
  ValidatorInterface *validator = NULL;
×
661

662
  if (!m_item_validators.empty()) {
×
663
    validator = m_item_validators.front();
×
664
    m_item_validators.pop_front();
×
665
  } else if (!m_default_validator) {
×
666
    // additional items aren't allowed
667
    m_is_valid = false;
×
668
    return;
×
669
  } else {
670
    validator = m_default_validator;
671
  }
672
  item.Accept(validator);
×
673
  m_is_valid = validator->IsValid();
×
674
}
675

676
// ConjunctionValidator
677
// -----------------------------------------------------------------------------
678
ConjunctionValidator::ConjunctionValidator(const string &keyword,
13✔
679
                                           ValidatorList *validators)
13✔
680
    : BaseValidator(JSON_UNDEFINED),
681
      m_keyword(keyword),
13✔
682
      m_validators(*validators) {
13✔
683
  validators->clear();
13✔
684
}
13✔
685

686
ConjunctionValidator::~ConjunctionValidator() {
13✔
687
  STLDeleteElements(&m_validators);
13✔
688
}
26✔
689

690
void ConjunctionValidator::ExtendSchema(JsonObject *schema) const {
10✔
691
  JsonArray *items = schema->AddArray(m_keyword);
10✔
692
  ValidatorList::const_iterator iter = m_validators.begin();
10✔
693
  for (; iter != m_validators.end(); ++iter) {
30✔
694
    JsonObject *child_schema = (*iter)->GetSchema();
20✔
695
    items->Append(child_schema);
20✔
696
  }
697
}
10✔
698

699
// AllOfValidator
700
// -----------------------------------------------------------------------------
701
void AllOfValidator::Validate(const JsonValue &value) {
9✔
702
  ValidatorList::iterator iter = m_validators.begin();
9✔
703
  for (; iter != m_validators.end(); ++iter) {
11✔
704
    value.Accept(*iter);
10✔
705
    if (!(*iter)->IsValid()) {
10✔
706
      m_is_valid = false;
8✔
707
      return;
8✔
708
    }
709
  }
710
  m_is_valid = true;
1✔
711
}
712

713
// AnyOfValidator
714
// -----------------------------------------------------------------------------
715
void AnyOfValidator::Validate(const JsonValue &value) {
9✔
716
  ValidatorList::iterator iter = m_validators.begin();
9✔
717
  for (; iter != m_validators.end(); ++iter) {
27✔
718
    value.Accept(*iter);
22✔
719
    if ((*iter)->IsValid()) {
22✔
720
      m_is_valid = true;
4✔
721
      return;
4✔
722
    }
723
  }
724
  m_is_valid = false;
5✔
725
}
726

727
// OneOfValidator
728
// -----------------------------------------------------------------------------
729
void OneOfValidator::Validate(const JsonValue &value) {
11✔
730
  bool matched = false;
11✔
731
  ValidatorList::iterator iter = m_validators.begin();
11✔
732
  for (; iter != m_validators.end(); ++iter) {
31✔
733
    value.Accept(*iter);
22✔
734
    if ((*iter)->IsValid()) {
22✔
735
      if (matched) {
6✔
736
        m_is_valid = false;
2✔
737
        return;
2✔
738
      } else {
739
        matched = true;
740
      }
741
    }
742
  }
743
  m_is_valid = matched;
9✔
744
}
745

746
// NotValidator
747
// -----------------------------------------------------------------------------
748
void NotValidator::Validate(const JsonValue &value) {
8✔
749
  value.Accept(m_validator.get());
8✔
750
  m_is_valid = !m_validator->IsValid();
8✔
751
}
8✔
752

753
void NotValidator::ExtendSchema(JsonObject *schema) const {
1✔
754
  JsonObject *child_schema = m_validator->GetSchema();
1✔
755
  schema->AddValue("not", child_schema);
1✔
756
}
1✔
757

758
// SchemaDefinitions
759
// -----------------------------------------------------------------------------
760
SchemaDefinitions::~SchemaDefinitions() {
300✔
761
  STLDeleteValues(&m_validators);
300✔
762
}
300✔
763

764
void SchemaDefinitions::Add(const string &schema_name,
11✔
765
                           ValidatorInterface *validator) {
766
  STLReplaceAndDelete(&m_validators, schema_name, validator);
11✔
767
}
11✔
768

769
ValidatorInterface *SchemaDefinitions::Lookup(const string &schema_name) const {
1✔
770
  return STLFindOrNull(m_validators, schema_name);
1✔
771
}
772

773
void SchemaDefinitions::AddToJsonObject(JsonObject *json) const {
2✔
774
  SchemaMap::const_iterator iter = m_validators.begin();
2✔
775
  for (; iter != m_validators.end(); ++iter) {
12✔
776
    JsonObject *schema = iter->second->GetSchema();
10✔
777
    json->AddValue(iter->first, schema);
10✔
778
  }
779
}
2✔
780

781
// JsonSchema
782
// -----------------------------------------------------------------------------
783
JsonSchema::JsonSchema(const std::string &schema_url,
90✔
784
                       ValidatorInterface *root_validator,
785
                       SchemaDefinitions *schema_defs)
90✔
786
    : m_schema_uri(schema_url),
90✔
787
      m_root_validator(root_validator),
90✔
788
      m_schema_defs(schema_defs) {
90✔
789
}
90✔
790

791
string JsonSchema::SchemaURI() const {
×
792
  return m_schema_uri;
×
793
}
794

795
bool JsonSchema::IsValid(const JsonValue &value) {
×
796
  value.Accept(m_root_validator.get());
×
797
  return m_root_validator->IsValid();
×
798
}
799

800
const JsonObject* JsonSchema::AsJson() const {
90✔
801
  JsonObject *json =  m_root_validator->GetSchema();
90✔
802
  if (json && m_schema_defs->HasDefinitions()) {
90✔
803
    JsonObject *definitions = json->AddObject("definitions");
2✔
804
    m_schema_defs->AddToJsonObject(definitions);
2✔
805
  }
806
  return json;
90✔
807
}
808

809
JsonSchema* JsonSchema::FromString(const string& schema_string,
306✔
810
                                   string *error) {
811
  *error = "";
306✔
812
  SchemaParser schema_parser;
306✔
813
  bool ok = JsonLexer::Parse(schema_string, &schema_parser);
306✔
814
  if (!ok || !schema_parser.IsValidSchema()) {
306✔
815
    *error = schema_parser.Error();
216✔
816
    return NULL;
216✔
817
  }
818
  return new JsonSchema("", schema_parser.ClaimRootValidator(),
90✔
819
                        schema_parser.ClaimSchemaDefs());
90✔
820
}
306✔
821
}  // namespace web
822
}  // namespace ola
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc