Skip to content

Commit

Permalink
Merge branch 'main' into pr/1275
Browse files Browse the repository at this point in the history
  • Loading branch information
stephenberry committed Sep 4, 2024
2 parents 9c6f036 + 6115adf commit c1da880
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 23 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ include(cmake/prelude.cmake)

project(
glaze
VERSION 3.3.1
VERSION 3.3.2
LANGUAGES CXX
)

Expand Down
20 changes: 17 additions & 3 deletions include/glaze/file/read_directory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,22 @@

namespace glz
{
[[nodiscard]] inline error_ctx directory_to_buffers(std::unordered_map<std::filesystem::path, std::string>& files,
const sv directory_path, const sv target_extension = ".json")
namespace detail
{
// TODO: When Apple Clang supports hashing on std::filesystem::path with precompiled headers, we can remove this
// std::hash<std::filesystem::path> 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)) {
if (entry.is_regular_file() && (target_extension.empty() || (entry.path().extension() == target_extension))) {
Expand All @@ -26,7 +40,7 @@ namespace glz
template <opts Opts = opts{}, detail::readable_map_t T>
[[nodiscard]] error_ctx read_directory(T& value, const sv directory_path, const sv target_extension = ".json")
{
std::unordered_map<std::filesystem::path, std::string> files{};
std::unordered_map<std::filesystem::path, std::string, detail::fs_path_hash> files{};
if (auto ec = directory_to_buffers(files, directory_path, target_extension)) {
return ec;
}
Expand Down
23 changes: 20 additions & 3 deletions include/glaze/json/read.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2679,9 +2679,26 @@ namespace glz
if (it != start) {
GLZ_MATCH_COMMA;
}
const sv key = parse_object_key<T, Opts, tag_literal>(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<T>()) {
std::string& static_key = string_buffer();
read<json>::op<opening_handled<Opts>()>(static_key, ctx, it, end);
--it; // reveal the quote
key = static_key;
}
else {
auto* start = it;
skip_string_view<Opts>(ctx, it, end);
if (bool(ctx.error)) [[unlikely]]
return;
key = {start, size_t(it - start)};
}

GLZ_MATCH_QUOTE;
GLZ_INVALID_END();

Expand Down
32 changes: 16 additions & 16 deletions include/glaze/util/dump.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ namespace glz::detail
}

template <uint32_t N, class B>
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<B>) {
if (const auto k = ix + N; k > b.size()) [[unlikely]] {
Expand All @@ -45,7 +45,7 @@ namespace glz::detail
}

template <class B>
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<B>) {
if (const auto k = ix + n; k > b.size()) [[unlikely]] {
Expand All @@ -55,7 +55,7 @@ namespace glz::detail
}

template <auto c>
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<decltype(b[0])>;
using C = std::decay_t<decltype(c)>;
Expand All @@ -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<decltype(b[0])>;
using C = std::decay_t<decltype(c)>;
Expand All @@ -80,7 +80,7 @@ namespace glz::detail
}

template <bool Checked = true, class B>
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<B>) {
if (ix == b.size()) [[unlikely]] {
Expand All @@ -92,7 +92,7 @@ namespace glz::detail
}

template <auto c, bool Checked = true, class B>
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<B>) {
if (ix == b.size()) [[unlikely]] {
Expand All @@ -104,7 +104,7 @@ namespace glz::detail
}

template <string_literal str, bool Checked = true, class B>
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();
Expand All @@ -121,7 +121,7 @@ namespace glz::detail
}

template <bool Checked = true, class B>
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<B>) {
Expand All @@ -136,7 +136,7 @@ namespace glz::detail
}

template <auto c, class B>
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<B>) {
if (ix + n > b.size()) [[unlikely]] {
Expand All @@ -148,14 +148,14 @@ namespace glz::detail
}

template <auto c, class B>
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 <char IndentChar, class B>
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<B>) {
if (const auto k = ix + n + write_padding_bytes; k > b.size()) [[unlikely]] {
Expand All @@ -170,7 +170,7 @@ namespace glz::detail
}

template <const sv& str, bool Checked = true, class B>
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();
Expand All @@ -187,7 +187,7 @@ namespace glz::detail
}

template <bool Checked = true, class B>
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<B>) {
Expand All @@ -202,7 +202,7 @@ namespace glz::detail
}

template <bool Checked = true, class B>
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) {
Expand All @@ -219,7 +219,7 @@ namespace glz::detail
}

template <class B>
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<B>) {
Expand All @@ -232,7 +232,7 @@ namespace glz::detail
}

template <size_t N, class B>
GLZ_ALWAYS_INLINE void dump(const std::array<uint8_t, N>& bytes, B& b, auto& ix) noexcept
GLZ_ALWAYS_INLINE void dump(const std::array<uint8_t, N>& bytes, B& b, size_t& ix) noexcept
{
if constexpr (vector_like<B>) {
if (ix + N > b.size()) [[unlikely]] {
Expand Down
34 changes: 34 additions & 0 deletions tests/json_test/json_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9333,6 +9333,40 @@ suite response_test = [] {
};
};

struct A_empty
{};

struct B_empty
{};

using C_empty = std::variant<A_empty, B_empty>;

template <>
struct glz::meta<C_empty>
{
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<glz::opts{.error_on_unknown_keys = false, .error_on_missing_keys = true}>(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<glz::opts{.error_on_unknown_keys = false, .error_on_missing_keys = true}>(c, text);
expect(not ec) << glz::format_error(ec, text);
expect(c.index() == 1);
};
};

int main()
{
trace.end("json_test");
Expand Down

0 comments on commit c1da880

Please sign in to comment.