Releases: stephenberry/glaze
v4.0.0
Glaze 4.0
This release brings a number of bug fixes with very few API breaking changes. The primary breaking change is a new integer parsing algorithm that is faster and rejects decimals and negative exponents to avoid implicit data loss.
New Integer Parsing Logic
When parsing integer types such as uint16_t
or int64_t
, Glaze will now reject decimal values and negative exponents, so a value such as 1.37
would produce a parse_number_failure
. This is important for avoiding implicit data loss. Developers often need to handle these conversions in various ways. Sometimes it is better to round (with various methodologies), other times truncate, and other times use the ceiling. It is recommended to use floating point types if you do not know if you will be receiving decimal values. A glz::custom
lambda in your meta can be used to invisibly convert a parsed floating point value into an integer if you do not wish to do this elsewhere.
We are open to requests for additional integer parsing options, but don't want to add complexity to Glaze unless there is a concrete need. So, please open an issue if this change causes problems.
By narrowing the definition of what it means to parse an integer in Glaze it will allow us to perform variant type deduction on integer vs floating point types. So, we will be able to parse either into an integer or a float in a variant. This has been requested a few times and would allow interfaces to avoid data loss with large integers and floating point decimal values simultaneously.
In summary, this change in integer parsing provides the benefits:
- Faster integer parsing
- No implicit data loss
- Disambiguation of integers and floats in JSON parsing to support dual integer/float types in variants and full numeric integrity
Positive exponents are still handled for integer parsing, such as 1e9
, which can save space and be easier to read than 1000000000
.
This release has no effect on integer serialization. Round-tripping in Glaze has not been affected.
Breaking Changes
-
String support for std::array<char, N> in #1247
std::array<char, N>
is now treated as a string type rather than an array of single character strings. -
Roundtrip support for
vector<pair>
, better concatenate option support, and BEVE support for these in #1418
When reading in avector<pair>
type objects are by default expected to be concatenated (as they are for output). Theconcatenate
option must be set tofalse
to read in a non-concatenated vector of pairs. Now both theconcatenate = true
andconcatenate = false
conditions properly roundtrip for both JSON and BEVE.
Improvements
- json_t assignment operators and string_view constructor in #1412
- Support for
std::atomic
in #1364 - Use clang format 18.1 in #1374
- Use jkj::dragonbox::to_decimal_ex for faster floating point serialization in #1392
- Adding roundtrip format agnostic testing in #1380
- Type "cls" or "clear" to bring the command line menu (
glz::cli_menu
) to the front in #1409
Fixes
- Removing lots of noexcept qualifiers to allow exceptions to propagate when Glaze is used with exceptions enabled in #1420
- Unknown fields fix with entirely null first object in #1367
- [Concept update] string_t with resize also needs to have .data() by @sjanel in #1372
- Support empty input NDJSON in #1381
- Fix JSON RPC documentation link to json-rpc.cpp source by @pentatonick in #1385
- Support reading into a const pointer to a member in #1387
- Fix JSON parsing from arrays to set like types with custom structs by @sjanel in #1394
- Put fast_float and dragonbox into glz namespace by @amosbird in #1398
- Naming more things beve instead of binary in #1399
- Using GLZ_ macro prefix for third party dependencies by @stephenberry in #1403
- Add missing include inside of threadpool.hpp by @X-rays5 in #1413
Active Development (use at your own risk)
- New binary REPE v1.0 spec implementation (repe::registry) in #1336
- Capture functions by reference in repe::registry by @stephenberry in #1396
- Removing repe::registry auto-locking in #1415
Full Changelog: v3.6.2...v4.0.0
v3.6.2
New AVX2 SIMD optimizations (faster string writing on some platforms)
The CMake now has the option glaze_ENABLE_AVX2. This will attempt to use AVX2 SIMD instructions in some cases to improve performance, as long as the system you are configuring on supports it. Set this option to OFF to disable the AVX2 instruction set, such as if you are cross-compiling for Arm. And, if you aren't using CMake the macro GLZ_USE_AVX2 enables the feature if defined.
- by @stephenberry in #1343
Improvements
Fixes
- Allow NDJSON in the skip_array requires statement. by @Haatschii in #1357
Full Changelog: v3.6.1...v3.6.2
v3.6.1
Generic JSON (glz::json_t) Improvements
See Generic JSON documentation for more details.
- dump() for json_t by @stephenberry in #1334
Calling
.dump()
on ajson_t
value is equivalent to callingglz::write_json(value)
, which returns anexpected<std::string, glz::error_ctx>
.
- Support for reading json_t value as the source in #1337
After parsing into a json_t
it is sometimes desirable to parse into a concrete struct or a portion of the json_t
into a struct. Glaze allows a json_t
value to be used as the source where a buffer would normally be passed.
auto json = glz::read_json<glz::json_t>(R"({"foo":"bar"})");
expect(json->contains("foo"));
auto obj = glz::read_json<std::map<std::string, std::string>>(json.value());
// This reads the json_t into a std::map
Another example:
glz::json_t json{};
expect(not glz::read_json(json, R"("Beautiful beginning")"));
std::string v{};
expect(not glz::read<glz::opts{}>(v, json));
expect(v == "Beautiful beginning");
Full Changelog: v3.6.0...v3.6.1
v3.6.0
Reflection API formalization progress
Caution
The glz::reflect
API is under development and may evolve with time, albeit slowly.
We are beginning to formalize the core reflection API in Glaze. glz::refl
was renamed to glz::reflect
and the inline definition was removed.
Internal Improvements
- Removed duplicate glz::custom code by @stephenberry in #1324
- Moving skip_member to core/write for more general usage in #1329
- Reflection API changes in #1327
- Adding glz::flat_map in #1332
- Updated feature test macros in
glaze/core/feature_test
Full Changelog: v3.5.0...v3.6.0
v3.5.0
Major API (naming) breaking changes
Important
This is only an API (naming) change. No internal logic was changed.
Format Specifiers
Format in glz::opts
are now all caps. This is to disambiguate from structs with similar names.
binary
-> BEVE
json
-> JSON
ndjson
-> NDJSON
csv
-> CSV
Important
If you set the format in glz::opts
the naming changes from glz::opts{.format = glz::json}
to glz::opts{.format = glz::JSON}
to/from specializations
For those who use custom serialization and have specialized to_json<T>
and from_json<T>
, these have been changed to be more generic. Use to<JSON, T>
and from<JSON, T>
instead.
This will significantly reduce internal code duplication across formats.
Binary (BEVE) name changes
Glaze used to refer to the BEVE format as binary
. This was confusing and would become even more confusing as we add more binary formats.
Pretty much everywhere binary
was referred to is now referred to as beve
. So write_binary
becomes write_beve
.
- The file paths
glaze/binary
have been renamed toglaze/beve
- The header
glaze/binary.hpp
has been renamed toglaze/beve.hpp
by @stephenberry in #1323
Full Changelog: v3.4.3...v3.5.0
v3.4.3
Internal cleanup and faster hashing
- Length 3 & 4 fast hashes by @stephenberry in #1321
- Improvements to full_flat hashing in #1322
Full Changelog: v3.4.2...v3.4.3
v3.4.2
Internal Improvements
- Internal hashing improvements for BEVE, CSV, stencils, and JSON seeking
by @stephenberry in #1307, #1309, #1310, and #1311 - Internal tuple handling cleanup in #1312
Full Changelog: v3.4.1...v3.4.2
v3.4.1
Improvements
- New
glz::write_at
, to write to a target value given a JSON Pointer path by @stephenberry in #1300 - Limit recursive depth in
beve_to_json
in #1301 new_lines_in_arrays
support for.prettify = true
write in #1302- Enum reading with new hash approach in #1303
- Support for partial writing of const qualified objects in #1304
- Using new hash approach in
glz::mustache
in #1306
glz::write_at
example:
std::string buffer = R"({"str":"hello","number":3.14,"sub":{"target":"X"}})";
auto ec = glz::write_at<"/sub/target">("42", buffer);
expect(buffer == R"({"str":"hello","number":3.14,"sub":{"target":42}})");
Full Changelog: v3.4.0...v3.4.1
v3.4.0
Breaking Change of glz::nameof
enum interface
The typical use case of
glz::enumerate
within aglz::meta
has been unaffected, and therefore most users will be unaffected by this change.
This update removes the enum_macro.hpp
header (GLZ_ENUM and GLZ_ENUM_MAP) and adds a new glz::meta
approach that takes an array of keys and an array of values. This keys/values approach only supports enums in Glaze (currently to support faster internal compilation of enums), but broader support can be added in the future.
The enum_macro
approach of using ADL created issues with other repositories that would declare a namespace nameof
, and the macro expansion increased compilation time and was not a good, generic solution.
glz::nameof
function for internal Glaze enums has been removed.
by @stephenberry in #1297
Other Fixes
- fixes min/max macro conflict in dragonbox.hpp on MSVC by @lambwheit in #1298
- glz::meta keys for enums, removing nameof ADL and enum_macro.hpp
Experimental glz::asio_client changes
- Support asynchronous clients with a socket pool by @stephenberry in #1291
Full Changelog: v3.3.4...v3.4.0
v3.3.4
Experimental glz::repe::registry
reworking of locking logic by @stephenberry in #1290
This makes the registry locking logic behave the same for reading and writing. This limits reading a bit more by not allowing asynchronous reads to the exact same field, but it makes asynchronous writing possible, and keeps the locking logic simpler. We can now asynchronously write to differing targets, and importantly we can call asynchronous invocations.
We are removing automatic invoke locking. With variables, there is no place for a user to put logic when it comes to locking/unlocking access. However, when it comes to functions, there is room for users to add mutexes and locks to customize lock behavior. Also, functions often have complex side effects that need to be known to the programmer. On top of this, if we don't manipulate references in an RPC, we'd like the default behavior to be able to asynchronously call these functions. For these reasons we don't automatically lock the path taken to the function call. Because we also don't want to assume that a function call would manipulate the returned state of a data, which would block reads to the data.
Full Changelog: v3.3.3...v3.3.4