From patchwork Mon Sep 16 22:28:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stefan Klug X-Patchwork-Id: 21287 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 9060BC324C for ; Mon, 16 Sep 2024 22:28:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 43612634FD; Tue, 17 Sep 2024 00:28:54 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="FFZUiTzj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 14700634F4 for ; Tue, 17 Sep 2024 00:28:52 +0200 (CEST) Received: from ideasonboard.com (unknown [31.12.6.210]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9709E23F; Tue, 17 Sep 2024 00:27:30 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1726525650; bh=3Ce91cmaduzVV9YHbJ4ak11uE2GaKncWTpCroJeL/Ks=; h=From:To:Cc:Subject:Date:From; b=FFZUiTzjR8/sl9csnSkKbOAcaWN9e/jTG3bZmVq6XLvGZk9XThOX/HYaWZB/1nSlN xablaFJkVBwUUwrGBKnqjkr45uw0A75K1vSZAEVeazMjWdbfcR70UteteAwLO1NwG+ 9/isYsOdJhaGLsTaGf0o65EA1PW58IRIzjxyH4hU= From: Stefan Klug To: libcamera-devel@lists.libcamera.org Cc: Stefan Klug Subject: [PATCH] libcamera: yaml-parser: Differentiate between empty and empty string Date: Tue, 17 Sep 2024 00:28:20 +0200 Message-ID: <20240916222834.464460-1-stefan.klug@ideasonboard.com> X-Mailer: git-send-email 2.43.0 MIME-Version: 1.0 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: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" When accessing a nonexistent key on a dict the YamlObject returns an empty element. This element can happily be casted to a string which is unexpected. For example the following statement: yamlDict["nonexistant"].get("default") is expected to return "default" but actually returns "". Fix this by introducing a empty type to distinguish between an empty YamlObject and a YamlObject of type value containing an empty string. For completeness add an isEmpty() function to be able to test for that type. Signed-off-by: Stefan Klug Reviewed-by: Paul Elder Reviewed-by: Laurent Pinchart --- include/libcamera/internal/yaml_parser.h | 5 +++++ src/libcamera/yaml_parser.cpp | 20 ++++++++++++++------ test/yaml-parser.cpp | 6 ++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/include/libcamera/internal/yaml_parser.h b/include/libcamera/internal/yaml_parser.h index 16708e488d88..33c3a96fed47 100644 --- a/include/libcamera/internal/yaml_parser.h +++ b/include/libcamera/internal/yaml_parser.h @@ -159,6 +159,10 @@ public: { return type_ == Type::Dictionary; } + bool isEmpty() const + { + return type_ == Type::Empty; + } std::size_t size() const; @@ -212,6 +216,7 @@ private: Dictionary, List, Value, + Empty, }; template diff --git a/src/libcamera/yaml_parser.cpp b/src/libcamera/yaml_parser.cpp index 8b6a403898be..eb72529136f7 100644 --- a/src/libcamera/yaml_parser.cpp +++ b/src/libcamera/yaml_parser.cpp @@ -38,12 +38,12 @@ static const YamlObject empty; * \brief A class representing the tree structure of the YAML content * * The YamlObject class represents the tree structure of YAML content. A - * YamlObject can be a dictionary or list of YamlObjects or a value if a tree - * leaf. + * YamlObject can be empty, a dictionary or list of YamlObjects or a value if a + * tree leaf. */ YamlObject::YamlObject() - : type_(Type::Value) + : type_(Type::Empty) { } @@ -70,6 +70,13 @@ YamlObject::~YamlObject() = default; * \return True if the YamlObject is a dictionary, false otherwise */ +/** + * \fn YamlObject::isEmpty() + * \brief Return whether the YamlObject is a empty + * + * \return True if the YamlObject is empty, false otherwise + */ + /** * \fn YamlObject::size() * \brief Retrieve the number of elements in a dictionary or list YamlObject @@ -443,7 +450,8 @@ template std::optional> YamlObject::getList() const; * * This function retrieves an element of the YamlObject. Only YamlObject * instances of List type associate elements with index, calling this function - * on other types of instances is invalid and results in undefined behaviour. + * on other types of instances or with an invalid index results in an empty + * object. * * \return The YamlObject as an element of the list */ @@ -480,8 +488,8 @@ bool YamlObject::contains(const std::string &key) const * * This function retrieve a member of a YamlObject by name. Only YamlObject * instances of Dictionary type associate elements with names, calling this - * function on other types of instances is invalid and results in undefined - * behaviour. + * function on other types of instances or with a non existant key results in an + * empty object. * * \return The YamlObject corresponding to the \a key member */ diff --git a/test/yaml-parser.cpp b/test/yaml-parser.cpp index 81c829834667..b8ae0b4c11f8 100644 --- a/test/yaml-parser.cpp +++ b/test/yaml-parser.cpp @@ -514,6 +514,12 @@ protected: i++; } + /* Test access to nonexistent member */ + if (dictObj["nonexistent"].get("default") != "default") { + cerr << "Accessing nonexistent dict fails to return default" << std::endl; + return TestFail; + } + /* Make sure utils::map_keys() works on the adapter. */ (void)utils::map_keys(dictObj.asDict());