Skip to content

Commit

Permalink
Add split/join for separating the link name from it's fully qualified…
Browse files Browse the repository at this point in the history
… name (#457)

* Add SlitName and JoinName
* Check if local name is empty
* Add tests and robustify logic

Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Stephen Brawner <brawner@gmail.com>
Signed-off-by: Steve Peters <scpeters@openrobotics.org>

Co-authored-by: Addisu Z. Taddese <addisu@openrobotics.org>
Co-authored-by: Steve Peters <scpeters@openrobotics.org>
  • Loading branch information
3 people authored Jan 27, 2021
1 parent 54a69c5 commit b9fc657
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 0 deletions.
20 changes: 20 additions & 0 deletions include/sdf/Types.hh
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <cstdint>
#include <sstream>
#include <string>
#include <utility>
#include <vector>

#include <sdf/sdf_config.h>
Expand Down Expand Up @@ -60,6 +61,8 @@ namespace sdf
inline namespace SDF_VERSION_NAMESPACE {
//

const std::string kSdfScopeDelimiter = "::";

/// \brief Split a string using the delimiter in splitter.
/// \param[in] str The string to split.
/// \param[in] splitter The delimiter to use.
Expand Down Expand Up @@ -228,6 +231,23 @@ namespace sdf
/// \param[in] _in String to convert to lowercase
/// \return Lowercase equilvalent of _in.
std::string SDFORMAT_VISIBLE lowercase(const std::string &_in);

/// \brief Split a name into a two strings based on the '::' delimeter
/// \param[in] _absoluteName The fully qualified absolute name
/// \return A pair with the absolute name minus the leaf node name, and the
/// leaf name
SDFORMAT_VISIBLE
std::pair<std::string, std::string> SplitName(
const std::string &_absoluteName);

/// \brief Join two strings with the '::' delimiter.
/// This checks for edge cases and is safe to use with any valid names
/// \param[in] _scopeName the left-hand-side component
/// \param[in] _localName the right-hand-side component
/// \return A full string with the names joined by the '::' delimeter.
SDFORMAT_VISIBLE
std::string JoinName(
const std::string &_scopeName, const std::string &_localName);
}
}
#endif
55 changes: 55 additions & 0 deletions src/Types.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,60 @@ std::ostream &operator<<(std::ostream &_out, const sdf::Errors &_errs)
}
return _out;
}

// Split a given absolute name into the parent model name and the local name.
// If the give name is not scoped, this will return an empty string for the
// parent model name and the given name as the local name.
std::pair<std::string, std::string> SplitName(
const std::string &_absoluteName)
{
const auto pos = _absoluteName.rfind(kSdfScopeDelimiter);
if (pos != std::string::npos)
{
const std::string first = _absoluteName.substr(0, pos);
const std::string second =
_absoluteName.substr(pos + kSdfScopeDelimiter.size());
return {first, second};
}
return {"", _absoluteName};
}

static bool EndsWithDelimiter(const std::string &_s)
{
if (_s.size() < kSdfScopeDelimiter.size())
return false;

const size_t startPosition = _s.size() - kSdfScopeDelimiter.size();
return _s.compare(
startPosition, kSdfScopeDelimiter.size(), kSdfScopeDelimiter) == 0;
}

static bool StartsWithDelimiter(const std::string &_s)
{
if (_s.size() < kSdfScopeDelimiter.size())
return false;

return _s.compare(0, kSdfScopeDelimiter.size(), kSdfScopeDelimiter) == 0;
}

// Join a scope name prefix with a local name using the scope delimeter
std::string JoinName(
const std::string &_scopeName, const std::string &_localName)
{
if (_scopeName.empty())
return _localName;
if (_localName.empty())
return _scopeName;

const bool scopeNameEndsWithDelimiter = EndsWithDelimiter(_scopeName);
const bool localNameStartsWithDelimiter = StartsWithDelimiter(_localName);

if (scopeNameEndsWithDelimiter && localNameStartsWithDelimiter)
return _scopeName + _localName.substr(kSdfScopeDelimiter.size());
else if (scopeNameEndsWithDelimiter || localNameStartsWithDelimiter)
return _scopeName + _localName;
else
return _scopeName + kSdfScopeDelimiter + _localName;
}
}
}
79 changes: 79 additions & 0 deletions src/Types_TEST.cc
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,85 @@ TEST(Types, ErrorsOutputStream)
EXPECT_EQ(expected, output.str());
}

TEST(Types, SplitName)
{
{
const auto[basePath, tipName] = sdf::SplitName("a::b");
EXPECT_EQ(basePath, "a");
EXPECT_EQ(tipName, "b");
}
{
const auto[basePath, tipName] = sdf::SplitName("a::b::c");
EXPECT_EQ(basePath, "a::b");
EXPECT_EQ(tipName, "c");
}
{
const auto[basePath, tipName] = sdf::SplitName("b");
EXPECT_EQ(basePath, "");
EXPECT_EQ(tipName, "b");
}
{
const auto[basePath, tipName] = sdf::SplitName("a::b::");
EXPECT_EQ(basePath, "a::b");
EXPECT_EQ(tipName, "");
}
{
const auto[basePath, tipName] = sdf::SplitName("::b");
EXPECT_EQ(basePath, "");
EXPECT_EQ(tipName, "b");
}
{
const auto[basePath, tipName] = sdf::SplitName("");
EXPECT_EQ(basePath, "");
EXPECT_EQ(tipName, "");
}
{
const auto[basePath, tipName] = sdf::SplitName("a::b::c::d");
EXPECT_EQ(basePath, "a::b::c");
EXPECT_EQ(tipName, "d");
}
}

TEST(Types, JoinName)
{
{
const auto joinedName = sdf::JoinName("a", "b");
EXPECT_EQ(joinedName, "a::b");
}
{
const auto joinedName = sdf::JoinName("a::b", "c");
EXPECT_EQ(joinedName, "a::b::c");
}
{
const auto joinedName = sdf::JoinName("a", "b::c");
EXPECT_EQ(joinedName, "a::b::c");
}
{
const auto joinedName = sdf::JoinName("a::", "b");
EXPECT_EQ(joinedName, "a::b");
}
{
const auto joinedName = sdf::JoinName("a", "::b");
EXPECT_EQ(joinedName, "a::b");
}
{
const auto joinedName = sdf::JoinName("a::", "::b");
EXPECT_EQ(joinedName, "a::b");
}
{
const auto joinedName = sdf::JoinName("", "b");
EXPECT_EQ(joinedName, "b");
}
{
const auto joinedName = sdf::JoinName("a", "");
EXPECT_EQ(joinedName, "a");
}
{
const auto joinedName = sdf::JoinName("", "");
EXPECT_EQ(joinedName, "");
}
}

/////////////////////////////////////////////////
/// Main
int main(int argc, char **argv)
Expand Down

0 comments on commit b9fc657

Please sign in to comment.