jsoncons 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. checksums.yaml +7 -0
  2. data/ext/jsoncons/extconf.rb +43 -0
  3. data/ext/jsoncons/jsoncons.cpp +161 -0
  4. data/ext/jsoncons/jsoncons.h +10 -0
  5. data/jsoncons.gemspec +44 -0
  6. data/lib/jsoncons/jsoncons/examples/input/address-book.json +13 -0
  7. data/lib/jsoncons/jsoncons/examples/input/books.json +28 -0
  8. data/lib/jsoncons/jsoncons/examples/input/countries.json +7 -0
  9. data/lib/jsoncons/jsoncons/examples/input/employees.json +30 -0
  10. data/lib/jsoncons/jsoncons/examples/input/jsonschema/name.json +15 -0
  11. data/lib/jsoncons/jsoncons/examples/input/multiple-json-objects.json +3 -0
  12. data/lib/jsoncons/jsoncons/examples/input/sales.csv +6 -0
  13. data/lib/jsoncons/jsoncons/examples/input/store.json +28 -0
  14. data/lib/jsoncons/jsoncons/examples/input/tasks.csv +6 -0
  15. data/lib/jsoncons/jsoncons/include/jsoncons/allocator_holder.hpp +38 -0
  16. data/lib/jsoncons/jsoncons/include/jsoncons/basic_json.hpp +5905 -0
  17. data/lib/jsoncons/jsoncons/include/jsoncons/bigint.hpp +1611 -0
  18. data/lib/jsoncons/jsoncons/include/jsoncons/byte_string.hpp +820 -0
  19. data/lib/jsoncons/jsoncons/include/jsoncons/config/binary_config.hpp +226 -0
  20. data/lib/jsoncons/jsoncons/include/jsoncons/config/compiler_support.hpp +375 -0
  21. data/lib/jsoncons/jsoncons/include/jsoncons/config/jsoncons_config.hpp +309 -0
  22. data/lib/jsoncons/jsoncons/include/jsoncons/config/version.hpp +40 -0
  23. data/lib/jsoncons/jsoncons/include/jsoncons/conv_error.hpp +218 -0
  24. data/lib/jsoncons/jsoncons/include/jsoncons/decode_json.hpp +209 -0
  25. data/lib/jsoncons/jsoncons/include/jsoncons/decode_traits.hpp +651 -0
  26. data/lib/jsoncons/jsoncons/include/jsoncons/detail/endian.hpp +44 -0
  27. data/lib/jsoncons/jsoncons/include/jsoncons/detail/grisu3.hpp +312 -0
  28. data/lib/jsoncons/jsoncons/include/jsoncons/detail/optional.hpp +483 -0
  29. data/lib/jsoncons/jsoncons/include/jsoncons/detail/parse_number.hpp +1133 -0
  30. data/lib/jsoncons/jsoncons/include/jsoncons/detail/span.hpp +188 -0
  31. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_view.hpp +537 -0
  32. data/lib/jsoncons/jsoncons/include/jsoncons/detail/string_wrapper.hpp +370 -0
  33. data/lib/jsoncons/jsoncons/include/jsoncons/detail/write_number.hpp +567 -0
  34. data/lib/jsoncons/jsoncons/include/jsoncons/encode_json.hpp +315 -0
  35. data/lib/jsoncons/jsoncons/include/jsoncons/encode_traits.hpp +378 -0
  36. data/lib/jsoncons/jsoncons/include/jsoncons/json.hpp +18 -0
  37. data/lib/jsoncons/jsoncons/include/jsoncons/json_array.hpp +324 -0
  38. data/lib/jsoncons/jsoncons/include/jsoncons/json_content_handler.hpp +12 -0
  39. data/lib/jsoncons/jsoncons/include/jsoncons/json_cursor.hpp +448 -0
  40. data/lib/jsoncons/jsoncons/include/jsoncons/json_decoder.hpp +420 -0
  41. data/lib/jsoncons/jsoncons/include/jsoncons/json_encoder.hpp +1587 -0
  42. data/lib/jsoncons/jsoncons/include/jsoncons/json_error.hpp +156 -0
  43. data/lib/jsoncons/jsoncons/include/jsoncons/json_exception.hpp +241 -0
  44. data/lib/jsoncons/jsoncons/include/jsoncons/json_filter.hpp +653 -0
  45. data/lib/jsoncons/jsoncons/include/jsoncons/json_fwd.hpp +23 -0
  46. data/lib/jsoncons/jsoncons/include/jsoncons/json_object.hpp +1772 -0
  47. data/lib/jsoncons/jsoncons/include/jsoncons/json_options.hpp +862 -0
  48. data/lib/jsoncons/jsoncons/include/jsoncons/json_parser.hpp +2900 -0
  49. data/lib/jsoncons/jsoncons/include/jsoncons/json_reader.hpp +731 -0
  50. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros.hpp +1072 -0
  51. data/lib/jsoncons/jsoncons/include/jsoncons/json_traits_macros_deprecated.hpp +144 -0
  52. data/lib/jsoncons/jsoncons/include/jsoncons/json_type.hpp +206 -0
  53. data/lib/jsoncons/jsoncons/include/jsoncons/json_type_traits.hpp +1830 -0
  54. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor.hpp +1560 -0
  55. data/lib/jsoncons/jsoncons/include/jsoncons/json_visitor2.hpp +2079 -0
  56. data/lib/jsoncons/jsoncons/include/jsoncons/pretty_print.hpp +89 -0
  57. data/lib/jsoncons/jsoncons/include/jsoncons/ser_context.hpp +62 -0
  58. data/lib/jsoncons/jsoncons/include/jsoncons/sink.hpp +289 -0
  59. data/lib/jsoncons/jsoncons/include/jsoncons/source.hpp +777 -0
  60. data/lib/jsoncons/jsoncons/include/jsoncons/source_adaptor.hpp +148 -0
  61. data/lib/jsoncons/jsoncons/include/jsoncons/staj2_cursor.hpp +1189 -0
  62. data/lib/jsoncons/jsoncons/include/jsoncons/staj_cursor.hpp +1254 -0
  63. data/lib/jsoncons/jsoncons/include/jsoncons/staj_iterator.hpp +449 -0
  64. data/lib/jsoncons/jsoncons/include/jsoncons/tag_type.hpp +245 -0
  65. data/lib/jsoncons/jsoncons/include/jsoncons/text_source_adaptor.hpp +144 -0
  66. data/lib/jsoncons/jsoncons/include/jsoncons/traits_extension.hpp +884 -0
  67. data/lib/jsoncons/jsoncons/include/jsoncons/typed_array_view.hpp +250 -0
  68. data/lib/jsoncons/jsoncons/include/jsoncons/unicode_traits.hpp +1330 -0
  69. data/lib/jsoncons/jsoncons/include/jsoncons/uri.hpp +635 -0
  70. data/lib/jsoncons/jsoncons/include/jsoncons/value_converter.hpp +340 -0
  71. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson.hpp +23 -0
  72. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_cursor.hpp +320 -0
  73. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_decimal128.hpp +865 -0
  74. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_encoder.hpp +585 -0
  75. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_error.hpp +103 -0
  76. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_oid.hpp +245 -0
  77. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_options.hpp +75 -0
  78. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_parser.hpp +645 -0
  79. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_reader.hpp +92 -0
  80. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/bson_type.hpp +44 -0
  81. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/decode_bson.hpp +201 -0
  82. data/lib/jsoncons/jsoncons/include/jsoncons_ext/bson/encode_bson.hpp +144 -0
  83. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor.hpp +26 -0
  84. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor.hpp +351 -0
  85. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_cursor2.hpp +265 -0
  86. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_detail.hpp +93 -0
  87. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_encoder.hpp +1766 -0
  88. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_error.hpp +105 -0
  89. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_options.hpp +113 -0
  90. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_parser.hpp +1942 -0
  91. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/cbor_reader.hpp +116 -0
  92. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/decode_cbor.hpp +203 -0
  93. data/lib/jsoncons/jsoncons/include/jsoncons_ext/cbor/encode_cbor.hpp +151 -0
  94. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv.hpp +17 -0
  95. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_cursor.hpp +358 -0
  96. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_encoder.hpp +954 -0
  97. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_error.hpp +85 -0
  98. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_options.hpp +973 -0
  99. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_parser.hpp +2099 -0
  100. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_reader.hpp +348 -0
  101. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/csv_serializer.hpp +12 -0
  102. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/decode_csv.hpp +208 -0
  103. data/lib/jsoncons/jsoncons/include/jsoncons_ext/csv/encode_csv.hpp +122 -0
  104. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath.hpp +5215 -0
  105. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jmespath/jmespath_error.hpp +215 -0
  106. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch.hpp +579 -0
  107. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpatch/jsonpatch_error.hpp +121 -0
  108. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/expression.hpp +3329 -0
  109. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/flatten.hpp +432 -0
  110. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_location.hpp +445 -0
  111. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/json_query.hpp +115 -0
  112. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath.hpp +13 -0
  113. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_error.hpp +240 -0
  114. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_expression.hpp +2612 -0
  115. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpath/jsonpath_selector.hpp +1322 -0
  116. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer.hpp +1577 -0
  117. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonpointer/jsonpointer_error.hpp +119 -0
  118. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/format_validator.hpp +968 -0
  119. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/json_validator.hpp +120 -0
  120. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema.hpp +13 -0
  121. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_error.hpp +105 -0
  122. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/jsonschema_version.hpp +18 -0
  123. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator.hpp +1745 -0
  124. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/keyword_validator_factory.hpp +556 -0
  125. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_draft7.hpp +198 -0
  126. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_location.hpp +200 -0
  127. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/schema_version.hpp +35 -0
  128. data/lib/jsoncons/jsoncons/include/jsoncons_ext/jsonschema/subschema.hpp +144 -0
  129. data/lib/jsoncons/jsoncons/include/jsoncons_ext/mergepatch/mergepatch.hpp +103 -0
  130. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/decode_msgpack.hpp +202 -0
  131. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/encode_msgpack.hpp +142 -0
  132. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack.hpp +24 -0
  133. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor.hpp +343 -0
  134. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_cursor2.hpp +259 -0
  135. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_encoder.hpp +753 -0
  136. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_error.hpp +94 -0
  137. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_options.hpp +74 -0
  138. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_parser.hpp +748 -0
  139. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_reader.hpp +116 -0
  140. data/lib/jsoncons/jsoncons/include/jsoncons_ext/msgpack/msgpack_type.hpp +63 -0
  141. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/decode_ubjson.hpp +201 -0
  142. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/encode_ubjson.hpp +142 -0
  143. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson.hpp +23 -0
  144. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_cursor.hpp +307 -0
  145. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_encoder.hpp +502 -0
  146. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_error.hpp +100 -0
  147. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_options.hpp +87 -0
  148. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_parser.hpp +880 -0
  149. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_reader.hpp +92 -0
  150. data/lib/jsoncons/jsoncons/include/jsoncons_ext/ubjson/ubjson_type.hpp +43 -0
  151. data/lib/jsoncons/version.rb +5 -0
  152. data/lib/jsoncons.rb +33 -0
  153. data/test/jsoncons_test.rb +108 -0
  154. data/test/test_helper.rb +7 -0
  155. metadata +268 -0
@@ -0,0 +1,968 @@
1
+ // Copyright 2020 Daniel Parker
2
+ // Distributed under the Boost license, Version 1.0.
3
+ // (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
4
+
5
+ // See https://github.com/danielaparker/jsoncons for latest version
6
+
7
+ #ifndef JSONCONS_JSONSCHEMA_FORMAT_VALIDATOR_HPP
8
+ #define JSONCONS_JSONSCHEMA_FORMAT_VALIDATOR_HPP
9
+
10
+ #include <jsoncons/config/jsoncons_config.hpp>
11
+ #include <jsoncons/uri.hpp>
12
+ #include <jsoncons/json.hpp>
13
+ #include <jsoncons_ext/jsonpointer/jsonpointer.hpp>
14
+ #include <jsoncons_ext/jsonschema/subschema.hpp>
15
+ #include <cassert>
16
+ #include <set>
17
+ #include <sstream>
18
+ #include <iostream>
19
+ #include <cassert>
20
+ #if defined(JSONCONS_HAS_STD_REGEX)
21
+ #include <regex>
22
+ #endif
23
+
24
+ namespace jsoncons {
25
+ namespace jsonschema {
26
+
27
+ inline
28
+ bool is_atext( char c)
29
+ {
30
+ switch (c)
31
+ {
32
+ case '!':
33
+ case '#':
34
+ case '$':
35
+ case '%':
36
+ case '&':
37
+ case '\'':
38
+ case '*':
39
+ case '+':
40
+ case '-':
41
+ case '/':
42
+ case '=':
43
+ case '?':
44
+ case '^':
45
+ case '_':
46
+ case '`':
47
+ case '{':
48
+ case '|':
49
+ case '}':
50
+ case '~':
51
+ return true;
52
+ default:
53
+ return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z');
54
+ }
55
+ }
56
+
57
+ inline
58
+ bool is_dtext( char c)
59
+ {
60
+ return (c >= 33 && c <= 90) || (c >= 94 && c <= 126);
61
+ }
62
+
63
+ // RFC 5322, section 3.4.1
64
+ inline
65
+ bool validate_email_rfc5322(const std::string& s)
66
+ {
67
+ enum class state_t {local_part,atom,dot_atom,quoted_string,amp,domain};
68
+
69
+ state_t state = state_t::local_part;
70
+ std::size_t part_length = 0;
71
+
72
+ for (char c : s)
73
+ {
74
+ switch (state)
75
+ {
76
+ case state_t::local_part:
77
+ {
78
+ if (is_atext(c))
79
+ {
80
+ state = state_t::atom;
81
+ }
82
+ else if (c == '"')
83
+ {
84
+ state = state_t::quoted_string;
85
+ }
86
+ else
87
+ {
88
+ return false;
89
+ }
90
+ break;
91
+ }
92
+ case state_t::dot_atom:
93
+ {
94
+ if (is_atext(c))
95
+ {
96
+ ++part_length;
97
+ state = state_t::atom;
98
+ }
99
+ else
100
+ return false;
101
+ break;
102
+ }
103
+ case state_t::atom:
104
+ {
105
+ switch (c)
106
+ {
107
+ case '@':
108
+ state = state_t::domain;
109
+ part_length = 0;
110
+ break;
111
+ case '.':
112
+ state = state_t::dot_atom;
113
+ ++part_length;
114
+ break;
115
+ default:
116
+ if (is_atext(c))
117
+ ++part_length;
118
+ else
119
+ return false;
120
+ break;
121
+ }
122
+ break;
123
+ }
124
+ case state_t::quoted_string:
125
+ {
126
+ if (c == '\"')
127
+ {
128
+ state = state_t::amp;
129
+ }
130
+ else
131
+ {
132
+ ++part_length;
133
+ }
134
+ break;
135
+ }
136
+ case state_t::amp:
137
+ {
138
+ if (c == '@')
139
+ {
140
+ state = state_t::domain;
141
+ part_length = 0;
142
+ }
143
+ else
144
+ {
145
+ return false;
146
+ }
147
+ break;
148
+ }
149
+ case state_t::domain:
150
+ {
151
+ if (is_dtext(c))
152
+ {
153
+ ++part_length;
154
+ }
155
+ else
156
+ {
157
+ return false;
158
+ }
159
+ break;
160
+ }
161
+ }
162
+ }
163
+
164
+ return state == state_t::domain && part_length > 0;
165
+ }
166
+
167
+ // RFC 2673, Section 3.2
168
+
169
+ inline
170
+ bool validate_ipv6_rfc2373(const std::string& s)
171
+ {
172
+ enum class state_t{start,expect_hexdig_or_unspecified,
173
+ hexdig, decdig,expect_unspecified, unspecified};
174
+
175
+ state_t state = state_t::start;
176
+
177
+ std::size_t digit_count = 0;
178
+ std::size_t piece_count = 0;
179
+ std::size_t piece_count2 = 0;
180
+ bool has_unspecified = false;
181
+ std::size_t dec_value = 0;
182
+
183
+ for (std::size_t i = 0; i < s.length(); ++i)
184
+ {
185
+ char c = s[i];
186
+ switch (state)
187
+ {
188
+ case state_t::start:
189
+ {
190
+ switch (c)
191
+ {
192
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
193
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
194
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
195
+ state = state_t::hexdig;
196
+ ++digit_count;
197
+ piece_count = 0;
198
+ break;
199
+ case ':':
200
+ if (!has_unspecified)
201
+ {
202
+ state = state_t::expect_unspecified;
203
+ }
204
+ else
205
+ {
206
+ return false;
207
+ }
208
+ break;
209
+ default:
210
+ return false;
211
+ }
212
+ break;
213
+ }
214
+ case state_t::expect_hexdig_or_unspecified:
215
+ {
216
+ switch (c)
217
+ {
218
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
219
+ dec_value = dec_value*10 + static_cast<std::size_t>(c - '0'); // just in case this piece is followed by a dot
220
+ state = state_t::hexdig;
221
+ ++digit_count;
222
+ break;
223
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
224
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
225
+ state = state_t::hexdig;
226
+ ++digit_count;
227
+ break;
228
+ case ':':
229
+ if (!has_unspecified)
230
+ {
231
+ has_unspecified = true;
232
+ state = state_t::unspecified;
233
+ }
234
+ else
235
+ {
236
+ return false;
237
+ }
238
+ break;
239
+ default:
240
+ return false;
241
+ }
242
+ break;
243
+ }
244
+ case state_t::expect_unspecified:
245
+ {
246
+ if (c == ':')
247
+ {
248
+ has_unspecified = true;
249
+ state = state_t::unspecified;
250
+ }
251
+ else
252
+ {
253
+ return false;
254
+ }
255
+ break;
256
+ }
257
+ case state_t::hexdig:
258
+ {
259
+ switch (c)
260
+ {
261
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
262
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
263
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
264
+ ++digit_count;
265
+ break;
266
+ case ':':
267
+ if (digit_count <= 4)
268
+ {
269
+ ++piece_count;
270
+ digit_count = 0;
271
+ dec_value = 0;
272
+ state = state_t::expect_hexdig_or_unspecified;
273
+ }
274
+ else
275
+ {
276
+ return false;
277
+ }
278
+ break;
279
+ case '.':
280
+ if (piece_count == 6 || has_unspecified)
281
+ {
282
+ ++piece_count2;
283
+ state = state_t::decdig;
284
+ dec_value = 0;
285
+ }
286
+ else
287
+ {
288
+ return false;
289
+ }
290
+ break;
291
+ default:
292
+ return false;
293
+ }
294
+ break;
295
+ }
296
+ case state_t::decdig:
297
+ {
298
+ switch (c)
299
+ {
300
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
301
+ dec_value = dec_value*10 + static_cast<std::size_t>(c - '0');
302
+ ++digit_count;
303
+ break;
304
+ case '.':
305
+ if (dec_value > 0xff)
306
+ {
307
+ return false;
308
+ }
309
+ digit_count = 0;
310
+ dec_value = 0;
311
+ ++piece_count2;
312
+ break;
313
+ default:
314
+ return false;
315
+ }
316
+ break;
317
+ }
318
+ case state_t::unspecified:
319
+ {
320
+ switch (c)
321
+ {
322
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
323
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
324
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
325
+ state = state_t::hexdig;
326
+ ++digit_count;
327
+ break;
328
+ default:
329
+ return false;
330
+ }
331
+ break;
332
+ }
333
+ default:
334
+ return false;
335
+ }
336
+ }
337
+
338
+ switch (state)
339
+ {
340
+ case state_t::unspecified:
341
+ return piece_count <= 8;
342
+ case state_t::hexdig:
343
+ if (digit_count <= 4)
344
+ {
345
+ ++piece_count;
346
+ return digit_count > 0 && (piece_count == 8 || (has_unspecified && piece_count <= 8));
347
+ }
348
+ else
349
+ {
350
+ return false;
351
+ }
352
+ case state_t::decdig:
353
+ ++piece_count2;
354
+ if (dec_value > 0xff)
355
+ {
356
+ return false;
357
+ }
358
+ return digit_count > 0 && piece_count2 == 4;
359
+ default:
360
+ return false;
361
+ }
362
+ }
363
+
364
+ // RFC 2673, Section 3.2
365
+
366
+ inline
367
+ bool validate_ipv4_rfc2673(const std::string& s)
368
+ {
369
+ enum class state_t {expect_indicator_or_dotted_quad,decbyte,
370
+ bindig, octdig, hexdig};
371
+
372
+ state_t state = state_t::expect_indicator_or_dotted_quad;
373
+
374
+ std::size_t digit_count = 0;
375
+ std::size_t decbyte_count = 0;
376
+ std::size_t value = 0;
377
+
378
+ for (std::size_t i = 0; i < s.length(); ++i)
379
+ {
380
+ char c = s[i];
381
+ switch (state)
382
+ {
383
+ case state_t::expect_indicator_or_dotted_quad:
384
+ {
385
+ switch (c)
386
+ {
387
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
388
+ state = state_t::decbyte;
389
+ decbyte_count = 0;
390
+ digit_count = 1;
391
+ value = 0;
392
+ break;
393
+ case 'b':
394
+ state = state_t::bindig;
395
+ digit_count = 0;
396
+ break;
397
+ case 'o':
398
+ state = state_t::octdig;
399
+ digit_count = 0;
400
+ break;
401
+ case 'x':
402
+ state = state_t::hexdig;
403
+ digit_count = 0;
404
+ break;
405
+ default:
406
+ return false;
407
+ }
408
+ break;
409
+ }
410
+ case state_t::bindig:
411
+ {
412
+ if (digit_count >= 256)
413
+ {
414
+ return false;
415
+ }
416
+ switch (c)
417
+ {
418
+ case '0':case '1':
419
+ ++digit_count;
420
+ break;
421
+ default:
422
+ return false;
423
+ }
424
+ break;
425
+ }
426
+ case state_t::octdig:
427
+ {
428
+ if (digit_count >= 86)
429
+ {
430
+ return false;
431
+ }
432
+ switch (c)
433
+ {
434
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':
435
+ ++digit_count;
436
+ break;
437
+ default:
438
+ return false;
439
+ }
440
+ break;
441
+ }
442
+ case state_t::hexdig:
443
+ {
444
+ if (digit_count >= 64)
445
+ {
446
+ return false;
447
+ }
448
+ switch (c)
449
+ {
450
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
451
+ case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':
452
+ case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':
453
+ ++digit_count;
454
+ break;
455
+ default:
456
+ return false;
457
+ }
458
+ break;
459
+ }
460
+ case state_t::decbyte:
461
+ {
462
+ if (decbyte_count >= 4)
463
+ {
464
+ return false;
465
+ }
466
+ switch (c)
467
+ {
468
+ case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8': case '9':
469
+ {
470
+ if (digit_count >= 3)
471
+ {
472
+ return false;
473
+ }
474
+ ++digit_count;
475
+ value = value*10 + static_cast<std::size_t>(c - '0');
476
+ if (value > 255)
477
+ {
478
+ return false;
479
+ }
480
+ break;
481
+ }
482
+ case '.':
483
+ if (decbyte_count > 3)
484
+ {
485
+ return false;
486
+ }
487
+ ++decbyte_count;
488
+ digit_count = 0;
489
+ value = 0;
490
+ break;
491
+ default:
492
+ return false;
493
+ }
494
+ break;
495
+ }
496
+ default:
497
+ return false;
498
+ }
499
+ }
500
+
501
+ switch (state)
502
+ {
503
+ case state_t::decbyte:
504
+ if (digit_count > 0)
505
+ {
506
+ ++decbyte_count;
507
+ }
508
+ else
509
+ {
510
+ return false;
511
+ }
512
+ return (decbyte_count == 4) ? true : false;
513
+ case state_t::bindig:
514
+ return digit_count > 0 ? true : false;
515
+ case state_t::octdig:
516
+ return digit_count > 0 ? true : false;
517
+ case state_t::hexdig:
518
+ return digit_count > 0 ? true : false;
519
+ default:
520
+ return false;
521
+ }
522
+ }
523
+
524
+ // RFC 1034, Section 3.1
525
+ inline
526
+ bool validate_hostname_rfc1034(const std::string& hostname)
527
+ {
528
+ enum class state_t {start_label,expect_letter_or_digit_or_hyphen_or_dot};
529
+
530
+ state_t state = state_t::start_label;
531
+ std::size_t length = hostname.length() - 1;
532
+ std::size_t label_length = 0;
533
+
534
+ for (std::size_t i = 0; i < length; ++i)
535
+ {
536
+ char c = hostname[i];
537
+ switch (state)
538
+ {
539
+ case state_t::start_label:
540
+ {
541
+ if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
542
+ {
543
+ ++label_length;
544
+ state = state_t::expect_letter_or_digit_or_hyphen_or_dot;
545
+ }
546
+ else
547
+ {
548
+ return false;
549
+ }
550
+ break;
551
+ }
552
+ case state_t::expect_letter_or_digit_or_hyphen_or_dot:
553
+ {
554
+ if (c == '.')
555
+ {
556
+ label_length = 0;
557
+ state = state_t::start_label;
558
+ }
559
+ else if (!((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ||
560
+ (c >= '0' && c < '9') || c == '-'))
561
+ {
562
+ return false;
563
+ }
564
+ if (++label_length > 63)
565
+ {
566
+ return false;
567
+ }
568
+ break;
569
+ }
570
+ }
571
+ }
572
+
573
+ char last = hostname.back();
574
+ if (!((last >= 'a' && last <= 'z') || (last >= 'A' && last <= 'Z') || (last >= '0' && last < '9')))
575
+ {
576
+ return false;
577
+ }
578
+ return true;
579
+ }
580
+
581
+ inline
582
+ bool is_leap_year(std::size_t year)
583
+ {
584
+ return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
585
+ }
586
+
587
+ inline
588
+ std::size_t days_in_month(std::size_t year, std::size_t month)
589
+ {
590
+ switch (month)
591
+ {
592
+ case 1: return 31;
593
+ case 2: return is_leap_year(year) ? 29 : 28;
594
+ case 3: return 31;
595
+ case 4: return 30;
596
+ case 5: return 31;
597
+ case 6: return 30;
598
+ case 7: return 31;
599
+ case 8: return 31;
600
+ case 9: return 30;
601
+ case 10: return 31;
602
+ case 11: return 30;
603
+ case 12: return 31;
604
+ default:
605
+ JSONCONS_UNREACHABLE();
606
+ break;
607
+ }
608
+ }
609
+
610
+ enum class date_time_type {date_time,date,time};
611
+ // RFC 3339, Section 5.6
612
+ inline
613
+ bool validate_date_time_rfc3339(const std::string& s, date_time_type type)
614
+ {
615
+ enum class state_t {fullyear,month,mday,hour,minute,second,secfrac,z,offset_hour,offset_minute};
616
+
617
+ std::size_t piece_length = 0;
618
+ std::size_t year = 0;
619
+ std::size_t month = 0;
620
+ std::size_t mday = 0;
621
+ std::size_t value = 0;
622
+ state_t state = (type == date_time_type::time) ? state_t::hour : state_t::fullyear;
623
+
624
+ for (char c : s)
625
+ {
626
+ switch (state)
627
+ {
628
+ case state_t::fullyear:
629
+ {
630
+ if (piece_length < 4 && (c >= '0' && c <= '9'))
631
+ {
632
+ piece_length++;
633
+ year = year*10 + static_cast<std::size_t>(c - '0');
634
+ }
635
+ else if (c == '-' && piece_length == 4)
636
+ {
637
+ state = state_t::month;
638
+ piece_length = 0;
639
+ }
640
+ else
641
+ {
642
+ return false;
643
+ }
644
+ break;
645
+ }
646
+ case state_t::month:
647
+ {
648
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
649
+ {
650
+ piece_length++;
651
+ month = month*10 + static_cast<std::size_t>(c - '0');
652
+ }
653
+ else if (c == '-' && piece_length == 2 && (month >=1 && month <= 12))
654
+ {
655
+ state = state_t::mday;
656
+ piece_length = 0;
657
+ }
658
+ else
659
+ {
660
+ return false;
661
+ }
662
+ break;
663
+ }
664
+ case state_t::mday:
665
+ {
666
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
667
+ {
668
+ piece_length++;
669
+ mday = mday *10 + static_cast<std::size_t>(c - '0');
670
+ }
671
+ else if ((c == 'T' || c == 't') && piece_length == 2 && (mday <= days_in_month(year, month)))
672
+ {
673
+ piece_length = 0;
674
+ state = state_t::hour;
675
+ }
676
+ else
677
+ {
678
+ return false;
679
+ }
680
+ break;
681
+ }
682
+ case state_t::hour:
683
+ {
684
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
685
+ {
686
+ piece_length++;
687
+ value = value*10 + static_cast<std::size_t>(c - '0');
688
+ }
689
+ else if (c == ':' && piece_length == 2 && (/*value >=0 && */ value <= 23))
690
+ {
691
+ state = state_t::minute;
692
+ value = 0;
693
+ piece_length = 0;
694
+ }
695
+ else
696
+ {
697
+ return false;
698
+ }
699
+ break;
700
+ }
701
+ case state_t::minute:
702
+ {
703
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
704
+ {
705
+ piece_length++;
706
+ value = value*10 + static_cast<std::size_t>(c - '0');
707
+ }
708
+ else if (c == ':' && piece_length == 2 && (/*value >=0 && */value <= 59))
709
+ {
710
+ state = state_t::second;
711
+ value = 0;
712
+ piece_length = 0;
713
+ }
714
+ else
715
+ {
716
+ return false;
717
+ }
718
+ break;
719
+ }
720
+ case state_t::second:
721
+ {
722
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
723
+ {
724
+ piece_length++;
725
+ value = value*10 + static_cast<std::size_t>(c - '0');
726
+ }
727
+ else if (piece_length == 2 && (/*value >=0 && */value <= 60)) // 00-58, 00-59, 00-60 based on leap second rules
728
+ {
729
+ switch (c)
730
+ {
731
+ case '.':
732
+ value = 0;
733
+ state = state_t::secfrac;
734
+ break;
735
+ case '+':
736
+ case '-':
737
+ value = 0;
738
+ piece_length = 0;
739
+ state = state_t::offset_hour;
740
+ break;
741
+ case 'Z':
742
+ case 'z':
743
+ state = state_t::z;
744
+ break;
745
+ default:
746
+ return false;
747
+ }
748
+ }
749
+ else
750
+ {
751
+ return false;
752
+ }
753
+ break;
754
+ }
755
+ case state_t::secfrac:
756
+ {
757
+ if (c >= '0' && c <= '9')
758
+ {
759
+ value = value*10 + static_cast<std::size_t>(c - '0');
760
+ }
761
+ else
762
+ {
763
+ switch (c)
764
+ {
765
+ case '+':
766
+ case '-':
767
+ value = 0;
768
+ piece_length = 0;
769
+ state = state_t::offset_hour;
770
+ break;
771
+ case 'Z':
772
+ case 'z':
773
+ state = state_t::z;
774
+ break;
775
+ default:
776
+ return false;
777
+ }
778
+ }
779
+ break;
780
+ }
781
+ case state_t::offset_hour:
782
+ {
783
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
784
+ {
785
+ piece_length++;
786
+ value = value*10 + static_cast<std::size_t>(c - '0');
787
+ }
788
+ else if (c == ':' && piece_length == 2 && (/*value >=0 && */value <= 23))
789
+ {
790
+ value = 0;
791
+ piece_length = 0;
792
+ state = state_t::offset_minute;
793
+ }
794
+ else
795
+ {
796
+ return false;
797
+ }
798
+ break;
799
+ }
800
+ case state_t::offset_minute:
801
+ {
802
+ if (piece_length < 2 && (c >= '0' && c <= '9'))
803
+ {
804
+ piece_length++;
805
+ value = value*10 + static_cast<std::size_t>(c - '0');
806
+ }
807
+ else if (c == ':' && piece_length == 2 && (/*value >=0 && */value <= 59))
808
+ {
809
+ value = 0;
810
+ piece_length = 0;
811
+ }
812
+ else
813
+ {
814
+ return false;
815
+ }
816
+ break;
817
+ }
818
+ case state_t::z:
819
+ return false;
820
+ }
821
+ }
822
+
823
+ if (type == date_time_type::date)
824
+ {
825
+ return state == state_t::mday && piece_length == 2 && (mday >= 1 && mday <= days_in_month(year, month));
826
+ }
827
+ else
828
+ {
829
+ return state == state_t::offset_minute || state == state_t::z || state == state_t::secfrac;
830
+ }
831
+ }
832
+
833
+ // format checkers
834
+ using format_checker = std::function<void(const std::string& absolute_keyword_location,
835
+ const jsonpointer::json_pointer& instance_location,
836
+ const std::string&,
837
+ error_reporter& reporter)>;
838
+
839
+ inline
840
+ void rfc3339_date_check(const std::string& absolute_keyword_location,
841
+ const jsonpointer::json_pointer& instance_location,
842
+ const std::string& value,
843
+ error_reporter& reporter)
844
+ {
845
+ if (!validate_date_time_rfc3339(value,date_time_type::date))
846
+ {
847
+ reporter.error(validation_output("date",
848
+ absolute_keyword_location,
849
+ instance_location.to_uri_fragment(),
850
+ "\"" + value + "\" is not a RFC 3339 date string"));
851
+ }
852
+ }
853
+
854
+ inline
855
+ void rfc3339_time_check(const std::string& absolute_keyword_location,
856
+ const jsonpointer::json_pointer& instance_location,
857
+ const std::string &value,
858
+ error_reporter& reporter)
859
+ {
860
+ if (!validate_date_time_rfc3339(value, date_time_type::time))
861
+ {
862
+ reporter.error(validation_output("time",
863
+ absolute_keyword_location,
864
+ instance_location.to_uri_fragment(),
865
+ "\"" + value + "\" is not a RFC 3339 time string"));
866
+ }
867
+ }
868
+
869
+ inline
870
+ void rfc3339_date_time_check(const std::string& absolute_keyword_location,
871
+ const jsonpointer::json_pointer& instance_location,
872
+ const std::string &value,
873
+ error_reporter& reporter)
874
+ {
875
+ if (!validate_date_time_rfc3339(value, date_time_type::date_time))
876
+ {
877
+ reporter.error(validation_output("date-time",
878
+ absolute_keyword_location,
879
+ instance_location.to_uri_fragment(),
880
+ "\"" + value + "\" is not a RFC 3339 date-time string"));
881
+ }
882
+ }
883
+
884
+ inline
885
+ void email_check(const std::string& absolute_keyword_location,
886
+ const jsonpointer::json_pointer& instance_location,
887
+ const std::string& value,
888
+ error_reporter& reporter)
889
+ {
890
+ if (!validate_email_rfc5322(value))
891
+ {
892
+ reporter.error(validation_output("email",
893
+ absolute_keyword_location,
894
+ instance_location.to_uri_fragment(),
895
+ "\"" + value + "\" is not a valid email address as defined by RFC 5322"));
896
+ }
897
+ }
898
+
899
+ inline
900
+ void hostname_check(const std::string& absolute_keyword_location,
901
+ const jsonpointer::json_pointer& instance_location,
902
+ const std::string& value,
903
+ error_reporter& reporter)
904
+ {
905
+ if (!validate_hostname_rfc1034(value))
906
+ {
907
+ reporter.error(validation_output("hostname",
908
+ absolute_keyword_location,
909
+ instance_location.to_uri_fragment(),
910
+ "\"" + value + "\" is not a valid hostname as defined by RFC 3986 Appendix A"));
911
+ }
912
+ }
913
+
914
+ inline
915
+ void ipv4_check(const std::string& absolute_keyword_location,
916
+ const jsonpointer::json_pointer& instance_location,
917
+ const std::string& value,
918
+ error_reporter& reporter)
919
+ {
920
+ if (!validate_ipv4_rfc2673(value))
921
+ {
922
+ reporter.error(validation_output("ipv4",
923
+ absolute_keyword_location,
924
+ instance_location.to_uri_fragment(),
925
+ "\"" + value + "\" is not a valid IPv4 address as defined by RFC 2673"));
926
+ }
927
+ }
928
+
929
+ inline
930
+ void ipv6_check(const std::string& absolute_keyword_location,
931
+ const jsonpointer::json_pointer& instance_location,
932
+ const std::string& value,
933
+ error_reporter& reporter)
934
+ {
935
+ if (!validate_ipv6_rfc2373(value))
936
+ {
937
+ reporter.error(validation_output("ipv6",
938
+ absolute_keyword_location,
939
+ instance_location.to_uri_fragment(),
940
+ "\"" + value + "\" is not a valid IPv6 address as defined by RFC 2373"));
941
+ }
942
+ }
943
+
944
+ inline
945
+ void regex_check(const std::string& absolute_keyword_location,
946
+ const jsonpointer::json_pointer& instance_location,
947
+ const std::string& value,
948
+ error_reporter& reporter)
949
+ {
950
+ #if defined(JSONCONS_HAS_STD_REGEX)
951
+ try
952
+ {
953
+ std::regex re(value, std::regex::ECMAScript);
954
+ }
955
+ catch (const std::exception& e)
956
+ {
957
+ reporter.error(validation_output("pattern",
958
+ absolute_keyword_location,
959
+ instance_location.to_uri_fragment(),
960
+ "\"" + value + "\" is not a valid ECMAScript regular expression. " + e.what()));
961
+ }
962
+ #endif
963
+ }
964
+
965
+ } // namespace jsonschema
966
+ } // namespace jsoncons
967
+
968
+ #endif // JSONCONS_JSONSCHEMA_FORMAT_CHECKERS_HPP