diff --git a/include/nlohmann/detail/view/document_data.hpp b/include/nlohmann/detail/view/document_data.hpp index 4784d0937..a72227aa5 100644 --- a/include/nlohmann/detail/view/document_data.hpp +++ b/include/nlohmann/detail/view/document_data.hpp @@ -54,7 +54,8 @@ struct document_data void* mem = ::operator new (sizeof(document_data) + (count * sizeof(node))); auto* d = new (mem) document_data(); // NOLINT(cppcoreguidelines-owning-memory): owned by the returned pointer, freed by deleter // (aligned: sizeof is a multiple of the alignment; through void*, as GCC's -Wcast-align wants) - d->inline_nodes = static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // NOLINT(bugprone-casting-through-void) + // (null without inline nodes, not a pointer past the end of the allocation) + d->inline_nodes = count == 0 ? nullptr : static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // NOLINT(bugprone-casting-through-void) d->inline_capacity = count; d->nodes = d->inline_nodes; d->node_capacity = count; diff --git a/include/nlohmann/detail/view/input.hpp b/include/nlohmann/detail/view/input.hpp index 0a0b5119c..7e1fea09a 100644 --- a/include/nlohmann/detail/view/input.hpp +++ b/include/nlohmann/detail/view/input.hpp @@ -42,12 +42,11 @@ enum class input_kind /// a single-byte character type (char, signed/unsigned char, char8_t, std::uint8_t, ...) template -struct is_byte_char : std::integral_constant < bool, std::is_integral::value && sizeof(T) == 1 > {}; // NOLINT(bugprone-sizeof-expression): T is any pointee or element type +struct is_byte_char : conjunction, std::integral_constant> {}; // NOLINT(bugprone-sizeof-expression): T is any pointee or element type /// a character type the library's input adapter converts to UTF-8 template -struct is_wide_char : std::integral_constant < bool, std::is_same::value || std::is_same::value - || std::is_same::value > {}; +struct is_wide_char : disjunction, std::is_same, std::is_same> {}; template struct classify_input @@ -146,7 +145,7 @@ inline void append_stream(std::string& buf, std::istream& is) const std::size_t room = (std::max)(buf.capacity() - used, std::size_t{4096}); buf.resize(used + room); const std::streamsize got = sb->sgetn(&buf[used], static_cast(room)); - buf.resize(used + static_cast(got > 0 ? got : 0)); + buf.resize(used + static_cast((std::max)(got, std::streamsize{0}))); if (got <= 0) { break; diff --git a/include/nlohmann/json_view.hpp b/include/nlohmann/json_view.hpp index c311d67e5..35612aca2 100644 --- a/include/nlohmann/json_view.hpp +++ b/include/nlohmann/json_view.hpp @@ -443,7 +443,10 @@ class basic_json_document if (shrink_nodes) { - std::memcpy(fresh, d.nodes, d.node_count * sizeof(node)); + if (d.node_count != 0) + { + std::memcpy(fresh, d.nodes, d.node_count * sizeof(node)); + } ::operator delete (d.nodes); d.nodes = fresh; d.node_capacity = into_header ? d.inline_capacity : d.node_count; diff --git a/single_include/nlohmann/json_view.hpp b/single_include/nlohmann/json_view.hpp index a9e6b4a8b..1527d7f29 100644 --- a/single_include/nlohmann/json_view.hpp +++ b/single_include/nlohmann/json_view.hpp @@ -324,7 +324,8 @@ struct document_data void* mem = ::operator new (sizeof(document_data) + (count * sizeof(node))); auto* d = new (mem) document_data(); // NOLINT(cppcoreguidelines-owning-memory): owned by the returned pointer, freed by deleter // (aligned: sizeof is a multiple of the alignment; through void*, as GCC's -Wcast-align wants) - d->inline_nodes = static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // NOLINT(bugprone-casting-through-void) + // (null without inline nodes, not a pointer past the end of the allocation) + d->inline_nodes = count == 0 ? nullptr : static_cast(static_cast(static_cast(mem) + sizeof(document_data))); // NOLINT(bugprone-casting-through-void) d->inline_capacity = count; d->nodes = d->inline_nodes; d->node_capacity = count; @@ -1927,12 +1928,11 @@ enum class input_kind /// a single-byte character type (char, signed/unsigned char, char8_t, std::uint8_t, ...) template -struct is_byte_char : std::integral_constant < bool, std::is_integral::value && sizeof(T) == 1 > {}; // NOLINT(bugprone-sizeof-expression): T is any pointee or element type +struct is_byte_char : conjunction, std::integral_constant> {}; // NOLINT(bugprone-sizeof-expression): T is any pointee or element type /// a character type the library's input adapter converts to UTF-8 template -struct is_wide_char : std::integral_constant < bool, std::is_same::value || std::is_same::value - || std::is_same::value > {}; +struct is_wide_char : disjunction, std::is_same, std::is_same> {}; template struct classify_input @@ -2031,7 +2031,7 @@ inline void append_stream(std::string& buf, std::istream& is) const std::size_t room = (std::max)(buf.capacity() - used, std::size_t{4096}); buf.resize(used + room); const std::streamsize got = sb->sgetn(&buf[used], static_cast(room)); - buf.resize(used + static_cast(got > 0 ? got : 0)); + buf.resize(used + static_cast((std::max)(got, std::streamsize{0}))); if (got <= 0) { break; @@ -2762,7 +2762,10 @@ class basic_json_document if (shrink_nodes) { - std::memcpy(fresh, d.nodes, d.node_count * sizeof(node)); + if (d.node_count != 0) + { + std::memcpy(fresh, d.nodes, d.node_count * sizeof(node)); + } ::operator delete (d.nodes); d.nodes = fresh; d.node_capacity = into_header ? d.inline_capacity : d.node_count;