Skip to content

Commit

Permalink
allow clients to specify their own toType/toString routines
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Smith committed Jan 5, 2021
1 parent 6670272 commit df8b746
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 16 deletions.
96 changes: 81 additions & 15 deletions modules/c++/xml.lite/include/xml/lite/Attributes.h
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,9 @@ class Attributes
* \param result The value after calling str::toType(), if found
* \return If an attribute with the key is found or not
*/
template <typename T, typename K>
inline bool getValue_(const Attributes& attributes, const K& key, T& result)
template <typename T, typename K, typename ToType>
inline bool getValue_(const Attributes& attributes, const K& key, T& result,
ToType toType)
{
std::string value;
if (!attributes.getValue(key, value))
Expand All @@ -395,25 +396,39 @@ inline bool getValue_(const Attributes& attributes, const K& key, T& result)
}
try
{
result = str::toType<T>(value);
result = toType(value);
}
catch (const except::BadCastException&)
{
return false;
}
return true;
}
namespace details
{
template <typename T>
inline T toType(const std::string& value)
{
return str::toType<T>(value);
}
}

/*!
* Look up an attribute's value by index.
* \param i The index for the attribute we want
* \param result The value after calling str::toType(), if found
* \return If the index is out of range or not
*/
template <typename T, typename ToType>
inline bool getValue(const Attributes& attributes, int i, T& result,
ToType toType)
{
return getValue_(attributes, i, result, toType);
}
template<typename T>
inline bool getValue(const Attributes& attributes, int i, T& result)
{
return getValue_(attributes, i, result);
return getValue(attributes, i, result, details::toType<T>);
}

/*!
Expand All @@ -422,10 +437,16 @@ inline bool getValue(const Attributes& attributes, int i, T& result)
* \param result The value after calling str::toType(), if found
* \return If the qname is not found or not
*/
template <typename T, typename ToType>
inline bool getValue(const Attributes& attributes, const std::string& qname, T& result,
ToType toType)
{
return getValue_(attributes, qname, result, toType);
}
template <typename T>
inline bool getValue(const Attributes& attributes, const std::string& qname, T& result)
{
return getValue_(attributes, qname, result);
return getValue(attributes, qname, result, details::toType<T>);
}

/*!
Expand All @@ -435,15 +456,27 @@ inline bool getValue(const Attributes& attributes, const std::string& qname, T&
* \param result The value after calling str::toType(), if found
* \return If the uri/localName is not found or not
*/
template <typename T, typename ToType>
inline bool getValue(const Attributes& attributes, const std::tuple<std::string, std::string>& name, T& result,
ToType toType)
{
return getValue_(attributes, name, result, toType);
}
template <typename T>
inline bool getValue(const Attributes& attributes, const std::tuple<std::string, std::string>& name, T& result)
{
return getValue_(attributes, name, result);
return getValue(attributes, name, result, details::toType<T>);
}
template <typename T, typename ToType>
inline bool getValue(const Attributes& attributes, const std::string & uri, const std::string & localName, T& result,
ToType toType)
{
return getValue(attributes, std::make_tuple(uri, localName), result, toType);
}
template <typename T>
inline bool getValue(const Attributes& attributes, const std::string & uri, const std::string & localName, T& result)
{
return getValue(attributes, std::make_tuple(uri, localName), result);
return getValue(attributes, uri, localName, result, details::toType<T>);
}

/*!
Expand All @@ -452,8 +485,9 @@ inline bool getValue(const Attributes& attributes, const std::string & uri, cons
* \param value The value to be converted by calling str::toString
* \return If an attribute with the key is found or not
*/
template <typename T, typename K>
inline bool setValue_(Attributes& attributes, const K& key, const T& value)
template <typename T, typename K, typename ToString>
inline bool setValue_(Attributes& attributes, const K& key, const T& value,
ToString toString)
{
int index = attributes.getIndex(key);
if (index < 0)
Expand All @@ -462,19 +496,33 @@ inline bool setValue_(Attributes& attributes, const K& key, const T& value)
}

auto& node = attributes.getNode(index);
node.setValue(str::toString(value));
node.setValue(toString(value));
return true;
}
namespace details
{
template <typename T>
inline std::string toString(const T& value)
{
return str::toString(value);
}
}

/*!
* Look up an attribute's value by index.
* \param i The index for the attribute we want
* \param result The value after calling str::toType(), if found
* \return If the index is out of range or not
*/
template<typename T>
template <typename T, typename ToString>
inline bool setValue(Attributes& attributes, int i, const T& value, ToString toString)
{
return setValue_(attributes, i, value, toString);
}
template <typename T>
inline bool setValue(Attributes& attributes, int i, const T& value)
{
return setValue_(attributes, i, value);
return setValue_(attributes, i, value, details::toString<T>);
}

/*!
Expand All @@ -483,10 +531,16 @@ inline bool setValue(Attributes& attributes, int i, const T& value)
* \param result The value after calling str::toType(), if found
* \return If the qname is not found or not
*/
template <typename T, typename ToString>
inline bool setValue(Attributes& attributes, const std::string& qname, const T& value,
ToString toString)
{
return setValue_(attributes, qname, value, toString);
}
template <typename T>
inline bool setValue(Attributes& attributes, const std::string& qname, const T& value)
{
return setValue_(attributes, qname, value);
return setValue_(attributes, qname, value, details::toString<T>);
}

/*!
Expand All @@ -496,15 +550,27 @@ inline bool setValue(Attributes& attributes, const std::string& qname, const T&
* \param result The value after calling str::toType(), if found
* \return If the uri/localName is not found or not
*/
template <typename T, typename ToString>
inline bool setValue(Attributes& attributes, const std::tuple<std::string, std::string>& name, const T& value,
ToString toString)
{
return setValue_(attributes, name, value, toString);
}
template <typename T>
inline bool setValue(Attributes& attributes, const std::tuple<std::string, std::string>& name, const T& value)
{
return setValue_(attributes, name, value);
return setValue_(attributes, name, value, details::toString<T>);
}
template <typename T, typename ToString>
inline bool setValue(Attributes& attributes, const std::string & uri, const std::string & localName, const T& value,
ToString toString)
{
return setValue(attributes, std::make_tuple(uri, localName), value, toString);
}
template <typename T>
inline bool setValue(Attributes& attributes, const std::string & uri, const std::string & localName, const T& value)
{
return setValue(attributes, std::make_tuple(uri, localName), value);
return setValue(attributes, uri, localName, value, details::toString<T>);
}

}
Expand Down
28 changes: 27 additions & 1 deletion modules/c++/xml.lite/unittests/test_xmlattribute.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ static const std::string strXml = R"(
<root>
<doc name="doc">
<a a="a">TEXT</a>
<values int="314" double="3.14" string="abc" empty=""/>
<values int="314" double="3.14" string="abc" bool="yes" empty=""/>
</doc>
</root>)";

Expand Down Expand Up @@ -127,7 +127,18 @@ TEST_CASE(test_getAttributeValue)
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ("abc", value);
}
{
auto toType = [](const std::string& value) { return value == "yes"; };
bool value;
auto result = getValue(attributes, "bool", value, toType);
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ(true, value);

std::string strValue;
result = getValue(attributes, "bool", strValue);
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ("yes", strValue);
}
{
std::string value;
const auto result = getValue(attributes, "not_found", value);
Expand Down Expand Up @@ -230,6 +241,21 @@ TEST_CASE(test_setAttributeValue)
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ("xyz", value);
}
{
auto toString = [](const bool& value) { return value ? "yes" : "no"; };
auto result = setValue(attributes, "bool", true, toString);
TEST_ASSERT_TRUE(result);

auto toType = [](const std::string& value) { return value == "yes"; };
bool value;
result = getValue(attributes, "bool", value, toType);
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ(true, value);
std::string strValue;
result = getValue(attributes, "bool", strValue);
TEST_ASSERT_TRUE(result);
TEST_ASSERT_EQ("yes", strValue);
}

{
const auto result = setValue(attributes, "not_found", 999);
Expand Down

0 comments on commit df8b746

Please sign in to comment.