From cda1953d49143e7d64a1e7193f25a1c3acf42a25 Mon Sep 17 00:00:00 2001 From: "Marco A. Gutierrez" Date: Thu, 15 Sep 2022 08:14:48 +0000 Subject: [PATCH 1/4] updating Element calls to use Errors Signed-off-by: Marco A. Gutierrez --- include/sdf/Element.hh | 249 +++++++++++++++++++++++++++++++++++++++-- src/Element.cc | 240 +++++++++++++++++++++++++++++++-------- 2 files changed, 435 insertions(+), 54 deletions(-) diff --git a/include/sdf/Element.hh b/include/sdf/Element.hh index 1afc35799..36b704c43 100644 --- a/include/sdf/Element.hh +++ b/include/sdf/Element.hh @@ -161,12 +161,26 @@ namespace sdf /// \param[in] _prefix String value to prefix to the output. public: void PrintDescription(const std::string &_prefix) const; + /// \brief Output Element's description to stdout. + /// \param[in] _prefix String value to prefix to the output. + /// \param[out] _errors Vector of errors. + public: void PrintDescription(const std::string &_prefix, + sdf::Errors &_errors) const; + /// \brief Output Element's values to stdout. /// \param[in] _prefix String value to prefix to the output. /// \param[in] _config Configuration for printing the values. public: void PrintValues(std::string _prefix, const PrintConfig &_config = PrintConfig()) const; + /// \brief Output Element's values to stdout. + /// \param[out] _errors Vector of errors. + /// \param[in] _prefix String value to prefix to the output. + /// \param[in] _config Configuration for printing the values. + public: void PrintValues(sdf::Errors &_errors, + std::string _prefix, + const PrintConfig &_config = PrintConfig()) const; + /// \brief Output Element's values to stdout. /// \param[in] _prefix String value to prefix to the output. /// \param[in] _includeDefaultElements flag to print default elements. @@ -177,6 +191,18 @@ namespace sdf bool _includeDefaultAttributes, const PrintConfig &_config = PrintConfig()) const; + /// \brief Output Element's values to stdout. + /// \param[out] _errors Vector of errors. + /// \param[in] _prefix String value to prefix to the output. + /// \param[in] _includeDefaultElements flag to print default elements. + /// \param[in] _includeDefaultAttributes flag to print default attributes. + /// \param[in] _config Configuration for printing the values. + public: void PrintValues(sdf::Errors &_errors, + const std::string &_prefix, + bool _includeDefaultElements, + bool _includeDefaultAttributes, + const PrintConfig &_config = PrintConfig()) const; + /// \brief Helper function for SDF::PrintDoc /// /// This generates the SDF html documentation. @@ -194,24 +220,60 @@ namespace sdf public: void PrintDocRightPane(std::string &_html, int _spacing, int &_index) const; + /// \brief Helper function for SDF::PrintDoc + /// + /// This generates the SDF html documentation. + /// \param[out] _html Accumulated HTML for output. + /// \param[in] _spacing Amount of spacing for this element. + /// \param[out] _errors Vector of errors. + public: void PrintDocRightPane(std::string &_html, int _spacing, + int &_index, sdf::Errors &_errors) const; + + /// \brief Convert the element values to a string representation. + /// \param[in] _prefix String value to prefix to the output. + /// \param[in] _config Configuration for printing the values. + /// \return The string representation. + public: std::string ToString( + const std::string &_prefix, + const PrintConfig &_config = PrintConfig()) const; + /// \brief Convert the element values to a string representation. + /// \param[out] _errors Vector of errors. /// \param[in] _prefix String value to prefix to the output. /// \param[in] _config Configuration for printing the values. /// \return The string representation. + public: std::string ToString( + sdf::Errors &_errors, + const std::string &_prefix, + const PrintConfig &_config = PrintConfig()) const; + + /// \brief Convert the element values to a string representation. + /// Current behavior of ToString(const std::string &_prefix) can be + /// achieved by calling this function with _includeDefaultElements=true + /// and _includeDefaultAttributes=false + /// \param[in] _prefix String value to prefix to the output. + /// \param[in] _includeDefaultElements flag to include default elements. + /// \param[in] _includeDefaultAttributes flag to include default attributes. + /// \param[in] _config Configuration for converting to string. + /// \return The string representation. public: std::string ToString( const std::string &_prefix, + bool _includeDefaultElements, + bool _includeDefaultAttributes, const PrintConfig &_config = PrintConfig()) const; /// \brief Convert the element values to a string representation. /// Current behavior of ToString(const std::string &_prefix) can be /// achieved by calling this function with _includeDefaultElements=true /// and _includeDefaultAttributes=false + /// \param[out] _errors Vector of errors. /// \param[in] _prefix String value to prefix to the output. /// \param[in] _includeDefaultElements flag to include default elements. /// \param[in] _includeDefaultAttributes flag to include default attributes. /// \param[in] _config Configuration for converting to string. /// \return The string representation. public: std::string ToString( + sdf::Errors &_errors, const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, @@ -371,6 +433,17 @@ namespace sdf public: std::any GetAny(sdf::Errors &_errors, const std::string &_key = "") const; + /// \brief Get the value of a key. This function assumes the _key + /// exists. + /// \param[out] _errors Vector of errors. + /// \param[in] _key the name of a child attribute or element. + /// \return The value of the _key. + /// \sa std::pair Get(const std::string &_key, + /// const T &_defaultValue) + public: template + T Get(sdf::Errors &_errors, + const std::string &_key = "") const; + /// \brief Get the value of a key. This function assumes the _key /// exists. /// \param[in] _key the name of a child attribute or element. @@ -381,6 +454,17 @@ namespace sdf T Get(const std::string &_key = "") const; /// \brief Get the value of a key. + /// \param[out] _errors Vector of errors. + /// \param[in] _key the name of a child attribute or element. + /// \param[in] _defaultValue a default value to use if _key is not + /// found. + /// \return A pair where the first element is the value of _key, and the + /// second element is true when the _key was found and false otherwise. + public: template + std::pair Get(sdf::Errors &_errors, + const std::string &_key, + const T &_defaultValue) const; + /// \brief Get the value of a key. /// \param[in] _key the name of a child attribute or element. /// \param[in] _defaultValue a default value to use if _key is not /// found. @@ -401,12 +485,32 @@ namespace sdf T &_param, const T &_defaultValue) const; + /// \brief Get the value of a key. + /// \param[out] _errors Vector of errors. + /// \param[in] _key the name of a child attribute or element. + /// \param[out] _param the parameter output + /// \param[in] _defaultValue a default value to use if _key is not + /// found. + /// \return True when the _key was found and false otherwise. + public: template + bool Get(sdf::Errors &_errors, + const std::string &_key, + T &_param, + const T &_defaultValue) const; + /// \brief Set the value of this element. /// \param[in] _value the value to set. /// \return True if the value was successfully set, false otherwise. public: template bool Set(const T &_value); + /// \brief Set the value of this element. + /// \param[in] _value the value to set. + /// \param[out] _errors Vector of errors. + /// \return True if the value was successfully set, false otherwise. + public: template + bool Set(const T &_value, sdf::Errors &_errors); + /// \brief Return true if the named element exists. /// \param[in] _name the name of the element to look for. /// \return True if the named element was found, false otherwise. @@ -443,9 +547,35 @@ namespace sdf /// names. Also return true if no elements of the specified type are found. public: bool HasUniqueChildNames(const std::string &_type = "") const; + /// \brief Checks whether any child elements of the specified element type + /// have identical name attribute values and returns false if so. + /// \param[out] _errors Vector of errors. + /// \param[in] _type The type of Element to check. If empty, check names + /// of all child elements. + /// \return True if all child elements with name attributes of the + /// specified type have unique names, return false if there are duplicated + /// names. Also return true if no elements of the specified type are found. + public: bool HasUniqueChildNames(sdf::Errors &_errors, + const std::string &_type = "") const; + + /// \brief Checks whether any child elements of the specified element type, + /// except those listed in \p _ignoreElements, have identical name attribute + /// values and returns false if so. + /// \param[in] _type The type of Element to check. If empty, check names + /// of all child elements. + /// \param[in] _ignoreElements A list of child element types to ignore when + /// checking for uniqueness. + /// \return True if all child elements with name attributes of the + /// specified type have unique names, return false if there are duplicated + /// names. Also return true if no elements of the specified type are found. + public: bool HasUniqueChildNames( + const std::string &_type, + const std::vector &_ignoreElements) const; + /// \brief Checks whether any child elements of the specified element type, /// except those listed in \p _ignoreElements, have identical name attribute /// values and returns false if so. + /// \param[out] _errors Vector of errors. /// \param[in] _type The type of Element to check. If empty, check names /// of all child elements. /// \param[in] _ignoreElements A list of child element types to ignore when @@ -454,6 +584,7 @@ namespace sdf /// specified type have unique names, return false if there are duplicated /// names. Also return true if no elements of the specified type are found. public: bool HasUniqueChildNames( + sdf::Errors &_errors, const std::string &_type, const std::vector &_ignoreElements) const; @@ -467,6 +598,18 @@ namespace sdf public: std::map CountNamedElements(const std::string &_type = "") const; + /// \brief Count the number of child elements of the specified element type + /// that have the same name attribute value. + /// \param[out] _errors Vector of errors. + /// \param[in] _type The type of Element to check. If empty, count names + /// of all child elements. + /// \return Map from Element names to a count of how many times the name + /// occurs. The count should never be 0. If all 2nd values are 1, then + /// there are exclusively unique names. + public: std::map + CountNamedElements(sdf::Errors &_errors, + const std::string &_type = "") const; + /// \brief Count the number of child elements of the specified element type /// that have the same name attribute value with the exception of elements /// listed in \p _ignoreElements. @@ -481,6 +624,22 @@ namespace sdf const std::string &_type, const std::vector &_ignoreElements) const; + /// \brief Count the number of child elements of the specified element type + /// that have the same name attribute value with the exception of elements + /// listed in \p _ignoreElements. + /// \param[out] _errors Vector of errors. + /// \param[in] _type The type of Element to check. If empty, count names + /// of all child elements. + /// \param[in] _ignoreElements A list of child element types to ignore when + /// checking for uniqueness. + /// \return Map from Element names to a count of how many times the name + /// occurs. The count should never be 0. If all 2nd values are 1, then + /// there are exclusively unique names. + public: std::map CountNamedElements( + sdf::Errors &_errors, + const std::string &_type, + const std::vector &_ignoreElements) const; + /// \brief Return a pointer to the child element with the provided name. /// /// A new child element, with the provided name, is added to this element @@ -575,6 +734,11 @@ namespace sdf /// the embedded Param. public: void Update(); + /// \brief Call the Update() callback on each element, as well as + /// the embedded Param. + /// \param[out] _errors Vector of errors. + public: void Update(sdf::Errors &_errors); + /// \brief Call reset on each element and element description /// before deleting all of them. Also clear out the /// embedded Param. @@ -661,16 +825,18 @@ namespace sdf public: static std::vector NameUniquenessExceptions(); /// \brief Generate a string (XML) representation of this object. + /// \param[out] _out the std::ostreamstream to write output to. + /// \param[out] _errors Vector of errors. /// \param[in] _prefix arbitrary prefix to put on the string. /// \param[in] _includeDefaultElements flag to include default elements. /// \param[in] _includeDefaultAttributes flag to include default attributes. /// \param[in] _config Configuration for converting to string. - /// \param[out] _out the std::ostreamstream to write output to. - private: void ToString(const std::string &_prefix, + private: void ToString(std::ostringstream &_out, + sdf::Errors &_errors, + const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, - const PrintConfig &_config, - std::ostringstream &_out) const; + const PrintConfig &_config) const; /// \brief Generate a string (XML) representation of this object. /// \param[in] _prefix arbitrary prefix to put on the string. @@ -678,11 +844,13 @@ namespace sdf /// \param[in] _includeDefaultAttributes flag to include default attributes. /// \param[in] _config Configuration for printing values. /// \param[out] _out the std::ostringstream to write output to. + /// \param[out] _errors Vector of errors. private: void PrintValuesImpl(const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, const PrintConfig &_config, - std::ostringstream &_out) const; + std::ostringstream &_out, + sdf::Errors &_errors) const; /// \brief Create a new Param object and return it. /// \param[in] _key Key for the parameter. @@ -782,8 +950,29 @@ namespace sdf public: void PrintAttributes(bool _includeDefaultAttributes, const PrintConfig &_config, std::ostringstream &_out) const; + + /// \brief Generate the string (XML) for the attributes. + /// \param[in] _includeDefaultAttributes flag to include default attributes. + /// \param[in] _config Configuration for printing attributes. + /// \param[out] _out the std::ostringstream to write output to. + /// \param[out] _errors Vector of errors. + public: void PrintAttributes(bool _includeDefaultAttributes, + const PrintConfig &_config, + std::ostringstream &_out, + sdf::Errors &_errors) const; }; + /////////////////////////////////////////////// + template + T Element::Get(sdf::Errors &_errors, const std::string &_key) const + { + T result = T(); + + std::pair ret = this->Get(_errors, _key, result); + + return ret.first; + } + /////////////////////////////////////////////// template T Element::Get(const std::string &_key) const @@ -795,6 +984,18 @@ namespace sdf return ret.first; } + /////////////////////////////////////////////// + template + bool Element::Get(sdf::Errors &_errors, + const std::string &_key, + T &_param, + const T &_defaultValue) const + { + std::pair ret = this->Get(_errors, _key, _defaultValue); + _param = ret.first; + return ret.second; + } + /////////////////////////////////////////////// template bool Element::Get(const std::string &_key, @@ -810,27 +1011,42 @@ namespace sdf template std::pair Element::Get(const std::string &_key, const T &_defaultValue) const + { + sdf::Errors errors; + std::pair result = this->Get(errors, _key, _defaultValue); + for(auto& error : errors) + { + sdferr << error.Message(); + } + return result; + } + + /////////////////////////////////////////////// + template + std::pair Element::Get(sdf::Errors &_errors, + const std::string &_key, + const T &_defaultValue) const { std::pair result(_defaultValue, true); if (_key.empty() && this->dataPtr->value) { - this->dataPtr->value->Get(result.first); + this->dataPtr->value->Get(result.first, _errors); } else if (!_key.empty()) { ParamPtr param = this->GetAttribute(_key); if (param) { - param->Get(result.first); + param->Get(result.first, _errors); } else if (this->HasElement(_key)) { - result.first = this->GetElementImpl(_key)->Get(); + result.first = this->GetElementImpl(_key)->Get(_errors); } else if (this->HasElementDescription(_key)) { - result.first = this->GetElementDescription(_key)->Get(); + result.first = this->GetElementDescription(_key)->Get(_errors); } else { @@ -848,10 +1064,23 @@ namespace sdf /////////////////////////////////////////////// template bool Element::Set(const T &_value) + { + sdf::Errors errors; + bool result = this->Set(_value, errors); + for(auto& error : errors) + { + sdferr << error.Message(); + } + return result; + } + + /////////////////////////////////////////////// + template + bool Element::Set(const T &_value, sdf::Errors &_errors) { if (this->dataPtr->value) { - this->dataPtr->value->Set(_value); + this->dataPtr->value->Set(_value, _errors); return true; } return false; diff --git a/src/Element.cc b/src/Element.cc index 5dfc243c6..2bc5452f5 100644 --- a/src/Element.cc +++ b/src/Element.cc @@ -141,7 +141,7 @@ void Element::AddValue(const std::string &_type, sdf::Errors errors; this->dataPtr->value = this->CreateParam(this->dataPtr->name, _type, _defaultValue, _required, errors, _description); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); } ///////////////////////////////////////////////// @@ -166,7 +166,7 @@ void Element::AddValue(const std::string &_type, sdf::Errors errors; this->AddValue(_type, _defaultValue, _required, _minValue, _maxValue, errors, _description); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); } ///////////////////////////////////////////////// @@ -218,7 +218,7 @@ void Element::AddAttribute(const std::string &_key, sdf::Errors errors; this->AddAttribute(_key, _type, _defaultValue, _required, errors, _description); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); } ///////////////////////////////////////////////// @@ -239,7 +239,7 @@ ElementPtr Element::Clone() const { sdf::Errors errors; ElementPtr elem = this->Clone(errors); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); return elem; } @@ -277,13 +277,13 @@ ElementPtr Element::Clone(sdf::Errors &_errors) const for (eiter = this->dataPtr->elementDescriptions.begin(); eiter != this->dataPtr->elementDescriptions.end(); ++eiter) { - clone->dataPtr->elementDescriptions.push_back((*eiter)->Clone()); + clone->dataPtr->elementDescriptions.push_back((*eiter)->Clone(_errors)); } for (eiter = this->dataPtr->elements.begin(); eiter != this->dataPtr->elements.end(); ++eiter) { - clone->dataPtr->elements.push_back((*eiter)->Clone()); + clone->dataPtr->elements.push_back((*eiter)->Clone(_errors)); clone->dataPtr->elements.back()->SetParent(clone); } @@ -314,7 +314,7 @@ void Element::Copy(const ElementPtr _elem) { sdf::Errors errors; this->Copy(_elem, errors); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); } ///////////////////////////////////////////////// @@ -404,6 +404,15 @@ void Element::Copy(const ElementPtr _elem, sdf::Errors &_errors) ///////////////////////////////////////////////// void Element::PrintDescription(const std::string &_prefix) const +{ + sdf::Errors errors; + this->PrintDescription(_prefix, errors); + sdf::throwOrPrintErrors(errors); +} + +///////////////////////////////////////////////// +void Element::PrintDescription(const std::string &_prefix, + sdf::Errors &_errors) const { std::cout << _prefix << "dataPtr->value->GetDefaultAsString(_errors) << "'"; - auto minValue = this->dataPtr->value->GetMinValueAsString(); + auto minValue = this->dataPtr->value->GetMinValueAsString(_errors); if (minValue.has_value()) { std::cout << " min ='" << *minValue << "'"; } - auto maxValue = this->dataPtr->value->GetMaxValueAsString(); + auto maxValue = this->dataPtr->value->GetMaxValueAsString(_errors); if (maxValue.has_value()) { std::cout << " max ='" << *maxValue << "'"; @@ -439,7 +449,7 @@ void Element::PrintDescription(const std::string &_prefix) const { std::cout << _prefix << " \n"; std::cout << _prefix << " GetDescription() @@ -464,7 +474,7 @@ void Element::PrintDescription(const std::string &_prefix) const for (eiter = this->dataPtr->elementDescriptions.begin(); eiter != this->dataPtr->elementDescriptions.end(); ++eiter) { - (*eiter)->PrintDescription(_prefix + " "); + (*eiter)->PrintDescription(_prefix + " ", _errors); } std::cout << _prefix << "\n"; @@ -473,6 +483,15 @@ void Element::PrintDescription(const std::string &_prefix) const ///////////////////////////////////////////////// void Element::PrintDocRightPane(std::string &_html, int _spacing, int &_index) const +{ + sdf::Errors errors; + this->PrintDocRightPane(_html, _spacing, _index, errors); + sdf::throwOrPrintErrors(errors); +} + +///////////////////////////////////////////////// +void Element::PrintDocRightPane(std::string &_html, int _spacing, + int &_index, sdf::Errors &_errors) const { std::ostringstream stream; ElementPtr_V::iterator eiter; @@ -483,7 +502,7 @@ void Element::PrintDocRightPane(std::string &_html, int _spacing, for (eiter = this->dataPtr->elementDescriptions.begin(); eiter != this->dataPtr->elementDescriptions.end(); ++eiter) { - (*eiter)->PrintDocRightPane(childHTML, _spacing + 4, _index); + (*eiter)->PrintDocRightPane(childHTML, _spacing + 4, _index, _errors); } stream << "dataPtr->name << start @@ -512,7 +531,7 @@ void Element::PrintDocRightPane(std::string &_html, int _spacing, stream << this->dataPtr->value->GetTypeName() << "   \n" << "Default: " - << this->dataPtr->value->GetDefaultAsString() << '\n'; + << this->dataPtr->value->GetDefaultAsString(_errors) << '\n'; } else { @@ -552,7 +571,7 @@ void Element::PrintDocRightPane(std::string &_html, int _spacing, stream << "Type: " << (*aiter)->GetTypeName() << "   " << "Default: " - << (*aiter)->GetDefaultAsString() << "
"; + << (*aiter)->GetDefaultAsString(_errors) << "
"; stream << "\n"; stream << "\n"; @@ -598,17 +617,19 @@ void Element::PrintValuesImpl(const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, const PrintConfig &_config, - std::ostringstream &_out) const + std::ostringstream &_out, + sdf::Errors &_errors) const { if (_config.PreserveIncludes() && this->GetIncludeElement() != nullptr) { - _out << this->GetIncludeElement()->ToString(_prefix, _config); + _out << this->GetIncludeElement()->ToString(_errors, _prefix, _config); } else if (this->GetExplicitlySetInFile() || _includeDefaultElements) { _out << _prefix << "<" << this->dataPtr->name; - this->dataPtr->PrintAttributes(_includeDefaultAttributes, _config, _out); + this->dataPtr->PrintAttributes( + _includeDefaultAttributes, _config, _out, _errors); if (this->dataPtr->elements.size() > 0) { @@ -617,11 +638,12 @@ void Element::PrintValuesImpl(const std::string &_prefix, for (eiter = this->dataPtr->elements.begin(); eiter != this->dataPtr->elements.end(); ++eiter) { - (*eiter)->ToString(_prefix + " ", + (*eiter)->ToString(_out, + _errors, + _prefix + " ", _includeDefaultElements, _includeDefaultAttributes, - _config, - _out); + _config); } _out << _prefix << "dataPtr->name << ">\n"; } @@ -629,7 +651,7 @@ void Element::PrintValuesImpl(const std::string &_prefix, { if (this->dataPtr->value) { - _out << ">" << this->dataPtr->value->GetAsString(_config) + _out << ">" << this->dataPtr->value->GetAsString(_errors, _config) << "dataPtr->name << ">\n"; } else @@ -644,6 +666,18 @@ void Element::PrintValuesImpl(const std::string &_prefix, void ElementPrivate::PrintAttributes(bool _includeDefaultAttributes, const PrintConfig &_config, std::ostringstream &_out) const +{ + sdf::Errors errors; + this->PrintAttributes(_includeDefaultAttributes, _config, + _out, errors); + sdf::throwOrPrintErrors(errors); +} + +///////////////////////////////////////////////// +void ElementPrivate::PrintAttributes(bool _includeDefaultAttributes, + const PrintConfig &_config, + std::ostringstream &_out, + sdf::Errors &_errors) const { // Attribute exceptions are used in the event of a non-default PrintConfig // which modifies the Attributes of this Element that are printed out. The @@ -678,17 +712,30 @@ void ElementPrivate::PrintAttributes(bool _includeDefaultAttributes, const auto it = attributeExceptions.find(key); if (it == attributeExceptions.end()) { - _out << " " << key << "='" << (*aiter)->GetAsString(_config) << "'"; + _out << " " << key << "='" + << (*aiter)->GetAsString(_errors, _config) << "'"; } } } } ///////////////////////////////////////////////// -void Element::PrintValues(std::string _prefix, const PrintConfig &_config) const +void Element::PrintValues(std::string _prefix, + const PrintConfig &_config) const { std::ostringstream ss; - PrintValuesImpl(_prefix, true, false, _config, ss); + sdf::Errors errors; + PrintValuesImpl(_prefix, true, false, _config, ss, errors); + sdf::throwOrPrintErrors(errors); + std::cout << ss.str(); +} + +///////////////////////////////////////////////// +void Element::PrintValues(sdf::Errors &_errors, std::string _prefix, + const PrintConfig &_config) const +{ + std::ostringstream ss; + PrintValuesImpl(_prefix, true, false, _config, ss, _errors); std::cout << ss.str(); } @@ -697,22 +744,54 @@ void Element::PrintValues(const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, const PrintConfig &_config) const +{ + std::ostringstream ss; + sdf::Errors errors; + PrintValuesImpl(_prefix, + _includeDefaultElements, + _includeDefaultAttributes, + _config, + ss, + errors); + sdf::throwOrPrintErrors(errors); + std::cout << ss.str(); +} + +///////////////////////////////////////////////// +void Element::PrintValues(sdf::Errors &_errors, + const std::string &_prefix, + bool _includeDefaultElements, + bool _includeDefaultAttributes, + const PrintConfig &_config) const { std::ostringstream ss; PrintValuesImpl(_prefix, _includeDefaultElements, _includeDefaultAttributes, _config, - ss); + ss, + _errors); std::cout << ss.str(); } ///////////////////////////////////////////////// std::string Element::ToString(const std::string &_prefix, const PrintConfig &_config) const +{ + sdf::Errors errors; + std::ostringstream out; + this->ToString(out, errors, _prefix, true, false, _config); + sdf::throwOrPrintErrors(errors); + return out.str(); +} + +///////////////////////////////////////////////// +std::string Element::ToString(sdf::Errors &_errors, + const std::string &_prefix, + const PrintConfig &_config) const { std::ostringstream out; - this->ToString(_prefix, true, false, _config, out); + this->ToString(out, _errors, _prefix, true, false, _config); return out.str(); } @@ -722,27 +801,49 @@ std::string Element::ToString(const std::string &_prefix, bool _includeDefaultAttributes, const PrintConfig &_config) const { + sdf::Errors errors; std::ostringstream out; - this->ToString(_prefix, + this->ToString(out, + errors, + _prefix, _includeDefaultElements, _includeDefaultAttributes, - _config, - out); + _config); + sdf::throwOrPrintErrors(errors); return out.str(); } ///////////////////////////////////////////////// -void Element::ToString(const std::string &_prefix, +std::string Element::ToString(sdf::Errors &_errors, + const std::string &_prefix, + bool _includeDefaultElements, + bool _includeDefaultAttributes, + const PrintConfig &_config) const +{ + std::ostringstream out; + this->ToString(out, + _errors, + _prefix, + _includeDefaultElements, + _includeDefaultAttributes, + _config); + return out.str(); +} + +///////////////////////////////////////////////// +void Element::ToString(std::ostringstream &_out, + sdf::Errors &_errors, + const std::string &_prefix, bool _includeDefaultElements, bool _includeDefaultAttributes, - const PrintConfig &_config, - std::ostringstream &_out) const + const PrintConfig &_config) const { PrintValuesImpl(_prefix, _includeDefaultElements, _includeDefaultAttributes, _config, - _out); + _out, + _errors); } ///////////////////////////////////////////////// @@ -957,12 +1058,33 @@ bool Element::HasUniqueChildNames(const std::string &_type) const return this->HasUniqueChildNames(_type, {}); } +///////////////////////////////////////////////// +bool Element::HasUniqueChildNames( + sdf::Errors &_errors, + const std::string &_type) const +{ + return this->HasUniqueChildNames(_errors, _type, {}); +} + ///////////////////////////////////////////////// bool Element::HasUniqueChildNames( const std::string &_type, const std::vector &_ignoreElements) const { - auto namedElementsCount = this->CountNamedElements(_type, _ignoreElements); + sdf::Errors errors; + bool result = this->HasUniqueChildNames(errors, _type, _ignoreElements); + sdf::throwOrPrintErrors(errors); + return result; +} + +///////////////////////////////////////////////// +bool Element::HasUniqueChildNames( + sdf::Errors &_errors, + const std::string &_type, + const std::vector &_ignoreElements) const +{ + auto namedElementsCount = this->CountNamedElements( + _errors, _type, _ignoreElements); for (auto &iter : namedElementsCount) { if (iter.second > 1) @@ -982,6 +1104,26 @@ std::map Element::CountNamedElements( ///////////////////////////////////////////////// std::map Element::CountNamedElements( + sdf::Errors &_errors, + const std::string &_type) const +{ + return this->CountNamedElements(_errors, _type, {}); +} + +///////////////////////////////////////////////// +std::map Element::CountNamedElements( + const std::string &_type, + const std::vector &_ignoreElements) const +{ + sdf::Errors errors; + auto result = this->CountNamedElements(errors, _type, _ignoreElements); + sdf::throwOrPrintErrors(errors); + return result; +} + +///////////////////////////////////////////////// +std::map Element::CountNamedElements( + sdf::Errors &_errors, const std::string &_type, const std::vector &_ignoreElements) const { @@ -1006,7 +1148,8 @@ std::map Element::CountNamedElements( // Get("name") returns attribute value if it exists before checking // for the value of a child element , so it's safe to use // here since we've checked HasAttribute("name"). - std::string childNameAttributeValue = elem->Get("name"); + std::string childNameAttributeValue = elem->Get( + _errors, "name"); if (result.find(childNameAttributeValue) == result.end()) { result[childNameAttributeValue] = 1; @@ -1028,7 +1171,7 @@ ElementPtr Element::GetElement(const std::string &_name) { sdf::Errors errors; ElementPtr result = this->GetElement(_name, errors); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); return result; } @@ -1081,7 +1224,7 @@ ElementPtr Element::AddElement(const std::string &_name) { sdf::Errors errors; ElementPtr elem = this->AddElement(_name, errors); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); return elem; } @@ -1153,24 +1296,33 @@ void Element::ClearElements() this->dataPtr->elements.clear(); } + ///////////////////////////////////////////////// void Element::Update() +{ + sdf::Errors errors; + this->Update(errors); + sdf::throwOrPrintErrors(errors); +} + +///////////////////////////////////////////////// +void Element::Update(sdf::Errors &_errors) { for (sdf::Param_V::iterator iter = this->dataPtr->attributes.begin(); iter != this->dataPtr->attributes.end(); ++iter) { - (*iter)->Update(); + (*iter)->Update(_errors); } for (sdf::ElementPtr_V::iterator iter = this->dataPtr->elements.begin(); iter != this->dataPtr->elements.end(); ++iter) { - (*iter)->Update(); + (*iter)->Update(_errors); } if (this->dataPtr->value) { - this->dataPtr->value->Update(); + this->dataPtr->value->Update(_errors); } } @@ -1305,7 +1457,7 @@ void Element::RemoveChild(ElementPtr _child) { sdf::Errors errors; RemoveChild(_child, errors); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); } ///////////////////////////////////////////////// @@ -1334,7 +1486,7 @@ std::any Element::GetAny(const std::string &_key) const { sdf::Errors errors; std::any result = this->GetAny(errors, _key); - throwOrPrintErrors(errors); + sdf::throwOrPrintErrors(errors); return result; } @@ -1344,7 +1496,7 @@ std::any Element::GetAny(sdf::Errors &_errors, const std::string &_key) const std::any result; if (_key.empty() && this->dataPtr->value) { - if (!this->dataPtr->value->GetAny(result)) + if (!this->dataPtr->value->GetAny(result, _errors)) { _errors.push_back({ErrorCode::ELEMENT_ERROR, "Couldn't get element [" + this->GetName() + "] as std::any\n"}); From 3b9585f3dfbb6bb98303a43be52ef7133b11e878 Mon Sep 17 00:00:00 2001 From: "Marco A. Gutierrez" Date: Mon, 19 Sep 2022 10:08:15 +0000 Subject: [PATCH 2/4] adding errors parameters to Physics function calls Signed-off-by: Marco A. Gutierrez --- include/sdf/Physics.hh | 8 ++++++++ src/Physics.cc | 34 +++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/sdf/Physics.hh b/include/sdf/Physics.hh index e20eebcef..0fa5ea5ef 100644 --- a/include/sdf/Physics.hh +++ b/include/sdf/Physics.hh @@ -121,6 +121,14 @@ namespace sdf /// \return SDF element pointer with updated physics values. public: sdf::ElementPtr ToElement() const; + /// \brief Create and return an SDF element filled with data from this + /// physics. + /// Note that parameter passing functionality is not captured with this + /// function. + /// \param[out] _errors Vector of errors. + /// \return SDF element pointer with updated physics values. + public: sdf::ElementPtr ToElement(sdf::Errors &_errors) const; + /// \brief Private data pointer. GZ_UTILS_IMPL_PTR(dataPtr) }; diff --git a/src/Physics.cc b/src/Physics.cc index 86f8b2e7d..dda730635 100644 --- a/src/Physics.cc +++ b/src/Physics.cc @@ -86,10 +86,10 @@ Errors Physics::Load(sdf::ElementPtr _sdf) } this->dataPtr->isDefault = - _sdf->Get("default", this->dataPtr->isDefault).first; + _sdf->Get(errors, "default", this->dataPtr->isDefault).first; std::pair stringPair = - _sdf->Get("type", this->dataPtr->type); + _sdf->Get(errors, "type", this->dataPtr->type); if (!stringPair.second) { errors.push_back({ErrorCode::ELEMENT_MISSING, @@ -99,7 +99,7 @@ Errors Physics::Load(sdf::ElementPtr _sdf) this->dataPtr->type = stringPair.first; std::pair doublePair = - _sdf->Get("max_step_size", this->dataPtr->stepSize); + _sdf->Get(errors, "max_step_size", this->dataPtr->stepSize); if (!doublePair.second) { errors.push_back({ErrorCode::ELEMENT_MISSING, @@ -108,7 +108,8 @@ Errors Physics::Load(sdf::ElementPtr _sdf) } this->dataPtr->stepSize = doublePair.first; - doublePair = _sdf->Get("real_time_factor", this->dataPtr->rtf); + doublePair = _sdf->Get( + errors, "real_time_factor", this->dataPtr->rtf); if (!doublePair.second) { errors.push_back({ErrorCode::ELEMENT_MISSING, @@ -118,7 +119,7 @@ Errors Physics::Load(sdf::ElementPtr _sdf) this->dataPtr->rtf = doublePair.first; this->dataPtr->maxContacts = - _sdf->Get("max_contacts", this->dataPtr->maxContacts).first; + _sdf->Get(errors, "max_contacts", this->dataPtr->maxContacts).first; return errors; } @@ -203,17 +204,28 @@ void Physics::SetMaxContacts(int _maxContacts) ///////////////////////////////////////////////// sdf::ElementPtr Physics::ToElement() const +{ + sdf::Errors errors; + auto result = this->ToElement(errors); + sdf::throwOrPrintErrors(errors); + return result; +} + +///////////////////////////////////////////////// +sdf::ElementPtr Physics::ToElement(sdf::Errors &_errors) const { sdf::ElementPtr elem(new sdf::Element); sdf::initFile("physics.sdf", elem); - elem->GetAttribute("name")->Set(this->Name()); - elem->GetAttribute("default")->Set(this->IsDefault()); - elem->GetAttribute("type")->Set(this->EngineType()); + elem->GetAttribute("name")->Set(this->Name(), _errors); + elem->GetAttribute("default")->Set(this->IsDefault(), _errors); + elem->GetAttribute("type")->Set(this->EngineType(), _errors); - elem->GetElement("max_step_size")->Set(this->MaxStepSize()); - elem->GetElement("real_time_factor")->Set(this->RealTimeFactor()); - elem->GetElement("max_contacts")->Set(this->MaxContacts()); + elem->GetElement("max_step_size", _errors)->Set( + this->MaxStepSize(), _errors); + elem->GetElement("real_time_factor", _errors)->Set( + this->RealTimeFactor(), _errors); + elem->GetElement("max_contacts", _errors)->Set(this->MaxContacts(), _errors); /// \todo(nkoenig) Support engine specific parameters. From bb373335e06a8edbf8eb9379acd528e77da915ea Mon Sep 17 00:00:00 2001 From: "Marco A. Gutierrez" Date: Fri, 24 Mar 2023 02:46:03 +0000 Subject: [PATCH 3/4] Fix calls to Element wiht error parameters Signed-off-by: Marco A. Gutierrez --- src/Physics.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Physics.cc b/src/Physics.cc index dda730635..b9dd69317 100644 --- a/src/Physics.cc +++ b/src/Physics.cc @@ -222,10 +222,11 @@ sdf::ElementPtr Physics::ToElement(sdf::Errors &_errors) const elem->GetAttribute("type")->Set(this->EngineType(), _errors); elem->GetElement("max_step_size", _errors)->Set( - this->MaxStepSize(), _errors); + _errors, this->MaxStepSize()); elem->GetElement("real_time_factor", _errors)->Set( - this->RealTimeFactor(), _errors); - elem->GetElement("max_contacts", _errors)->Set(this->MaxContacts(), _errors); + _errors, this->RealTimeFactor()); + elem->GetElement("max_contacts", _errors)->Set( + _errors, this->MaxContacts()); /// \todo(nkoenig) Support engine specific parameters. From 26b071ea94bd6a5bd8ea3a78a42f67cb6efbc48d Mon Sep 17 00:00:00 2001 From: "Marco A. Gutierrez" Date: Tue, 28 Mar 2023 03:10:10 +0000 Subject: [PATCH 4/4] Add ToElement Errors test Signed-off-by: Marco A. Gutierrez --- src/Physics_TEST.cc | 46 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/Physics_TEST.cc b/src/Physics_TEST.cc index 43bf95fa0..25ad32b02 100644 --- a/src/Physics_TEST.cc +++ b/src/Physics_TEST.cc @@ -17,6 +17,7 @@ #include #include "sdf/Physics.hh" +#include "test_utils.hh" ///////////////////////////////////////////////// TEST(DOMPhysics, DefaultConstruction) @@ -131,3 +132,48 @@ TEST(DOMPhysics, ToElement) EXPECT_DOUBLE_EQ(physics.RealTimeFactor(), physics2.RealTimeFactor()); EXPECT_EQ(physics.MaxContacts(), physics2.MaxContacts()); } + +///////////////////////////////////////////////// +TEST(DOMPhysics, ToElementErrorOutput) +{ + std::stringstream buffer; + sdf::testing::RedirectConsoleStream redir( + sdf::Console::Instance()->GetMsgStream(), &buffer); + + #ifdef _WIN32 + sdf::Console::Instance()->SetQuiet(false); + sdf::testing::ScopeExit revertSetQuiet( + [] + { + sdf::Console::Instance()->SetQuiet(true); + }); + #endif + + sdf::Physics physics; + sdf::Errors errors; + physics.SetName("my-bullet-engine"); + physics.SetDefault(true); + physics.SetEngineType("bullet"); + physics.SetMaxStepSize(0.1); + physics.SetRealTimeFactor(20.4); + physics.SetMaxContacts(42); + + sdf::ElementPtr elem = physics.ToElement(errors); + EXPECT_TRUE(errors.empty()); + ASSERT_NE(nullptr, elem); + + sdf::Physics physics2; + errors = physics2.Load(elem); + EXPECT_TRUE(errors.empty()); + + // verify values after loading the element back + EXPECT_EQ(physics.Name(), physics2.Name()); + EXPECT_EQ(physics.IsDefault(), physics2.IsDefault()); + EXPECT_EQ(physics.EngineType(), physics2.EngineType()); + EXPECT_DOUBLE_EQ(physics.MaxStepSize(), physics2.MaxStepSize()); + EXPECT_DOUBLE_EQ(physics.RealTimeFactor(), physics2.RealTimeFactor()); + EXPECT_EQ(physics.MaxContacts(), physics2.MaxContacts()); + + // Check nothing has been printed + EXPECT_TRUE(buffer.str().empty()) << buffer.str(); +}