Merge bitcoin/bitcoin#25879: refactor: Make Join() util work with any container type

fa95315655 Use new Join() helper for ListBlockFilterTypes() (MacroFake)
fa1c716955 Make Join() util work with any container type (MacroFake)
faf8da3c8d Remove Join() helper only used in tests (MacroFake)

Pull request description:

  This allows to drop some code

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

Tree-SHA512: efd65b65722f46b221bd53140ff22bd8e45adc83617980233f28f695be3108a6ab01affd751d715134ffcb9762228ba8952e9467e590cff022c83e0f5404cb74
This commit is contained in:
MacroFake
2022-08-24 11:29:32 +02:00
3 changed files with 24 additions and 40 deletions

View File

@ -3,7 +3,6 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <mutex> #include <mutex>
#include <sstream>
#include <set> #include <set>
#include <blockfilter.h> #include <blockfilter.h>
@ -13,6 +12,7 @@
#include <script/script.h> #include <script/script.h>
#include <streams.h> #include <streams.h>
#include <util/golombrice.h> #include <util/golombrice.h>
#include <util/string.h>
/// SerType used to serialize parameters in GCS filter encoding. /// SerType used to serialize parameters in GCS filter encoding.
static constexpr int GCS_SER_TYPE = SER_NETWORK; static constexpr int GCS_SER_TYPE = SER_NETWORK;
@ -179,19 +179,7 @@ const std::set<BlockFilterType>& AllBlockFilterTypes()
const std::string& ListBlockFilterTypes() const std::string& ListBlockFilterTypes()
{ {
static std::string type_list; static std::string type_list{Join(g_filter_types, ", ", [](const auto& entry) { return entry.second; })};
static std::once_flag flag;
std::call_once(flag, []() {
std::stringstream ret;
bool first = true;
for (const auto& entry : g_filter_types) {
if (!first) ret << ", ";
ret << entry.second;
first = false;
}
type_list = ret.str();
});
return type_list; return type_list;
} }

View File

@ -238,15 +238,15 @@ BOOST_AUTO_TEST_CASE(span_write_bytes)
BOOST_AUTO_TEST_CASE(util_Join) BOOST_AUTO_TEST_CASE(util_Join)
{ {
// Normal version // Normal version
BOOST_CHECK_EQUAL(Join({}, ", "), ""); BOOST_CHECK_EQUAL(Join(std::vector<std::string>{}, ", "), "");
BOOST_CHECK_EQUAL(Join({"foo"}, ", "), "foo"); BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo"}, ", "), "foo");
BOOST_CHECK_EQUAL(Join({"foo", "bar"}, ", "), "foo, bar"); BOOST_CHECK_EQUAL(Join(std::vector<std::string>{"foo", "bar"}, ", "), "foo, bar");
// Version with unary operator // Version with unary operator
const auto op_upper = [](const std::string& s) { return ToUpper(s); }; const auto op_upper = [](const std::string& s) { return ToUpper(s); };
BOOST_CHECK_EQUAL(Join<std::string>({}, ", ", op_upper), ""); BOOST_CHECK_EQUAL(Join(std::list<std::string>{}, ", ", op_upper), "");
BOOST_CHECK_EQUAL(Join<std::string>({"foo"}, ", ", op_upper), "FOO"); BOOST_CHECK_EQUAL(Join(std::list<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>{"foo", "bar"}, ", ", op_upper), "FOO, BAR");
} }
BOOST_AUTO_TEST_CASE(util_ReplaceAll) BOOST_AUTO_TEST_CASE(util_ReplaceAll)

View File

@ -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 container The items to join
* @param separator The separator * @param separator The separator
* @param unary_op Apply this operator to each item in the list * @param unary_op Apply this operator to each item
*/ */
template <typename T, typename BaseType, typename UnaryOp> template <typename C, typename S, typename UnaryOp>
auto Join(const std::vector<T>& list, const BaseType& separator, UnaryOp unary_op) auto Join(const C& container, const S& separator, UnaryOp unary_op)
-> decltype(unary_op(list.at(0)))
{ {
decltype(unary_op(list.at(0))) ret; decltype(unary_op(*container.begin())) ret;
for (size_t i = 0; i < list.size(); ++i) { bool first{true};
if (i > 0) ret += separator; for (const auto& item : container) {
ret += unary_op(list.at(i)); if (!first) ret += separator;
ret += unary_op(item);
first = false;
} }
return ret; return ret;
} }
template <typename T, typename T2> template <typename C, typename S>
T Join(const std::vector<T>& list, const T2& separator) auto Join(const C& container, const S& separator)
{ {
return Join(list, separator, [](const T& i) { return i; }); return Join(container, separator, [](const auto& 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);
} }
/** /**