[{"id":36604,"web_url":"https://patchwork.libcamera.org/comment/36604/","msgid":"<20251102004711.GK797@pendragon.ideasonboard.com>","date":"2025-11-02T00:47:11","subject":"Re: [PATCH v3 2/2] libcamera: base: utils: Simplify hex adaptor","submitter":{"id":2,"url":"https://patchwork.libcamera.org/api/people/2/","name":"Laurent Pinchart","email":"laurent.pinchart@ideasonboard.com"},"content":"On Fri, Oct 31, 2025 at 08:38:54PM +0000, Kieran Bingham wrote:\n> The libcamera hex string adaptor specifies and casts each type\n> specifically to map the size of each type.\n> \n> This needlessly repeats itself for each type and further more has a bug\n> with signed integer extension which causes values such as 0x80 to be\n> printed as 0xffffffffffffff80 instead.\n> \n> Remove the template specialisations for each type, and unify with a\n> single templated constructor of the struct hex trait.\n> \n> Suggested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\n> Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n\nReviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\n> ---\n>  include/libcamera/base/utils.h | 68 +++++++---------------------------\n>  src/libcamera/base/utils.cpp   |  3 +-\n>  test/meson.build               |  2 +-\n>  3 files changed, 17 insertions(+), 56 deletions(-)\n> \n> diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\n> index d32bd1cd62e0..0b7407f7724b 100644\n> --- a/include/libcamera/base/utils.h\n> +++ b/include/libcamera/base/utils.h\n> @@ -77,70 +77,30 @@ using time_point = std::chrono::steady_clock::time_point;\n>  struct timespec duration_to_timespec(const duration &value);\n>  std::string time_point_to_string(const time_point &time);\n>  \n> -#ifndef __DOXYGEN__\n> -struct _hex {\n> +namespace details {\n> +\n> +struct hex {\n>  \tuint64_t v;\n>  \tunsigned int w;\n>  };\n>  \n> +template<typename T>\n> +constexpr unsigned int hex_width()\n> +{\n> +\treturn sizeof(T) * 2;\n> +}\n> +\n>  std::basic_ostream<char, std::char_traits<char>> &\n> -operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h);\n> -#endif\n> +operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const hex &h);\n>  \n> -template<typename T,\n> -\t std::enable_if_t<std::is_integral<T>::value> * = nullptr>\n> -_hex hex(T value, unsigned int width = 0);\n> +} /* namespace details */\n>  \n> -#ifndef __DOXYGEN__\n> -template<>\n> -inline _hex hex<int8_t>(int8_t value, unsigned int width)\n> +template<typename T, std::enable_if_t<std::is_integral_v<T>> * = nullptr>\n> +details::hex hex(T value, unsigned int width = details::hex_width<T>())\n>  {\n> -\treturn { static_cast<uint64_t>(value), width ? width : 2 };\n> +\treturn { static_cast<std::make_unsigned_t<T>>(value), width };\n>  }\n>  \n> -template<>\n> -inline _hex hex<uint8_t>(uint8_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 2 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<int16_t>(int16_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 4 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<uint16_t>(uint16_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 4 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<int32_t>(int32_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 8 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<uint32_t>(uint32_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 8 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<int64_t>(int64_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 16 };\n> -}\n> -\n> -template<>\n> -inline _hex hex<uint64_t>(uint64_t value, unsigned int width)\n> -{\n> -\treturn { static_cast<uint64_t>(value), width ? width : 16 };\n> -}\n> -#endif\n> -\n>  size_t strlcpy(char *dst, const char *src, size_t size);\n>  \n>  #ifndef __DOXYGEN__\n> diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\n> index cb9fe0049c83..65d9181c927f 100644\n> --- a/src/libcamera/base/utils.cpp\n> +++ b/src/libcamera/base/utils.cpp\n> @@ -187,7 +187,8 @@ std::string time_point_to_string(const time_point &time)\n>  }\n>  \n>  std::basic_ostream<char, std::char_traits<char>> &\n> -operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const _hex &h)\n> +details::operator<<(std::basic_ostream<char, std::char_traits<char>> &stream,\n> +\t\t    const details::hex &h)\n>  {\n>  \tstream << \"0x\";\n>  \n> diff --git a/test/meson.build b/test/meson.build\n> index 96c4477f04b2..52f04364e4fc 100644\n> --- a/test/meson.build\n> +++ b/test/meson.build\n> @@ -73,7 +73,7 @@ internal_tests = [\n>      {'name': 'timer-fail', 'sources': ['timer-fail.cpp'], 'should_fail': true},\n>      {'name': 'timer-thread', 'sources': ['timer-thread.cpp']},\n>      {'name': 'unique-fd', 'sources': ['unique-fd.cpp']},\n> -    {'name': 'utils', 'sources': ['utils.cpp'], 'should_fail': true},\n> +    {'name': 'utils', 'sources': ['utils.cpp']},\n>      {'name': 'vector', 'sources': ['vector.cpp']},\n>      {'name': 'yaml-parser', 'sources': ['yaml-parser.cpp']},\n>  ]","headers":{"Return-Path":"<libcamera-devel-bounces@lists.libcamera.org>","X-Original-To":"parsemail@patchwork.libcamera.org","Delivered-To":"parsemail@patchwork.libcamera.org","Received":["from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 1B843BDE4C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tSun,  2 Nov 2025 00:47:27 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 4A92D6086F;\n\tSun,  2 Nov 2025 01:47:26 +0100 (CET)","from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6BCE46086F\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tSun,  2 Nov 2025 01:47:24 +0100 (CET)","from pendragon.ideasonboard.com (82-203-160-149.bb.dnainternet.fi\n\t[82.203.160.149])\n\tby perceval.ideasonboard.com (Postfix) with UTF8SMTPSA id 5F12611DA; \n\tSun,  2 Nov 2025 01:45:32 +0100 (CET)"],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"NRSI+f4G\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1762044332;\n\tbh=GvubgWmxpzHEtPD/4O68XUI8Fv5fySRjirkvt2KhEkI=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=NRSI+f4Gz+ZuFGN4fwpbyOFXzaalXXKdwJ2U4yvZf2OKb6vgEGp/nAVnlAiQSYkKn\n\tMQ3YYmOQXmdEK7UL5XKwVLFdkRQxDqVjLFVkHh2vg3/uLvEPvkrsjUmnkwXgHJfsti\n\tyVq8YNmRV4ik6pWqz2al8xRjRVkfYm3ou6DouV/c=","Date":"Sun, 2 Nov 2025 02:47:11 +0200","From":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","To":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Cc":"libcamera devel <libcamera-devel@lists.libcamera.org>, =?utf-8?q?Barna?=\n\t=?utf-8?b?YsOhcyBQxZFjemU=?= <barnabas.pocze@ideasonboard.com>","Subject":"Re: [PATCH v3 2/2] libcamera: base: utils: Simplify hex adaptor","Message-ID":"<20251102004711.GK797@pendragon.ideasonboard.com>","References":"<20251031203854.19021-1-kieran.bingham@ideasonboard.com>\n\t<20251031203854.19021-3-kieran.bingham@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","Content-Transfer-Encoding":"8bit","In-Reply-To":"<20251031203854.19021-3-kieran.bingham@ideasonboard.com>","X-BeenThere":"libcamera-devel@lists.libcamera.org","X-Mailman-Version":"2.1.29","Precedence":"list","List-Id":"<libcamera-devel.lists.libcamera.org>","List-Unsubscribe":"<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>","List-Archive":"<https://lists.libcamera.org/pipermail/libcamera-devel/>","List-Post":"<mailto:libcamera-devel@lists.libcamera.org>","List-Help":"<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>","List-Subscribe":"<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]