Skip to content

Commit

Permalink
Merge bitcoin#25879: refactor: Make Join() util work with any contain…
Browse files Browse the repository at this point in the history
…er type

fa95315 Use new Join() helper for ListBlockFilterTypes() (MacroFake)
fa1c716 Make Join() util work with any container type (MacroFake)
faf8da3 Remove Join() helper only used in tests (MacroFake)

Pull request description:

  This allows to drop some code

ACKs for top commit:
  naumenkogs:
    ACK fa95315
  stickies-v:
    ACK [fa95315](bitcoin@fa95315)

Tree-SHA512: efd65b65722f46b221bd53140ff22bd8e45adc83617980233f28f695be3108a6ab01affd751d715134ffcb9762228ba8952e9467e590cff022c83e0f5404cb74
  • Loading branch information
MacroFake authored and vijaydasmp committed Feb 4, 2025
1 parent 5f37096 commit d58ebb1
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 40 deletions.
16 changes: 2 additions & 14 deletions src/blockfilter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <mutex>
#include <sstream>
#include <set>

#include <blockfilter.h>
Expand All @@ -13,6 +12,7 @@
#include <script/script.h>
#include <streams.h>
#include <util/golombrice.h>
#include <util/string.h>

/// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK;
Expand Down Expand Up @@ -179,19 +179,7 @@ const std::set<BlockFilterType>& AllBlockFilterTypes()

const std::string& ListBlockFilterTypes()
{
static std::string type_list;

static std::once_flag flag;
std::call_once(flag, []() {
std::stringstream ret;
bool first = true;
for (auto entry : g_filter_types) {
if (!first) ret << ", ";
ret << entry.second;
first = false;
}
type_list = ret.str();
});
static std::string type_list{Join(g_filter_types, ", ", [](const auto& entry) { return entry.second; })};

return type_list;
}
Expand Down
12 changes: 6 additions & 6 deletions src/test/util_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,15 +248,15 @@ BOOST_AUTO_TEST_CASE(span_write_bytes)
BOOST_AUTO_TEST_CASE(util_Join)
{
// Normal version
BOOST_CHECK_EQUAL(Join({}, ", "), "");
BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo");
BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar");
BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");

// Version with unary operator
const auto op_upper = [](const std::string& s) { return ToUpper(s); };
BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), "");
BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO");
BOOST_CHECK_EQUAL(Join<std::string>({"foo", "bar"}, ", ", op_upper), "FOO, BAR");
BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo"}, ", ", op_upper), "FOO");
BOOST_CHECK_EQUAL(Join(std::list<std::string>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
}

BOOST_AUTO_TEST_CASE(util_ReplaceAll)
Expand Down
36 changes: 16 additions & 20 deletions src/util/string.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,34 +58,30 @@ void ReplaceAll(std::string& in_out, const std::string& search, const std::strin
}

/**
* Join a list of items
* Join all container items. Typically used to concatenate strings but accepts
* containers with elements of any type.
*
* @param list The list to join
* @param separator The separator
* @param unary_op Apply this operator to each item in the list
* @param container The items to join
* @param separator The separator
* @param unary_op Apply this operator to each item
*/
template <typename T, typename BaseType, typename UnaryOp>
auto Join(const std::vector<T>& list, const BaseType& separator, UnaryOp unary_op)
-> decltype(unary_op(list.at(0)))
template <typename C, typename S, typename UnaryOp>
auto Join(const C& container, const S& separator, UnaryOp unary_op)
{
decltype(unary_op(list.at(0))) ret;
for (size_t i = 0; i < list.size(); ++i) {
if (i > 0) ret += separator;
ret += unary_op(list.at(i));
decltype(unary_op(*container.begin())) ret;
bool first{true};
for (const auto& item : container) {
if (!first) ret += separator;
ret += unary_op(item);
first = false;
}
return ret;
}

template <typename T, typename T2>
T Join(const std::vector<T>& list, const T2& separator)
template <typename C, typename S>
auto Join(const C& container, const S& separator)
{
return Join(list, separator, [](const T& i) { return i; });
}

// Explicit overload needed for c_str arguments, which would otherwise cause a substitution failure in the template above.
inline std::string Join(const std::vector<std::string>& list, std::string_view separator)
{
return Join<std::string>(list, separator);
return Join(container, separator, [](const auto& i) { return i; });
}

/**
Expand Down

0 comments on commit d58ebb1

Please sign in to comment.