50 constexpr static double kNaN = std::numeric_limits<double>::quiet_NaN();
69 require(is_object(result) || is_array(result),
"object or array");
75 if (!is_structural_char(
'{'))
79 if (is_string(
string)) {
80 require(is_structural_char(
':'),
":");
82 require(is_value(value),
"value");
83 T::move_append(
object,
string, value);
85 while (is_structural_char(
',')) {
86 require(is_string(
string),
"string");
87 require(is_structural_char(
':'),
":");
88 require(is_value(value),
"value");
89 T::move_append(
object,
string, value);
92 require(is_structural_char(
'}'),
"}");
98 if (!is_structural_char(
'['))
102 if (is_value(value)) {
103 T::move_append(
array, value);
104 while (is_structural_char(
',')) {
105 require(is_value(value),
"value");
106 T::move_append(
array, value);
109 require(is_structural_char(
']'),
"]");
117 return is_string(t) || is_number(t) || is_object(t) || is_array(t) || is_bool(t) ||
123 bool is_sequence(
const char* p) {
129 require(*p == 0,
"valid constant");
134 if (is_sequence(
"true")) {
138 if (is_sequence(
"false")) {
146 if (!is_sequence(
"null"))
152 template <
typename S>
153 bool is_string(S& s) {
156 while (!is_char(
'"')) {
158 while (!(
'\x00' <= *p_ && *p_ <
'\x20') && *p_ !=
'"' && *p_ !=
'\\')
160 require(!(
'\x00' <= *p_ && *p_ <
'\x20'),
"valid character");
164 char c = escape()[
static_cast<unsigned char>(*p_++)];
165 require(c,
"valid escape character");
167 std::uint32_t utf = get_four_digits();
169 if (0xD800 <= utf && utf <= 0xDBFF) {
170 require(is_char(
'u'),
"trail surrogate");
171 std::uint32_t trailing = get_four_digits();
172 require(0xDC00 <= trailing && trailing <= 0xDFFF,
"trail surrogate");
173 utf = ((utf - 0xD800) << 10) + (trailing - 0xDC00);
176 auto end = utf8(utf, buffer);
177 T::append(s, buffer, end);
179 T::append(s, &c, &c + 1);
186 bool result = is_string(
string);
194 bool neg = is_char(
'-');
196 require(!neg,
"digit");
202 char* p_end =
nullptr;
203 double value = std::strtod(p, &p_end);
204 require(std::isfinite(value),
"finite number");
205 ADOBE_ASSERT((p_ - p) == (p_end - p) &&
"std::strtod() failure");
215 require(is_digit(),
"digit");
222 if (!is_char(
'e') && !is_char(
'E'))
224 is_char(
'-') || is_char(
'+');
225 require(is_digit(),
"exponent digit");
231 if (!(
'0' <= *p_ && *p_ <=
'9'))
247 std::uint32_t get_four_digits() {
248 std::uint32_t result;
249 char digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
252 result = digit * 0x1000;
253 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
256 result += digit * 0x0100;
257 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
260 result += digit * 0x0010;
261 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
267 require(
false,
"four hex digits");
275 void require(
bool x,
const char* failure) {
279 throw logic_error(failure +
string(
" is required"));
283 void skip_white_space() {
284 while (ws()[
static_cast<unsigned char>(*p_)]) {
289 bool is_char(
char x) {
296 bool is_structural_char(
char x) {
305 char* utf8(std::uint32_t x,
char* f) {
307 std::size_t bytes_to_write(0);
313 else if (x < 0x10000)
315 else if (x < 0x0010FFFF)
318 require(
false,
"valid utf-32 character");
320 const std::uint32_t mark = 0x80;
321 const std::uint32_t mask = 0xBF;
323 static const unsigned char first_mark[] = {0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC};
327 switch (bytes_to_write) {
329 *--f =
static_cast<char>((x | mark) & mask);
332 *--f =
static_cast<char>((x | mark) & mask);
335 *--f =
static_cast<char>((x | mark) & mask);
338 *--f =
static_cast<char>(x | first_mark[bytes_to_write]);
341 return f + bytes_to_write;
346 typedef char table_t_[256];
348 static const table_t_& hex_digit() {
349 static const char hex_digit_[] = {
352 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
353 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
354 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
355 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
356 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
357 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
358 '\x00',
'\x01',
'\x02',
'\x03',
'\x04',
'\x05',
'\x06',
'\x07',
359 '\x08',
'\x09',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
360 '\xFF',
'\x0A',
'\x0B',
'\x0C',
'\x0D',
'\x0E',
'\x0F',
'\xFF',
361 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
362 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
363 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
364 '\xFF',
'\x0A',
'\x0B',
'\x0C',
'\x0D',
'\x0E',
'\x0F',
'\xFF',
365 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
366 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
367 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
368 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
369 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
370 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
371 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
372 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
373 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
374 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
375 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
376 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
377 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
378 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
379 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
380 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
381 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
382 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
383 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF'};
387 static const table_t_& escape() {
388 static const char escape_[] = {
391 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
392 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
393 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
394 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
395 '\x00',
'\x00',
'\x22',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
396 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x2F',
397 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
398 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
399 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
400 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
401 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
402 '\x00',
'\x00',
'\x00',
'\x00',
'\x5C',
'\x00',
'\x00',
'\x00',
403 '\x00',
'\x00',
'\x08',
'\x00',
'\x00',
'\x00',
'\x0C',
'\x00',
404 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x0A',
'\x00',
405 '\x00',
'\x00',
'\x0D',
'\x00',
'\x09',
'\x75',
'\x00',
'\x00',
406 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
407 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
408 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
409 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
410 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
411 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
412 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
413 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
414 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
415 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
416 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
417 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
418 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
419 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
420 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
421 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
422 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00'};
426 static const table_t_& ws() {
427 static const char ws_[] = {
430 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
431 '\x00',
'\x01',
'\x01',
'\x00',
'\x00',
'\x01',
'\x00',
'\x00',
432 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
433 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
434 '\x01',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
435 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
436 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
437 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
438 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
439 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
440 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
441 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
442 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
443 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
444 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
445 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
446 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
447 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
448 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
449 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
450 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
451 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
452 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
453 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
454 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
455 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
456 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
457 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
458 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
459 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
460 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
461 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00'};
493 switch (T::type(value)) {
496 generate_(value, indent);
499 require(
false,
"object or array");
505 void require(
bool x,
const char* message) {
507 throw std::logic_error(message);
510 void generate_(
const value_type& value, std::size_t indent) {
511 switch (T::type(value)) {
513 generate_(as<object_type>(value), indent);
516 generate_(as<array_type>(value), indent);
519 generate_string(as<string_type>(value));
522 generate_(as<double>(value));
525 generate_(as<bool>(value));
531 require(
false,
"valid type");
537 static const char null_[] =
"null";
538 out_ = std::copy(std::begin(null_), std::end(null_) - 1, out_);
541 void generate_(
bool x) {
542 static const char true_[] =
"true";
543 static const char false_[] =
"false";
545 out_ = std::copy(std::begin(true_), std::end(true_) - 1, out_);
547 out_ = std::copy(std::begin(false_), std::end(false_) - 1, out_);
550 void generate_(
double x) {
551 require(!std::isnan(x) && !std::isinf(x),
"valid double");
555 template <
typename U>
557 return T::template as<U>(x);
560 void indent(std::size_t n) {
561 for (std::size_t n_ = 0; n_ != n; ++n_)
564 void space() { *out_++ =
' '; }
565 void endl() { *out_++ =
'\n'; }
567 template <
typename S>
568 void generate_string(
const S& x) {
569 static const char hex_digits[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
570 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'};
574 for (
const auto& e : x) {
575 if ((
'\x00' <= e && e <=
'\x1F') || e ==
'"' || e ==
'\\') {
603 *out_++ = hex_digits[
static_cast<unsigned char>((e >> 4) &
'\x0F')];
604 *out_++ = hex_digits[
static_cast<unsigned char>(e &
'\x0F')];
613 void generate_(
const pair_type& value, std::size_t n) {
614 generate_string(value.first);
617 generate_(value.second, n);
620 template <
typename I>
621 bool list(I f, I l, std::size_t n) {
627 bool is_one = next == l;
655 void generate_(
const object_type& value, std::size_t n) {
657 if (list(std::begin(value), std::end(value), n))
664 void generate_(
const array_type& value, std::size_t n) {
666 if (list(std::begin(value), std::end(value), n))