{"id":24935,"url":"https://patchwork.libcamera.org/api/patches/24935/?format=json","web_url":"https://patchwork.libcamera.org/patch/24935/","project":{"id":1,"url":"https://patchwork.libcamera.org/api/projects/1/?format=json","name":"libcamera","link_name":"libcamera","list_id":"libcamera_core","list_email":"libcamera-devel@lists.libcamera.org","web_url":"","scm_url":"","webscm_url":""},"msgid":"<20251031203854.19021-3-kieran.bingham@ideasonboard.com>","date":"2025-10-31T20:38:54","name":"[v3,2/2] libcamera: base: utils: Simplify hex adaptor","commit_ref":null,"pull_url":null,"state":"accepted","archived":false,"hash":"732a5b6053fc67863d8740f3d7c76db730273e08","submitter":{"id":4,"url":"https://patchwork.libcamera.org/api/people/4/?format=json","name":"Kieran Bingham","email":"kieran.bingham@ideasonboard.com"},"delegate":null,"mbox":"https://patchwork.libcamera.org/patch/24935/mbox/","series":[{"id":5549,"url":"https://patchwork.libcamera.org/api/series/5549/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5549","date":"2025-10-31T20:38:52","name":"libcamera: base: utils: Prevent hex signed extension","version":3,"mbox":"https://patchwork.libcamera.org/series/5549/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/24935/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/24935/checks/","tags":{},"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 18427C32DB\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 31 Oct 2025 20:39:06 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 6360E609E0;\n\tFri, 31 Oct 2025 21:39:03 +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 8A44360947\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 31 Oct 2025 21:38:58 +0100 (CET)","from charm.hippo-penny.ts.net\n\t(cpc89244-aztw30-2-0-cust6594.18-1.cable.virginm.net [86.31.185.195])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id 78F7D1691;\n\tFri, 31 Oct 2025 21:37:07 +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=\"STC9q6B2\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1761943027;\n\tbh=1bm/SqHeujeQ4kcDobrPwskmL3V7FCo1abcyR3IOGsc=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=STC9q6B2m9KgJTC3tWCi5i2/0SuuS1SviUx9rHJgbD3sU2fZy9YDyjr4Jlg52Dxue\n\tL6fuBGt0Bc8aRnB9ggKiBoYmX3bHivB8fD884CL+exloaBpKDPHBKwJ/ConiYuAVR1\n\tPnRyBoyfpOQlu0H1AwWAZJHxkpulVvBgNjaOopms=","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"libcamera devel <libcamera-devel@lists.libcamera.org>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>, =?utf-8?q?Barnab?=\n\t=?utf-8?b?w6FzIFDFkWN6ZQ==?= <barnabas.pocze@ideasonboard.com>","Subject":"[PATCH v3 2/2] libcamera: base: utils: Simplify hex adaptor","Date":"Fri, 31 Oct 2025 20:38:54 +0000","Message-ID":"<20251031203854.19021-3-kieran.bingham@ideasonboard.com>","X-Mailer":"git-send-email 2.51.0","In-Reply-To":"<20251031203854.19021-1-kieran.bingham@ideasonboard.com>","References":"<20251031203854.19021-1-kieran.bingham@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","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>"},"content":"The libcamera hex string adaptor specifies and casts each type\nspecifically to map the size of each type.\n\nThis needlessly repeats itself for each type and further more has a bug\nwith signed integer extension which causes values such as 0x80 to be\nprinted as 0xffffffffffffff80 instead.\n\nRemove the template specialisations for each type, and unify with a\nsingle templated constructor of the struct hex trait.\n\nSuggested-by: Barnabás Pőcze <barnabas.pocze@ideasonboard.com>\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\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(-)","diff":"diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\nindex 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__\ndiff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\nindex 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 \ndiff --git a/test/meson.build b/test/meson.build\nindex 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 ]\n","prefixes":["v3","2/2"]}