[{"id":24633,"web_url":"https://patchwork.libcamera.org/comment/24633/","msgid":"<20220818122454.GH2412817@pyrite.rasen.tech>","date":"2022-08-18T12:24:54","subject":"Re: [libcamera-devel] [PATCH v4 5/9] libcamera: yaml_parser: Enable\n\tYamlObject::get() for int8_t and uint8_t","submitter":{"id":97,"url":"https://patchwork.libcamera.org/api/people/97/","name":"Nicolas Dufresne via libcamera-devel","email":"libcamera-devel@lists.libcamera.org"},"content":"On Tue, Aug 16, 2022 at 04:54:10AM +0300, Laurent Pinchart via libcamera-devel wrote:\n> The YamlObject::get() function template is implemented for 16-bit and\n> 32-bit integers. Add an 8-bit specialization that will be used in the\n> rkisp1 IPA module, and extend the unit tests accordingly.\n> \n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nReviewed-by: Paul Elder <paul.elder@ideasonboard.com>\n\n> ---\n>  include/libcamera/internal/yaml_parser.h |  4 ++\n>  src/libcamera/yaml_parser.cpp            | 59 ++++++++++++++++\n>  test/yaml-parser.cpp                     | 86 ++++++++++++++++++++----\n>  3 files changed, 137 insertions(+), 12 deletions(-)\n> \n> diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h\n> index 5ba777d364fa..8ca71df867ab 100644\n> --- a/include/libcamera/internal/yaml_parser.h\n> +++ b/include/libcamera/internal/yaml_parser.h\n> @@ -166,6 +166,8 @@ public:\n>  \t\t std::enable_if_t<\n>  \t\t\t std::is_same_v<bool, T> ||\n>  \t\t\t std::is_same_v<double, T> ||\n> +\t\t\t std::is_same_v<int8_t, T> ||\n> +\t\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t\t std::is_same_v<int16_t, T> ||\n>  \t\t\t std::is_same_v<uint16_t, T> ||\n>  \t\t\t std::is_same_v<int32_t, T> ||\n> @@ -188,6 +190,8 @@ public:\n>  \t\t std::enable_if_t<\n>  \t\t\t std::is_same_v<bool, T> ||\n>  \t\t\t std::is_same_v<double, T> ||\n> +\t\t\t std::is_same_v<int8_t, T> ||\n> +\t\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t\t std::is_same_v<int16_t, T> ||\n>  \t\t\t std::is_same_v<uint16_t, T> ||\n>  \t\t\t std::is_same_v<int32_t, T> ||\n> diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp\n> index f928b7238a19..85a52c05e682 100644\n> --- a/src/libcamera/yaml_parser.cpp\n> +++ b/src/libcamera/yaml_parser.cpp\n> @@ -131,6 +131,61 @@ std::optional<bool> YamlObject::get() const\n>  \treturn std::nullopt;\n>  }\n>  \n> +template<>\n> +std::optional<int8_t> YamlObject::get() const\n> +{\n> +\tif (type_ != Type::Value)\n> +\t\treturn std::nullopt;\n> +\n> +\tif (value_ == \"\")\n> +\t\treturn std::nullopt;\n> +\n> +\tchar *end;\n> +\n> +\terrno = 0;\n> +\tlong value = std::strtol(value_.c_str(), &end, 10);\n> +\n> +\tif ('\\0' != *end || errno == ERANGE ||\n> +\t    value < std::numeric_limits<int8_t>::min() ||\n> +\t    value > std::numeric_limits<int8_t>::max())\n> +\t\treturn std::nullopt;\n> +\n> +\treturn value;\n> +}\n> +\n> +template<>\n> +std::optional<uint8_t> YamlObject::get() const\n> +{\n> +\tif (type_ != Type::Value)\n> +\t\treturn std::nullopt;\n> +\n> +\tif (value_ == \"\")\n> +\t\treturn std::nullopt;\n> +\n> +\t/*\n> +\t * libyaml parses all scalar values as strings. When a string has\n> +\t * leading spaces before a minus sign, for example \"  -10\", strtoul\n> +\t * skips leading spaces, accepts the leading minus sign, and the\n> +\t * calculated digits are negated as if by unary minus. Rule it out in\n> +\t * case the user gets a large number when the value is negative.\n> +\t */\n> +\tstd::size_t found = value_.find_first_not_of(\" \\t\");\n> +\tif (found != std::string::npos && value_[found] == '-')\n> +\t\treturn std::nullopt;\n> +\n> +\tchar *end;\n> +\n> +\terrno = 0;\n> +\tunsigned long value = std::strtoul(value_.c_str(), &end, 10);\n> +\n> +\tif ('\\0' != *end || errno == ERANGE ||\n> +\t    value < std::numeric_limits<uint8_t>::min() ||\n> +\t    value > std::numeric_limits<uint8_t>::max())\n> +\t\treturn std::nullopt;\n> +\n> +\treturn value;\n> +}\n> +\n>  template<>\n>  std::optional<int16_t> YamlObject::get() const\n>  {\n> @@ -310,6 +365,8 @@ template<typename T,\n>  \t std::enable_if_t<\n>  \t\t std::is_same_v<bool, T> ||\n>  \t\t std::is_same_v<double, T> ||\n> +\t\t std::is_same_v<int8_t, T> ||\n> +\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t std::is_same_v<int16_t, T> ||\n>  \t\t std::is_same_v<uint16_t, T> ||\n>  \t\t std::is_same_v<int32_t, T> ||\n> @@ -336,6 +393,8 @@ std::optional<std::vector<T>> YamlObject::getList() const\n>  \n>  template std::optional<std::vector<bool>> YamlObject::getList<bool>() const;\n>  template std::optional<std::vector<double>> YamlObject::getList<double>() const;\n> +template std::optional<std::vector<int8_t>> YamlObject::getList<int8_t>() const;\n> +template std::optional<std::vector<uint8_t>> YamlObject::getList<uint8_t>() const;\n>  template std::optional<std::vector<int16_t>> YamlObject::getList<int16_t>() const;\n>  template std::optional<std::vector<uint16_t>> YamlObject::getList<uint16_t>() const;\n>  template std::optional<std::vector<int32_t>> YamlObject::getList<int32_t>() const;\n> diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp\n> index 28f8cc8822b3..2d92463aed98 100644\n> --- a/test/yaml-parser.cpp\n> +++ b/test/yaml-parser.cpp\n> @@ -24,6 +24,8 @@ using namespace std;\n>  static const string testYaml =\n>  \t\"string: libcamera\\n\"\n>  \t\"double: 3.14159\\n\"\n> +\t\"int8_t: -100\\n\"\n> +\t\"uint8_t: 100\\n\"\n>  \t\"int16_t: -1000\\n\"\n>  \t\"uint16_t: 1000\\n\"\n>  \t\"int32_t: -100000\\n\"\n> @@ -76,6 +78,8 @@ protected:\n>  \n>  \tenum class Type {\n>  \t\tString,\n> +\t\tInt8,\n> +\t\tUInt8,\n>  \t\tInt16,\n>  \t\tUInt16,\n>  \t\tInt32,\n> @@ -90,10 +94,13 @@ protected:\n>  \t{\n>  \t\tbool isList = type == Type::List || type == Type::Size;\n>  \t\tbool isScalar = !isList && type != Type::Dictionary;\n> +\t\tbool isInteger8 = type == Type::Int8 || type == Type::UInt8;\n>  \t\tbool isInteger16 = type == Type::Int16 || type == Type::UInt16;\n>  \t\tbool isInteger32 = type == Type::Int32 || type == Type::UInt32;\n> -\t\tbool isInteger = isInteger16 || isInteger32;\n> -\t\tbool isSigned = type == Type::Int16 || type == Type::Int32;\n> +\t\tbool isIntegerUpTo16 = isInteger8 || isInteger16;\n> +\t\tbool isIntegerUpTo32 = isIntegerUpTo16 || isInteger32;\n> +\t\tbool isSigned = type == Type::Int8 || type == Type::Int16 ||\n> +\t\t\t        type == Type::Int32;\n>  \n>  \t\tif ((isScalar && !obj.isValue()) || (!isScalar && obj.isValue())) {\n>  \t\t\tstd::cerr\n> @@ -124,35 +131,49 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (!isInteger16 && obj.get<int16_t>()) {\n> +\t\tif (!isInteger8 && obj.get<int8_t>()) {\n> +\t\t\tstd::cerr\n> +\t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n> +\t\t\t\t<< \"int8_t\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif ((!isInteger8 || isSigned) && obj.get<uint8_t>()) {\n> +\t\t\tstd::cerr\n> +\t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n> +\t\t\t\t<< \"uint8_t\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif (!isIntegerUpTo16 && obj.get<int16_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"int16_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif ((!isInteger16 || isSigned) && obj.get<uint16_t>()) {\n> +\t\tif ((!isIntegerUpTo16 || isSigned) && obj.get<uint16_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"uint16_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (!isInteger && obj.get<int32_t>()) {\n> +\t\tif (!isIntegerUpTo32 && obj.get<int32_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"int32_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif ((!isInteger || isSigned) && obj.get<uint32_t>()) {\n> +\t\tif ((!isIntegerUpTo32 || isSigned) && obj.get<uint32_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"uint32_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (!isInteger && type != Type::Double && obj.get<double>()) {\n> +\t\tif (!isIntegerUpTo32 && type != Type::Double && obj.get<double>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"double\" << std::endl;\n> @@ -174,8 +195,10 @@ protected:\n>  \t{\n>  \t\tuint64_t unsignedValue = static_cast<uint64_t>(value);\n>  \t\tstd::string strValue = std::to_string(value);\n> +\t\tbool isInteger8 = type == Type::Int8 || type == Type::UInt8;\n>  \t\tbool isInteger16 = type == Type::Int16 || type == Type::UInt16;\n> -\t\tbool isSigned = type == Type::Int16 || type == Type::Int32;\n> +\t\tbool isSigned = type == Type::Int8 || type == Type::Int16 ||\n> +\t\t\t\ttype == Type::Int32;\n>  \n>  \t\t/* All integers can be parsed as strings or double. */\n>  \n> @@ -195,7 +218,27 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> -\t\tif (isInteger16) {\n> +\t\tif (isInteger8) {\n> +\t\t\tif (obj.get<int8_t>().value_or(0) != value ||\n> +\t\t\t    obj.get<int8_t>(0) != value) {\n> +\t\t\t\tstd::cerr\n> +\t\t\t\t\t<< \"Object \" << name << \" failed to parse as \"\n> +\t\t\t\t\t<< \"int8_t\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (isInteger8 && !isSigned) {\n> +\t\t\tif (obj.get<uint8_t>().value_or(0) != unsignedValue ||\n> +\t\t\t    obj.get<uint8_t>(0) != unsignedValue) {\n> +\t\t\t\tstd::cerr\n> +\t\t\t\t\t<< \"Object \" << name << \" failed to parse as \"\n> +\t\t\t\t\t<< \"uint8_t\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (isInteger8 || isInteger16) {\n>  \t\t\tif (obj.get<int16_t>().value_or(0) != value ||\n>  \t\t\t    obj.get<int16_t>(0) != value) {\n>  \t\t\t\tstd::cerr\n> @@ -205,7 +248,7 @@ protected:\n>  \t\t\t}\n>  \t\t}\n>  \n> -\t\tif (isInteger16 && !isSigned) {\n> +\t\tif ((isInteger8 || isInteger16) && !isSigned) {\n>  \t\t\tif (obj.get<uint16_t>().value_or(0) != unsignedValue ||\n>  \t\t\t    obj.get<uint16_t>(0) != unsignedValue) {\n>  \t\t\t\tstd::cerr\n> @@ -272,8 +315,9 @@ protected:\n>  \t\t}\n>  \n>  \t\tstd::vector<const char *> rootElemNames = {\n> -\t\t\t\"string\", \"double\", \"int16_t\", \"uint16_t\", \"int32_t\",\n> -\t\t\t\"uint32_t\", \"size\", \"list\", \"dictionary\", \"level1\",\n> +\t\t\t\"string\", \"double\", \"int8_t\", \"uint8_t\", \"int16_t\",\n> +\t\t\t\"uint16_t\", \"int32_t\", \"uint32_t\", \"size\", \"list\",\n> +\t\t\t\"dictionary\", \"level1\",\n>  \t\t};\n>  \n>  \t\tfor (const char *name : rootElemNames) {\n> @@ -296,6 +340,24 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>  \n> +\t\t/* Test int8_t object */\n> +\t\tauto &int8Obj = (*root)[\"int8_t\"];\n> +\n> +\t\tif (testObjectType(int8Obj, \"int8_t\", Type::Int8) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\tif (testIntegerObject(int8Obj, \"int8_t\", Type::Int8, -100) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\t/* Test uint8_t object */\n> +\t\tauto &uint8Obj = (*root)[\"uint8_t\"];\n> +\n> +\t\tif (testObjectType(uint8Obj, \"uint8_t\", Type::UInt8) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\tif (testIntegerObject(uint8Obj, \"uint8_t\", Type::UInt8, 100) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n>  \t\t/* Test int16_t object */\n>  \t\tauto &int16Obj = (*root)[\"int16_t\"];\n>  \n> -- \n> Regards,\n> \n> Laurent Pinchart\n>","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 89910BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 18 Aug 2022 12:25:04 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id E1D5C61FC0;\n\tThu, 18 Aug 2022 14:25:03 +0200 (CEST)","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 92CBC61FA7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 18 Aug 2022 14:25:02 +0200 (CEST)","from pyrite.rasen.tech (KD027085204050.au-net.ne.jp [27.85.204.50])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id DE8AB8B;\n\tThu, 18 Aug 2022 14:25:00 +0200 (CEST)"],"DKIM-Signature":["v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1660825503;\n\tbh=2mm0AklOnzky6IX+huspJFq7ayg3cS5giG9swvp18Sc=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=JpoNV/hMqNr15bT+xOif0tXxzL/d1amleDs7tuUWVuKqPdC6F50oiTCr09V6eQbnt\n\tXV00eUksZLZsoUhIXivcUyxNtDYRW/+qosNnAC0QDN3WuD63jvzjs5rTopinEOC2OV\n\tzb+hCiEpGXc0ieJ7i1lOKGj4gmVH1GqOZICPOws6kdNWwcwxjUnUXFJqtJ2lrGmPKv\n\tK1yUXasp9OR5nLGTq+QwZMoWHlHvdPcq5MO5FtIQumyEy25SynfchYbHDhK18yhNP3\n\tzF8ldGSMAIQxrn/ThQGoNSBVDkzuS4xXIS99rVIAhvULRjme+2bVKK1TsgxUn18xr5\n\tYguy0+7j290nA==","v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1660825502;\n\tbh=2mm0AklOnzky6IX+huspJFq7ayg3cS5giG9swvp18Sc=;\n\th=Date:From:To:Cc:Subject:References:In-Reply-To:From;\n\tb=kM+UkOQfPxCDN+BhJB8Cu21HS8Ixs5GOtCcVq/sGoctPCCyU3N09C7PVZSm362NG4\n\tDaaCzMJAb9d9K+yZJczszymGW7yuOdjhIUdhpH8Z5Kiq2U8F3+z2m5EZlOuJO+Z5xq\n\tbpMTHthl0NoAFnzWk72BpnWRJN7KhEK1m2iqNSUc="],"Authentication-Results":"lancelot.ideasonboard.com; dkim=pass (1024-bit key; \n\tunprotected) header.d=ideasonboard.com\n\theader.i=@ideasonboard.com\n\theader.b=\"kM+UkOQf\"; dkim-atps=neutral","Date":"Thu, 18 Aug 2022 21:24:54 +0900","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20220818122454.GH2412817@pyrite.rasen.tech>","References":"<20220816015414.7462-1-laurent.pinchart@ideasonboard.com>\n\t<20220816015414.7462-6-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=us-ascii","Content-Disposition":"inline","In-Reply-To":"<20220816015414.7462-6-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 5/9] libcamera: yaml_parser: Enable\n\tYamlObject::get() for int8_t and uint8_t","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>","From":"Paul Elder via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"paul.elder@ideasonboard.com","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}},{"id":24639,"web_url":"https://patchwork.libcamera.org/comment/24639/","msgid":"<20220818131113.jkmk4zxd2ybzf5gn@uno.localdomain>","date":"2022-08-18T13:11:13","subject":"Re: [libcamera-devel] [PATCH v4 5/9] libcamera: yaml_parser: Enable\n\tYamlObject::get() for int8_t and uint8_t","submitter":{"id":3,"url":"https://patchwork.libcamera.org/api/people/3/","name":"Jacopo Mondi","email":"jacopo@jmondi.org"},"content":"Hi Laurent\n\nOn Tue, Aug 16, 2022 at 04:54:10AM +0300, Laurent Pinchart via libcamera-devel wrote:\n> The YamlObject::get() function template is implemented for 16-bit and\n> 32-bit integers. Add an 8-bit specialization that will be used in the\n> rkisp1 IPA module, and extend the unit tests accordingly.\n>\n> Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>\n\nLooks good!\nReviewed-by: Jacopo Mondi <jacopo@jmondi.org>\n\nThanks\n  j\n\n> ---\n>  include/libcamera/internal/yaml_parser.h |  4 ++\n>  src/libcamera/yaml_parser.cpp            | 59 ++++++++++++++++\n>  test/yaml-parser.cpp                     | 86 ++++++++++++++++++++----\n>  3 files changed, 137 insertions(+), 12 deletions(-)\n>\n> diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h\n> index 5ba777d364fa..8ca71df867ab 100644\n> --- a/include/libcamera/internal/yaml_parser.h\n> +++ b/include/libcamera/internal/yaml_parser.h\n> @@ -166,6 +166,8 @@ public:\n>  \t\t std::enable_if_t<\n>  \t\t\t std::is_same_v<bool, T> ||\n>  \t\t\t std::is_same_v<double, T> ||\n> +\t\t\t std::is_same_v<int8_t, T> ||\n> +\t\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t\t std::is_same_v<int16_t, T> ||\n>  \t\t\t std::is_same_v<uint16_t, T> ||\n>  \t\t\t std::is_same_v<int32_t, T> ||\n> @@ -188,6 +190,8 @@ public:\n>  \t\t std::enable_if_t<\n>  \t\t\t std::is_same_v<bool, T> ||\n>  \t\t\t std::is_same_v<double, T> ||\n> +\t\t\t std::is_same_v<int8_t, T> ||\n> +\t\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t\t std::is_same_v<int16_t, T> ||\n>  \t\t\t std::is_same_v<uint16_t, T> ||\n>  \t\t\t std::is_same_v<int32_t, T> ||\n> diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp\n> index f928b7238a19..85a52c05e682 100644\n> --- a/src/libcamera/yaml_parser.cpp\n> +++ b/src/libcamera/yaml_parser.cpp\n> @@ -131,6 +131,61 @@ std::optional<bool> YamlObject::get() const\n>  \treturn std::nullopt;\n>  }\n>\n> +template<>\n> +std::optional<int8_t> YamlObject::get() const\n> +{\n> +\tif (type_ != Type::Value)\n> +\t\treturn std::nullopt;\n> +\n> +\tif (value_ == \"\")\n> +\t\treturn std::nullopt;\n> +\n> +\tchar *end;\n> +\n> +\terrno = 0;\n> +\tlong value = std::strtol(value_.c_str(), &end, 10);\n> +\n> +\tif ('\\0' != *end || errno == ERANGE ||\n> +\t    value < std::numeric_limits<int8_t>::min() ||\n> +\t    value > std::numeric_limits<int8_t>::max())\n> +\t\treturn std::nullopt;\n> +\n> +\treturn value;\n> +}\n> +\n> +template<>\n> +std::optional<uint8_t> YamlObject::get() const\n> +{\n> +\tif (type_ != Type::Value)\n> +\t\treturn std::nullopt;\n> +\n> +\tif (value_ == \"\")\n> +\t\treturn std::nullopt;\n> +\n> +\t/*\n> +\t * libyaml parses all scalar values as strings. When a string has\n> +\t * leading spaces before a minus sign, for example \"  -10\", strtoul\n> +\t * skips leading spaces, accepts the leading minus sign, and the\n> +\t * calculated digits are negated as if by unary minus. Rule it out in\n> +\t * case the user gets a large number when the value is negative.\n> +\t */\n> +\tstd::size_t found = value_.find_first_not_of(\" \\t\");\n> +\tif (found != std::string::npos && value_[found] == '-')\n> +\t\treturn std::nullopt;\n> +\n> +\tchar *end;\n> +\n> +\terrno = 0;\n> +\tunsigned long value = std::strtoul(value_.c_str(), &end, 10);\n> +\n> +\tif ('\\0' != *end || errno == ERANGE ||\n> +\t    value < std::numeric_limits<uint8_t>::min() ||\n> +\t    value > std::numeric_limits<uint8_t>::max())\n> +\t\treturn std::nullopt;\n> +\n> +\treturn value;\n> +}\n> +\n>  template<>\n>  std::optional<int16_t> YamlObject::get() const\n>  {\n> @@ -310,6 +365,8 @@ template<typename T,\n>  \t std::enable_if_t<\n>  \t\t std::is_same_v<bool, T> ||\n>  \t\t std::is_same_v<double, T> ||\n> +\t\t std::is_same_v<int8_t, T> ||\n> +\t\t std::is_same_v<uint8_t, T> ||\n>  \t\t std::is_same_v<int16_t, T> ||\n>  \t\t std::is_same_v<uint16_t, T> ||\n>  \t\t std::is_same_v<int32_t, T> ||\n> @@ -336,6 +393,8 @@ std::optional<std::vector<T>> YamlObject::getList() const\n>\n>  template std::optional<std::vector<bool>> YamlObject::getList<bool>() const;\n>  template std::optional<std::vector<double>> YamlObject::getList<double>() const;\n> +template std::optional<std::vector<int8_t>> YamlObject::getList<int8_t>() const;\n> +template std::optional<std::vector<uint8_t>> YamlObject::getList<uint8_t>() const;\n>  template std::optional<std::vector<int16_t>> YamlObject::getList<int16_t>() const;\n>  template std::optional<std::vector<uint16_t>> YamlObject::getList<uint16_t>() const;\n>  template std::optional<std::vector<int32_t>> YamlObject::getList<int32_t>() const;\n> diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp\n> index 28f8cc8822b3..2d92463aed98 100644\n> --- a/test/yaml-parser.cpp\n> +++ b/test/yaml-parser.cpp\n> @@ -24,6 +24,8 @@ using namespace std;\n>  static const string testYaml =\n>  \t\"string: libcamera\\n\"\n>  \t\"double: 3.14159\\n\"\n> +\t\"int8_t: -100\\n\"\n> +\t\"uint8_t: 100\\n\"\n>  \t\"int16_t: -1000\\n\"\n>  \t\"uint16_t: 1000\\n\"\n>  \t\"int32_t: -100000\\n\"\n> @@ -76,6 +78,8 @@ protected:\n>\n>  \tenum class Type {\n>  \t\tString,\n> +\t\tInt8,\n> +\t\tUInt8,\n>  \t\tInt16,\n>  \t\tUInt16,\n>  \t\tInt32,\n> @@ -90,10 +94,13 @@ protected:\n>  \t{\n>  \t\tbool isList = type == Type::List || type == Type::Size;\n>  \t\tbool isScalar = !isList && type != Type::Dictionary;\n> +\t\tbool isInteger8 = type == Type::Int8 || type == Type::UInt8;\n>  \t\tbool isInteger16 = type == Type::Int16 || type == Type::UInt16;\n>  \t\tbool isInteger32 = type == Type::Int32 || type == Type::UInt32;\n> -\t\tbool isInteger = isInteger16 || isInteger32;\n> -\t\tbool isSigned = type == Type::Int16 || type == Type::Int32;\n> +\t\tbool isIntegerUpTo16 = isInteger8 || isInteger16;\n> +\t\tbool isIntegerUpTo32 = isIntegerUpTo16 || isInteger32;\n> +\t\tbool isSigned = type == Type::Int8 || type == Type::Int16 ||\n> +\t\t\t        type == Type::Int32;\n>\n>  \t\tif ((isScalar && !obj.isValue()) || (!isScalar && obj.isValue())) {\n>  \t\t\tstd::cerr\n> @@ -124,35 +131,49 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif (!isInteger16 && obj.get<int16_t>()) {\n> +\t\tif (!isInteger8 && obj.get<int8_t>()) {\n> +\t\t\tstd::cerr\n> +\t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n> +\t\t\t\t<< \"int8_t\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif ((!isInteger8 || isSigned) && obj.get<uint8_t>()) {\n> +\t\t\tstd::cerr\n> +\t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n> +\t\t\t\t<< \"uint8_t\" << std::endl;\n> +\t\t\treturn TestFail;\n> +\t\t}\n> +\n> +\t\tif (!isIntegerUpTo16 && obj.get<int16_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"int16_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif ((!isInteger16 || isSigned) && obj.get<uint16_t>()) {\n> +\t\tif ((!isIntegerUpTo16 || isSigned) && obj.get<uint16_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"uint16_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif (!isInteger && obj.get<int32_t>()) {\n> +\t\tif (!isIntegerUpTo32 && obj.get<int32_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"int32_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif ((!isInteger || isSigned) && obj.get<uint32_t>()) {\n> +\t\tif ((!isIntegerUpTo32 || isSigned) && obj.get<uint32_t>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"uint32_t\" << std::endl;\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif (!isInteger && type != Type::Double && obj.get<double>()) {\n> +\t\tif (!isIntegerUpTo32 && type != Type::Double && obj.get<double>()) {\n>  \t\t\tstd::cerr\n>  \t\t\t\t<< \"Object \" << name << \" didn't fail to parse as \"\n>  \t\t\t\t<< \"double\" << std::endl;\n> @@ -174,8 +195,10 @@ protected:\n>  \t{\n>  \t\tuint64_t unsignedValue = static_cast<uint64_t>(value);\n>  \t\tstd::string strValue = std::to_string(value);\n> +\t\tbool isInteger8 = type == Type::Int8 || type == Type::UInt8;\n>  \t\tbool isInteger16 = type == Type::Int16 || type == Type::UInt16;\n> -\t\tbool isSigned = type == Type::Int16 || type == Type::Int32;\n> +\t\tbool isSigned = type == Type::Int8 || type == Type::Int16 ||\n> +\t\t\t\ttype == Type::Int32;\n>\n>  \t\t/* All integers can be parsed as strings or double. */\n>\n> @@ -195,7 +218,27 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> -\t\tif (isInteger16) {\n> +\t\tif (isInteger8) {\n> +\t\t\tif (obj.get<int8_t>().value_or(0) != value ||\n> +\t\t\t    obj.get<int8_t>(0) != value) {\n> +\t\t\t\tstd::cerr\n> +\t\t\t\t\t<< \"Object \" << name << \" failed to parse as \"\n> +\t\t\t\t\t<< \"int8_t\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (isInteger8 && !isSigned) {\n> +\t\t\tif (obj.get<uint8_t>().value_or(0) != unsignedValue ||\n> +\t\t\t    obj.get<uint8_t>(0) != unsignedValue) {\n> +\t\t\t\tstd::cerr\n> +\t\t\t\t\t<< \"Object \" << name << \" failed to parse as \"\n> +\t\t\t\t\t<< \"uint8_t\" << std::endl;\n> +\t\t\t\treturn TestFail;\n> +\t\t\t}\n> +\t\t}\n> +\n> +\t\tif (isInteger8 || isInteger16) {\n>  \t\t\tif (obj.get<int16_t>().value_or(0) != value ||\n>  \t\t\t    obj.get<int16_t>(0) != value) {\n>  \t\t\t\tstd::cerr\n> @@ -205,7 +248,7 @@ protected:\n>  \t\t\t}\n>  \t\t}\n>\n> -\t\tif (isInteger16 && !isSigned) {\n> +\t\tif ((isInteger8 || isInteger16) && !isSigned) {\n>  \t\t\tif (obj.get<uint16_t>().value_or(0) != unsignedValue ||\n>  \t\t\t    obj.get<uint16_t>(0) != unsignedValue) {\n>  \t\t\t\tstd::cerr\n> @@ -272,8 +315,9 @@ protected:\n>  \t\t}\n>\n>  \t\tstd::vector<const char *> rootElemNames = {\n> -\t\t\t\"string\", \"double\", \"int16_t\", \"uint16_t\", \"int32_t\",\n> -\t\t\t\"uint32_t\", \"size\", \"list\", \"dictionary\", \"level1\",\n> +\t\t\t\"string\", \"double\", \"int8_t\", \"uint8_t\", \"int16_t\",\n> +\t\t\t\"uint16_t\", \"int32_t\", \"uint32_t\", \"size\", \"list\",\n> +\t\t\t\"dictionary\", \"level1\",\n>  \t\t};\n>\n>  \t\tfor (const char *name : rootElemNames) {\n> @@ -296,6 +340,24 @@ protected:\n>  \t\t\treturn TestFail;\n>  \t\t}\n>\n> +\t\t/* Test int8_t object */\n> +\t\tauto &int8Obj = (*root)[\"int8_t\"];\n> +\n> +\t\tif (testObjectType(int8Obj, \"int8_t\", Type::Int8) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\tif (testIntegerObject(int8Obj, \"int8_t\", Type::Int8, -100) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\t/* Test uint8_t object */\n> +\t\tauto &uint8Obj = (*root)[\"uint8_t\"];\n> +\n> +\t\tif (testObjectType(uint8Obj, \"uint8_t\", Type::UInt8) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n> +\t\tif (testIntegerObject(uint8Obj, \"uint8_t\", Type::UInt8, 100) != TestPass)\n> +\t\t\treturn TestFail;\n> +\n>  \t\t/* Test int16_t object */\n>  \t\tauto &int16Obj = (*root)[\"int16_t\"];\n>\n> --\n> Regards,\n>\n> Laurent Pinchart\n>","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 36E36BE173\n\tfor <parsemail@patchwork.libcamera.org>;\n\tThu, 18 Aug 2022 13:11:17 +0000 (UTC)","from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 831AC61FC0;\n\tThu, 18 Aug 2022 15:11:16 +0200 (CEST)","from relay9-d.mail.gandi.net (relay9-d.mail.gandi.net\n\t[217.70.183.199])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 935B661FA7\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tThu, 18 Aug 2022 15:11:15 +0200 (CEST)","(Authenticated sender: jacopo@jmondi.org)\n\tby mail.gandi.net (Postfix) with ESMTPSA id C98E8FF810;\n\tThu, 18 Aug 2022 13:11:14 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/simple; d=libcamera.org;\n\ts=mail; t=1660828276;\n\tbh=GdaDY3hRknY4assg3Nu22aTWA5hY3ooNghqebR997bM=;\n\th=Date:To:References:In-Reply-To:Subject:List-Id:List-Unsubscribe:\n\tList-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc:\n\tFrom;\n\tb=VIK3fFmmxdy2UtgiUrKMCHrvKly4bJu7rCEISd1q7vYMzvRoLxN309eNbgIZ+4ced\n\tUjzb+UribC5/AiiVAMh1SaS5AMnxFUj/YjtkOClrX2DpqRLcGwQ0KK8mKXI+MIZel+\n\tCuV6FhT1HtKvEt6ytLSWnxu6QqFrgtI1bxrW5DgFNlqb4JIm+Q7fpF08OrblJMbki9\n\tvi2n6FE2Jbd56cWefhAWK27eaHfQWZBFHxIsNbCOkY66Fgtu2Y8Lj9avhyrz/xggqm\n\tqswp+/QmJ7Phmk105YGWwumthCqfjgdlBoGhtFWmtS+n7w/Dob4WKBaMAF44aUmvfg\n\tt1FHD16AE16Ug==","Date":"Thu, 18 Aug 2022 15:11:13 +0200","To":"Laurent Pinchart <laurent.pinchart@ideasonboard.com>","Message-ID":"<20220818131113.jkmk4zxd2ybzf5gn@uno.localdomain>","References":"<20220816015414.7462-1-laurent.pinchart@ideasonboard.com>\n\t<20220816015414.7462-6-laurent.pinchart@ideasonboard.com>","MIME-Version":"1.0","Content-Type":"text/plain; charset=utf-8","Content-Disposition":"inline","In-Reply-To":"<20220816015414.7462-6-laurent.pinchart@ideasonboard.com>","Subject":"Re: [libcamera-devel] [PATCH v4 5/9] libcamera: yaml_parser: Enable\n\tYamlObject::get() for int8_t and uint8_t","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>","From":"Jacopo Mondi via libcamera-devel <libcamera-devel@lists.libcamera.org>","Reply-To":"Jacopo Mondi <jacopo@jmondi.org>","Cc":"libcamera-devel@lists.libcamera.org","Errors-To":"libcamera-devel-bounces@lists.libcamera.org","Sender":"\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>"}}]