mirror of
https://git.libcamera.org/libcamera/libcamera.git
synced 2025-07-12 14:59:44 +03:00
libcamera: yaml-parser: Differentiate between empty and empty string
When accessing a nonexistent key on a dict the YamlObject returns an empty element. This element can happily be cast to a string which is unexpected. For example the following statement: yamlDict["nonexistent"].get<string>("default") is expected to return "default" but actually returns "". Fix this by introducing an empty type to distinguish between an empty YamlObject and a YamlObject of type value containing an empty string. For completeness add an isEmpty() function and an explicit cast to bool to be able to test for that type. Extend the tests accordingly. Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com> Reviewed-by: Kieran Bingham <kieran.bingham@ideasonboard.com> Reviewed-by: Paul Elder <paul.elder@ideasonboard.com>
This commit is contained in:
parent
f623f3ed64
commit
6b67094cd2
4 changed files with 49 additions and 7 deletions
|
@ -159,6 +159,14 @@ public:
|
||||||
{
|
{
|
||||||
return type_ == Type::Dictionary;
|
return type_ == Type::Dictionary;
|
||||||
}
|
}
|
||||||
|
bool isEmpty() const
|
||||||
|
{
|
||||||
|
return type_ == Type::Empty;
|
||||||
|
}
|
||||||
|
explicit operator bool() const
|
||||||
|
{
|
||||||
|
return type_ != Type::Empty;
|
||||||
|
}
|
||||||
|
|
||||||
std::size_t size() const;
|
std::size_t size() const;
|
||||||
|
|
||||||
|
@ -212,6 +220,7 @@ private:
|
||||||
Dictionary,
|
Dictionary,
|
||||||
List,
|
List,
|
||||||
Value,
|
Value,
|
||||||
|
Empty,
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -38,12 +38,12 @@ static const YamlObject empty;
|
||||||
* \brief A class representing the tree structure of the YAML content
|
* \brief A class representing the tree structure of the YAML content
|
||||||
*
|
*
|
||||||
* The YamlObject class represents the tree structure of YAML content. A
|
* 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
|
* YamlObject can be empty, a dictionary or list of YamlObjects, or a value if a
|
||||||
* leaf.
|
* tree leaf.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
YamlObject::YamlObject()
|
YamlObject::YamlObject()
|
||||||
: type_(Type::Value)
|
: type_(Type::Empty)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +70,20 @@ YamlObject::~YamlObject() = default;
|
||||||
* \return True if the YamlObject is a dictionary, false otherwise
|
* \return True if the YamlObject is a dictionary, false otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn YamlObject::isEmpty()
|
||||||
|
* \brief Return whether the YamlObject is an empty
|
||||||
|
*
|
||||||
|
* \return True if the YamlObject is empty, false otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \fn YamlObject::operator bool()
|
||||||
|
* \brief Return whether the YamlObject is a non-empty
|
||||||
|
*
|
||||||
|
* \return False if the YamlObject is empty, true otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \fn YamlObject::size()
|
* \fn YamlObject::size()
|
||||||
* \brief Retrieve the number of elements in a dictionary or list YamlObject
|
* \brief Retrieve the number of elements in a dictionary or list YamlObject
|
||||||
|
@ -443,7 +457,8 @@ template std::optional<std::vector<Size>> YamlObject::getList<Size>() const;
|
||||||
*
|
*
|
||||||
* This function retrieves an element of the YamlObject. Only YamlObject
|
* This function retrieves an element of the YamlObject. Only YamlObject
|
||||||
* instances of List type associate elements with index, calling this function
|
* 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
|
* \return The YamlObject as an element of the list
|
||||||
*/
|
*/
|
||||||
|
@ -480,8 +495,8 @@ bool YamlObject::contains(const std::string &key) const
|
||||||
*
|
*
|
||||||
* This function retrieve a member of a YamlObject by name. Only YamlObject
|
* This function retrieve a member of a YamlObject by name. Only YamlObject
|
||||||
* instances of Dictionary type associate elements with names, calling this
|
* instances of Dictionary type associate elements with names, calling this
|
||||||
* function on other types of instances is invalid and results in undefined
|
* function on other types of instances or with a nonexistent key results in an
|
||||||
* behaviour.
|
* empty object.
|
||||||
*
|
*
|
||||||
* \return The YamlObject corresponding to the \a key member
|
* \return The YamlObject corresponding to the \a key member
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -73,7 +73,7 @@ internal_tests = [
|
||||||
{'name': 'timer-thread', 'sources': ['timer-thread.cpp']},
|
{'name': 'timer-thread', 'sources': ['timer-thread.cpp']},
|
||||||
{'name': 'unique-fd', 'sources': ['unique-fd.cpp']},
|
{'name': 'unique-fd', 'sources': ['unique-fd.cpp']},
|
||||||
{'name': 'utils', 'sources': ['utils.cpp']},
|
{'name': 'utils', 'sources': ['utils.cpp']},
|
||||||
{'name': 'yaml-parser', 'sources': ['yaml-parser.cpp'], 'should_fail': true},
|
{'name': 'yaml-parser', 'sources': ['yaml-parser.cpp']},
|
||||||
]
|
]
|
||||||
|
|
||||||
internal_non_parallel_tests = [
|
internal_non_parallel_tests = [
|
||||||
|
|
|
@ -542,6 +542,24 @@ protected:
|
||||||
return TestFail;
|
return TestFail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test nonexistent object has value type empty. */
|
||||||
|
if (!dictObj["nonexistent"].isEmpty()) {
|
||||||
|
cerr << "Accessing nonexistent object returns non-empty object" << std::endl;
|
||||||
|
return TestFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test explicit cast to bool on an empty object returns true. */
|
||||||
|
if (!!dictObj["empty"] != true) {
|
||||||
|
cerr << "Casting empty entry to bool returns false" << std::endl;
|
||||||
|
return TestFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test explicit cast to bool on nonexistent object returns false. */
|
||||||
|
if (!!dictObj["nonexistent"] != false) {
|
||||||
|
cerr << "Casting nonexistent dict entry to bool returns true" << std::endl;
|
||||||
|
return TestFail;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure utils::map_keys() works on the adapter. */
|
/* Make sure utils::map_keys() works on the adapter. */
|
||||||
(void)utils::map_keys(dictObj.asDict());
|
(void)utils::map_keys(dictObj.asDict());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue