Skip to content

Add overload of join_string() that takes a function argument #3997

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 30 additions & 5 deletions src/util/string_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,26 +47,51 @@ std::string trim_from_last_delimiter(
/// \param b: Iterator pointing to first item to print
/// \param e: Iterator pointing past last item to print
/// \param delimiter: Object to print between each item in the iterator range
/// \param transform_func: Transform to apply to the value returned by the
/// iterator
/// \return A reference to the ostream that was passed in
template<typename Stream, typename It, typename Delimiter>
template <
typename Stream,
typename It,
typename Delimiter,
typename TransformFunc>
Stream &join_strings(
Stream &os,
Stream &&os,
const It b,
const It e,
const Delimiter &delimiter)
const Delimiter &delimiter,
TransformFunc &&transform_func)
{
if(b==e)
{
return os;
}
os << *b;
os << transform_func(*b);
for(auto it=std::next(b); it!=e; ++it)
{
os << delimiter << *it;
os << delimiter << transform_func(*it);
}
return os;
}

/// Prints items to an stream, separated by a constant delimiter
/// \tparam It: An iterator type
/// \tparam Delimiter: A delimiter type which supports printing to ostreams
/// \param os: An ostream to write to
/// \param b: Iterator pointing to first item to print
/// \param e: Iterator pointing past last item to print
/// \param delimiter: Object to print between each item in the iterator range
/// \return A reference to the ostream that was passed in
template <typename Stream, typename It, typename Delimiter>
Stream &
join_strings(Stream &&os, const It b, const It e, const Delimiter &delimiter)
{
using value_type = decltype(*b);
// Call auxiliary function with identity function
return join_strings(
os, b, e, delimiter, [](const value_type &x) { return x; });
}

/// Generic escaping of strings; this is not meant to be a particular
/// programming language.
std::string escape(const std::string &);
Expand Down
3 changes: 2 additions & 1 deletion unit/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ SRC += analyses/ai/ai.cpp \
util/simplify_expr.cpp \
util/small_map.cpp \
util/small_shared_two_way_ptr.cpp \
util/std_expr.cpp \
util/std_expr.cpp \
util/string_utils/join_string.cpp \
util/string_utils/split_string.cpp \
util/string_utils/strip_string.cpp \
util/symbol_table.cpp \
Expand Down
44 changes: 44 additions & 0 deletions unit/util/string_utils/join_string.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*******************************************************************\

Module: Unit tests of join_string

Author: Diffblue Ltd.

\*******************************************************************/

/// \file
/// join_string Unit Tests

#include <sstream>
#include <string>
#include <vector>

#include <testing-utils/use_catch.h>
#include <util/string_utils.h>

TEST_CASE(
"join_strings() should apply the function argument its passed to the "
"elements of the container",
"[core][utils][string_utils][join_strings]")
{
std::vector<int> vec{1, 2, 3};
auto result = join_strings(
std::ostringstream(),
vec.begin(),
vec.end(),
"-",
[](int x) { return std::to_string(x + 1); })
.str();
REQUIRE(result == "2-3-4");
}

TEST_CASE(
"join_strings() when passed no function argument should apply the default "
"identity function to the elements of the container",
"[core][utils][string_utils][join_strings]")
{
std::vector<int> vec{1, 2, 3};
auto result =
join_strings(std::ostringstream(), vec.begin(), vec.end(), ",").str();
REQUIRE(result == "1,2,3");
}