Parsnip
parsing library
Loading...
Searching...
No Matches
parsnip_schema.h
Go to the documentation of this file.
1
9
10#pragma once
11
12#include <config.h>
13
14#include <map>
15#include <unordered_map>
16#include <string>
17#include <set>
18#include <limits>
19#include <regex>
20
21#include "parsnip.h"
22#include "parsnip_command.h"
23
24namespace Parsnip {
25 using SchemaIntegratorCallback = std::function <void (const int, const class DictionarySchema &)>;
26
27 // Base class for schema validation components.
28 class SchemaBase {
29 friend class ListSchema;
30 protected:
31 using StringType = Data::StringType;
32 using SchemaRegex = std::basic_regex <StringType::value_type>;
33
34 bool nullable = false;
35
36 SchemaBase () = default;
37 SchemaBase (const SchemaBase &) = default;
38 SchemaBase (SchemaBase &&) = default;
39 SchemaBase &operator =(const SchemaBase &) = default;
40 SchemaBase &operator =(SchemaBase &&) = default;
41 SchemaBase (const Parsnip::Data &schema_spec);
42
47 inline void checkType (Data::Type expected, const Parsnip::Data &entry) const {
48 if (!nullable || entry.datatype != Data::Type::Null) {
49 entry.mandateType (expected);
50 }
51 }
52
56 inline bool isValidlyNull (const Parsnip::Data &entry) const {
57 return (nullable && entry.datatype == Data::Type::Null);
58 }
59
64 inline bool isType (Data::Type expected, const Parsnip::Data &entry) const {
65 return (entry.datatype == expected);
66 }
67
68 public:
71 virtual SchemaBase *createCopy () const = 0;
72 virtual ~SchemaBase() = default;
73
77 virtual void validate (const Parsnip::Data &entry) const = 0;
78
82 virtual bool operator== (const SchemaBase &other) const;
83 inline bool operator!= (const SchemaBase &other) const {
84 return !operator== (other);
85 }
86
95 virtual void mergeSchemas (const SchemaBase &from);
96
101 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_indent = false) const = 0;
102 };
103
104 /*
105 * Schema Elements
106 */
107
110 public:
111 UncheckedSchema() = default;
112 UncheckedSchema (const UncheckedSchema &) = default;
113 UncheckedSchema (UncheckedSchema &&) = default;
114 UncheckedSchema &operator= (const UncheckedSchema &) = default;
115 UncheckedSchema &operator= (UncheckedSchema &&) = default;
116 virtual UncheckedSchema *createCopy () const override;
117
118 virtual void validate (const Parsnip::Data &) const override;
119 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
120 };
121
123 class TypeSchema : public SchemaBase {
124 private:
125 Data::Type expected = Data::Type::Null;
126
127 public:
128 TypeSchema() = default;
129 TypeSchema (const TypeSchema &) = default;
130 TypeSchema (TypeSchema &&) = default;
131 TypeSchema &operator= (const TypeSchema &) = default;
132 TypeSchema &operator= (TypeSchema &&) = default;
133 TypeSchema (const Data::Type require);
134 TypeSchema (const Data::Type require, const Parsnip::Data &schema_spec);
135 virtual TypeSchema *createCopy () const override;
136
137 virtual void validate (const Parsnip::Data &entry) const override;
138 virtual bool operator== (const SchemaBase &other) const override;
139 virtual void mergeSchemas (const SchemaBase &from) override;
140 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
141 };
142
146 class StringSchema : public SchemaBase {
147 public:
148 using size_type = StringType::size_type;
149 protected:
150 size_type min_length;
151 size_type max_length;
152 public:
154 StringSchema (size_type min = 0, size_type max = std::numeric_limits<size_type>::max());
155 StringSchema (const StringSchema &) = default;
156 StringSchema (StringSchema &&) = default;
157 StringSchema &operator= (const StringSchema &) = default;
158 StringSchema &operator= (StringSchema &&) = default;
159 StringSchema (const Parsnip::Data &schema_spec);
160 virtual StringSchema *createCopy () const override;
161
162 virtual void validate (const Parsnip::Data &entry) const override;
163 virtual bool operator== (const SchemaBase &other) const override;
164 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
165 };
166
167
170 class RegExSchema : public StringSchema {
171 public:
172 using size_type = StringType::size_type;
173 private:
174 StringType expression;
175 SchemaRegex regex;
176 public:
177 RegExSchema (const StringType &express, bool case_blind = false, size_type min = 0, size_type max = std::numeric_limits<size_type>::max());
178 RegExSchema (const RegExSchema &) = default;
179 RegExSchema (RegExSchema &&) = default;
180 RegExSchema &operator= (const RegExSchema &) = default;
181 RegExSchema &operator= (RegExSchema &&) = default;
182 RegExSchema (const Parsnip::Data &schema_spec);
183 virtual RegExSchema *createCopy () const override;
184
185 virtual void validate (const Parsnip::Data &entry) const override;
186 virtual bool operator== (const SchemaBase &other) const override;
187 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
188 };
189
190
192 class KeywordSchema : public SchemaBase {
193 private:
194 std::set<StringType> valid_values;
195 bool ignore_case = true;
196 public:
197 KeywordSchema() = default;
198 KeywordSchema (const KeywordSchema &) = default;
199 KeywordSchema (KeywordSchema &&) = default;
200 KeywordSchema &operator= (const KeywordSchema &) = default;
201 KeywordSchema &operator= (KeywordSchema &&) = default;
202 KeywordSchema (const std::string &word);
203 KeywordSchema (const Parsnip::Data &schema_spec);
204 virtual KeywordSchema *createCopy () const override ;
205 void addKeyword (const std::string &word);
206 virtual void validate (const Parsnip::Data &entry) const override;
207 virtual bool operator== (const SchemaBase &other) const override;
208 virtual void mergeSchemas (const SchemaBase &from) override;
209 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
210 };
211
213 template <typename NumericType>
214 class RangeSchema : public SchemaBase {
215 public:
216 using value_type = NumericType;
217
218 private:
219 bool minimumIsInclusive = true;
220 NumericType minimum;
221 bool maximumIsInclusive = true;
222 NumericType maximum;
223
224 public:
225 RangeSchema (const NumericType min = std::numeric_limits<NumericType>::lowest(),
226 const NumericType max = std::numeric_limits<NumericType>::max());
227 RangeSchema() = default;
228 RangeSchema (const RangeSchema &) = default;
229 RangeSchema (RangeSchema &&) = default;
230 RangeSchema &operator= (const RangeSchema &) = default;
231 RangeSchema &operator= (RangeSchema &&) = default;
232 RangeSchema (const Parsnip::Data &schema_spec);
233 virtual RangeSchema *createCopy () const override;
234
235 virtual void validate (const Parsnip::Data &entry) const override;
236 virtual bool operator== (const SchemaBase &other) const override;
237 virtual void mergeSchemas (const SchemaBase &from) override;
238 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
239 };
240
241 using NumberSchema = RangeSchema <double>;
242
243 // Schema class for accepting integers.
244 class IntegerSchema : public RangeSchema <long> {
245 using range_type = RangeSchema <long>;
246 private:
247 value_type multiple = 0;
248 public:
249 using range_type::RangeSchema;
250 IntegerSchema (const Parsnip::Data &schema_spec);
251 virtual IntegerSchema *createCopy () const override;
252
253 virtual bool operator== (const SchemaBase &other) const override;
254 virtual void validate (const Parsnip::Data &entry) const override;
255 };
256
258 class OptionSchema : public SchemaBase {
259 private:
260 SchemaRef schema;
261
262 public:
264 OptionSchema() = default;
265 OptionSchema (const OptionSchema &) = default;
266 OptionSchema (OptionSchema &&) = default;
267 OptionSchema &operator= (const OptionSchema &) = default;
268 OptionSchema &operator= (OptionSchema &&) = default;
269 OptionSchema (const SchemaRef &option_schema);
270 virtual OptionSchema *createCopy () const override;
271
272 virtual void validate (const Parsnip::Data &entry) const override;
273 virtual bool operator== (const SchemaBase &other) const override;
274 virtual void mergeSchemas (const SchemaBase &from) override;
275 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
276 };
277
280 class ListSchema : public SchemaBase {
281 public:
282 using size_type = Data::ListType::size_type;
283 private:
284 SchemaBaseRef member_schema;
285 size_type minimum_required = 0;
286 size_type maximum_allowed = std::numeric_limits<int>::max();
287 bool single_as_nonlist_allowed = false;
288
289 public:
290 ListSchema() = default;
291 ListSchema (const ListSchema &from) = default;
292 ListSchema (ListSchema &&) = default;
293 ListSchema &operator= (const ListSchema &from) = default;
294 ListSchema &operator= (ListSchema &&) = default;
295 ListSchema (SchemaBaseRef &&, size_type minimum = 0, size_type maximum = std::numeric_limits<size_type>::max());
296 ListSchema (const SchemaBase &, size_type minimum = 0, size_type maximum = std::numeric_limits<size_type>::max());
297 ListSchema (const Parsnip::Data &schema_spec);
298 virtual ListSchema *createCopy () const override;
299
300 virtual void validate (const Parsnip::Data &entry) const override;
301 virtual bool operator== (const SchemaBase &other) const override;
302 virtual void mergeSchemas (const SchemaBase &from) override;
303 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
304 };
305
308 friend class ValueEvaluator;
309 friend class RemainingValuesEvaluator;
310 friend class KeywordEvaluator;
311 friend class OptionEvaluator;
312 public:
313 using Dependencies = std::set<std::string>;
314 using size_type = unsigned int;
315 static const Dependencies NoDependencies;
316 private:
317 size_type minimum_members {0};
318 size_type maximum_members = std::numeric_limits<size_type>::max();
319 protected:
321 public:
323 Dependencies expects;
324 bool mandatory = false;
325
326 bool operator== (const DictionaryMember &other) const;
327 };
328
329 enum AdditionalMemberNames { NONE, ANY, PATTERN };
330 std::map <std::string, DictionaryMember> members;
331 AdditionalMemberNames tolerance = AdditionalMemberNames::NONE;
332 SchemaRegex additional_member_regex;
333 SchemaBaseRef additional_member_schema;
334
335 public:
336 DictionarySchema() = default;
337 DictionarySchema (const DictionarySchema &) = default;
338 DictionarySchema (DictionarySchema &&) = default;
339 DictionarySchema &operator= (const DictionarySchema &) = default;
340 DictionarySchema &operator= (DictionarySchema &&) = default;
341 DictionarySchema (const Parsnip::Data &schema_spec);
342 virtual DictionarySchema *createCopy () const override;
343
344 void addMember (const char *name, const SchemaBase &schema, bool mandatory = false,
345 const Dependencies &dependencies = NoDependencies);
346 void replaceMember (const char *name, const SchemaBase &schema);
347 void removeMember (const char *name);
348
349 virtual void validate (const Parsnip::Data &entry) const override;
350 virtual bool operator== (const SchemaBase &other) const override;
351 virtual void mergeSchemas (const SchemaBase &from) override;
352 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
353 };
354
355
359 public:
360 enum class Action {
361 All,
362 Any,
363 ExactlyOne,
364 Not
365 };
366 static bool is_conjunction (const Parsnip::Data &schema_spec);
367 private:
368 static const std::unordered_map<std::string, Action> key_names;
369 std::string action_name;
370 Action action = Action::Any;
371 using ChildrenList = std::vector<SchemaBaseRef>;
372 ChildrenList children;
373 static std::string get_action_name (const Parsnip::Data &schema_spec);
374 Parsnip::Data merge_dictionaries (const Parsnip::Data &baseline, const Parsnip::Data &overrides);
375 public:
376 ConjunctionSchema (const ConjunctionSchema &) = default;
378 ConjunctionSchema &operator= (const ConjunctionSchema &) = default;
379 ConjunctionSchema &operator= (ConjunctionSchema &&) = default;
380 ConjunctionSchema (const Parsnip::Data &schema_spec);
381 virtual ConjunctionSchema *createCopy () const override;
382
383 virtual void validate (const Parsnip::Data &entry) const override;
384 virtual bool operator== (const SchemaBase &other) const override;
385 virtual std::ostream &dump (std::ostream &target, int indent, bool suppress_ident = false) const override;
386 };
387
389 class InvalidSchema : public Exception {
390 public:
391 inline InvalidSchema (const std::string &reason) : Exception ("invalid schema", reason) {};
392 };
393
394}
A meta-schema that determines if any, all, or exactly one or none of its subschemas are valid.
Definition parsnip_schema.h:358
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:1020
virtual void validate(const Parsnip::Data &entry) const override
Verify that Data matches the schema.
Definition parsnip_schema.cpp:977
static bool is_conjunction(const Parsnip::Data &schema_spec)
Checks a schema specification for a conjunction.
Definition parsnip_schema.cpp:900
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:1010
virtual ConjunctionSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:973
Generic data type.
Definition parsnip.h:81
Type
Types that may be stored in the data.
Definition parsnip.h:99
@ Null
Nothing is present.
Type datatype
Type presently stored in object.
Definition parsnip.h:117
Definition parsnip_schema.h:320
bool operator==(const DictionaryMember &other) const
Determine if two dictionary members are equivalent to each other, deep comparing the schema.
Definition parsnip_schema.cpp:607
SchemaBaseRef member_schema
Schema for this dictionary member.
Definition parsnip_schema.h:322
bool mandatory
Whether element must be present.
Definition parsnip_schema.h:324
Dependencies expects
Other elements that must be present when this one is.
Definition parsnip_schema.h:323
Schema component for validating dictionaries.
Definition parsnip_schema.h:307
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:753
void removeMember(const char *name)
Remove a member from the schema.
Definition parsnip_schema.cpp:716
virtual void validate(const Parsnip::Data &entry) const override
Validate a dictionary:
Definition parsnip_schema.cpp:764
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:820
AdditionalMemberNames tolerance
Allow unrecognized members in the dictionary?
Definition parsnip_schema.h:331
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:723
void addMember(const char *name, const SchemaBase &schema, bool mandatory=false, const Dependencies &dependencies=NoDependencies)
Add a member to a dictionary schema.
Definition parsnip_schema.cpp:696
virtual DictionarySchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:749
void replaceMember(const char *name, const SchemaBase &schema)
Replace a member in the schema, retaining original mandatory status and dependencies.
Definition parsnip_schema.cpp:710
Class representing issues related to serialization & parsing.
Definition parsnip.h:41
std::string reason
Storage for the exception explanation.
Definition parsnip.h:45
Definition parsnip_schema.h:244
virtual IntegerSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:432
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:436
virtual void validate(const Parsnip::Data &entry) const override
Validate item range: ensure the datatype falls within the allowed range.
Definition parsnip_schema.cpp:441
Parsing/command patterns produce schema inconsistency.
Definition parsnip_schema.h:389
Evaluate a keyword in a command line.
Definition parsnip_evaluate.h:244
Schema component accepting strings with certain values.
Definition parsnip_schema.h:192
virtual KeywordSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:263
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:288
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:308
virtual void validate(const Parsnip::Data &entry) const override
Validate a Keyword: ensure the datatype is a string, and that it matches one of the allowed values.
Definition parsnip_schema.cpp:295
void addKeyword(const std::string &word)
Add an additional keyword that the schema will allow.
Definition parsnip_schema.cpp:269
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:316
Schema component for lists.
Definition parsnip_schema.h:280
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:545
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:577
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:589
virtual ListSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:541
virtual void validate(const Parsnip::Data &entry) const override
Validate a list: ensure all elements conform to a single schema.
Definition parsnip_schema.cpp:555
Evaluate remainder with a different parser.
Definition parsnip_evaluate.h:315
Schema adapter component that allows use of schemas from option parsers.
Definition parsnip_schema.h:258
virtual void validate(const Parsnip::Data &entry) const override
Validate the option's schema by calling that scheme's validator.
Definition parsnip_schema.cpp:474
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:492
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:479
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:468
OptionSchema()=default
Validate a type schema: ensure the datatype is as expected.
virtual OptionSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:464
Schema component for numeric data, either Integer or Real.
Definition parsnip_schema.h:214
virtual RangeSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:341
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:386
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:394
virtual void validate(const Parsnip::Data &entry) const override
Validate item range: ensure the datatype falls within the allowed range.
Definition parsnip_schema.cpp:367
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:403
Schema component requiring data be a string of characters matching a regular expression.
Definition parsnip_schema.h:170
virtual RegExSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:224
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:249
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:243
virtual void validate(const Parsnip::Data &entry) const override
Verify that Data matches the schema.
Definition parsnip_schema.cpp:228
Gather the rest of the command line tokens in a list.
Definition parsnip_evaluate.h:302
Definition parsnip_schema.h:28
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_indent=false) const =0
Render the schema in human-friendly text.
void checkType(Data::Type expected, const Parsnip::Data &entry) const
Check that Data item is an allowed type.
Definition parsnip_schema.h:47
virtual void validate(const Parsnip::Data &entry) const =0
Verify that Data matches the schema.
virtual SchemaBase * createCopy() const =0
Create an identical, deep copy of the schema.
bool isValidlyNull(const Parsnip::Data &entry) const
Determine if the data is Null and if that is allowed.
Definition parsnip_schema.h:56
virtual void mergeSchemas(const SchemaBase &from)
Merge elements into the current schema.
Definition parsnip_schema.cpp:82
bool nullable
If true, element may be null.
Definition parsnip_schema.h:34
bool isType(Data::Type expected, const Parsnip::Data &entry) const
Check if a data object is a particular type.
Definition parsnip_schema.h:64
virtual bool operator==(const SchemaBase &other) const
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:77
Smart pointer for schemas, with unusual ability to be copied.
Definition parsnip.h:601
Schema component requiring data be a string of characters (no control characters).
Definition parsnip_schema.h:146
virtual StringSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:166
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:186
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:192
virtual void validate(const Parsnip::Data &entry) const override
Verify that Data matches the schema.
Definition parsnip_schema.cpp:170
Schema component requiring data be a particular type.
Definition parsnip_schema.h:123
virtual TypeSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:127
virtual bool operator==(const SchemaBase &other) const override
Check if two schemas perform the same validation.
Definition parsnip_schema.cpp:131
virtual void mergeSchemas(const SchemaBase &from) override
Merge elements into the current schema.
Definition parsnip_schema.cpp:136
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:143
virtual void validate(const Parsnip::Data &entry) const override
Verify that Data matches the schema.
Definition parsnip_schema.cpp:123
Schema component requiring data be a particular type.
Definition parsnip_schema.h:109
virtual std::ostream & dump(std::ostream &target, int indent, bool suppress_ident=false) const override
Render the schema in human-friendly text.
Definition parsnip_schema.cpp:102
virtual void validate(const Parsnip::Data &) const override
Construct a schema element that does no checking.
Definition parsnip_schema.cpp:94
virtual UncheckedSchema * createCopy() const override
Create an identical, deep copy of the schema.
Definition parsnip_schema.cpp:98
Evaluate a value/fill-in field.
Definition parsnip_evaluate.h:150
Serialization and parsing library.
Definition parsnip.h:38
Parsnip serialization.
Parsnip command-line parsing.