Merge branch 'develop' into fix/custom-key-type-compat

develop (#5798) added tests/src/unit-custom-object-key-type.cpp with the
custom object key tests moved out of unit-cbor.cpp and unit-msgpack.cpp.
This branch added a file of the same name; keep develop's file and move
this branch's tests:

- the key types, helpers, and test bodies go to custom_key_test.hpp;
- unit-custom-key-type-{full,no-eq,explicit,to-json,c-str}.cpp run the
  tests for one object type each, as one file with all five
  specializations failed to link with MinGW ("relocation truncated to
  fit", more than 65535 sections, see .github/workflows/windows.yml);
- the at() test expects the "(bytes 0-7)" prefix with
  JSON_DIAGNOSTIC_POSITIONS.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
Niels Lohmann committed 2026-10-10 00:25:55 +02:00
commit 37bee747e9
22 files changed
+1523 -824

No files matched your search

@@ -85,6 +85,12 @@ template<typename BasicJsonType, typename CharType, typename OutputSinkType = ou
class binary_writer
{
using string_t = typename BasicJsonType::string_t;
/// an object key as string_t: a reference when object_t::key_type already is
/// string_t, otherwise a converted copy that outlives sanitize_utf8_for_write's result
using object_key_string_t = typename std::conditional <
std::is_same<typename BasicJsonType::object_t::key_type, string_t>::value,
const string_t&, string_t >::type;
using binary_t = typename BasicJsonType::binary_t;
using number_float_t = typename BasicJsonType::number_float_t;
@@ -764,8 +770,10 @@ class binary_writer
for (const auto& el : *j.m_data.m_value.object)
{
// a converted key must outlive the reference returned by sanitize_utf8_for_write
const object_key_string_t key_string = el.first;
string_t storage;
const string_t& key = sanitize_utf8_for_write(el.first, j, storage);
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
oa.write_characters(
reinterpret_cast<const CharType*>(key.data()),
@@ -1305,8 +1313,10 @@ class binary_writer
continue;
}
// a converted key must outlive the reference returned by sanitize_utf8_for_write
const object_key_string_t key_string = current.object_it->first;
string_t storage;
const string_t& key = sanitize_utf8_for_write(current.object_it->first, j, storage);
const string_t& key = sanitize_utf8_for_write(key_string, j, storage);
write_number_with_ubjson_prefix(key.size(), true, use_bjdata);
oa.write_characters(
reinterpret_cast<const CharType*>(key.data()),
@@ -2797,6 +2807,11 @@ class binary_writer
itself in every case but a sanitized `replace`/`ignore` one, so @a
storage must outlive the returned reference only then.
@a s must be an lvalue that outlives the returned reference. An object key
whose `key_type` is not @ref string_t must therefore first be converted
into a named string_t (see @ref object_key_string_t); the deleted overload
below enforces this at compile time.
@param[in] s the string (value or object key) to write
@param[in] context the value @a s belongs to (for diagnostics)
@param[out] storage backing storage for a sanitized copy
@@ -2826,6 +2841,10 @@ class binary_writer
}
}
/// deleted: anything but a string_t would bind a temporary that dies before the returned reference is used
template < typename T, enable_if_t < !std::is_same<T, string_t>::value, int > = 0 >
const string_t& sanitize_utf8_for_write(const T& /*s*/, const BasicJsonType& /*context*/, string_t& /*storage*/) const = delete; // NOLINT(hicpp-use-equals-delete,modernize-use-equals-delete): a private helper's guard, not part of the interface
/*!
@brief write an integer in the shortest encoding