18 #include <unordered_map>
21 #include <double-conversion/src/double-conversion.h>
23 #include <adobe/cassert.hpp>
24 #include <adobe/string/to_string.hpp>
54 constexpr
static double kNaN = std::numeric_limits<double>::quiet_NaN();
69 s2d_(double_conversion::StringToDoubleConverter::ALLOW_TRAILING_JUNK,
70 kNaN, kNaN, nullptr, nullptr)
75 require(is_object(result) || is_array(result),
"object or array");
81 if (!is_structural_char(
'{'))
return false;
84 if (is_string(
string)) {
85 require(is_structural_char(
':'),
":");
87 require(is_value(value),
"value");
88 T::move_append(
object,
string, value);
90 while (is_structural_char(
',')) {
91 require(is_string(
string),
"string");
92 require(is_structural_char(
':'),
":");
93 require(is_value(value),
"value");
94 T::move_append(
object,
string, value);
97 require(is_structural_char(
'}'),
"}");
103 if (!is_structural_char(
'['))
return false;
106 if (is_value(value)) {
107 T::move_append(array, value);
108 while (is_structural_char(
',')) {
109 require(is_value(value),
"value");
110 T::move_append(array, value);
113 require(is_structural_char(
']'),
"]");
131 bool is_sequence(
const char* p) {
132 if (!is_char(*p))
return false;
134 while (is_char(*p)) ++p;
135 require(*p == 0,
"valid constant");
140 if (is_sequence(
"true")) { t =
true;
return true; }
141 if (is_sequence(
"false")) { t =
false;
return true; }
146 if (!is_sequence(
"null"))
return false;
151 template <
typename S>
152 bool is_string(S& s) {
153 if (!is_char(
'"'))
return false;
154 while (!is_char(
'"')) {
156 while (!(
'\x00' <= *p_ && *p_ <
'\x20') && *p_ !=
'"' && *p_ !=
'\\') ++p_;
157 require(!(
'\x00' <= *p_ && *p_ <
'\x20'),
"valid character");
159 if (!is_char(
'\\'))
continue;
160 char c = escape()[
static_cast<unsigned char>(*p_++)];
161 require(c,
"valid escape character");
163 std::uint32_t utf = get_four_digits();
165 if (0xD800 <= utf && utf <= 0xDBFF) {
166 require(is_char(
'u'),
"trail surrogate");
167 std::uint32_t trailing = get_four_digits();
168 require(0xDC00 <= trailing && trailing <= 0xDFFF,
"trail surrogate");
169 utf = ((utf - 0xD800) << 10) + (trailing - 0xDC00);
172 auto end = utf8(utf, buffer);
173 T::append(s, buffer, end);
175 else T::append(s, &c, &c + 1);
182 bool result = is_string(
string);
183 if (result) t = move(
string);
189 bool neg = is_char(
'-');
191 require(!neg,
"digit");
198 double value = s2d_.StringToDouble(p, static_cast<int>(p_ - p), &count);
200 require(std::isfinite(value),
"finite number");
201 ADOBE_ASSERT(count == p_ - p &&
"StringToDouble() failure");
208 if (!is_char(
'.'))
return;
209 require(is_digit(),
"digit");
215 if (!is_char(
'e') && !is_char(
'E'))
return;
216 is_char(
'-') || is_char(
'+');
217 require(is_digit(),
"exponent digit");
222 if (!(
'0' <= *p_ && *p_ <=
'9'))
return false;
228 if (is_char(
'0'))
return true;
229 if (!is_digit())
return false;
234 std::uint32_t get_four_digits() {
235 std::uint32_t result;
236 char digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
237 if (digit ==
'\xFF')
goto fail;
238 result = digit * 0x1000;
239 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
240 if (digit ==
'\xFF')
goto fail;
241 result += digit * 0x0100;
242 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
243 if (digit ==
'\xFF')
goto fail;
244 result += digit * 0x0010;
245 digit = hex_digit()[
static_cast<unsigned char>(*p_++)];
246 if (digit ==
'\xFF')
goto fail;
250 require(
false,
"four hex digits");
258 void require(
bool x,
const char* failure) {
261 if (!x)
throw logic_error(failure +
string(
" is required"));
265 void skip_white_space() {
while (ws()[static_cast<unsigned char>(*p_)]) { ++p_; } }
267 bool is_char(
char x) {
268 if (*p_ != x)
return false;
273 bool is_structural_char(
char x) {
275 if (!is_char(x))
return false;
281 char* utf8(std::uint32_t x,
char* f) {
283 std::size_t bytes_to_write(0);
285 if (x < 0x80) bytes_to_write = 1;
286 else if (x < 0x800) bytes_to_write = 2;
287 else if (x < 0x10000) bytes_to_write = 3;
288 else if (x < 0x0010FFFF) bytes_to_write = 4;
289 else require(
false,
"valid utf-32 character");
291 const std::uint32_t mark = 0x80;
292 const std::uint32_t mask = 0xBF;
294 static const unsigned char first_mark[] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
298 switch (bytes_to_write) {
299 case 4: *--f =
static_cast<char>((x | mark) & mask); x >>= 6;
300 case 3: *--f =
static_cast<char>((x | mark) & mask); x >>= 6;
301 case 2: *--f =
static_cast<char>((x | mark) & mask); x >>= 6;
302 case 1: *--f =
static_cast<char> (x | first_mark[bytes_to_write]);
305 return f + bytes_to_write;
309 double_conversion::StringToDoubleConverter s2d_;
311 typedef char table_t_[256];
313 static const table_t_& hex_digit() {
314 static const char hex_digit_[] = {
316 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
317 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
318 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
319 '\x00',
'\x01',
'\x02',
'\x03',
'\x04',
'\x05',
'\x06',
'\x07',
'\x08',
'\x09',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
320 '\xFF',
'\x0A',
'\x0B',
'\x0C',
'\x0D',
'\x0E',
'\x0F',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
321 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
322 '\xFF',
'\x0A',
'\x0B',
'\x0C',
'\x0D',
'\x0E',
'\x0F',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
323 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
324 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
325 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
326 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
327 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
328 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
329 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
330 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
331 '\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF',
'\xFF'
336 static const table_t_& escape() {
337 static const char escape_[] = {
339 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
340 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
341 '\x00',
'\x00',
'\x22',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x2F',
342 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
343 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
344 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x5C',
'\x00',
'\x00',
'\x00',
345 '\x00',
'\x00',
'\x08',
'\x00',
'\x00',
'\x00',
'\x0C',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x0A',
'\x00',
346 '\x00',
'\x00',
'\x0D',
'\x00',
'\x09',
'\x75',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
347 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
348 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
349 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
350 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
351 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
352 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
353 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
354 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00'
359 static const table_t_& ws() {
360 static const char ws_[] = {
362 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x01',
'\x01',
'\x00',
'\x00',
'\x01',
'\x00',
'\x00',
363 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
364 '\x01',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
365 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
366 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
367 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
368 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
369 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
370 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
371 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
372 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
373 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
374 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
375 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
376 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
377 '\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00',
'\x00'
399 template <
typename T,
413 switch (T::type(value)) {
416 generate_(value, indent);
419 require(
false,
"object or array");
425 void require(
bool x,
const char* message) {
426 if (!x)
throw std::logic_error(message);
429 void generate_(
const value_type& value, std::size_t indent) {
430 switch (T::type(value)) {
432 generate_(as<object_type>(value), indent);
435 generate_(as<array_type>(value), indent);
438 generate_string(as<string_type>(value));
441 generate_(as<double>(value));
444 generate_(as<bool>(value));
450 require(
false,
"valid type");
456 static const char null_[] =
"null";
457 out_ = std::copy(std::begin(null_), std::end(null_) - 1, out_);
460 void generate_(
bool x) {
461 static const char true_[] =
"true";
462 static const char false_[] =
"false";
463 if (x) out_ = std::copy(std::begin(true_), std::end(true_) - 1, out_);
464 else out_ = std::copy(std::begin(false_), std::end(false_) - 1, out_);
467 void generate_(
double x) {
468 require(!std::isnan(x) && !std::isinf(x),
"valid double");
469 out_ = adobe::to_string(x, out_);
473 static const U& as(
const value_type& x) {
return T::template as<U>(x); }
475 void indent(std::size_t n) {
476 for(std::size_t n_ = 0; n_ != n; ++n_) *out_++ =
'\t';
478 void space() { *out_++ =
' ';}
479 void endl() { *out_++ =
'\n'; }
481 template <
typename S>
482 void generate_string(
const S& x) {
483 static const char hex_digits[] = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'A',
'B',
'C',
'D',
'E',
'F' };
487 for (
const auto& e : x) {
488 if ((
'\x00' <= e && e <=
'\x1F') || e ==
'"' || e ==
'\\') {
491 case '"': *out_++ =
'"';
break;
492 case '\\': *out_++ =
'\\';
break;
493 case '\b': *out_++ =
'b';
break;
494 case '\f': *out_++ =
'f';
break;
495 case '\n': *out_++ =
'n';
break;
496 case '\r': *out_++ =
'r';
break;
497 case '\t': *out_++ =
't';
break;
502 *out_++ = hex_digits[
static_cast<unsigned char>((e >> 4) &
'\x0F')];
503 *out_++ = hex_digits[
static_cast<unsigned char>(e &
'\x0F')];
511 void generate_(
const pair_type& value, std::size_t n) {
512 generate_string(value.first); *out_++ =
':'; space(); generate_(value.second, n);
515 template <
typename I>
516 bool list(I f, I l, std::size_t n) {
517 if (f == l)
return false;
520 bool is_one = next == l;
522 if (is_one) { space(); }
523 else { endl(); n += 1; indent(n); }
527 if (is_one) {
return false; }
531 *out_++ =
','; endl();
532 indent(n); generate_(*f, n);
539 void generate_(
const object_type& value, std::size_t n) {
541 if (list(begin(value), end(value), n)) indent(n);
546 void generate_(
const array_type& value, std::size_t n) {
548 if (list(begin(value), end(value), n)) indent(n);
A utility class that uses a helper class to access a provided data structure and output well-formed J...
T::string_type string_type
T::object_type object_type
A utility class that parses raw JSON data and uses a helper class to construct the desired representa...
T::string_type string_type
json_parser(const char *p)
T::object_type object_type
O generate(const value_type &value, std::size_t indent=0)