Releases: stephenberry/glaze
v3.1.1
Important
Fixed potential out of bounds table lookups when parsing invalid JSON due to missing unsigned conversions.
by @stephenberry in #1168
Thanks @pauldreik for reporting this.
Improvements
- Removed the temporary string_decode_buffer when reading strings. This results in significant memory savings when dealing with large strings.
- Faster string decoding and encoding in the general case due to less branches.
Full Changelog: v3.1.0...v3.1.1
v3.1.0
Breaking change: removed force_conformance
option
By default Glaze is now strictly conformant with the latest JSON standard except in two cases with associated options (see new conformance options below).
Previously the force_conformance option was necessary to have JSON conformant number parsing. This update applies the more stringent rules from the JSON specification, such as not allowing leading zeros.
Rules applied now by default:
- JSON requires a digit after the decimal place in numbers.
- JSON requires a digit after an exponent e or E
This does NOT break how Glaze serializes or parses numbers, it will simply now reject invalid numbers due to more stringent JSON specification rules.
New conformance options
-
validate_skipped
This option does full JSON validation for skipped values when parsing. This is not set by default because values are typically skipped when the user is unconcerned with them, and Glaze still validates for major issues. But, this makes skipping faster by not caring if the skipped values are exactly JSON conformant. For example, by default Glaze will ensure skipped numbers have all valid numerical characters, but it will not validate for issues like leading zeros in skipped numbers unless validate_skipped is on. Wherever Glaze parses a value to be used it is fully validated. -
validate_trailing_whitespace
This option validates the trailing whitespace in a parsed document. Because Glaze parses C++ structs, there is typically no need to continue parsing after the object of interest has been read. Turn on this option if you want to ensure that the rest of the document has valid whitespace, otherwise Glaze will just ignore the content after the content of interest has been parsed.
Full Changelog: v3.0.0...v3.1.0
v3.0.0
Glaze 3.0.0
This release brings core architecture improvements along with breaking changes to improve compile time and runtime performance.
Moving to C++23
While this release still builds with C++20, Glaze will begin using more C++23 features in version 3. All compilers that currently build Glaze already have C++23 modes, so if you could build the code before you should be able to change the version to C++23 without issue. This release does not reduce the current supported compiler versions.
Why require C++23? The core architecture can be cleaned up and result in faster compile times via the use of static constexpr
within constexpr functions. More constexpr support, resize_and_overwrite
, and std::flat_map
will also bring performance improvements to various parts of Glaze.
Breaking Changes
Removed glz::schema
support in glz::object
template <> struct glz::meta<my_struct> {
static constexpr auto value = object("i", &my_struct::i, schema{.description = "i is an integer"}); // schema is no longer allowed here
};
Cleaner JSON Schema metadata has been supported for a while with the improved glz::json_schema
approach:
template <> struct glz::json_schema<my_struct> {
schema i{.description = "i is an integer"};
};
Use this decoupled approach in version 3. The old approach was slower to compile and didn't cleanly separate the normal reflection metadata from JSON schema logic. The older approach was also harder to read when dealing with lots of JSON Schema metadata.
Removed Machine Generated Comments in glz::object
Comments do not conform to the core JSON specification. They were also difficult to roundtrip, and machine generated comments are not as useful for human interaction because humans like putting comments is less ideal places and with //
syntax rather than the /**/
syntax that can be minified.
template <> struct glz::meta<my_struct> {
static constexpr auto value = object("i", &my_struct::i, "old comment"_c); // The comment here is no longer allowed
};
Now that we have more robust JSON schema support, we have found this to be a better solution to machine generated comments in JSON using tools like Visual Studio Code.
- Reading comments via the JSONC syntax is still supported. So, humans can still add comments to input files. Use the
.comments = true
option when reading. - This change improves compile times.
Escaped keys must be registered in escaped form (for glz::object)
For backslashes \
and quotes "
, which need to be escaped in JSON, the user must now register the escaped forms of these keys with glz::object
. It is not common, nor recommended to have escaped characters in JSON keys, but this improves the performance of handling these keys.
struct Escaped {
int escaped_key{};
std::string escaped_key2{"hi"};
};
template <> struct glz::meta<Escaped> {
using T = Escaped;
static constexpr auto value = object(R"(escaped\"key)", &T::escaped_key,
R"(escaped\"\"key2)", &T::escaped_key2);
};
New Option: escaped_unicode_key_conversion
The default behavior for escaped unicode \u...
has been changed. The JSON specification does not require escaped and unescaped unicode keys to match. To improve performance, especially for foreign languages, the default behavior in Glaze will not automatically convert escaped unicode to unescaped unicode.
If you desire escaped unicode \u...
keys to match with unescaped unicode then enable the new option: .escaped_unicode_key_conversion = true
It is recommended to use unescaped UTF-8 for keys, as it is much faster for reading/writing and typically easier to work with for developers. Unescaped unicode lets you see the characters wherever UTF-8 is supported, e.g. 😀😃😄💐🌹🥀🌺🌷🌸💮🏵️🌻🌼
Removed glz::poly and the supporting glz::any
glz::poly
was an experiment in polymorphism without inheritance that Glaze did not use anywhere. It was an neat proof of concept, but we've since discovered better approaches to static polymorphism which we intend to add to Glaze. These newer approaches result in faster runtimes, cleaner code, faster compilation, and easier debugging.
Improvements
New Hash Maps
More advanced and faster hash maps.
Glaze adds a new core mechanism for compile time perfect hashing. This approach eliminates the use of std::variant
and directly builds jump tables. Key comparisons are now embedded at the call site and in many cases with compile time known keys we can avoid the key parsing step by jumping to a direct comparison. Many times a single character lookup can be used as the hashing algorithm as Glaze will search at compile time for a unique character column among keys to build extremely efficient hash tables.
Additional Improvements
- Removed extra template/function instantiations due to unnecessary indirections. This makes debugging easier as well.
Full Changelog: v2.9.5...v3.0.0
v2.9.5
Minor Fixes
- Fix GCC warnings by @stephenberry in #1134
- Fixing MSVC max macro collision by @stephenberry in #1137
Full Changelog: v2.9.4...v2.9.5
v2.9.4
Reduced the output length of compile time errors.
Fixes
- Fixing
glz::format_error
with no buffer by @stephenberry in #1129
Improvements
- Packing internal options for shorter compile time errors by @stephenberry in #1125
- using uint8_t alias for opts by @stephenberry in #1126
- Adding target_extension to read_directory by @stephenberry in #1128
- Silence MSVC warning about including
<expected>
by @helmesjo in #1130
Full Changelog: v2.9.3...v2.9.4
v2.9.3
Continuing to improve compilation and runtime performance.
Fixes
Fixed an issue where .comments = true
option would break write compilation for reflected structs
- Guarding against comments option when not a glaze object in #1124
Improvements
- Less forced inlining and faster visiting by @stephenberry in #1112
- to_json_schema nullable_t throws instead of segfault by @jbbjarnason in #1116
- to_tuple registry guard for glz::repe::registry in #1111
- GLZ_ENUM - faster enum reflection compilation by @stephenberry in #1119
- Fixed remove_cvref_t location in #1120
Full Changelog: v2.9.2...v2.9.3
v2.9.2
Hotfix for v2.9.1 for missing inline
on new functions
Full Changelog: v2.9.1...v2.9.2
v2.9.1
Initial Mustache support
- Added
glz::mustache
in #1102
Given a struct:
struct person
{
std::string first_name{};
std::string last_name{};
uint32_t age{};
bool hungry{};
};
Apply the struct to a template (layout) to replace mustaches with content:
std::string_view layout = R"({{first_name}} {{last_name}}, age: {{age}})";
person p{"Henry", "Foster", 34};
auto result = glz::mustache(p, layout).value_or("error");
expect(result == "Henry Foster, age: 34");
- Located at:
#include "glaze/mustache/mustache.hpp"
More advanced features of the mustache specification will be added in the future.
JSON concepts
- Added in #1105
Example:
static_assert(glz::json_string<std::string>);
static_assert(glz::json_string<std::string_view>);
static_assert(glz::json_object<my_struct>);
static_assert(glz::json_array<std::array<float, 3>>);
static_assert(glz::json_boolean<bool>);
static_assert(glz::json_number<float>);
static_assert(glz::json_integer<uint64_t>);
static_assert(glz::json_null<std::nullptr_t>);
glz::read_directory and glz::write_directory
- Adds the ability to read and write maps as directories of files
std::map<std::filesystem::path, my_struct> files{{"./dir/alpha.json", {}}, {"./dir/beta.json", {.i = 0}}};
expect(not glz::write_directory(files, "./dir"));
std::map<std::filesystem::path, my_struct> input{};
expect(not glz::read_directory(input, "./dir"));
expect(input.size() == 2);
expect(input.contains("./dir/alpha.json"));
expect(input.contains("./dir/beta.json"));
expect(input["./dir/beta.json"].i == 0);
- Added in #1109
Other Features
- glz::format_to for numbers by @stephenberry in #1106
Full Changelog: v2.9.0...v2.9.1
v2.9.0
Breaking change: Removed pure reflection support for C style arrays
This does not break C style array registration in glz::meta
or the local glaze
metadata. It should also produce compile time errors that are obvious.
C++ allows flattening of brace initializers for C style arrays, which means that they break how we count fields in a struct. The work around was to count the number of initializer lists that we can use to construct the type. However, this approach was not consistent across MSVC, Clang, and GCC, and it restricted commonly used types with custom constructors (like std::filesystem::path
and std::chrono::seconds
).
After lots of experimenting, reading the C++ specification and papers, and submitting compiler bugs, it's become clear that dropping this support will make Glaze more stable for the future until we get compile time reflection into the language.
Tip
Reflection still works with std::array
, so the C style arrays can be converted to std::array
and pure reflection in Glaze will work as before.
- by @stephenberry in #1097
Improvements
- Internal thread pool improvements and fixed
std::promise<void>
handling in #1085 - Using buffer pool for asio client in #1095
- Fix MSVC warnings in #1099
Full Changelog: v2.8.4...v2.9.0
v2.8.4
Improvements and Fixes
std::vector<std::byte>
buffer support for write by @stephenberry in #1089- get_[JSON type] methods for
glz::json_t
and binary support forglz::json_t
by @stephenberry in #1090
Full Changelog: v2.8.3...v2.8.4