From patchwork Tue Aug 16 01:54:11 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 17133 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 0D8CAC3275 for ; Tue, 16 Aug 2022 01:54:40 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 914CE61FD4; Tue, 16 Aug 2022 03:54:39 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org; s=mail; t=1660614879; bh=JZ9nVNOV0g5kaaCyiDfyY+ChH3PMrrXzF4SuNMylqAc=; 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=PnUqg76Uy9mS/SuqLOiRFUiZD3RHLVdVqf7JFFc7hWJyNu7O4n2L92RTPq2GoKZaK dk6VxaNqCru+kxonmkmIJrYf1LccuCQZym9ADoJAU2AfO0938XWSnCQv564TbXFgl4 RUa1fO20LvJ9MrjBH+tBew31HBmS3KB+JNdfdZYBqbWqDWXQ9UVtnBkhEnEHxhdqCF AE7hfWkQxA3oE9Iu/xRS/EuV7cjm3PEmUNUW6+khBoDfpWEAC08DarCu7AqemWsUGr BUzd9Vovpxmqct0nPIqkNIYh+SMy0lNimxS9aH8HK61ENacjLUs5epdmpqm5JWSVEb DLTV9Y899PyWQ== Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B676A61FBD for ; Tue, 16 Aug 2022 03:54:36 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="JYA3IGPe"; dkim-atps=neutral Received: from pendragon.ideasonboard.com (62-78-145-57.bb.dnainternet.fi [62.78.145.57]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 56598496; Tue, 16 Aug 2022 03:54:36 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1660614876; bh=JZ9nVNOV0g5kaaCyiDfyY+ChH3PMrrXzF4SuNMylqAc=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=JYA3IGPeetLW6XUKvQwvv+kgjaNiUOcZfwBLnXGEXDWhLHcF3DTKJcQhUhNAN2Feq fYnitQOEUTc7cl/W6RsK3nSWSLLZkvpYvsst+5yAg1clL9nuqPfREGHlhPy7207Klk 5si4vrzvodYqz84tzlr4zlvDzpKMZqweDyEO7yQM= To: libcamera-devel@lists.libcamera.org Date: Tue, 16 Aug 2022 04:54:11 +0300 Message-Id: <20220816015414.7462-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: <20220816015414.7462-1-laurent.pinchart@ideasonboard.com> References: <20220816015414.7462-1-laurent.pinchart@ideasonboard.com> MIME-Version: 1.0 Subject: [libcamera-devel] [PATCH v4 6/9] libcamera: yaml_parser: De-duplicate common code in YamlObject::get() 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 specializations of the YamlObject::get() function template for integer types duplicate code that doesn't directly depend on the template type argument. Move it to separate helper functions to reduce the object size. While at it, rephrase the comment about unsigned integer parsing. Signed-off-by: Laurent Pinchart Reviewed-by: Paul Elder Reviewed-by: Jacopo Mondi --- src/libcamera/yaml_parser.cpp | 160 ++++++++++++++-------------------- 1 file changed, 67 insertions(+), 93 deletions(-) diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp index 85a52c05e682..3d5efdc4419b 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/yaml_parser.cpp @@ -131,23 +131,65 @@ std::optional YamlObject::get() const return std::nullopt; } +namespace { + +bool parseSignedInteger(const std::string &str, int32_t min, int32_t max, + int32_t *result) +{ + if (str == "") + return false; + + char *end; + + errno = 0; + long value = std::strtol(str.c_str(), &end, 10); + + if ('\0' != *end || errno == ERANGE || value < min || value > max) + return false; + + *result = value; + return true; +} + +bool parseUnsignedInteger(const std::string &str, uint32_t max, uint32_t *result) +{ + if (str == "") + return false; + + /* + * strtoul() accepts strings representing a negative number, in which + * case it negates the converted value. We don't want to silently accept + * negative values and return a large positive number, so check for a + * minus sign (after optional whitespace) and return an error. + */ + std::size_t found = str.find_first_not_of(" \t"); + if (found != std::string::npos && str[found] == '-') + return false; + + char *end; + + errno = 0; + unsigned long value = std::strtoul(str.c_str(), &end, 10); + + if ('\0' != *end || errno == ERANGE || value > max) + return false; + + *result = value; + return true; +} + +} /* namespace */ + template<> std::optional YamlObject::get() const { if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + int32_t value; - char *end; - - errno = 0; - long value = std::strtol(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseSignedInteger(value_, std::numeric_limits::min(), + std::numeric_limits::max(), &value)) return std::nullopt; return value; @@ -159,28 +201,10 @@ std::optional YamlObject::get() const if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + uint32_t value; - /* - * libyaml parses all scalar values as strings. When a string has - * leading spaces before a minus sign, for example " -10", strtoul - * skips leading spaces, accepts the leading minus sign, and the - * calculated digits are negated as if by unary minus. Rule it out in - * case the user gets a large number when the value is negative. - */ - std::size_t found = value_.find_first_not_of(" \t"); - if (found != std::string::npos && value_[found] == '-') - return std::nullopt; - - char *end; - - errno = 0; - unsigned long value = std::strtoul(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseUnsignedInteger(value_, std::numeric_limits::max(), + &value)) return std::nullopt; return value; @@ -192,17 +216,10 @@ std::optional YamlObject::get() const if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + int32_t value; - char *end; - - errno = 0; - long value = std::strtol(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseSignedInteger(value_, std::numeric_limits::min(), + std::numeric_limits::max(), &value)) return std::nullopt; return value; @@ -214,28 +231,10 @@ std::optional YamlObject::get() const if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + uint32_t value; - /* - * libyaml parses all scalar values as strings. When a string has - * leading spaces before a minus sign, for example " -10", strtoul - * skips leading spaces, accepts the leading minus sign, and the - * calculated digits are negated as if by unary minus. Rule it out in - * case the user gets a large number when the value is negative. - */ - std::size_t found = value_.find_first_not_of(" \t"); - if (found != std::string::npos && value_[found] == '-') - return std::nullopt; - - char *end; - - errno = 0; - unsigned long value = std::strtoul(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseUnsignedInteger(value_, std::numeric_limits::max(), + &value)) return std::nullopt; return value; @@ -247,17 +246,10 @@ std::optional YamlObject::get() const if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + int32_t value; - char *end; - - errno = 0; - long value = std::strtol(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseSignedInteger(value_, std::numeric_limits::min(), + std::numeric_limits::max(), &value)) return std::nullopt; return value; @@ -269,28 +261,10 @@ std::optional YamlObject::get() const if (type_ != Type::Value) return std::nullopt; - if (value_ == "") - return std::nullopt; + uint32_t value; - /* - * libyaml parses all scalar values as strings. When a string has - * leading spaces before a minus sign, for example " -10", strtoul - * skips leading spaces, accepts the leading minus sign, and the - * calculated digits are negated as if by unary minus. Rule it out in - * case the user gets a large number when the value is negative. - */ - std::size_t found = value_.find_first_not_of(" \t"); - if (found != std::string::npos && value_[found] == '-') - return std::nullopt; - - char *end; - - errno = 0; - unsigned long value = std::strtoul(value_.c_str(), &end, 10); - - if ('\0' != *end || errno == ERANGE || - value < std::numeric_limits::min() || - value > std::numeric_limits::max()) + if (!parseUnsignedInteger(value_, std::numeric_limits::max(), + &value)) return std::nullopt; return value;