2 #ifndef SIMDJSON_SERIALIZATION_INL_H
3 #define SIMDJSON_SERIALIZATION_INL_H
5 #include "simdjson/dom/serialization.h"
12 inline bool parser::print_json(std::ostream &os)
const noexcept {
13 if (!valid) {
return false; }
14 simdjson::internal::string_builder<> sb;
15 sb.append(doc.root());
16 std::string_view answer = sb.str();
31 struct escape_sequence {
44 char *fast_itoa(
char *output, int64_t value) noexcept {
47 uint64_t value_positive;
55 std::memcpy(&value_positive, &value,
sizeof(value));
56 value_positive = (~value_positive) + 1;
58 value_positive = value;
63 const char *
const end_buffer = buffer + 20;
64 char *write_pointer = buffer + 19;
68 while(value_positive >= 10) {
69 *write_pointer-- = char(
'0' + (value_positive % 10));
72 *write_pointer = char(
'0' + value_positive);
73 size_t len = end_buffer - write_pointer;
74 std::memcpy(output, write_pointer, len);
86 char *fast_itoa(
char *output, uint64_t value) noexcept {
89 const char *
const end_buffer = buffer + 20;
90 char *write_pointer = buffer + 19;
95 *write_pointer-- = char(
'0' + (value % 10));
98 *write_pointer = char(
'0' + value);
99 size_t len = end_buffer - write_pointer;
100 std::memcpy(output, write_pointer, len);
110 simdjson_inline
void mini_formatter::number(uint64_t x) {
111 char number_buffer[24];
112 char *newp = fast_itoa(number_buffer, x);
113 buffer.insert(buffer.end(), number_buffer, newp);
116 simdjson_inline
void mini_formatter::number(int64_t x) {
117 char number_buffer[24];
118 char *newp = fast_itoa(number_buffer, x);
119 buffer.insert(buffer.end(), number_buffer, newp);
122 simdjson_inline
void mini_formatter::number(
double x) {
123 char number_buffer[24];
127 char *newp = internal::to_chars(number_buffer,
nullptr, x);
128 buffer.insert(buffer.end(), number_buffer, newp);
131 simdjson_inline
void mini_formatter::start_array() { one_char(
'['); }
132 simdjson_inline
void mini_formatter::end_array() { one_char(
']'); }
133 simdjson_inline
void mini_formatter::start_object() { one_char(
'{'); }
134 simdjson_inline
void mini_formatter::end_object() { one_char(
'}'); }
135 simdjson_inline
void mini_formatter::comma() { one_char(
','); }
138 simdjson_inline
void mini_formatter::true_atom() {
139 const char * s =
"true";
140 buffer.insert(buffer.end(), s, s + 4);
142 simdjson_inline
void mini_formatter::false_atom() {
143 const char * s =
"false";
144 buffer.insert(buffer.end(), s, s + 5);
146 simdjson_inline
void mini_formatter::null_atom() {
147 const char * s =
"null";
148 buffer.insert(buffer.end(), s, s + 4);
150 simdjson_inline
void mini_formatter::one_char(
char c) { buffer.push_back(c); }
151 simdjson_inline
void mini_formatter::key(std::string_view unescaped) {
155 simdjson_inline
void mini_formatter::string(std::string_view unescaped) {
163 constexpr
static char needs_escaping[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
164 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
165 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
166 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
167 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
168 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
169 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
170 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
171 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
172 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
173 for(;i + 8 <= unescaped.length(); i += 8) {
177 if(needs_escaping[uint8_t(unescaped[i])] | needs_escaping[uint8_t(unescaped[i+1])]
178 | needs_escaping[uint8_t(unescaped[i+2])] | needs_escaping[uint8_t(unescaped[i+3])]
179 | needs_escaping[uint8_t(unescaped[i+4])] | needs_escaping[uint8_t(unescaped[i+5])]
180 | needs_escaping[uint8_t(unescaped[i+6])] | needs_escaping[uint8_t(unescaped[i+7])]
183 for(;i < unescaped.length(); i++) {
184 if(needs_escaping[uint8_t(unescaped[i])]) {
break; }
192 buffer.insert(buffer.end(), unescaped.data(), unescaped.data() + i);
196 for (; i < unescaped.length(); i++) {
197 switch (unescaped[i]) {
200 const char * s =
"\\\"";
201 buffer.insert(buffer.end(), s, s + 2);
206 const char * s =
"\\\\";
207 buffer.insert(buffer.end(), s, s + 2);
211 if (uint8_t(unescaped[i]) <= 0x1F) {
215 constexpr
static escape_sequence escaped[32] = {
216 {6,
"\\u0000"}, {6,
"\\u0001"}, {6,
"\\u0002"}, {6,
"\\u0003"},
217 {6,
"\\u0004"}, {6,
"\\u0005"}, {6,
"\\u0006"}, {6,
"\\u0007"},
218 {2,
"\\b"}, {2,
"\\t"}, {2,
"\\n"}, {6,
"\\u000b"},
219 {2,
"\\f"}, {2,
"\\r"}, {6,
"\\u000e"}, {6,
"\\u000f"},
220 {6,
"\\u0010"}, {6,
"\\u0011"}, {6,
"\\u0012"}, {6,
"\\u0013"},
221 {6,
"\\u0014"}, {6,
"\\u0015"}, {6,
"\\u0016"}, {6,
"\\u0017"},
222 {6,
"\\u0018"}, {6,
"\\u0019"}, {6,
"\\u001a"}, {6,
"\\u001b"},
223 {6,
"\\u001c"}, {6,
"\\u001d"}, {6,
"\\u001e"}, {6,
"\\u001f"}};
224 auto u = escaped[uint8_t(unescaped[i])];
225 buffer.insert(buffer.end(), u.string, u.string + u.length);
227 one_char(unescaped[i]);
234 inline void mini_formatter::clear() {
238 simdjson_inline std::string_view mini_formatter::str()
const {
239 return std::string_view(buffer.data(), buffer.size());
247 template <
class serializer>
251 constexpr
size_t MAX_DEPTH = 16;
252 bool is_object[MAX_DEPTH];
253 is_object[0] =
false;
254 bool after_value =
false;
256 internal::tape_ref iter(value.tape);
264 if (is_object[depth]) {
265 format.key(iter.get_string_view());
268 switch (iter.tape_ref_type()) {
271 case tape_type::START_ARRAY: {
274 if (simdjson_unlikely(depth >= MAX_DEPTH)) {
276 iter.json_index = iter.matching_brace_index() - 1;
282 format.start_array();
286 if (iter.tape_ref_type() == tape_type::END_ARRAY) {
292 is_object[depth] =
false;
298 case tape_type::START_OBJECT: {
301 if (simdjson_unlikely(depth >= MAX_DEPTH)) {
303 iter.json_index = iter.matching_brace_index() - 1;
309 format.start_object();
313 if (iter.tape_ref_type() == tape_type::END_OBJECT) {
319 is_object[depth] =
true;
325 case tape_type::STRING:
326 format.string(iter.get_string_view());
328 case tape_type::INT64:
329 format.number(iter.next_tape_value<int64_t>());
333 case tape_type::UINT64:
334 format.number(iter.next_tape_value<uint64_t>());
338 case tape_type::DOUBLE:
339 format.number(iter.next_tape_value<
double>());
343 case tape_type::TRUE_VALUE:
346 case tape_type::FALSE_VALUE:
349 case tape_type::NULL_VALUE:
354 case tape_type::END_ARRAY:
355 case tape_type::END_OBJECT:
356 case tape_type::ROOT:
357 SIMDJSON_UNREACHABLE();
363 while (depth != 0 && (iter.tape_ref_type() == tape_type::END_ARRAY ||
364 iter.tape_ref_type() == tape_type::END_OBJECT)) {
365 if (iter.tape_ref_type() == tape_type::END_ARRAY) {
375 }
while (depth != 0);
378 template <
class serializer>
380 format.start_object();
381 auto pair = value.begin();
382 auto end = value.end();
385 for (++pair; pair != end; ++pair) {
393 template <
class serializer>
395 format.start_array();
396 auto iter = value.begin();
397 auto end = value.end();
400 for (++iter; iter != end; ++iter) {
408 template <
class serializer>
414 template <
class serializer>
415 simdjson_inline
void string_builder<serializer>::clear() {
419 template <
class serializer>
420 simdjson_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
We want to support argument-dependent lookup (ADL).