From patchwork Sun Jan 8 21:43:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 18098 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 1DECEC322E for ; Sun, 8 Jan 2023 21:44:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id CAD3F625E2; Sun, 8 Jan 2023 22:44:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1673214244; bh=KNj4VmbsOtr15SGL6TtOBEOGJUOlMlXXBv6eM1MclHU=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=BbHjpRbBq0DGmlC6WaywU1SpB8383Rej7Y3t1Q190gKnjHMfMhhzvJU/gP1cGEndb nVMv215yveE85IpwbbszLXNCkxZOdNsC06all7nxh2Vfku9N3J1K8y5SnRfh0WrosD onaopjrCvCyMrIAOh3leHTS7TZrVGEc92Uq+dalS1cQmsywI/hx5MqZLL5ng6FENjS n2NztIrkJe4QFBpD0IUhaq7BuebQuqQizXz/B4BXy7/eqfvJE82uQNOM8J2GeLAkVA mgNFekoToFW1gyN1g4+e2e02lIFq9CgcDzlJGFQvzB8gXA4snmSnNRIuLVVUkYn9nO 0Y95rILzoSrig== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id C3191625D8 for ; Sun, 8 Jan 2023 22:44:02 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="K326f5h8"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (213-243-189-158.bb.dnainternet.fi [213.243.189.158]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 3BD106CF for ; Sun, 8 Jan 2023 22:44:02 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1673214242; bh=KNj4VmbsOtr15SGL6TtOBEOGJUOlMlXXBv6eM1MclHU=; h=From:To:Subject:Date:In-Reply-To:References:From; b=K326f5h8CJ5RqechnGOZmUX33WVv858A4xIK6mU3Oz7mvO3PVvtBO297w7K3cLlxi 8c5c7j5+YjBBnnjCfbLwGEg4xtAt2KP2THNtBS0fdo5L+DY3Y1uAy09qTlpAbwN4+P g+gg8MNC/hKv4PBbwoKEo7HLdRfyQObfv1R7hyEg= To: libcamera-devel@lists.libcamera.org Date: Sun, 8 Jan 2023 23:43:56 +0200 Message-Id: <20230108214357.12641-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.38.2 In-Reply-To: <20230108214357.12641-1-laurent.pinchart@ideasonboard.com> References: <20230108214357.12641-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v1 1/2] base: utils: Add and use strtod() helper X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Laurent Pinchart via libcamera-devel From: Laurent Pinchart Reply-To: Laurent Pinchart Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" The strtod() function is locale-dependent, and thus ill-suited to parse numbers coming from, for instance, YAML files. The YamlObject class uses strtod_l() to fix that issue, but that function is not available with all libc implementations. Correctly handling this problem is becoming out of scope for the YamlObject class. As a first step, add a strtod() helper function in the utils namespace that copies the implementation from YamlObject, and use it in YamlObject. The core issue will then be fixed in utils::strtod(). Signed-off-by: Laurent Pinchart Reviewed-by: Kieran Bingham --- include/libcamera/base/utils.h | 2 ++ src/libcamera/base/utils.cpp | 46 ++++++++++++++++++++++++++++++++++ src/libcamera/yaml_parser.cpp | 34 +------------------------ 3 files changed, 49 insertions(+), 33 deletions(-) diff --git a/include/libcamera/base/utils.h b/include/libcamera/base/utils.h index eb7bcdf4c173..37d9af609ec7 100644 --- a/include/libcamera/base/utils.h +++ b/include/libcamera/base/utils.h @@ -367,6 +367,8 @@ decltype(auto) abs_diff(const T &a, const T &b) return a - b; } +double strtod(const char *__restrict nptr, char **__restrict endptr); + } /* namespace utils */ #ifndef __DOXYGEN__ diff --git a/src/libcamera/base/utils.cpp b/src/libcamera/base/utils.cpp index 6a307940448e..4a239427a4d9 100644 --- a/src/libcamera/base/utils.cpp +++ b/src/libcamera/base/utils.cpp @@ -8,6 +8,7 @@ #include #include +#include #include #include #include @@ -463,6 +464,51 @@ std::string toAscii(const std::string &str) * \a b */ +namespace { + +/* + * RAII wrapper around locale_t instances, to support global locale instances + * without leaking memory. + */ +class Locale +{ +public: + Locale(const char *locale) + { + locale_ = newlocale(LC_ALL_MASK, locale, static_cast(0)); + } + + ~Locale() + { + freelocale(locale_); + } + + locale_t locale() { return locale_; } + +private: + locale_t locale_; +}; + +Locale cLocale("C"); + +} /* namespace */ + +/** + * \brief Convert a string to a double independently of the current locale + * \param[in] nptr The string to convert + * \param[out] endptr Pointer to trailing portion of the string after conversion + * + * This function is a locale-independent version of the std::strtod() function. + * It behaves as the standard function, but uses the "C" locale instead of the + * current locale. + * + * \return The converted value, if any, or 0.0 if the conversion failed. + */ +double strtod(const char *__restrict nptr, char **__restrict endptr) +{ + return strtod_l(nptr, endptr, cLocale.locale()); +} + } /* namespace utils */ #ifndef __DOXYGEN__ diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp index 2806c591f75d..153a6d53c3f9 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/yaml_parser.cpp @@ -31,38 +31,6 @@ namespace { /* Empty static YamlObject as a safe result for invalid operations */ static const YamlObject empty; -/* - * Construct a global RAII locale for use by all YAML parser instances to - * ensure consistency when parsing configuration files and types regardless of - * the system locale configuration. - * - * For more information see: - * - https://bugs.libcamera.org/show_bug.cgi?id=174 - */ -class Locale -{ -public: - Locale(const char *locale) - { - locale_ = newlocale(LC_ALL_MASK, locale, static_cast(0)); - if (locale_ == static_cast(0)) - LOG(YamlParser, Fatal) - << "Failed to construct a locale"; - } - - ~Locale() - { - freelocale(locale_); - } - - locale_t locale() { return locale_; } - -private: - locale_t locale_; -}; - -Locale yamlLocale("C"); - } /* namespace */ /** @@ -315,7 +283,7 @@ std::optional YamlObject::get() const char *end; errno = 0; - double value = strtod_l(value_.c_str(), &end, yamlLocale.locale()); + double value = utils::strtod(value_.c_str(), &end); if ('\0' != *end || errno == ERANGE) return std::nullopt;