1#ifndef SIMDJSON_GENERIC_BUILDER_H
3#ifndef SIMDJSON_CONDITIONAL_INCLUDE
4#define SIMDJSON_GENERIC_STRING_BUILDER_H
5#include "simdjson/generic/builder/json_string_builder.h"
6#include "simdjson/concepts.h"
9#if SIMDJSON_STATIC_REFLECTION
22namespace SIMDJSON_IMPLEMENTATION {
30simdjson_really_inline
char *write_uint_jeaiii(
char *p, uint64_t v)
noexcept;
31simdjson_inline
char *write_double(
char *p,
double v)
noexcept;
33simdjson_really_inline
size_t write_string_escaped(
const std::string_view input,
char *out);
35SIMDJSON_PUSH_DISABLE_WARNINGS
36SIMDJSON_DISABLE_GCC_WARNING(-Warray-bounds)
37#if !defined(__clang__)
38SIMDJSON_DISABLE_GCC_WARNING(-Wstringop-overflow)
57template <
bool Checked>
59 static constexpr bool checked = Checked;
67 simdjson_really_inline basic_writer(string_builder &builder) noexcept
68 : ptr(builder.unsafe_data())
69 , pos(builder.unsafe_position())
70 , cap(builder.unsafe_capacity())
76 simdjson_really_inline
void sync() noexcept {
77 sb.unsafe_set_position(pos);
83 simdjson_really_inline
bool ensure(
size_t n)
noexcept {
89 if (simdjson_likely(pos + n <= cap)) {
return true; }
93 simdjson_never_inline
bool grow_slow(
size_t n)
noexcept {
96 if (simdjson_unlikely(pos + n < pos))
return false;
97 sb.unsafe_set_position(pos);
100 if (!sb.unsafe_grow((std::max)(cap * 2, pos + n))) {
110 ptr = sb.unsafe_data();
111 cap = sb.unsafe_capacity();
119struct basic_writer<false> {
120 static constexpr bool checked =
false;
124 simdjson_really_inline basic_writer(
char *buffer,
size_t position) noexcept
125 : ptr(buffer), pos(position) {}
127 simdjson_really_inline
bool ensure(
size_t)
const noexcept {
return true; }
130using writer = basic_writer<true>;
131using unchecked_writer = basic_writer<false>;
136inline constexpr size_t unchecked_slack = 64;
138consteval size_t padded_key_length(
size_t length) {
139 return (length + 15) / 16 * 16;
148template <
class W,
class F>
149simdjson_really_inline
void call_through_string_builder(W &w, F &&f)
noexcept(
noexcept(f(w.sb))) {
152 w.ptr = w.sb.unsafe_data();
153 w.pos = w.sb.unsafe_position();
154 w.cap = w.sb.unsafe_capacity();
159namespace annotation_detail {
162consteval bool is_serialized_member(std::meta::info dm) {
163 return !simdjson::detail::has_annotation(dm, ^^simdjson::detail::skip_tag)
164 && !simdjson::detail::has_annotation(dm, ^^simdjson::detail::skip_serializing_tag);
169template <auto dm,
typename V>
170simdjson_really_inline
bool should_serialize(
const V &value) {
171 constexpr std::meta::info skip_if_type = simdjson::detail::annotation_of_template(dm, ^^simdjson::detail::skip_serializing_if_t);
172 if constexpr (skip_if_type != std::meta::info{}) {
173 using skip_if =
typename [: skip_if_type :];
174 return !skip_if::predicate(value);
183template <auto dm,
class W,
typename V>
184simdjson_really_inline
void atom_member(W &w,
const V &value) {
185 constexpr std::meta::info with_type = simdjson::detail::annotation_of_template(dm, ^^simdjson::detail::with_t);
186 if constexpr (with_type != std::meta::info{}) {
187 using adapter =
typename [: with_type :]::adapter;
188 if constexpr (
requires(string_builder &b) { adapter::serialize(b, value); }) {
189 call_through_string_builder(w, [&](string_builder &b) { adapter::serialize(b, value); });
201template <
class W,
class T>
202simdjson_really_inline
void atom_fields(W &w,
const T &t,
bool &first) {
207 template for (
constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
208 if constexpr (is_serialized_member(dm)) {
209 if (should_serialize<dm>(t.[:dm:])) {
210 if constexpr (simdjson::detail::has_annotation(dm, ^^simdjson::detail::flatten_tag)) {
211 static_assert(std::meta::is_class_type(simdjson::detail::flattened_type(dm)));
212 using flattened = std::remove_cvref_t<
decltype(t.[:dm:])>;
213 static_assert(!concepts::container_but_not_string<flattened> && !concepts::string_view_keyed_map<flattened> &&
214 !concepts::appendable_containers<flattened> && !concepts::optional_type<flattened> &&
215 !concepts::smart_pointer<flattened> && !std::is_same_v<flattened, std::string> &&
216 !std::is_same_v<flattened, std::string_view> && !require_custom_serialization<flattened>,
217 "simdjson::flatten requires a member whose type is a structure serialized member by member");
218 atom_fields(w, t.[:dm:], first);
223 constexpr const char* key_name = simdjson::get_json_key_name<dm>();
224 constexpr size_t first_key_len = constevalutil::consteval_to_quoted_escaped(key_name).size() + 1;
225 constexpr size_t rest_key_len = first_key_len + 1;
226 constexpr auto first_key = std::define_static_string(
227 constevalutil::consteval_to_quoted_escaped(key_name) +
":" +
228 std::string(padded_key_length(first_key_len) - first_key_len,
'\0'));
229 constexpr auto rest_key = std::define_static_string(
230 std::string(
",") + constevalutil::consteval_to_quoted_escaped(key_name) +
":" +
231 std::string(padded_key_length(rest_key_len) - rest_key_len,
'\0'));
232 if (!w.ensure(padded_key_length(rest_key_len))) {
return; }
234 std::memcpy(w.ptr + w.pos, first_key, padded_key_length(first_key_len));
235 w.pos += first_key_len;
237 std::memcpy(w.ptr + w.pos, rest_key, padded_key_length(rest_key_len));
238 w.pos += rest_key_len;
241 atom_member<dm>(w, t.[:dm:]);
250template <
class W,
class T>
251 requires(concepts::container_but_not_string<T> && !require_custom_serialization<T>)
252simdjson_really_inline
constexpr void atom(W &w,
const T &t) {
256 if (!w.ensure(2))
return;
257 std::memcpy(w.ptr + w.pos,
"[]", 2);
261 if (!w.ensure(1))
return;
262 w.ptr[w.pos++] =
'[';
265 for (; it != end; ++it) {
266 if (!w.ensure(1))
return;
267 w.ptr[w.pos++] =
',';
270 if (!w.ensure(1))
return;
271 w.ptr[w.pos++] =
']';
274template <
class W,
class T>
275 requires(std::is_same_v<T, std::string> ||
276 std::is_same_v<T, std::string_view> ||
277 std::is_same_v<T, const char *> ||
278 std::is_same_v<T, char>)
279simdjson_really_inline
constexpr void atom(W &w,
const T &t) {
283 std::string_view input;
284 if constexpr (std::is_same_v<T, char>) {
285 input = std::string_view(&t, 1);
287 input = std::string_view(t);
295 if constexpr (W::checked) {
296 if (simdjson_unlikely(input.size() >= ((std::numeric_limits<size_t>::max)() - w.pos) / 6)) {
return; }
297 if (!w.ensure(2 + 6 * input.size())) {
return; }
299 w.ptr[w.pos++] =
'"';
300 w.pos += write_string_escaped(input, w.ptr + w.pos);
301 w.ptr[w.pos++] =
'"';
304template <
class W, concepts::
string_view_keyed_map T>
305 requires(!require_custom_serialization<T>)
306simdjson_really_inline
constexpr void atom(W &w,
const T &m) {
308 if (!w.ensure(2))
return;
309 std::memcpy(w.ptr + w.pos,
"{}", 2);
313 if (!w.ensure(1))
return;
314 w.ptr[w.pos++] =
'{';
316 for (
const auto& [key, value] : m) {
318 if (!w.ensure(1))
return;
319 w.ptr[w.pos++] =
',';
323 std::string_view key_sv(key);
329 if constexpr (W::checked) {
330 if (simdjson_unlikely(key_sv.size() >= ((std::numeric_limits<size_t>::max)() - w.pos) / 6)) {
return; }
331 if (!w.ensure(2 + 6 * key_sv.size() + 1)) {
return; }
333 w.ptr[w.pos++] =
'"';
334 w.pos += write_string_escaped(key_sv, w.ptr + w.pos);
335 w.ptr[w.pos++] =
'"';
336 w.ptr[w.pos++] =
':';
339 if (!w.ensure(1))
return;
340 w.ptr[w.pos++] =
'}';
344template<
class W,
typename number_type,
345 typename =
typename std::enable_if<std::is_arithmetic<number_type>::value && !std::is_same_v<number_type, char>>::type>
346simdjson_really_inline
constexpr void atom(W &w,
const number_type t) {
350 if constexpr (std::is_same_v<number_type, bool>) {
352 if (!w.ensure(4))
return;
353 std::memcpy(w.ptr + w.pos,
"true", 4);
356 if (!w.ensure(5))
return;
357 std::memcpy(w.ptr + w.pos,
"false", 5);
360 }
else if constexpr (std::is_floating_point_v<number_type>) {
361 if constexpr (W::checked) {
362 call_through_string_builder(w, [&](string_builder &b) { b.append(t); });
364 w.pos = size_t(internal::write_double(w.ptr + w.pos,
double(t)) - w.ptr);
366 }
else if constexpr (std::is_unsigned_v<number_type>) {
367 if (!w.ensure(20))
return;
368 char *end = internal::write_uint_jeaiii(
369 w.ptr + w.pos,
static_cast<uint64_t
>(t));
370 w.pos =
static_cast<size_t>(end - w.ptr);
373 if (!w.ensure(20))
return;
374 using U =
typename std::make_unsigned<number_type>::type;
375 bool negative = t < 0;
376 U pv = negative ? U(0) -
static_cast<U
>(t) : static_cast<U>(t);
379 char *end = internal::write_uint_jeaiii(
380 w.ptr + w.pos,
static_cast<uint64_t
>(pv));
381 w.pos =
static_cast<size_t>(end - w.ptr);
385template <
class W,
class T>
386 requires(std::is_class_v<T> && !concepts::container_but_not_string<T> &&
387 !concepts::string_view_keyed_map<T> &&
388 !concepts::optional_type<T> &&
389 !concepts::smart_pointer<T> &&
390 !concepts::appendable_containers<T> &&
391 !std::is_same_v<T, std::string> &&
392 !std::is_same_v<T, std::string_view> &&
393 !std::is_same_v<T, const char*> &&
394 !std::is_same_v<T, char> && !require_custom_serialization<T>)
395simdjson_really_inline
constexpr void atom(W &w,
const T &t) {
396 if constexpr (simdjson::detail::has_annotation(^^T, ^^simdjson::detail::transparent_tag)) {
398 constexpr auto dm = simdjson::detail::transparent_member(^^T);
399 annotation_detail::atom_member<dm>(w, t.[:dm:]);
402 if (!w.ensure(1)) {
return; }
403 w.ptr[w.pos++] =
'{';
404 annotation_detail::atom_fields(w, t, first);
405 if (!w.ensure(1)) {
return; }
406 w.ptr[w.pos++] =
'}';
411template <
class W, concepts::optional_type T>
412 requires(!require_custom_serialization<T>)
413simdjson_really_inline
constexpr void atom(W &w,
const T &opt) {
415 atom(w, opt.value());
417 if (!w.ensure(4))
return;
418 std::memcpy(w.ptr + w.pos,
"null", 4);
424template <
class W, concepts::smart_po
inter T>
425 requires(!require_custom_serialization<T>)
426simdjson_really_inline
constexpr void atom(W &w,
const T &ptr) {
430 if (!w.ensure(4))
return;
431 std::memcpy(w.ptr + w.pos,
"null", 4);
437template <
class W,
typename T>
438 requires(std::is_enum_v<T> && !require_custom_serialization<T>)
439simdjson_really_inline
void atom(W &w,
const T &e) {
440#if SIMDJSON_STATIC_REFLECTION
441 static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
442 template for (
constexpr auto enum_val : enumerators) {
443 constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(simdjson::get_json_key_name<enum_val>()));
444 constexpr size_t enum_str_len = std::char_traits<char>::length(enum_str);
445 if (e == [:enum_val:]) {
446 if (!w.ensure(enum_str_len))
return;
447 std::memcpy(w.ptr + w.pos, enum_str, enum_str_len);
448 w.pos += enum_str_len;
453 atom(w,
static_cast<std::underlying_type_t<T>
>(e));
456 atom(w,
static_cast<std::underlying_type_t<T>
>(e));
461template <
class W, concepts::appendable_containers T>
462 requires(!concepts::container_but_not_string<T> && !concepts::string_view_keyed_map<T> &&
463 !concepts::optional_type<T> && !concepts::smart_pointer<T> &&
464 !std::is_same_v<T, std::string> &&
465 !std::is_same_v<T, std::string_view> && !std::is_same_v<T, const char*> && !require_custom_serialization<T>)
466simdjson_really_inline
constexpr void atom(W &w,
const T &container) {
467 if (container.empty()) {
468 if (!w.ensure(2))
return;
469 std::memcpy(w.ptr + w.pos,
"[]", 2);
473 if (!w.ensure(1))
return;
474 w.ptr[w.pos++] =
'[';
476 for (
const auto& item : container) {
478 if (!w.ensure(1))
return;
479 w.ptr[w.pos++] =
',';
484 if (!w.ensure(1))
return;
485 w.ptr[w.pos++] =
']';
494namespace bound_detail {
500consteval bool is_bounded() {
501 if constexpr (require_custom_serialization<T>) {
503 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view> ||
504 std::is_same_v<T, const char *> || std::is_arithmetic_v<T> || std::is_enum_v<T>) {
506 }
else if constexpr (concepts::optional_type<T> || concepts::smart_pointer<T>) {
507 return is_bounded<std::remove_cvref_t<decltype(*std::declval<const T &>())>>();
508 }
else if constexpr (concepts::string_view_keyed_map<T>) {
509 return is_bounded<std::remove_cvref_t<typename T::mapped_type>>();
510 }
else if constexpr (concepts::container_but_not_string<T> || concepts::appendable_containers<T>) {
511 return is_bounded<std::remove_cvref_t<std::ranges::range_value_t<T>>>();
514 template for (
constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
515 if constexpr (annotation_detail::is_serialized_member(dm)) {
516 bounded = bounded && simdjson::detail::annotation_of_template(dm, ^^simdjson::detail::with_t) == std::meta::info{} &&
517 is_bounded<std::remove_cvref_t<decltype(std::declval<const T &>().[:dm:])>>();
525consteval size_t enum_bound() {
527 template for (
constexpr auto enum_val : std::define_static_array(std::meta::enumerators_of(^^T))) {
528 constexpr size_t len = std::char_traits<char>::length(std::define_static_string(
529 constevalutil::consteval_to_quoted_escaped(simdjson::get_json_key_name<enum_val>())));
530 bound = (std::max)(bound, len);
536simdjson_really_inline
size_t size_bound(
const T &t)
noexcept;
540simdjson_really_inline
size_t fields_bound(
const T &t)
noexcept {
542 template for (
constexpr auto dm : std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
543 if constexpr (annotation_detail::is_serialized_member(dm)) {
544 if constexpr (simdjson::detail::has_annotation(dm, ^^simdjson::detail::flatten_tag)) {
545 bound += fields_bound(t.[:dm:]);
547 constexpr size_t rest_key_len = constevalutil::consteval_to_quoted_escaped(simdjson::get_json_key_name<dm>()).size() + 2;
548 bound += rest_key_len + size_bound(t.[:dm:]);
556simdjson_really_inline
size_t size_bound([[maybe_unused]]
const T &t)
noexcept {
557 if constexpr (std::is_same_v<T, char>) {
559 }
else if constexpr (std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view> ||
560 std::is_same_v<T, const char *>) {
562 return 2 + 6 * std::string_view(t).size();
563 }
else if constexpr (std::is_same_v<T, bool>) {
565 }
else if constexpr (std::is_floating_point_v<T>) {
566 return simdjson::internal::to_chars_buffer_size;
567 }
else if constexpr (std::is_arithmetic_v<T>) {
569 }
else if constexpr (std::is_enum_v<T>) {
570 return enum_bound<T>();
571 }
else if constexpr (concepts::optional_type<T> || concepts::smart_pointer<T>) {
572 return t ? size_bound(*t) : 4;
573 }
else if constexpr (concepts::string_view_keyed_map<T>) {
575 for (
const auto &[key, value] : t) {
577 bound += 4 + 6 * std::string_view(key).size() + size_bound(value);
580 }
else if constexpr (concepts::container_but_not_string<T> || concepts::appendable_containers<T>) {
581 using value_type = std::remove_cvref_t<std::ranges::range_value_t<T>>;
582 if constexpr (std::is_arithmetic_v<value_type> && !std::is_same_v<value_type, char>) {
584 return 2 + size_t(std::ranges::distance(t)) * (1 + size_bound(value_type{}));
587#if defined(__GNUC__) && !defined(__clang__)
591 for (
const auto &item : t) {
592 bound += 1 + size_bound(item);
596 }
else if constexpr (simdjson::detail::has_annotation(^^T, ^^simdjson::detail::transparent_tag)) {
597 constexpr auto dm = simdjson::detail::transparent_member(^^T);
598 return size_bound(t.[:dm:]);
600 return 2 + fields_bound(t);
609simdjson_really_inline
void append_bounded(string_builder &b,
const T &t) {
611 if constexpr (
sizeof(size_t) >= 8 && bound_detail::is_bounded<T>()) {
612 const size_t bound = bound_detail::size_bound(t) + unchecked_slack;
613 const size_t pos = b.unsafe_position();
616 if (
sizeof(
size_t) >= 8 || bound <= (std::numeric_limits<size_t>::max)() - pos) {
617 const size_t cap = b.unsafe_capacity();
619 if (pos + bound <= cap || b.unsafe_grow((std::max)(cap * 2, pos + bound))) {
620 unchecked_writer w(b.unsafe_data(), pos);
622 b.unsafe_set_position(w.pos);
636 requires(std::is_arithmetic_v<T> && !std::is_same_v<T, char>)
637simdjson_inline
void append(string_builder &b,
const T &t) {
644 requires(std::is_same_v<T, std::string> ||
645 std::is_same_v<T, std::string_view> ||
646 std::is_same_v<T, const char *> ||
647 std::is_same_v<T, char>)
648simdjson_inline
void append(string_builder &b,
const T &t) {
654template <concepts::optional_type T>
655 requires(!require_custom_serialization<T>)
656simdjson_inline
void append(string_builder &b,
const T &t) {
657 append_bounded(b, t);
660template <concepts::smart_po
inter T>
661 requires(!require_custom_serialization<T>)
662simdjson_inline
void append(string_builder &b,
const T &t) {
663 append_bounded(b, t);
666template <concepts::appendable_containers T>
667 requires(!concepts::container_but_not_string<T> && !concepts::string_view_keyed_map<T> &&
668 !concepts::optional_type<T> && !concepts::smart_pointer<T> &&
669 !std::is_same_v<T, std::string> &&
670 !std::is_same_v<T, std::string_view> && !std::is_same_v<T, const char*> && !require_custom_serialization<T>)
671simdjson_inline
void append(string_builder &b,
const T &t) {
672 append_bounded(b, t);
675template <concepts::
string_view_keyed_map T>
676 requires(!require_custom_serialization<T>)
677simdjson_inline
void append(string_builder &b,
const T &t) {
678 append_bounded(b, t);
683 requires(std::is_class_v<Z> && !concepts::container_but_not_string<Z> &&
684 !concepts::string_view_keyed_map<Z> &&
685 !concepts::optional_type<Z> &&
686 !concepts::smart_pointer<Z> &&
687 !concepts::appendable_containers<Z> &&
688 !std::is_same_v<Z, std::string> &&
689 !std::is_same_v<Z, std::string_view> &&
690 !std::is_same_v<Z, const char*> &&
691 !std::is_same_v<Z, char> && !require_custom_serialization<Z>)
692simdjson_inline
void append(string_builder &b,
const Z &z) {
693 append_bounded(b, z);
698 requires(concepts::container_but_not_string<Z> && !require_custom_serialization<Z>)
699simdjson_inline
void append(string_builder &b,
const Z &z) {
700 append_bounded(b, z);
704 requires (require_custom_serialization<Z>)
705void append(string_builder &b,
const Z &z) {
711simdjson_warn_unused
error_code to_json(
const Z &z, std::string &s,
size_t initial_capacity = string_builder::DEFAULT_INITIAL_CAPACITY) {
712 if constexpr (
sizeof(size_t) >= 8 && bound_detail::is_bounded<Z>()) {
714 (void)initial_capacity;
715 const size_t bound = bound_detail::size_bound(z) + unchecked_slack;
716 auto write = [&z](
char *p)
noexcept {
717 unchecked_writer w(p, 0);
721#if defined(__cpp_lib_string_resize_and_overwrite) && __cpp_lib_string_resize_and_overwrite >= 202110L
722 s.resize_and_overwrite(bound, [&write](
char *p,
size_t)
noexcept {
return write(p); });
725 s.resize(write(s.data()));
729 string_builder b(initial_capacity);
731 std::string_view view;
732 if(
auto e = b.view().get(view); e) {
return e; }
739simdjson_warn_unused simdjson_result<std::string>
to_json_string(
const Z &z,
size_t initial_capacity = string_builder::DEFAULT_INITIAL_CAPACITY) {
741 if(
auto e = to_json(z, s, initial_capacity); e) {
return e; }
746string_builder& operator<<(string_builder& b,
const Z& z) {
752template<constevalutil::fixed_string... FieldNames,
typename T>
753 requires(std::is_class_v<T> && (
sizeof...(FieldNames) > 0))
754void extract_from(string_builder &b,
const T &obj) {
756 if (!w.ensure(1)) { w.sync();
return; }
757 w.ptr[w.pos++] =
'{';
760 static constexpr auto members = std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()));
761 template for (
constexpr auto mem : members) {
762 if constexpr (std::meta::is_public(mem)) {
763 static constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
766 if constexpr (((FieldNames.view() == key) || ...)) {
767 static constexpr auto first_key = std::define_static_string(
768 constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)) +
":");
769 static constexpr auto rest_key = std::define_static_string(
770 std::string(
",") + constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)) +
":");
771 constexpr size_t first_key_len = std::char_traits<char>::length(first_key);
772 constexpr size_t rest_key_len = std::char_traits<char>::length(rest_key);
773 if (!w.ensure(rest_key_len)) { w.sync();
return; }
775 std::memcpy(w.ptr + w.pos, first_key, first_key_len);
776 w.pos += first_key_len;
778 std::memcpy(w.ptr + w.pos, rest_key, rest_key_len);
779 w.pos += rest_key_len;
782 atom(w, obj.[:mem:]);
787 if (!w.ensure(1)) { w.sync();
return; }
788 w.ptr[w.pos++] =
'}';
792template<constevalutil::fixed_string... FieldNames,
typename T>
793 requires(std::is_class_v<T> && (
sizeof...(FieldNames) > 0))
794simdjson_warn_unused simdjson_result<std::string> extract_from(
const T &obj,
size_t initial_capacity = string_builder::DEFAULT_INITIAL_CAPACITY) {
795 string_builder b(initial_capacity);
796 extract_from<FieldNames...>(b, obj);
798 if(
auto e = b.view().get(s); e) {
return e; }
799 return std::string(s);
802SIMDJSON_POP_DISABLE_WARNINGS
808simdjson_warn_unused simdjson_result<std::string> to_json(
const Z &z,
size_t initial_capacity = SIMDJSON_IMPLEMENTATION::builder::string_builder::DEFAULT_INITIAL_CAPACITY) {
809 return SIMDJSON_IMPLEMENTATION::builder::to_json_string(z, initial_capacity);
812simdjson_warn_unused
error_code to_json(
const Z &z, std::string &s,
size_t initial_capacity = SIMDJSON_IMPLEMENTATION::builder::string_builder::DEFAULT_INITIAL_CAPACITY) {
813 return SIMDJSON_IMPLEMENTATION::builder::to_json(z, s, initial_capacity);
816template<constevalutil::fixed_string... FieldNames,
typename T>
817 requires(std::is_class_v<T> && (
sizeof...(FieldNames) > 0))
818simdjson_warn_unused simdjson_result<std::string> extract_from(
const T &obj,
size_t initial_capacity = SIMDJSON_IMPLEMENTATION::builder::string_builder::DEFAULT_INITIAL_CAPACITY) {
819 SIMDJSON_IMPLEMENTATION::builder::string_builder b(initial_capacity);
820 SIMDJSON_IMPLEMENTATION::builder::extract_from<FieldNames...>(b, obj);
822 if(
auto e = b.view().get(s); e) {
return e; }
823 return std::string(s);
Provides compile-time annotations for simdjson structures.
The top level simdjson namespace, containing everything the library provides.
simdjson_result< std::string_view > to_json_string(SIMDJSON_IMPLEMENTATION::ondemand::document &x) noexcept
Create a string-view instance out of a document instance.
error_code
All possible errors returned by simdjson.