Get reflection working without warnings under GCC 16 (#2658)

* wip gcc16

* progress

* minor gcc16 fixes

* final step

* Update include/simdjson/padded_string-inl.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update include/simdjson/padded_string.h

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* renaming test function

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Daniel Lemire
2026-04-03 15:32:42 -04:00
committed by GitHub
parent fb83b114ef
commit 73e69a5e84
23 changed files with 750 additions and 779 deletions
+24
View File
@@ -167,13 +167,37 @@ if(MSVC)
endif()
endif()
if(SIMDJSON_STATIC_REFLECTION)
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION MATCHES "^21")
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} --version
OUTPUT_VARIABLE CLANG_VERSION_OUTPUT
ERROR_VARIABLE CLANG_VERSION_ERROR
RESULT_VARIABLE CLANG_VERSION_RESULT
)
if(CLANG_VERSION_RESULT EQUAL 0 AND CLANG_VERSION_OUTPUT MATCHES "https://github.com/bloomberg/clang-p2996.git")
set(IS_BLOOMBERG_P2996_CLANG ON)
message(STATUS "Using Bloomberg P2996 Clang fork")
endif()
endif()
# We would like to require C++26, but no compiler supports that!
# This is a hack:
if(IS_BLOOMBERG_P2996_CLANG)
simdjson_add_props(
target_compile_options PUBLIC
-freflection -fexpansion-statements -stdlib=libc++ -std=c++26
)
else()
simdjson_add_props(
target_compile_options PUBLIC
-freflection -std=c++26
)
endif()
else()
simdjson_add_props(target_compile_features PUBLIC cxx_std_11)
endif()
-4
View File
@@ -1300,10 +1300,6 @@ You can also use the custom `Car` type as part of a template such as `std::vecto
simdjson::ondemand::parser parser;
simdjson::ondemand::document doc = parser.iterate(json);
std::vector<Car> cars(doc);
// visual studio users need an explicit call:
// std::vector<Car> cars = doc.get<std::vector<Car>>();
// because the compiler does not know whether to convert
// doc to an unsigned int or to a vector.
for(Car& c : cars) {
std::cout << c.year << std::endl;
}
+35 -34
View File
@@ -266,6 +266,12 @@ consteval std::pair<double, size_t> parse_double(const char *src,
}
} // namespace number_parsing
consteval auto make_data_member_options(auto&& name_str) {
std::meta::data_member_options options{};
options.name = std::forward<decltype(name_str)>(name_str);
return options;
}
// JSON string may contain embedded nulls, and C++26 reflection does not yet
// support std::string_view as a data member type. As a workaround, we define
// a custom type that holds a const char* and a size.
@@ -320,7 +326,8 @@ using class_type = type_builder<meta_info...>::constructed_type;
/**
* @brief Variable template for constructing instances with values
*/
template <typename T, auto... Vs> constexpr auto construct_from = T{Vs...};
template <typename T, auto... Vs> constexpr T construct_from = T{Vs...};
// in JSON, there are only a few whitespace characters that are allowed
// outside of objects, arrays, strings, and numbers.
@@ -410,7 +417,7 @@ parse_number(std::string_view json,
std::from_chars(json.data(), json.data() + json.size(), int_value);
if (res.ec == std::errc()) {
out = int_value;
if ((res.ptr - json.data()) != scope) {
if (static_cast<std::size_t>(res.ptr - json.data()) != scope) {
simdjson_consteval_error(
"Internal error: cannot agree on the character range of the float");
}
@@ -424,7 +431,7 @@ parse_number(std::string_view json,
std::from_chars(json.data(), json.data() + json.size(), uint_value);
if (res.ec == std::errc()) {
out = uint_value;
if ((res.ptr - json.data()) != scope) {
if (static_cast<std::size_t>(res.ptr - json.data()) != scope) {
simdjson_consteval_error(
"Internal error: cannot agree on the character range of the float");
}
@@ -533,7 +540,7 @@ parse_string(std::string_view json) {
// present, we have an error (isolated high surrogate), which we
// tolerate by substituting the substitution_code_point.
if (end - cursor < 6 || *cursor != '\\' ||
*(cursor + 1) != 'u' > 0xFFFF) {
*(cursor + 1) != 'u') {
code_point = substitution_code_point;
} else { // we have \u following the high surrogate
cursor += 2; // skip \u
@@ -887,10 +894,19 @@ parse_json_array_impl(const std::string_view json) {
std::size_t count = values.size() - 1;
// We assume all elements have the same type as the first element.
// However, if the array is heterogeneous, we should use std::variant.
auto elem_type = std::meta::type_of(values[1]);
// String literals reflected via reflect_constant_string have type const
// char[N], but when passed as template auto parameters they decay to
// const char*. Use const char* as the element type so that
// construct_from can aggregate-initialize the array.
if (std::meta::is_array_type(elem_type) &&
std::meta::remove_all_extents(elem_type) == ^^const char) {
elem_type = ^^const char *;
}
auto array_type = std::meta::substitute(
^^std::array,
{
std::meta::type_of(values[1]), std::meta::reflect_constant(count)});
elem_type, std::meta::reflect_constant(count)});
// Create array instance with values
values[0] = array_type;
@@ -957,8 +973,7 @@ parse_json_object_impl(std::string_view json) {
simdjson_consteval_error("Expected '}'");
}
cursor += object_size;
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
{.name = field_name});
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed), make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(parsed);
@@ -967,8 +982,7 @@ parse_json_object_impl(std::string_view json) {
case '[': {
std::string_view value(cursor, end);
auto [parsed, array_size] = parse_json_array_impl(value);
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed),
{.name = field_name});
auto dms = std::meta::data_member_spec(std::meta::type_of(parsed), make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(parsed);
if (*(cursor + array_size - 1) != ']') {
@@ -989,8 +1003,7 @@ parse_json_object_impl(std::string_view json) {
}
}
auto dms =
std::meta::data_member_spec(^^const char *, {
.name = field_name});
std::meta::data_member_spec(^^const char *, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant_string(value));
break;
@@ -1001,8 +1014,7 @@ parse_json_object_impl(std::string_view json) {
}
cursor += 4;
auto dms = std::meta::data_member_spec(^^bool, {
.name = field_name});
auto dms = std::meta::data_member_spec(^^bool, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(true));
break;
@@ -1013,8 +1025,7 @@ parse_json_object_impl(std::string_view json) {
}
cursor += 5;
auto dms = std::meta::data_member_spec(^^bool, {
.name = field_name});
auto dms = std::meta::data_member_spec(^^bool, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(false));
break;
@@ -1025,9 +1036,7 @@ parse_json_object_impl(std::string_view json) {
}
cursor += 4;
auto dms = std::meta::data_member_spec(^^std::nullptr_t,
{
.name = field_name});
auto dms = std::meta::data_member_spec(^^std::nullptr_t, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(nullptr));
break;
@@ -1051,22 +1060,19 @@ parse_json_object_impl(std::string_view json) {
if (std::holds_alternative<int64_t>(out)) {
int64_t int_value = std::get<int64_t>(out);
auto dms =
std::meta::data_member_spec(^^int64_t, {
.name = field_name});
std::meta::data_member_spec(^^int64_t, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(int_value));
} else if (std::holds_alternative<uint64_t>(out)) {
uint64_t uint_value = std::get<uint64_t>(out);
auto dms =
std::meta::data_member_spec(^^uint64_t, {
.name = field_name});
std::meta::data_member_spec(^^uint64_t, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(uint_value));
} else {
double float_value = std::get<double>(out);
auto dms =
std::meta::data_member_spec(^^double, {
.name = field_name});
std::meta::data_member_spec(^^double, make_data_member_options(field_name));
members.push_back(std::meta::reflect_constant(dms));
values.push_back(std::meta::reflect_constant(float_value));
}
@@ -1111,16 +1117,11 @@ template <constevalutil::fixed_string json_str> consteval auto parse_json() {
"Only JSON objects and arrays are supported at the top level, this "
"limitation will be lifted in the future.");*/
constexpr auto result = json.front() == '['
? parse_json_array_impl(json)
: parse_json_object_impl(json);
return [: result.first :];
/*
if(json.front() == '[') {
return [:parse_json_array_impl(json).first:];
} else if(json.front() == '{') {
// return [:parse_json_object_impl(json).first:];
}*/
if constexpr (json.front() == '[') {
return [: parse_json_array_impl(json).first :];
} else {
return [: parse_json_object_impl(json).first :];
}
}
} // namespace compile_time
+5
View File
@@ -58,6 +58,11 @@ struct fixed_string {
data[i] = str[i];
}
}
constexpr fixed_string(const unsigned char (&str)[N]) {
for (std::size_t i = 0; i < N; ++i) {
data[i] = static_cast<char>(str[i]);
}
}
char data[N];
constexpr std::string_view view() const { return {data, N - 1}; }
constexpr size_t size() const { return N ; }
@@ -22,7 +22,7 @@ namespace SIMDJSON_IMPLEMENTATION {
namespace builder {
template <class T>
requires(concepts::container_but_not_string<T> && !require_custom_serialization<T>)
requires(concepts::container_but_not_string<T> && ! concepts::optional_type<T> && !require_custom_serialization<T>)
constexpr void atom(string_builder &b, const T &t) {
auto it = t.begin();
auto end = t.end();
@@ -130,7 +130,7 @@ template <typename T>
requires(std::is_enum_v<T> && !require_custom_serialization<T>)
void atom(string_builder &b, const T &e) {
#if SIMDJSON_STATIC_REFLECTION
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
template for (constexpr auto enum_val : enumerators) {
constexpr auto enum_str = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(enum_val)));
if (e == [:enum_val:]) {
@@ -294,30 +294,23 @@ string_builder& operator<<(string_builder& b, const Z& z) {
template<constevalutil::fixed_string... FieldNames, typename T>
requires(std::is_class_v<T> && (sizeof...(FieldNames) > 0))
void extract_from(string_builder &b, const T &obj) {
// Helper to check if a field name matches any of the requested fields
auto should_extract = [](std::string_view field_name) constexpr -> bool {
return ((FieldNames.view() == field_name) || ...);
};
b.append('{');
bool first = true;
// Iterate through all members of T using reflection
template for (constexpr auto mem : std::define_static_array(
std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()))) {
static constexpr auto members = std::define_static_array(std::meta::nonstatic_data_members_of(^^T, std::meta::access_context::unchecked()));
template for (constexpr auto mem : members) {
if constexpr (std::meta::is_public(mem)) {
constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
static constexpr std::string_view key = std::define_static_string(std::meta::identifier_of(mem));
// Only serialize this field if it's in our list of requested fields
if constexpr (should_extract(key)) {
if constexpr (((FieldNames.view() == key) || ...)) {
if (!first) {
b.append(',');
}
first = false;
// Serialize the key
constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
static constexpr auto quoted_key = std::define_static_string(constevalutil::consteval_to_quoted_escaped(std::meta::identifier_of(mem)));
b.append_raw(quoted_key);
b.append(':');
@@ -505,7 +505,7 @@ simdjson_inline bool string_builder::capacity_check(size_t upcoming_bytes) {
return is_valid;
}
simdjson_inline void string_builder::grow_buffer(size_t desired_capacity) {
inline void string_builder::grow_buffer(size_t desired_capacity) {
if (!is_valid) {
return;
}
@@ -842,7 +842,7 @@ simdjson_inline void string_builder::append(const T &value) {
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
// Support for range-based appending (std::ranges::view, etc.)
template <std::ranges::range R>
requires(!std::is_convertible<R, std::string_view>::value && !require_custom_serialization<R>)
requires(!std::is_convertible<R, std::string_view>::value && !concepts::optional_type<R> && !require_custom_serialization<R>)
simdjson_inline void string_builder::append(const R &range) noexcept {
auto it = std::ranges::begin(range);
auto end = std::ranges::end(range);
@@ -171,7 +171,7 @@ public:
#if SIMDJSON_SUPPORTS_RANGES && SIMDJSON_SUPPORTS_CONCEPTS
// Support for range-based appending (std::ranges::view, etc.)
template <std::ranges::range R>
requires (!std::is_convertible<R, std::string_view>::value && !require_custom_serialization<R>)
requires (!std::is_convertible<R, std::string_view>::value && !concepts::optional_type<R> && !require_custom_serialization<R>)
simdjson_inline void append(const R &range) noexcept;
#endif
/**
@@ -249,7 +249,7 @@ private:
* If the allocation fails, is_valid is set to false. We expect
* that this function would not be repeatedly called.
*/
simdjson_inline void grow_buffer(size_t desired_capacity);
inline void grow_buffer(size_t desired_capacity);
/**
* We use this helper function to make sure that is_valid is kept consistent.
@@ -653,27 +653,27 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::op
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator uint64_t() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_uint64();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator int64_t() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_int64();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator double() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_double();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator std::string_view() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_string();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_raw_json_string();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator bool() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_bool();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
@@ -1042,27 +1042,27 @@ simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_refe
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator uint64_t() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_uint64();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator int64_t() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_int64();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator double() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_double();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator std::string_view() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_string();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_raw_json_string();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator bool() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
return first;
return first.get_bool();
}
simdjson_inline simdjson_result<SIMDJSON_IMPLEMENTATION::ondemand::document_reference>::operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false) {
if (error()) { throw simdjson_error(error()); }
+24 -24
View File
@@ -319,21 +319,21 @@ public:
* @returns A signed 64-bit integer.
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit unsigned integer.
*/
simdjson_inline operator uint64_t() noexcept(false);
explicit simdjson_inline operator uint64_t() noexcept(false);
/**
* Cast this JSON value to a signed integer.
*
* @returns A signed 64-bit integer.
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a 64-bit integer.
*/
simdjson_inline operator int64_t() noexcept(false);
explicit simdjson_inline operator int64_t() noexcept(false);
/**
* Cast this JSON value to a double.
*
* @returns A double.
* @exception simdjson_error(INCORRECT_TYPE) If the JSON value is not a valid floating-point number.
*/
simdjson_inline operator double() noexcept(false);
explicit simdjson_inline operator double() noexcept(false);
/**
* Cast this JSON value to a string.
*
@@ -343,7 +343,7 @@ public:
* time it parses a document or when it is destroyed.
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
*/
simdjson_inline operator std::string_view() noexcept(false) simdjson_lifetime_bound;
explicit simdjson_inline operator std::string_view() noexcept(false) simdjson_lifetime_bound;
/**
* Cast this JSON value to a raw_json_string.
*
@@ -352,14 +352,14 @@ public:
* @returns A pointer to the raw JSON for the given string.
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not a string.
*/
simdjson_inline operator raw_json_string() noexcept(false) simdjson_lifetime_bound;
explicit simdjson_inline operator raw_json_string() noexcept(false) simdjson_lifetime_bound;
/**
* Cast this JSON value to a bool.
*
* @returns A bool value.
* @exception simdjson_error(INCORRECT_TYPE) if the JSON value is not true or false.
*/
simdjson_inline operator bool() noexcept(false);
explicit simdjson_inline operator bool() noexcept(false);
/**
* Cast this JSON value to a value when the document is an object or an array.
*
@@ -945,12 +945,12 @@ public:
explicit simdjson_inline operator T() noexcept(false);
simdjson_inline operator array() & noexcept(false);
simdjson_inline operator object() & noexcept(false);
simdjson_inline operator uint64_t() noexcept(false);
simdjson_inline operator int64_t() noexcept(false);
simdjson_inline operator double() noexcept(false);
simdjson_inline operator std::string_view() noexcept(false);
simdjson_inline operator raw_json_string() noexcept(false);
simdjson_inline operator bool() noexcept(false);
explicit simdjson_inline operator uint64_t() noexcept(false);
explicit simdjson_inline operator int64_t() noexcept(false);
explicit simdjson_inline operator double() noexcept(false);
explicit simdjson_inline operator std::string_view() noexcept(false);
explicit simdjson_inline operator raw_json_string() noexcept(false);
explicit simdjson_inline operator bool() noexcept(false);
simdjson_inline operator value() noexcept(false);
#endif
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
@@ -1030,12 +1030,12 @@ public:
explicit simdjson_inline operator T() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
simdjson_inline operator uint64_t() noexcept(false);
simdjson_inline operator int64_t() noexcept(false);
simdjson_inline operator double() noexcept(false);
simdjson_inline operator std::string_view() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
simdjson_inline operator bool() noexcept(false);
explicit simdjson_inline operator uint64_t() noexcept(false);
explicit simdjson_inline operator int64_t() noexcept(false);
explicit simdjson_inline operator double() noexcept(false);
explicit simdjson_inline operator std::string_view() noexcept(false);
explicit simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
explicit simdjson_inline operator bool() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
#endif
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
@@ -1116,12 +1116,12 @@ public:
explicit simdjson_inline operator T() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::array() & noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::object() & noexcept(false);
simdjson_inline operator uint64_t() noexcept(false);
simdjson_inline operator int64_t() noexcept(false);
simdjson_inline operator double() noexcept(false);
simdjson_inline operator std::string_view() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
simdjson_inline operator bool() noexcept(false);
explicit simdjson_inline operator uint64_t() noexcept(false);
explicit simdjson_inline operator int64_t() noexcept(false);
explicit simdjson_inline operator double() noexcept(false);
explicit simdjson_inline operator std::string_view() noexcept(false);
explicit simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::raw_json_string() noexcept(false);
explicit simdjson_inline operator bool() noexcept(false);
simdjson_inline operator SIMDJSON_IMPLEMENTATION::ondemand::value() noexcept(false);
#endif
simdjson_inline simdjson_result<size_t> count_elements() & noexcept;
@@ -305,7 +305,7 @@ error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept {
#if SIMDJSON_STATIC_REFLECTION
std::string_view str;
SIMDJSON_TRY(val.get_string().get(str));
constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
static constexpr auto enumerators = std::define_static_array(std::meta::enumerators_of(^^T));
template for (constexpr auto enum_val : enumerators) {
if (str == std::meta::identifier_of(enum_val)) {
out = [:enum_val:];
+11
View File
@@ -0,0 +1,11 @@
{
"app_name": "MyApp",
"version": "1.0.0",
"port": 8080,
"debug": true,
"features": ["logging", "caching"],
"database": {
"host": "localhost",
"port": 5432
}
}
+6 -1
View File
@@ -1,4 +1,4 @@
/* auto-generated on 2026-04-03 15:25:03 -0400. version 4.6.1 Do not edit! */
/* auto-generated on 2026-04-02 19:14:16 -0400. version 4.6.1 Do not edit! */
/* including simdjson.cpp: */
/* begin file simdjson.cpp */
#define SIMDJSON_SRC_SIMDJSON_CPP
@@ -3168,6 +3168,11 @@ struct fixed_string {
data[i] = str[i];
}
}
constexpr fixed_string(const unsigned char (&str)[N]) {
for (std::size_t i = 0; i < N; ++i) {
data[i] = static_cast<char>(str[i]);
}
}
char data[N];
constexpr std::string_view view() const { return {data, N - 1}; }
constexpr size_t size() const { return N ; }
+473 -530
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.
@@ -6,40 +6,40 @@
using namespace simdjson;
struct Car {
std::string make;
std::string model;
int64_t year;
std::vector<double> tire_pressure;
std::string make{};
std::string model{};
int64_t year{};
std::vector<double> tire_pressure{};
};
struct kid {
int age;
std::string name;
std::vector<std::string> toys;
int age{};
std::string name{};
std::vector<std::string> toys{};
bool operator<=> (const kid&) const = default;
};
struct Z {
int x;
int x{};
bool operator<=> (const Z&) const = default;
};
struct Y {
int g;
std::string h;
std::vector<int> i;
Z z;
int g{};
std::string h{};
std::vector<int> i{};
Z z{};
bool operator<=> (const Y&) const = default;
};
struct X {
char a;
int b;
int c;
std::string d;
std::vector<int> e;
std::vector<std::string> f;
Y y;
char a{};
int b{};
int c{};
std::string d{};
std::vector<int> e{};
std::vector<std::string> f{};
Y y{};
bool operator<=> (const X&) const = default;
};
@@ -16,8 +16,8 @@ namespace builder_tests {
#if SIMDJSON_STATIC_REFLECTION
// Custom type for testing tag_invoke with extract_into
struct Price {
double amount;
std::string currency;
double amount{};
std::string currency{};
// Custom deserializer that applies currency conversion
friend error_code tag_invoke(deserialize_tag,
@@ -46,17 +46,37 @@ namespace builder_tests {
return SUCCESS;
}
};
struct Car {
std::string make{};
std::string model{};
int year{};
double price{};
bool electric{};
};
struct CarOpt {
std::string make;
std::string model;
int year;
double price;
std::optional<std::string> color;
};
struct CarColor {
std::string make;
std::string model;
int year;
double price;
std::string color;
};
struct Product {
std::string name;
Price price; // Custom deserializable type
int stock;
std::string name{};
Price price{}; // Custom deserializable type
int stock{};
};
// Another custom type for testing
struct Dimensions {
double value;
std::string unit;
double value{};
std::string unit{};
// Custom deserializer that converts to metric
friend error_code tag_invoke(deserialize_tag,
@@ -89,6 +109,13 @@ namespace builder_tests {
Dimensions weight;
Dimensions length;
};
struct Person {
std::string name;
int age;
std::optional<std::string> email;
std::optional<std::string> phone;
};
#endif
bool test_primitive_types() {
@@ -132,8 +159,8 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct StringTypes {
std::string string_val;
std::string_view string_view_val;
std::string string_val{};
std::string_view string_view_val{};
};
StringTypes test{"hello world", "test_view"};
@@ -159,10 +186,10 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct OptionalTypes {
std::optional<int> opt_int_with_value;
std::optional<std::string> opt_string_with_value;
std::optional<int> opt_int_null;
std::optional<std::string> opt_string_null;
std::optional<int> opt_int_with_value{};
std::optional<std::string> opt_string_with_value{};
std::optional<int> opt_int_null{};
std::optional<std::string> opt_string_null{};
};
OptionalTypes test;
@@ -200,11 +227,11 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct SmartPointerTypes {
std::unique_ptr<int> unique_int_with_value;
std::shared_ptr<std::string> shared_string_with_value;
std::unique_ptr<bool> unique_bool_with_value;
std::unique_ptr<int> unique_int_null;
std::shared_ptr<std::string> shared_string_null;
std::unique_ptr<int> unique_int_with_value{};
std::shared_ptr<std::string> shared_string_with_value{};
std::unique_ptr<bool> unique_bool_with_value{};
std::unique_ptr<int> unique_int_null{};
std::shared_ptr<std::string> shared_string_null{};
};
SmartPointerTypes test;
@@ -245,9 +272,9 @@ namespace builder_tests {
#if SIMDJSON_STATIC_REFLECTION
// Test basic container types
struct ContainerTypes {
std::vector<int> int_vector;
std::set<std::string> string_set;
std::map<std::string, int> string_map;
std::vector<int> int_vector{};
std::set<std::string> string_set{};
std::map<std::string, int> string_map{};
};
ContainerTypes test;
@@ -278,8 +305,8 @@ namespace builder_tests {
// Test std::list with iterator-based serialization
struct ListContainer {
std::list<int> int_list;
std::list<std::string> string_list;
std::list<int> int_list{};
std::list<std::string> string_list{};
};
ListContainer list_test;
@@ -319,13 +346,7 @@ namespace builder_tests {
bool test_extract_into() {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct Car {
std::string make;
std::string model;
int year;
double price;
std::optional<std::string> color;
};
ondemand::parser parser;
@@ -341,7 +362,7 @@ namespace builder_tests {
"transmission": "Automatic"
})"_padded;
Car car{};
CarOpt car{};
ondemand::document doc;
ASSERT_SUCCESS( parser.iterate(padded).get(doc) );
@@ -377,7 +398,7 @@ namespace builder_tests {
"color": "Red"
})"_padded;
Car car{};
CarOpt car{};
ondemand::document doc;
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
@@ -402,7 +423,7 @@ namespace builder_tests {
"price": 35999.99
})"_padded;
Car car{};
CarOpt car{};
ondemand::document doc;
ASSERT_SUCCESS(parser.iterate(padded).get(doc));
@@ -495,13 +516,6 @@ namespace builder_tests {
#if SIMDJSON_STATIC_REFLECTION
// Test 1: Extract specific fields from Car struct
{
struct Car {
std::string make;
std::string model;
int year;
double price;
bool electric;
};
Car car{"Tesla", "Model 3", 2023, 42000.0, true};
@@ -533,13 +547,7 @@ namespace builder_tests {
// Test 2: Extract different field combination
{
struct Car {
std::string make;
std::string model;
int year;
double price;
bool electric;
};
Car car{"Ford", "F-150", 2024, 55000.0, false};
@@ -566,13 +574,6 @@ namespace builder_tests {
// Test 3: Extract from struct with optional fields
{
struct Person {
std::string name;
int age;
std::optional<std::string> email;
std::optional<std::string> phone;
};
Person person{"John Doe", 30, "john@example.com", std::nullopt};
// Extract name and email
@@ -594,13 +595,6 @@ namespace builder_tests {
// Test 4: Extract with optional that has value
{
struct Person {
std::string name;
int age;
std::optional<std::string> email;
std::optional<std::string> phone;
};
Person person{"Jane Smith", 25, "jane@example.com", "555-1234"};
// Extract name, age, and phone
@@ -629,21 +623,21 @@ namespace builder_tests {
// Test 5: Round-trip test - serialize with extract_from, deserialize with extract_into
{
struct Product {
std::string id;
std::string name;
double price;
int stock;
struct MyProduct {
std::string id{};
std::string name{};
double price{};
int stock{};
};
Product original{"P123", "Widget", 19.99, 100};
MyProduct original{"P123", "Widget", 19.99, 100};
// Extract specific fields to JSON
std::string json;
ASSERT_SUCCESS((extract_from<"id", "name", "price">(original).get(json)));
// Parse and extract back
Product restored{"", "", 0.0, 0};
MyProduct restored{"", "", 0.0, 0};
auto padded = pad(json);
ondemand::parser parser;
auto doc = parser.iterate(padded);
@@ -11,10 +11,10 @@ using namespace simdjson;
// Suppose that we want to serialize/deserialize Car using
// strings for the year
struct Car {
std::string make;
std::string model;
int64_t year;
std::vector<float> tire_pressure;
std::string make{};
std::string model{};
int64_t year{};
std::vector<float> tire_pressure{};
};
@@ -14,11 +14,11 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct EmptyValues {
std::string empty_string;
std::vector<int> empty_vector;
std::optional<int> null_optional;
std::unique_ptr<int> null_unique_ptr;
std::shared_ptr<std::string> null_shared_ptr;
std::string empty_string{};
std::vector<int> empty_vector{};
std::optional<int> null_optional{};
std::unique_ptr<int> null_unique_ptr{};
std::shared_ptr<std::string> null_shared_ptr{};
};
EmptyValues test;
@@ -56,11 +56,11 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct SpecialChars {
std::string quotes;
std::string backslashes;
std::string newlines;
std::string unicode;
char null_char;
std::string quotes{};
std::string backslashes{};
std::string newlines{};
std::string unicode{};
char null_char{};
};
SpecialChars test;
@@ -82,10 +82,10 @@ namespace builder_tests {
// Test round-trip (excluding null char which has special handling)
struct SpecialCharsNoNull {
std::string quotes;
std::string backslashes;
std::string newlines;
std::string unicode;
std::string quotes{};
std::string backslashes{};
std::string newlines{};
std::string unicode{};
};
SpecialCharsNoNull test_no_null;
@@ -157,15 +157,15 @@ namespace builder_tests {
TEST_START();
#if SIMDJSON_STATIC_REFLECTION
struct Inner {
int value;
std::string name;
int value{};
std::string name{};
};
struct Outer {
Inner inner_obj;
std::vector<Inner> inner_vector;
std::optional<Inner> optional_inner;
std::unique_ptr<Inner> unique_inner;
Inner inner_obj{};
std::vector<Inner> inner_vector{};
std::optional<Inner> optional_inner{};
std::unique_ptr<Inner> unique_inner{};
};
Outer test;
@@ -51,8 +51,8 @@ namespace builder_tests {
};
struct StatusStruct {
Status status;
std::string name;
Status status{};
std::string name{};
};
// Test deserialization of different enum values with string representation
@@ -104,9 +104,9 @@ namespace builder_tests {
};
struct Task {
Priority priority;
std::string description;
int id;
Priority priority{};
std::string description{};
int id{};
};
Task original{Priority::High, "Important task", 123};
@@ -144,8 +144,8 @@ namespace builder_tests {
};
struct Response {
ErrorCode error;
std::string message;
ErrorCode error{};
std::string message{};
};
Response test{ErrorCode::NotFound, "Resource not found"};
@@ -8,26 +8,26 @@ using namespace simdjson;
// Test structures for FracturedJson builder integration
struct SimpleUser {
int id;
std::string name;
bool active;
int id{};
std::string name{};
bool active{};
};
struct UserWithEmail {
int id;
std::string name;
std::string email;
bool active;
int id{};
std::string name{};
std::string email{};
bool active{};
};
struct NestedData {
std::string title;
std::vector<SimpleUser> users;
int count;
std::string title{};
std::vector<SimpleUser> users{};
int count{};
};
struct TableTestData {
std::vector<SimpleUser> records;
std::vector<SimpleUser> records{};
};
namespace fractured_json_builder_tests {
+10 -11
View File
@@ -666,27 +666,27 @@ bool test_array_of_objects_with_concept() {
/**
* Test: #embed support for external JSON files (C++26)
*/
bool test_embed_twitter_json() {
bool test_embed_example_config_json() {
TEST_START();
// C++26 #embed allows embedding files directly into the binary at compile time
// This creates a const char array with the file contents plus null terminator
constexpr const char twitter_json[] = {
#embed TWITTER_JSON
constexpr const unsigned char example_config_json[] = {
#embed "../../jsonexamples/example_config.json"
, 0
};
// Parse the embedded JSON at compile time
constexpr auto parsed_twitter = simdjson::compile_time::parse_json<twitter_json>();
constexpr auto parsed_example_config = simdjson::compile_time::parse_json<example_config_json>();
// Verify the structure - twitter.json should have a "statuses" array
static_assert(parsed_twitter.statuses.size() > 0);
// Verify the structure - example_config.json should have an "app_name" field
static_assert(std::string_view(parsed_example_config.app_name) == "MyApp");
// Runtime verification
ASSERT_TRUE(parsed_twitter.statuses.size() > 0);
ASSERT_TRUE(std::string_view(parsed_example_config.app_name) == "MyApp");
std::cout << "Successfully parsed embedded twitter.json with "
<< parsed_twitter.statuses.size() << " statuses" << std::endl;
std::cout << "Successfully parsed embedded example_config.json with "
<< parsed_example_config.app_name << " as app_name" << std::endl;
TEST_SUCCEED();
}
@@ -718,11 +718,10 @@ bool run() {
test_top_level_array_example() &&
test_array_of_objects_with_concept()
#ifdef TEST_EMBED_SUPPORTED
&& test_embed_twitter_json()
&& test_embed_example_config_json()
#endif
;
}
} // namespace compile_time_json_tests
int main(int argc, char *argv[]) {
+12 -12
View File
@@ -19,7 +19,7 @@ public:
return date_str;
}
private:
std::string date_str;
std::string date_str{};
};
@@ -52,8 +52,8 @@ auto tag_invoke(deserialize_tag, simdjson_value &val, MyDate& date) {
} // namespace simdjson
struct complicated_weather_data {
std::vector<MyDate> time;
std::vector<float> temperature;
std::vector<MyDate> time{};
std::vector<float> temperature{};
};
@@ -152,19 +152,19 @@ simdjson::padded_string json_cars =
TEST_SUCCEED();
}
struct Player {
std::string username;
int level;
double health;
std::string username{};
int level{};
double health{};
};
struct BadPlayer {
int username; // Oops, should be string!
int level;
double health;
int username{}; // Oops, should be string!
int level{};
double health{};
};
struct OptionalPlayer {
std::string username;
std::optional<int> level;
double health;
std::string username{};
std::optional<int> level{};
double health{};
};
#if SIMDJSON_STATIC_REFLECTION
bool missing_key_player() {
@@ -15,9 +15,9 @@ namespace wrong_type_error_tests {
return false; \
} \
{ \
padded_string a_json(std::string(R"({ "a": )") + JSON + " }"); \
std::string a_json(R"({ "a": )"); a_json += JSON; a_json += " }"; \
std::cout << R"(- Subtest: get_)" << (#TYPE) << "() - JSON: " << a_json << std::endl; \
if (!test_ondemand_doc(a_json, [&](auto doc_result) { \
if (!test_ondemand_doc(simdjson::pad(a_json), [&](auto doc_result) { \
ASSERT_ERROR( doc_result["a"].get_##TYPE(), (ERROR) ); \
return true; \
})) { \