2#ifndef SIMDJSON_SERIALIZATION_INL_H
3#define SIMDJSON_SERIALIZATION_INL_H
5#include "simdjson/dom/base.h"
6#include "simdjson/dom/parser.h"
7#include "simdjson/dom/serialization.h"
8#include "simdjson/internal/tape_type.h"
10#include "simdjson/dom/array-inl.h"
11#include "simdjson/dom/object-inl.h"
12#include "simdjson/internal/tape_ref-inl.h"
19inline bool parser::print_json(std::ostream &os)
const noexcept {
23 simdjson::internal::string_builder<> sb;
24 sb.append(doc.root());
25 std::string_view answer = sb.str();
30inline std::ostream &operator<<(std::ostream &out,
32 simdjson::internal::string_builder<> sb;
34 return (out << sb.str());
36#if SIMDJSON_EXCEPTIONS
38operator<<(std::ostream &out,
43 return (out << x.
value());
47 simdjson::internal::string_builder<> sb;
49 return (out << sb.str());
51#if SIMDJSON_EXCEPTIONS
53operator<<(std::ostream &out,
58 return (out << x.
value());
61inline std::ostream &operator<<(std::ostream &out,
63 simdjson::internal::string_builder<> sb;
65 return (out << sb.str());
67#if SIMDJSON_EXCEPTIONS
69operator<<(std::ostream &out,
74 return (out << x.
value());
88struct escape_sequence {
102static char *fast_itoa(
char *output, int64_t value)
noexcept {
105 uint64_t value_positive;
113 std::memcpy(&value_positive, &value,
sizeof(value));
114 value_positive = (~value_positive) + 1;
116 value_positive = value;
121 const char *
const end_buffer = buffer + 20;
122 char *write_pointer = buffer + 19;
126 while (value_positive >= 10) {
127 *write_pointer-- = char(
'0' + (value_positive % 10));
128 value_positive /= 10;
130 *write_pointer = char(
'0' + value_positive);
131 size_t len = end_buffer - write_pointer;
132 std::memcpy(output, write_pointer, len);
144static char *fast_itoa(
char *output, uint64_t value)
noexcept {
147 const char *
const end_buffer = buffer + 20;
148 char *write_pointer = buffer + 19;
152 while (value >= 10) {
153 *write_pointer-- = char(
'0' + (value % 10));
156 *write_pointer = char(
'0' + value);
157 size_t len = end_buffer - write_pointer;
158 std::memcpy(output, write_pointer, len);
169template <
class formatter>
170simdjson_inline
void base_formatter<formatter>::number(uint64_t x) {
171 char number_buffer[24];
172 char *newp = fast_itoa(number_buffer, x);
173 chars(number_buffer, newp);
176template <
class formatter>
177simdjson_inline
void base_formatter<formatter>::number(int64_t x) {
178 char number_buffer[24];
179 char *newp = fast_itoa(number_buffer, x);
180 chars(number_buffer, newp);
183template <
class formatter>
184simdjson_inline
void base_formatter<formatter>::number(
double x) {
185#if SIMDJSON_ENABLE_NAN_INF
186 if (simdjson_unlikely(!std::isfinite(x))) {
188 char const *s =
"NaN";
194 char const *s =
"Infinity";
203 char number_buffer[simdjson::internal::to_chars_buffer_size];
207 char *newp = simdjson::internal::to_chars(number_buffer,
nullptr, x);
208 chars(number_buffer, newp);
211template <
class formatter>
212simdjson_inline
void base_formatter<formatter>::start_array() {
216template <
class formatter>
217simdjson_inline
void base_formatter<formatter>::end_array() {
221template <
class formatter>
222simdjson_inline
void base_formatter<formatter>::start_object() {
226template <
class formatter>
227simdjson_inline
void base_formatter<formatter>::end_object() {
231template <
class formatter>
232simdjson_inline
void base_formatter<formatter>::comma() {
236template <
class formatter>
237simdjson_inline
void base_formatter<formatter>::true_atom() {
238 const char *s =
"true";
242template <
class formatter>
243simdjson_inline
void base_formatter<formatter>::false_atom() {
244 const char *s =
"false";
248template <
class formatter>
249simdjson_inline
void base_formatter<formatter>::null_atom() {
250 const char *s =
"null";
254template <
class formatter>
255simdjson_inline
void base_formatter<formatter>::one_char(
char c) {
259template <
class formatter>
260simdjson_inline
void base_formatter<formatter>::chars(
const char *begin,
262 buffer.append(begin, end);
265template <
class formatter>
267base_formatter<formatter>::key(std::string_view unescaped) {
272template <
class formatter>
274base_formatter<formatter>::string(std::string_view unescaped) {
282 constexpr static char needs_escaping[] = {
283 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
284 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
285 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
286 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
287 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
288 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
289 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
290 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
291 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
292 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
293 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
294 for (; i + 8 <= unescaped.length(); i += 8) {
299 if (needs_escaping[uint8_t(unescaped[i])] |
300 needs_escaping[uint8_t(unescaped[i + 1])] |
301 needs_escaping[uint8_t(unescaped[i + 2])] |
302 needs_escaping[uint8_t(unescaped[i + 3])] |
303 needs_escaping[uint8_t(unescaped[i + 4])] |
304 needs_escaping[uint8_t(unescaped[i + 5])] |
305 needs_escaping[uint8_t(unescaped[i + 6])] |
306 needs_escaping[uint8_t(unescaped[i + 7])]) {
310 for (; i < unescaped.length(); i++) {
311 if (needs_escaping[uint8_t(unescaped[i])]) {
321 chars(unescaped.data(), unescaped.data() + i);
325 for (; i < unescaped.length(); i++) {
326 switch (unescaped[i]) {
328 const char *s =
"\\\"";
332 const char *s =
"\\\\";
336 if (uint8_t(unescaped[i]) <= 0x1F) {
340 constexpr static escape_sequence escaped[32] = {
341 {6,
"\\u0000"}, {6,
"\\u0001"}, {6,
"\\u0002"}, {6,
"\\u0003"},
342 {6,
"\\u0004"}, {6,
"\\u0005"}, {6,
"\\u0006"}, {6,
"\\u0007"},
343 {2,
"\\b"}, {2,
"\\t"}, {2,
"\\n"}, {6,
"\\u000b"},
344 {2,
"\\f"}, {2,
"\\r"}, {6,
"\\u000e"}, {6,
"\\u000f"},
345 {6,
"\\u0010"}, {6,
"\\u0011"}, {6,
"\\u0012"}, {6,
"\\u0013"},
346 {6,
"\\u0014"}, {6,
"\\u0015"}, {6,
"\\u0016"}, {6,
"\\u0017"},
347 {6,
"\\u0018"}, {6,
"\\u0019"}, {6,
"\\u001a"}, {6,
"\\u001b"},
348 {6,
"\\u001c"}, {6,
"\\u001d"}, {6,
"\\u001e"}, {6,
"\\u001f"}};
349 auto u = escaped[uint8_t(unescaped[i])];
350 chars(u.string, u.string + u.length);
352 one_char(unescaped[i]);
359template <
class formatter>
inline void base_formatter<formatter>::clear() {
363template <
class formatter>
364simdjson_inline std::string_view base_formatter<formatter>::str()
const {
368simdjson_inline
void mini_formatter::print_newline() {
return; }
370simdjson_inline
void mini_formatter::print_indents(
size_t depth) {
375simdjson_inline
void mini_formatter::print_space() {
return; }
377simdjson_inline
void pretty_formatter::print_newline() { one_char(
'\n'); }
379simdjson_inline
void pretty_formatter::print_indents(
size_t depth) {
380 if (this->indent_step <= 0) {
383 for (
size_t i = 0; i < this->indent_step * depth; i++) {
388simdjson_inline
void pretty_formatter::print_space() { one_char(
' '); }
394template <
class serializer>
398 constexpr size_t MAX_DEPTH = 16;
399 bool is_object[MAX_DEPTH];
400 is_object[0] =
false;
401 bool after_value =
false;
403 internal::tape_ref iter(value.tape);
408 format.print_newline();
411 format.print_indents(depth);
415 if (is_object[depth]) {
416 format.key(iter.get_string_view());
417 format.print_space();
420 switch (iter.tape_ref_type()) {
423 case tape_type::START_ARRAY: {
426 if (simdjson_unlikely(depth >= MAX_DEPTH)) {
428 iter.json_index = iter.matching_brace_index() - 1;
434 format.start_array();
438 if (iter.tape_ref_type() == tape_type::END_ARRAY) {
444 is_object[depth] =
false;
446 format.print_newline();
451 case tape_type::START_OBJECT: {
454 if (simdjson_unlikely(depth >= MAX_DEPTH)) {
456 iter.json_index = iter.matching_brace_index() - 1;
462 format.start_object();
466 if (iter.tape_ref_type() == tape_type::END_OBJECT) {
472 is_object[depth] =
true;
474 format.print_newline();
479 case tape_type::STRING:
480 format.string(iter.get_string_view());
482 case tape_type::BIGINT: {
484 auto sv = iter.get_string_view();
485 format.chars(sv.data(), sv.data() + sv.size());
488 case tape_type::INT64:
489 format.number(iter.next_tape_value<int64_t>());
493 case tape_type::UINT64:
494 format.number(iter.next_tape_value<uint64_t>());
498 case tape_type::DOUBLE:
499 format.number(iter.next_tape_value<
double>());
503 case tape_type::TRUE_VALUE:
506 case tape_type::FALSE_VALUE:
509 case tape_type::NULL_VALUE:
514 case tape_type::END_ARRAY:
515 case tape_type::END_OBJECT:
516 case tape_type::ROOT:
517 SIMDJSON_UNREACHABLE();
523 while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
524 iter.tape_ref_type() == tape_type::END_OBJECT)) {
525 format.print_newline();
527 format.print_indents(depth);
528 if (iter.tape_ref_type() == tape_type::END_ARRAY) {
537 }
while (depth != 0);
539 format.print_newline();
542template <
class serializer>
544 format.start_object();
545 auto pair = value.begin();
546 auto end = value.end();
549 for (++pair; pair != end; ++pair) {
557template <
class serializer>
559 format.start_array();
560 auto iter = value.begin();
561 auto end = value.end();
564 for (++iter; iter != end; ++iter) {
572template <
class serializer>
579template <
class serializer>
580simdjson_inline
void string_builder<serializer>::clear() {
584template <
class serializer>
585simdjson_inline std::string_view string_builder<serializer>::str()
const {
Key/value pair in an object.
std::string_view key
key in the key-value pair
element value
value in the key-value pair
The top level simdjson namespace, containing everything the library provides.
Exception thrown when an exception-supporting simdjson method is called.
The result of a simdjson operation that could fail.
simdjson_inline error_code error() const noexcept
The error.
simdjson_inline T & value() &noexcept(false)
Get the result value.