Skip to content

Commit

Permalink
Making PrintValues() and ToString() able to not print default elements (
Browse files Browse the repository at this point in the history
#575)

Now PrintValues() and ToString() will not output the elements that were added by default during parsing. There's also the option to call them with a boolean flag that will allow the caller to decide weather they want defaults in the output or not.

Signed-off-by: Marco A. Gutierrez <marco@openrobotics.org>

Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Jenn Nguyen <jenn@openrobotics.org>
  • Loading branch information
2 people authored and jennuine committed Jul 29, 2021
1 parent f3c01ae commit cec38a3
Show file tree
Hide file tree
Showing 5 changed files with 275 additions and 40 deletions.
28 changes: 28 additions & 0 deletions include/sdf/Element.hh
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ namespace sdf
/// \param[in] _prefix String value to prefix to the output.
public: void PrintValues(std::string _prefix) 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.
/// \param[in] _includeDefaultAttributes flag to print default attributes.
public: void PrintValues(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes) const;

/// \brief Helper function for SDF::PrintDoc
///
/// This generates the SDF html documentation.
Expand All @@ -171,6 +179,18 @@ namespace sdf
/// \return The string representation.
public: std::string ToString(const std::string &_prefix) 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.
/// \return The string representation.
public: std::string ToString(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes) const;

/// \brief Add an attribute value.
/// \param[in] _key Key value.
/// \param[in] _type Type of data the attribute will hold.
Expand Down Expand Up @@ -437,14 +457,22 @@ namespace sdf

/// \brief Generate a string (XML) representation of this object.
/// \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[out] _out the std::ostreamstream to write output to.
private: void ToString(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes,
std::ostringstream &_out) const;

/// \brief Generate a string (XML) representation of this object.
/// \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[out] _out the std::ostreamstream to write output to.
private: void PrintValuesImpl(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes,
std::ostringstream &_out) const;

/// \brief Create a new Param object and return it.
Expand Down
111 changes: 77 additions & 34 deletions src/Element.cc
Original file line number Diff line number Diff line change
Expand Up @@ -466,47 +466,59 @@ void Element::PrintDocLeftPane(std::string &_html, int _spacing,
}

void Element::PrintValuesImpl(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes,
std::ostringstream &_out) const
{
_out << _prefix << "<" << this->dataPtr->name;

Param_V::const_iterator aiter;
for (aiter = this->dataPtr->attributes.begin();
aiter != this->dataPtr->attributes.end(); ++aiter)
if (this->GetExplicitlySetInFile() || _includeDefaultElements)
{
// Only print attribute values if they were set
// TODO(anyone): GetRequired is added here to support up-conversions where a
// new required attribute with a default value is added. We would have
// better separation of concerns if the conversion process set the required
// attributes with their default values.
if ((*aiter)->GetSet() || (*aiter)->GetRequired())
{
_out << " " << (*aiter)->GetKey() << "='"
<< (*aiter)->GetAsString() << "'";
}
}
_out << _prefix << "<" << this->dataPtr->name;

if (this->dataPtr->elements.size() > 0)
{
_out << ">\n";
ElementPtr_V::const_iterator eiter;
for (eiter = this->dataPtr->elements.begin();
eiter != this->dataPtr->elements.end(); ++eiter)
Param_V::const_iterator aiter;
for (aiter = this->dataPtr->attributes.begin();
aiter != this->dataPtr->attributes.end(); ++aiter)
{
(*eiter)->ToString(_prefix + " ", _out);
// Only print attribute values if they were set
// TODO(anyone): GetRequired is added here to support up-conversions where
// a new required attribute with a default value is added. We would have
// better separation of concerns if the conversion process set the
// required attributes with their default values.
if ((*aiter)->GetSet() || (*aiter)->GetRequired() ||
_includeDefaultAttributes)
{
_out << " " << (*aiter)->GetKey() << "='"
<< (*aiter)->GetAsString() << "'";
}
}
_out << _prefix << "</" << this->dataPtr->name << ">\n";
}
else
{
if (this->dataPtr->value)

if (this->dataPtr->elements.size() > 0)
{
_out << ">" << this->dataPtr->value->GetAsString()
<< "</" << this->dataPtr->name << ">\n";
_out << ">\n";
ElementPtr_V::const_iterator eiter;
for (eiter = this->dataPtr->elements.begin();
eiter != this->dataPtr->elements.end(); ++eiter)
{
if ((*eiter)->GetExplicitlySetInFile() || _includeDefaultElements)
{
(*eiter)->ToString(_prefix + " ",
_includeDefaultElements,
_includeDefaultAttributes,
_out);
}
}
_out << _prefix << "</" << this->dataPtr->name << ">\n";
}
else
{
_out << "/>\n";
if (this->dataPtr->value)
{
_out << ">" << this->dataPtr->value->GetAsString()
<< "</" << this->dataPtr->name << ">\n";
}
else
{
_out << "/>\n";
}
}
}
}
Expand All @@ -515,25 +527,56 @@ void Element::PrintValuesImpl(const std::string &_prefix,
void Element::PrintValues(std::string _prefix) const
{
std::ostringstream ss;
PrintValuesImpl(_prefix, ss);
PrintValuesImpl(_prefix, true, false, ss);
std::cout << ss.str();
}

/////////////////////////////////////////////////
void Element::PrintValues(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes) const
{
std::ostringstream ss;
PrintValuesImpl(_prefix,
_includeDefaultElements,
_includeDefaultAttributes,
ss);
std::cout << ss.str();
}

/////////////////////////////////////////////////
std::string Element::ToString(const std::string &_prefix) const
{
std::ostringstream out;
this->ToString(_prefix, out);
this->ToString(_prefix, true, false, out);
return out.str();
}

/////////////////////////////////////////////////
std::string Element::ToString(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes) const
{
std::ostringstream out;
this->ToString(_prefix,
_includeDefaultElements,
_includeDefaultAttributes,
out);
return out.str();
}

/////////////////////////////////////////////////
void Element::ToString(const std::string &_prefix,
bool _includeDefaultElements,
bool _includeDefaultAttributes,
std::ostringstream &_out) const
{
if (this->dataPtr->includeFilename.empty())
{
PrintValuesImpl(_prefix, _out);
PrintValuesImpl(_prefix,
_includeDefaultElements,
_includeDefaultAttributes,
_out);
}
else
{
Expand Down
70 changes: 69 additions & 1 deletion src/Element_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,6 @@ TEST(Element, ToStringValue)
"myprefix< test='foo'>val</>\n");
}


/////////////////////////////////////////////////
TEST(Element, ToStringClonedElement)
{
Expand Down Expand Up @@ -575,6 +574,75 @@ TEST(Element, ToStringInclude)
ASSERT_EQ(stringval, "myprefix<include filename='foo.txt'/>\n");
}

/////////////////////////////////////////////////
TEST(Element, ToStringDefaultElements)
{
sdf::ElementPtr parent = std::make_shared<sdf::Element>();
parent->SetName("parent");
sdf::ElementPtr elem = std::make_shared<sdf::Element>();
elem->SetName("elem");
elem->SetParent(parent);
parent->InsertElement(elem);
sdf::ElementPtr elem2 = std::make_shared<sdf::Element>();
elem2->SetName("elem2");
elem2->SetParent(parent);
parent->InsertElement(elem2);

std::ostringstream stream;
stream
<< "<parent>\n"
<< " <elem/>\n"
<< " <elem2/>\n"
<< "</parent>\n";

EXPECT_EQ(parent->ToString("", false, false), stream.str());
EXPECT_EQ(parent->ToString(""), stream.str());
EXPECT_EQ(parent->ToString("", true, false), stream.str());

elem->SetExplicitlySetInFile(false);

std::ostringstream stream2;
stream2
<< "<parent>\n"
<< " <elem2/>\n"
<< "</parent>\n";

EXPECT_EQ(parent->ToString("", false, false), stream2.str());
EXPECT_EQ(parent->ToString(""), stream.str());
EXPECT_EQ(parent->ToString("", true, false), stream.str());

parent->SetExplicitlySetInFile(false);

EXPECT_EQ(parent->ToString("", false, false), "");
EXPECT_EQ(parent->ToString(""), stream.str());
EXPECT_EQ(parent->ToString("", true, false), stream.str());
}

/////////////////////////////////////////////////
TEST(Element, ToStringDefaultAttributes)
{
sdf::ElementPtr element = std::make_shared<sdf::Element>();
element->SetName("foo");
element->AddAttribute("test", "string", "foo", false, "foo description");
element->AddAttribute("test2", "string", "bar", true, "bar description");

EXPECT_EQ(element->ToString(""), element->ToString("", true, false));
EXPECT_EQ(element->ToString(""), element->ToString("", false, false));

std::ostringstream stream;
stream << "<foo test2='bar'/>\n";

EXPECT_EQ(element->ToString(""), stream.str());
EXPECT_EQ(element->ToString("", true, false), stream.str());
EXPECT_EQ(element->ToString("", false, false), stream.str());

std::ostringstream stream2;
stream2 << "<foo test='foo' test2='bar'/>\n";

EXPECT_EQ(element->ToString("", true, true), stream2.str());
EXPECT_EQ(element->ToString("", false, true), stream2.str());
}

/////////////////////////////////////////////////
TEST(Element, DocLeftPane)
{
Expand Down
Loading

0 comments on commit cec38a3

Please sign in to comment.