{"id":24932,"url":"https://patchwork.libcamera.org/api/patches/24932/?format=json","web_url":"https://patchwork.libcamera.org/patch/24932/","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":"<20251031115216.3776845-3-kieran.bingham@ideasonboard.com>","date":"2025-10-31T11:52:15","name":"[v3,2/2] libcamera: base: utils: Simplify hex adaptor","commit_ref":null,"pull_url":null,"state":"superseded","archived":false,"hash":"2fb783327f6c3f13c6111d0e4d4b3398f050a216","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/24932/mbox/","series":[{"id":5548,"url":"https://patchwork.libcamera.org/api/series/5548/?format=json","web_url":"https://patchwork.libcamera.org/project/libcamera/list/?series=5548","date":"2025-10-31T11:52:13","name":"libcamera: base: utils: Prevent hex signed extension","version":3,"mbox":"https://patchwork.libcamera.org/series/5548/mbox/"}],"comments":"https://patchwork.libcamera.org/api/patches/24932/comments/","check":"pending","checks":"https://patchwork.libcamera.org/api/patches/24932/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 C13E0C32CE\n\tfor <parsemail@patchwork.libcamera.org>;\n\tFri, 31 Oct 2025 11:52:29 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id BAC00609DE;\n\tFri, 31 Oct 2025 12:52:27 +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 96196600CC\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tFri, 31 Oct 2025 12:52:23 +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 C985215D2;\n\tFri, 31 Oct 2025 12:50: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=\"CWdXaMpc\"; dkim-atps=neutral","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1761911432;\n\tbh=p5oQ5BPJu1xDQNkES/R6dHAS5DWX9MdWCogu7uLPwh0=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=CWdXaMpcJjLNYYEzhHYQwMaDjdvAvBCTpbdMk5d0Ue7v0qbYZ6NhPf8gsd+BE1ttw\n\tk80tfHrUfoSt8BJtNpQORrRhNOxA1lcAG9gKH3DNBpgd3MSQt6Fg29Q8wT3yAFSblQ\n\tJgWEJMjsy40OqB3q+TjIFqt0soJigEFX/aqYgXVo=","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 11:52:15 +0000","Message-ID":"<20251031115216.3776845-3-kieran.bingham@ideasonboard.com>","X-Mailer":"git-send-email 2.50.1","In-Reply-To":"<20251031115216.3776845-1-kieran.bingham@ideasonboard.com>","References":"<20251031115216.3776845-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   |  2 +-\n test/meson.build               |  2 +-\n 3 files changed, 14 insertions(+), 58 deletions(-)","diff":"diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h\nindex d32bd1cd62e0..555da71f124b 100644\n--- a/include/libcamera/base/utils.h\n+++ b/include/libcamera/base/utils.h\n@@ -78,67 +78,23 @@ 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_v<T>> * = nullptr>\n+\thex(T value, unsigned int width = sizeof(T) * 2)\n+\t\t: v(static_cast<std::make_unsigned_t<T>>(value)),\n+\t\t  w(width)\n+\t{\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 hex &h);\n+#else\n+template<typename T, std::enable_if_t<std::is_integral_v<T>> * = nullptr>\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..446c9a05e96d 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 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"]}