{"id":24928,"url":"https://patchwork.libcamera.org/api/patches/24928/?format=json","web_url":"https://patchwork.libcamera.org/patch/24928/","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":"<20251030181127.1059501-3-kieran.bingham@ideasonboard.com>","date":"2025-10-30T18:11:27","name":"[v2,2/2] libcamera: base: utils: Simplify hex adaptor","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"58d0a38f2065a292de6d4e2e5a2062f682a94375","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/24928/mbox/","series":[{"id":5546,"url":"https://patchwork.libcamera.org/api/series/5546/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5546","date":"2025-10-30T18:11:25","name":"libcamera: base: utils: Prevent hex signed extension","version":2,"mbox":"https://patchwork.libcamera.org/series/5546/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/24928/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/24928/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 ABCC9C32CE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 30 Oct 2025 18:11:37 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 265F260967;\n\tThu, 30 Oct 2025 19:11:35 +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 5965C608DF\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 30 Oct 2025 19:11:32 +0100 (CET)","from Monstersaurus.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 36AF41E33;\n\tThu, 30 Oct 2025 19:09:42 +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=\"UainzoJb\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1761847782;\n\tbh=/ST+k2N8Z6PCUh+tw/WoKA/TdEXlroxmkP8nKiH2gvQ=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=UainzoJbyH/Vhuz5SbFPb/mOg982Djd2EbHn12JVkZ7YyZamqPAfmEXT5cVTbzK9K\n\t76fzu/CHynUfiWyWdq11PsBa7i7mbf19Dpm1ReIpfQiZg6Dz/ojM7pjNc2Z0MePVZs\n\tVBcNxWshAywO5hssrDsdlBMxuUjotLxn3jOq3+iE=","From":"Kieran Bingham <kieran.bingham@ideasonboard.com>","To":"libcamera devel <libcamera-devel@lists.libcamera.org>","Cc":"Kieran Bingham <kieran.bingham@ideasonboard.com>","Subject":"[PATCH v2 2/2] libcamera: base: utils: Simplify hex adaptor","Date":"Thu, 30 Oct 2025 18:11:27 +0000","Message-ID":"<20251030181127.1059501-3-kieran.bingham@ideasonboard.com>","X-Mailer":"git-send-email 2.50.1","In-Reply-To":"<20251030181127.1059501-1-kieran.bingham@ideasonboard.com>","References":"<20251030181127.1059501-1-kieran.bingham@ideasonboard.com>","MIME-Version":"1.0","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\nSigned-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>\n---\n include/libcamera/base/utils.h | 66 ++++++----------------------------\n src/libcamera/base/utils.cpp   |  2 +-\n test/meson.build               |  2 +-\n 3 files changed, 12 insertions(+), 58 deletions(-)","diff":"diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\nindex d32bd1cd62e0..3b3da7b2a887 100644\n--- a/include/libcamera/base/utils.h\n+++ b/include/libcamera/base/utils.h\n@@ -78,67 +78,21 @@ 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+struct hex {\n \tuint64_t v;\n \tunsigned int w;\n+\n+\ttemplate<typename T, std::enable_if_t<std::is_integral<T>::value> * = nullptr>\n+\thex(T value, unsigned int width = 0)\n+\t: v(static_cast<std::make_unsigned_t<T>>(value)),\n+\t  w(width ? width : sizeof(T) * 2)\n+\t{ }\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-\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-\n-#ifndef __DOXYGEN__\n-template<>\n-inline _hex hex<int8_t>(int8_t value, unsigned int width)\n-{\n-\treturn { static_cast<uint64_t>(value), width ? width : 2 };\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+operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const struct hex &h);\n+#else\n+void hex(T value, unsigned int width = 0);\n #endif\n \n size_t strlcpy(char *dst, const char *src, size_t size);\ndiff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp\nindex cb9fe0049c83..db868be224a2 100644\n--- a/src/libcamera/base/utils.cpp\n+++ b/src/libcamera/base/utils.cpp\n@@ -187,7 +187,7 @@ 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+operator<<(std::basic_ostream<char, std::char_traits<char>> &stream, const struct 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":["v2","2/2"]}