Skip to content

Releases: stephenberry/glaze

v3.1.1

18 Jul 17:43
Compare
Choose a tag to compare

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

17 Jul 15:13
Compare
Choose a tag to compare

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

16 Jul 14:32
Compare
Choose a tag to compare

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

04 Jul 13:30
Compare
Choose a tag to compare

Minor Fixes

Full Changelog: v2.9.4...v2.9.5

v2.9.4

02 Jul 13:51
Compare
Choose a tag to compare

Reduced the output length of compile time errors.

Fixes

Improvements

Full Changelog: v2.9.3...v2.9.4

v2.9.3

01 Jul 13:03
Compare
Choose a tag to compare

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

Full Changelog: v2.9.2...v2.9.3

v2.9.2

24 Jun 14:56
Compare
Choose a tag to compare

Hotfix for v2.9.1 for missing inline on new functions

Full Changelog: v2.9.1...v2.9.2

v2.9.1

24 Jun 13:58
Compare
Choose a tag to compare

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);

Other Features

Full Changelog: v2.9.0...v2.9.1

v2.9.0

14 Jun 13:14
Compare
Choose a tag to compare

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.

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

13 Jun 13:26
Compare
Choose a tag to compare

Improvements and Fixes

Full Changelog: v2.8.3...v2.8.4