diff --git a/include/ignition/common/StringUtils.hh b/include/ignition/common/StringUtils.hh index 9836e40ff..6075fc935 100644 --- a/include/ignition/common/StringUtils.hh +++ b/include/ignition/common/StringUtils.hh @@ -33,6 +33,30 @@ namespace ignition std::vector IGNITION_COMMON_VISIBLE Split( const std::string &_orig, char _delim); + /// \brief Join a sequence of strings with a delimiter + /// + /// Note that this will skip any empty entries in the vector, + /// and will also not prepend or append the delimiter to the + /// final output string + /// + /// \param[in] _orig The input sequence of strings + /// \param[in] _delim a string delimiter to join the string with + /// \returns a single string composed of strings joined with the delimiter + std::string IGNITION_COMMON_VISIBLE Join( + const std::vector &_orig, const std::string &_delim); + + /// \brief Join a sequence of strings with a delimiter + /// + /// Note that this will skip any empty entries in the vector, + /// and will also not prepend or append the delimiter to the + /// final output string + /// + /// \param[in] _orig The input sequence of strings + /// \param[in] _delim a character to join the string with + /// \returns a single string composed of strings joined with the delimiter + std::string IGNITION_COMMON_VISIBLE Join( + const std::vector &_orig, char _delim); + /// \brief return true if string starts with another string /// \param[in] _s1 the string to check /// \param[in] _s2 the possible prefix diff --git a/src/StringUtils.cc b/src/StringUtils.cc index f6c5434e0..e7ef22aa1 100644 --- a/src/StringUtils.cc +++ b/src/StringUtils.cc @@ -38,6 +38,29 @@ namespace ignition return pieces; } + ////////////////////////////////////////////////// + std::string Join(const std::vector &_orig, const std::string &_delim) + { + std::string ret = ""; + for (size_t ii = 0; ii < _orig.size(); ++ii) + { + if (_orig[ii].empty()) + continue; + + ret += _orig[ii]; + if (ii < _orig.size() - 1) + { + ret += _delim; + } + } + return ret; + } + ////////////////////////////////////////////////// + std::string Join(const std::vector &_orig, char _delim) + { + return Join(_orig, std::string(1, _delim)); + } + ////////////////////////////////////////////////// bool StartsWith(const std::string &_s1, const std::string &_s2) { diff --git a/src/StringUtils_TEST.cc b/src/StringUtils_TEST.cc index b8aedf993..5c7b31b48 100644 --- a/src/StringUtils_TEST.cc +++ b/src/StringUtils_TEST.cc @@ -70,6 +70,59 @@ TEST(StringUtils, SplitOneDelimiterAtEnd) EXPECT_EQ("", pieces[1]); } +///////////////////////////////////////////////// +TEST(Join, Simple) +{ + { + std::string delim = " "; + auto pieces = std::vector{"Hello", "World"}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("Hello World", joined); + } + + { + std::string delim = "x"; + auto pieces = std::vector{"Hello", "World"}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("HelloxWorld", joined); + } + + { + std::string delim = "x"; + auto pieces = std::vector{ + "foo", "bar", "baz", "bing"}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("fooxbarxbazxbing", joined); + } +} + +///////////////////////////////////////////////// +TEST(Join, EmptyDelim) +{ + std::string delim = ""; + auto pieces = std::vector{"Hello", "World"}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("HelloWorld", joined); +} + +///////////////////////////////////////////////// +TEST(Join, EmptyPart) +{ + std::string delim = " "; + auto pieces = std::vector{"Hello", "", "World"}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("Hello World", joined); +} + +///////////////////////////////////////////////// +TEST(Join, EmptyParts) +{ + std::string delim = "x"; + auto pieces = std::vector{}; + auto joined = common::Join(pieces, delim); + EXPECT_EQ("", joined); +} + ///////////////////////////////////////////////// TEST(StartsWith, NotInString) {