libcamera: base: utils: Simplify hex adaptor

The libcamera hex string adaptor specifies and casts each type
specifically to map the size of each type.

This needlessly repeats itself for each type and further more has a bug
with signed integer extension which causes values such as 0x80 to be
printed as 0xffffffffffffff80 instead.

Remove the template specialisations for each type, and unify with a
single templated constructor of the struct hex trait.

Suggested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>
Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
This commit is contained in:
Kieran Bingham
2025-10-31 20:38:54 +00:00
committed by Laurent Pinchart
parent 06044ca70d
commit 760456acfc
3 changed files with 17 additions and 56 deletions

View File

@@ -77,70 +77,30 @@ using time_point = std::chrono::steady_clock::time_point;
struct timespec duration_to_timespec(const duration &value);
std::string time_point_to_string(const time_point &time);
#ifndef __DOXYGEN__
struct _hex {
namespace details {
struct hex {
uint64_t v;
unsigned int w;
};
template<typename T>
constexpr unsigned int hex_width()
{
return sizeof(T) * 2;
}
std::basic_ostream<char, std::char_traits<char>> &
operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);
#endif
operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const hex &h);
template<typename T,
std::enable_if_t<std::is_integral<T>::value> * = nullptr>
_hex hex(T value, unsigned int width = 0);
} /* namespace details */
#ifndef __DOXYGEN__
template<>
inline _hex hex<int8_t>(int8_t value, unsigned int width)
template<typename T, std::enable_if_t<std::is_integral_v<T>> * = nullptr>
details::hex hex(T value, unsigned int width = details::hex_width<T>())
{
return { static_cast<uint64_t>(value), width ? width : 2 };
return { static_cast<std::make_unsigned_t<T>>(value), width };
}
template<>
inline _hex hex<uint8_t>(uint8_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 2 };
}
template<>
inline _hex hex<int16_t>(int16_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 4 };
}
template<>
inline _hex hex<uint16_t>(uint16_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 4 };
}
template<>
inline _hex hex<int32_t>(int32_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 8 };
}
template<>
inline _hex hex<uint32_t>(uint32_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 8 };
}
template<>
inline _hex hex<int64_t>(int64_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 16 };
}
template<>
inline _hex hex<uint64_t>(uint64_t value, unsigned int width)
{
return { static_cast<uint64_t>(value), width ? width : 16 };
}
#endif
size_t strlcpy(char *dst, const char *src, size_t size);
#ifndef __DOXYGEN__

View File

@@ -187,7 +187,8 @@ std::string time_point_to_string(const time_point &time)
}
std::basic_ostream<char, std::char_traits<char>> &
operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h)
details::operator<<(std::basic_ostream<char, std::char_traits<char>> &stream,
const details::hex &h)
{
stream << "0x";

View File

@@ -73,7 +73,7 @@ internal_tests = [
{'name': 'timer-fail', 'sources': ['timer-fail.cpp'], 'should_fail': true},
{'name': 'timer-thread', 'sources': ['timer-thread.cpp']},
{'name': 'unique-fd', 'sources': ['unique-fd.cpp']},
{'name': 'utils', 'sources': ['utils.cpp'], 'should_fail': true},
{'name': 'utils', 'sources': ['utils.cpp']},
{'name': 'vector', 'sources': ['vector.cpp']},
{'name': 'yaml-parser', 'sources': ['yaml-parser.cpp']},
]