From c854a52be8feeb9e2d8a5c5563c510e4f59c2802 Mon Sep 17 00:00:00 2001 From: Stephen Berry Date: Tue, 3 Sep 2024 05:36:49 -0500 Subject: [PATCH 1/6] Use size_t explicitly to catch bugs (#1282) --- include/glaze/util/dump.hpp | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/include/glaze/util/dump.hpp b/include/glaze/util/dump.hpp index 17723e47d5..3200cc2a56 100644 --- a/include/glaze/util/dump.hpp +++ b/include/glaze/util/dump.hpp @@ -35,7 +35,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void maybe_pad(B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void maybe_pad(B& b, size_t& ix) noexcept { if constexpr (vector_like) { if (const auto k = ix + N; k > b.size()) [[unlikely]] { @@ -45,7 +45,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void maybe_pad(const size_t n, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void maybe_pad(const size_t n, B& b, size_t& ix) noexcept { if constexpr (vector_like) { if (const auto k = ix + n; k > b.size()) [[unlikely]] { @@ -55,7 +55,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void assign_maybe_cast(auto& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void assign_maybe_cast(auto& b, size_t& ix) noexcept { using V = std::decay_t; using C = std::decay_t; @@ -67,7 +67,7 @@ namespace glz::detail } } - GLZ_ALWAYS_INLINE void assign_maybe_cast(const byte_sized auto c, auto& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void assign_maybe_cast(const byte_sized auto c, auto& b, size_t& ix) noexcept { using V = std::decay_t; using C = std::decay_t; @@ -80,7 +80,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(const byte_sized auto c, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(const byte_sized auto c, B& b, size_t& ix) noexcept { if constexpr (Checked && vector_like) { if (ix == b.size()) [[unlikely]] { @@ -92,7 +92,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(B& b, size_t& ix) noexcept { if constexpr (Checked && vector_like) { if (ix == b.size()) [[unlikely]] { @@ -104,7 +104,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(B& b, size_t& ix) noexcept { static constexpr auto s = str.sv(); static constexpr auto n = s.size(); @@ -121,7 +121,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(const sv str, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(const sv str, B& b, size_t& ix) noexcept { const auto n = str.size(); if constexpr (vector_like) { @@ -136,7 +136,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dumpn(size_t n, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dumpn(size_t n, B& b, size_t& ix) noexcept { if constexpr (vector_like) { if (ix + n > b.size()) [[unlikely]] { @@ -148,14 +148,14 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dumpn_unchecked(size_t n, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dumpn_unchecked(size_t n, B& b, size_t& ix) noexcept { std::memset(&b[ix], c, n); ix += n; } template - GLZ_ALWAYS_INLINE void dump_newline_indent(size_t n, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump_newline_indent(size_t n, B& b, size_t& ix) noexcept { if constexpr (vector_like) { if (const auto k = ix + n + write_padding_bytes; k > b.size()) [[unlikely]] { @@ -170,7 +170,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(B& b, size_t& ix) noexcept { static constexpr auto s = str; static constexpr auto n = s.size(); @@ -187,7 +187,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump_not_empty(const sv str, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump_not_empty(const sv str, B& b, size_t& ix) noexcept { const auto n = str.size(); if constexpr (vector_like) { @@ -202,7 +202,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump_maybe_empty(const sv str, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump_maybe_empty(const sv str, B& b, size_t& ix) noexcept { const auto n = str.size(); if (n) { @@ -219,7 +219,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(const vector_like auto& bytes, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(const vector_like auto& bytes, B& b, size_t& ix) noexcept { const auto n = bytes.size(); if constexpr (vector_like) { @@ -232,7 +232,7 @@ namespace glz::detail } template - GLZ_ALWAYS_INLINE void dump(const std::array& bytes, B& b, auto& ix) noexcept + GLZ_ALWAYS_INLINE void dump(const std::array& bytes, B& b, size_t& ix) noexcept { if constexpr (vector_like) { if (ix + N > b.size()) [[unlikely]] { From 7bd39f1819a48cb06bcbf9624b870f85e2e66080 Mon Sep 17 00:00:00 2001 From: Stephen Berry Date: Tue, 3 Sep 2024 06:18:02 -0500 Subject: [PATCH 2/6] Fixed issue with variant object reading of unknown keys (#1283) --- include/glaze/json/read.hpp | 23 ++++++++++++++++--- tests/json_test/json_test.cpp | 42 +++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/include/glaze/json/read.hpp b/include/glaze/json/read.hpp index 3dc33baa96..30391f2a87 100644 --- a/include/glaze/json/read.hpp +++ b/include/glaze/json/read.hpp @@ -2679,9 +2679,26 @@ namespace glz if (it != start) { GLZ_MATCH_COMMA; } - const sv key = parse_object_key(ctx, it, end); - if (bool(ctx.error)) [[unlikely]] - return; + + GLZ_SKIP_WS(); + GLZ_MATCH_QUOTE; + GLZ_INVALID_END(); + + sv key{}; + if constexpr (Opts.escaped_unicode_key_conversion && keys_may_contain_escape()) { + std::string& static_key = string_buffer(); + read::op()>(static_key, ctx, it, end); + --it; // reveal the quote + key = static_key; + } + else { + auto* start = it; + skip_string_view(ctx, it, end); + if (bool(ctx.error)) [[unlikely]] + return; + key = {start, size_t(it - start)}; + } + GLZ_MATCH_QUOTE; GLZ_INVALID_END(); diff --git a/tests/json_test/json_test.cpp b/tests/json_test/json_test.cpp index d27f39e594..bb73d3efb8 100644 --- a/tests/json_test/json_test.cpp +++ b/tests/json_test/json_test.cpp @@ -9333,6 +9333,48 @@ suite response_test = [] { }; }; +struct A_empty { + +}; + +struct B_empty { + +}; + +using C_empty = std::variant; + + +template <> +struct glz::meta { + static constexpr std::string_view tag = "op"; +}; + +suite empty_variant_testing = [] { + "empty_variant 1"_test = [] { + std::string_view text = R"({"xxx":"x","op":"B_empty"})"; + + C_empty c; + auto ec = glz::read(c, text); + expect(not ec) << glz::format_error(ec, text); + expect(c.index() == 1); + }; + + "empty_variant 2"_test = [] { + std::string_view text = R"({"xx":"x","op":"B_empty"})"; + + C_empty c; + auto ec = glz::read(c, text); + expect(not ec) << glz::format_error(ec, text); + expect(c.index() == 1); + }; +}; + int main() { trace.end("json_test"); From cac6f86b62f33b9236ea74123632999af759ccd2 Mon Sep 17 00:00:00 2001 From: stephenberry Date: Tue, 3 Sep 2024 11:18:30 +0000 Subject: [PATCH 3/6] Committing clang-format changes --- include/glaze/json/read.hpp | 4 ++-- tests/json_test/json_test.cpp | 30 +++++++++++------------------- 2 files changed, 13 insertions(+), 21 deletions(-) diff --git a/include/glaze/json/read.hpp b/include/glaze/json/read.hpp index 30391f2a87..b15d23802d 100644 --- a/include/glaze/json/read.hpp +++ b/include/glaze/json/read.hpp @@ -2679,7 +2679,7 @@ namespace glz if (it != start) { GLZ_MATCH_COMMA; } - + GLZ_SKIP_WS(); GLZ_MATCH_QUOTE; GLZ_INVALID_END(); @@ -2698,7 +2698,7 @@ namespace glz return; key = {start, size_t(it - start)}; } - + GLZ_MATCH_QUOTE; GLZ_INVALID_END(); diff --git a/tests/json_test/json_test.cpp b/tests/json_test/json_test.cpp index bb73d3efb8..f3d19e76a8 100644 --- a/tests/json_test/json_test.cpp +++ b/tests/json_test/json_test.cpp @@ -9333,43 +9333,35 @@ suite response_test = [] { }; }; -struct A_empty { - -}; - -struct B_empty { +struct A_empty +{}; -}; +struct B_empty +{}; using C_empty = std::variant; - template <> -struct glz::meta { - static constexpr std::string_view tag = "op"; +struct glz::meta +{ + static constexpr std::string_view tag = "op"; }; suite empty_variant_testing = [] { "empty_variant 1"_test = [] { std::string_view text = R"({"xxx":"x","op":"B_empty"})"; - + C_empty c; - auto ec = glz::read(c, text); + auto ec = glz::read(c, text); expect(not ec) << glz::format_error(ec, text); expect(c.index() == 1); }; - + "empty_variant 2"_test = [] { std::string_view text = R"({"xx":"x","op":"B_empty"})"; C_empty c; - auto ec = glz::read(c, text); + auto ec = glz::read(c, text); expect(not ec) << glz::format_error(ec, text); expect(c.index() == 1); }; From 16d05ef5545555fd9567708580c7df58be8c3492 Mon Sep 17 00:00:00 2001 From: Stephen Berry Date: Tue, 3 Sep 2024 06:36:10 -0500 Subject: [PATCH 4/6] Fix Apple clang precompiled headers due to path hashing (#1284) * Fix Apple clang precompiled headers due to path hashing * Fix namespace --- include/glaze/file/read_directory.hpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/include/glaze/file/read_directory.hpp b/include/glaze/file/read_directory.hpp index 2bb2fa9c38..f44888a9b4 100644 --- a/include/glaze/file/read_directory.hpp +++ b/include/glaze/file/read_directory.hpp @@ -10,7 +10,19 @@ namespace glz { - [[nodiscard]] inline error_ctx directory_to_buffers(std::unordered_map& files, + namespace detail + { + // TODO: When Apple Clang supports hashing on std::filesystem::path with precompiled headers, we can remove this + // std::hash not in the C++20 standard by default + struct fs_path_hash { + [[nodiscard]] auto operator()(const std::filesystem::path& path) const noexcept { + return std::filesystem::hash_value(path); + } + }; + } + + // files should be a map of std::filesystem::path to std::string buffers + [[nodiscard]] inline error_ctx directory_to_buffers(auto& files, const sv directory_path, const sv target_extension = ".json") { for (const auto& entry : std::filesystem::directory_iterator(directory_path)) { @@ -26,7 +38,7 @@ namespace glz template [[nodiscard]] error_ctx read_directory(T& value, const sv directory_path, const sv target_extension = ".json") { - std::unordered_map files{}; + std::unordered_map files{}; if (auto ec = directory_to_buffers(files, directory_path, target_extension)) { return ec; } From bb30bdafe61afb417fcfd142bbd47f77832dccef Mon Sep 17 00:00:00 2001 From: stephenberry Date: Tue, 3 Sep 2024 11:36:37 +0000 Subject: [PATCH 5/6] Committing clang-format changes --- include/glaze/file/read_directory.hpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/include/glaze/file/read_directory.hpp b/include/glaze/file/read_directory.hpp index f44888a9b4..4a0acc8761 100644 --- a/include/glaze/file/read_directory.hpp +++ b/include/glaze/file/read_directory.hpp @@ -14,16 +14,18 @@ namespace glz { // TODO: When Apple Clang supports hashing on std::filesystem::path with precompiled headers, we can remove this // std::hash not in the C++20 standard by default - struct fs_path_hash { - [[nodiscard]] auto operator()(const std::filesystem::path& path) const noexcept { + struct fs_path_hash + { + [[nodiscard]] auto operator()(const std::filesystem::path& path) const noexcept + { return std::filesystem::hash_value(path); } }; } - + // files should be a map of std::filesystem::path to std::string buffers - [[nodiscard]] inline error_ctx directory_to_buffers(auto& files, - const sv directory_path, const sv target_extension = ".json") + [[nodiscard]] inline error_ctx directory_to_buffers(auto& files, const sv directory_path, + const sv target_extension = ".json") { for (const auto& entry : std::filesystem::directory_iterator(directory_path)) { if (entry.is_regular_file() && (target_extension.empty() || (entry.path().extension() == target_extension))) { From 6115adf616413b6f8b82d3ecb449016cee901ed8 Mon Sep 17 00:00:00 2001 From: Stephen Berry Date: Tue, 3 Sep 2024 08:18:55 -0500 Subject: [PATCH 6/6] version 3.3.2 bump --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 06bec4b80c..b989bd2ba7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ include(cmake/prelude.cmake) project( glaze - VERSION 3.3.1 + VERSION 3.3.2 LANGUAGES CXX )