mirror of
https://github.com/nlohmann/json.git
synced 2026-09-01 14:07:14 +00:00
Fix GCC narrowing warning and address review feedback
- get_bytes(): replace `len -= static_cast<NumberType>(wanted)` with an explicit `len = static_cast<NumberType>(len - ...)`. The compound assignment promoted the operands to int and narrowed back, which GCC rejects under -Werror=arith-conversion when NumberType is narrower than int (e.g. UBJSON's int16 length). This also fixes the CodeQL build. - get_bytes(): add JSON_ASSERT(read == wanted) documenting that get_elements() never returns more than requested (per review). - iterator_input_adapter: de-duplicate the iterator_is_contiguous definition with the #if inside the initializer (per review). - Add a comment explaining why the memcpy source is &*current (needed for non-pointer contiguous iterators), and drop the redundant parentheses. - Run astyle on the new unit test so the amalgamation/format check passes. Signed-off-by: Niels Lohmann <mail@nlohmann.me> Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
9eee7a7b9b
commit
282ff6ce5c
@@ -2975,13 +2975,16 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY(read < wanted))
|
if (JSON_HEDLEY_UNLIKELY(read < wanted))
|
||||||
{
|
{
|
||||||
// premature end of input: shrink to what was actually read and
|
// premature end of input: shrink to what was actually read and
|
||||||
// report the failure at the first missing byte
|
// report the failure at the first missing byte (same position
|
||||||
|
// accounting as get_to() for partial number reads)
|
||||||
result.resize(old_size + read);
|
result.resize(old_size + read);
|
||||||
++chars_read;
|
++chars_read;
|
||||||
current = char_traits<char_type>::eof();
|
current = char_traits<char_type>::eof();
|
||||||
return unexpect_eof(format, context);
|
return unexpect_eof(format, context);
|
||||||
}
|
}
|
||||||
len -= static_cast<NumberType>(wanted);
|
// a full chunk was read; get_elements() never returns more than requested
|
||||||
|
JSON_ASSERT(read == wanted);
|
||||||
|
len = static_cast<NumberType>(len - static_cast<NumberType>(wanted));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -191,11 +191,11 @@ class iterator_input_adapter
|
|||||||
// whether IteratorType refers to a contiguous range and therefore supports
|
// whether IteratorType refers to a contiguous range and therefore supports
|
||||||
// a std::memcpy fast path (pointers always do; in C++20 we can also detect
|
// a std::memcpy fast path (pointers always do; in C++20 we can also detect
|
||||||
// library iterators such as those of std::vector and std::string)
|
// library iterators such as those of std::vector and std::string)
|
||||||
|
static constexpr bool iterator_is_contiguous =
|
||||||
#if defined(__cpp_lib_concepts) && defined(JSON_HAS_CPP_20)
|
#if defined(__cpp_lib_concepts) && defined(JSON_HAS_CPP_20)
|
||||||
static constexpr bool iterator_is_contiguous = std::is_pointer<IteratorType>::value || std::contiguous_iterator<IteratorType>;
|
std::contiguous_iterator<IteratorType> ||
|
||||||
#else
|
|
||||||
static constexpr bool iterator_is_contiguous = std::is_pointer<IteratorType>::value;
|
|
||||||
#endif
|
#endif
|
||||||
|
std::is_pointer<IteratorType>::value;
|
||||||
|
|
||||||
// contiguous fast path: bulk copy the remaining range with std::memcpy
|
// contiguous fast path: bulk copy the remaining range with std::memcpy
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -206,7 +206,9 @@ class iterator_input_adapter
|
|||||||
const std::size_t copied = (std::min)(wanted, available);
|
const std::size_t copied = (std::min)(wanted, available);
|
||||||
if (JSON_HEDLEY_LIKELY(copied != 0))
|
if (JSON_HEDLEY_LIKELY(copied != 0))
|
||||||
{
|
{
|
||||||
std::memcpy(dest, &(*current), copied);
|
// &*current yields the raw address for both raw pointers and
|
||||||
|
// non-pointer contiguous iterators (e.g. std::vector's iterator)
|
||||||
|
std::memcpy(dest, &*current, copied);
|
||||||
std::advance(current, static_cast<typename std::iterator_traits<IteratorType>::difference_type>(copied / sizeof(char_type)));
|
std::advance(current, static_cast<typename std::iterator_traits<IteratorType>::difference_type>(copied / sizeof(char_type)));
|
||||||
}
|
}
|
||||||
return copied;
|
return copied;
|
||||||
|
|||||||
@@ -7023,11 +7023,11 @@ class iterator_input_adapter
|
|||||||
// whether IteratorType refers to a contiguous range and therefore supports
|
// whether IteratorType refers to a contiguous range and therefore supports
|
||||||
// a std::memcpy fast path (pointers always do; in C++20 we can also detect
|
// a std::memcpy fast path (pointers always do; in C++20 we can also detect
|
||||||
// library iterators such as those of std::vector and std::string)
|
// library iterators such as those of std::vector and std::string)
|
||||||
|
static constexpr bool iterator_is_contiguous =
|
||||||
#if defined(__cpp_lib_concepts) && defined(JSON_HAS_CPP_20)
|
#if defined(__cpp_lib_concepts) && defined(JSON_HAS_CPP_20)
|
||||||
static constexpr bool iterator_is_contiguous = std::is_pointer<IteratorType>::value || std::contiguous_iterator<IteratorType>;
|
std::contiguous_iterator<IteratorType> ||
|
||||||
#else
|
|
||||||
static constexpr bool iterator_is_contiguous = std::is_pointer<IteratorType>::value;
|
|
||||||
#endif
|
#endif
|
||||||
|
std::is_pointer<IteratorType>::value;
|
||||||
|
|
||||||
// contiguous fast path: bulk copy the remaining range with std::memcpy
|
// contiguous fast path: bulk copy the remaining range with std::memcpy
|
||||||
template<class T>
|
template<class T>
|
||||||
@@ -7038,7 +7038,9 @@ class iterator_input_adapter
|
|||||||
const std::size_t copied = (std::min)(wanted, available);
|
const std::size_t copied = (std::min)(wanted, available);
|
||||||
if (JSON_HEDLEY_LIKELY(copied != 0))
|
if (JSON_HEDLEY_LIKELY(copied != 0))
|
||||||
{
|
{
|
||||||
std::memcpy(dest, &(*current), copied);
|
// &*current yields the raw address for both raw pointers and
|
||||||
|
// non-pointer contiguous iterators (e.g. std::vector's iterator)
|
||||||
|
std::memcpy(dest, &*current, copied);
|
||||||
std::advance(current, static_cast<typename std::iterator_traits<IteratorType>::difference_type>(copied / sizeof(char_type)));
|
std::advance(current, static_cast<typename std::iterator_traits<IteratorType>::difference_type>(copied / sizeof(char_type)));
|
||||||
}
|
}
|
||||||
return copied;
|
return copied;
|
||||||
@@ -13174,13 +13176,16 @@ class binary_reader
|
|||||||
if (JSON_HEDLEY_UNLIKELY(read < wanted))
|
if (JSON_HEDLEY_UNLIKELY(read < wanted))
|
||||||
{
|
{
|
||||||
// premature end of input: shrink to what was actually read and
|
// premature end of input: shrink to what was actually read and
|
||||||
// report the failure at the first missing byte
|
// report the failure at the first missing byte (same position
|
||||||
|
// accounting as get_to() for partial number reads)
|
||||||
result.resize(old_size + read);
|
result.resize(old_size + read);
|
||||||
++chars_read;
|
++chars_read;
|
||||||
current = char_traits<char_type>::eof();
|
current = char_traits<char_type>::eof();
|
||||||
return unexpect_eof(format, context);
|
return unexpect_eof(format, context);
|
||||||
}
|
}
|
||||||
len -= static_cast<NumberType>(wanted);
|
// a full chunk was read; get_elements() never returns more than requested
|
||||||
|
JSON_ASSERT(read == wanted);
|
||||||
|
len = static_cast<NumberType>(len - static_cast<NumberType>(wanted));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2785,10 +2785,10 @@ TEST_CASE("CBOR large strings and binaries (chunked reader)")
|
|||||||
// sure roundtripping is correct for lengths around and beyond the internal
|
// sure roundtripping is correct for lengths around and beyond the internal
|
||||||
// chunk size (4096 bytes), for both vector (iterator) and pointer inputs.
|
// chunk size (4096 bytes), for both vector (iterator) and pointer inputs.
|
||||||
for (const std::size_t len :
|
for (const std::size_t len :
|
||||||
{
|
{
|
||||||
std::size_t{0}, std::size_t{1}, std::size_t{4095}, std::size_t{4096},
|
std::size_t{0}, std::size_t{1}, std::size_t{4095}, std::size_t{4096},
|
||||||
std::size_t{4097}, std::size_t{8192}, std::size_t{100000}
|
std::size_t{4097}, std::size_t{8192}, std::size_t{100000}
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
CAPTURE(len);
|
CAPTURE(len);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user