Skip to content

Commit 9ff78d9

Browse files
authored
Merge pull request #1680 from evoskuil/master
Add and test new part() collection function.
2 parents eeb4c78 + 2e30229 commit 9ff78d9

File tree

3 files changed

+123
-18
lines changed

3 files changed

+123
-18
lines changed

include/bitcoin/system/data/collection.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,11 @@ template <typename Left, typename Right>
111111
constexpr bool is_intersecting(const typename Left::const_iterator& begin,
112112
const typename Left::const_iterator& end, const Right& right) NOEXCEPT;
113113

114+
/// Move all elements from positions at or above found element position.
115+
template <typename Collection>
116+
bool part(Collection& from, Collection& to,
117+
const typename Collection::value_type& element) NOEXCEPT;
118+
114119
/// Reverse the order of collection elements.
115120
/// Use reverse_view for reverse iteration.
116121
template <typename Collection>

include/bitcoin/system/impl/data/collection.ipp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ constexpr binary_search(const Collection& list,
6969
return negative_one;
7070
}
7171

72-
// C++17: Parallel policy for std::transform.
7372
template <typename To, typename From>
7473
inline To projection(const From& source) NOEXCEPT
7574
{
@@ -85,7 +84,6 @@ inline To projection(const From& source) NOEXCEPT
8584
return out;
8685
}
8786

88-
// C++17: Parallel policy for std::equal.
8987
template <typename Left, typename Right>
9088
constexpr bool deep_equal(const Left& left, const Right& right) NOEXCEPT
9189
{
@@ -100,7 +98,6 @@ constexpr bool deep_equal(const Left& left, const Right& right) NOEXCEPT
10098
});
10199
}
102100

103-
// C++17: Parallel policy for std::any_of.
104101
template <typename Collection, typename Element>
105102
constexpr bool contains(const Collection& list,
106103
const Element& element) NOEXCEPT
@@ -109,7 +106,6 @@ constexpr bool contains(const Collection& list,
109106
std::end(list);
110107
}
111108

112-
// C++17: Parallel policy for std::find_if.
113109
template <typename Collection>
114110
typename Collection::difference_type
115111
constexpr find_pair_position(const Collection& list,
@@ -125,7 +121,6 @@ constexpr find_pair_position(const Collection& list,
125121
std::distance(std::begin(list), position);
126122
}
127123

128-
// C++17: Parallel policy for std::find.
129124
template <typename Collection>
130125
typename Collection::difference_type
131126
constexpr find_position(const Collection& list,
@@ -172,7 +167,6 @@ inline pop_front(Collection& stack) NOEXCEPT
172167
return element;
173168
}
174169

175-
// C++17: Parallel policy for std::sort, std::unique.
176170
template <typename Collection>
177171
constexpr bool is_distinct(Collection&& list) NOEXCEPT
178172
{
@@ -187,14 +181,12 @@ constexpr bool is_distinct(const Collection& list) NOEXCEPT
187181
return is_distinct(copy);
188182
}
189183

190-
// C++17: Parallel policy for std::is_sorted.
191184
template <typename Collection>
192185
constexpr bool is_sorted(const Collection& list) NOEXCEPT
193186
{
194187
return std::is_sorted(std::begin(list), std::end(list));
195188
}
196189

197-
// C++17: Parallel policy for std::sort, std::erase.
198190
template <typename Collection>
199191
constexpr void distinct(Collection& list) NOEXCEPT
200192
{
@@ -244,7 +236,6 @@ constexpr bool is_intersecting(const Left& left, const Right& right) NOEXCEPT
244236
return is_intersecting<Left>(std::begin(left), std::end(left), right);
245237
}
246238

247-
// C++17: Parallel policy for std::find_first_of.
248239
template <typename Left, typename Right>
249240
constexpr bool is_intersecting(const typename Left::const_iterator& begin,
250241
const typename Left::const_iterator& end, const Right& right) NOEXCEPT
@@ -253,7 +244,26 @@ constexpr bool is_intersecting(const typename Left::const_iterator& begin,
253244
std::end(right)) != end;
254245
}
255246

256-
// C++17: Parallel policy for std::reverse.
247+
template <typename Collection>
248+
bool part(Collection& from, Collection& to,
249+
const typename Collection::value_type& element) NOEXCEPT
250+
{
251+
using Type = typename Collection::value_type;
252+
const auto it = std::find_if(from.begin(), from.end(),
253+
[&](const Type& value) noexcept
254+
{
255+
return value == element;
256+
});
257+
258+
if (it == from.end())
259+
return false;
260+
261+
to.insert(to.end(), std::make_move_iterator(it),
262+
std::make_move_iterator(from.end()));
263+
from.erase(it, from.end());
264+
return true;
265+
}
266+
257267
template <typename Collection>
258268
inline Collection reverse(Collection&& list) NOEXCEPT
259269
{
@@ -267,7 +277,6 @@ inline Collection reverse_copy(const Collection& list) NOEXCEPT
267277
return reverse(Collection{ list });
268278
}
269279

270-
// C++17: Parallel policy for std::sort.
271280
template <typename Collection>
272281
constexpr void sort(Collection& list) NOEXCEPT
273282
{
@@ -287,7 +296,6 @@ inline Collection sort_copy(const Collection& list) NOEXCEPT
287296
return sort(Collection{ list });
288297
}
289298

290-
// C++17: Parallel policy for std::equal.
291299
template <typename Collection>
292300
constexpr bool starts_with(const typename Collection::const_iterator& begin,
293301
const typename Collection::const_iterator& end,

test/data/collection.cpp

Lines changed: 98 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ BOOST_AUTO_TEST_CASE(limits__binary_search_native__sorted_contained__expected)
8888
BOOST_AUTO_TEST_CASE(limits__binary_search_native__reverse_sorted_contained__unlucky)
8989
{
9090
const std::string unsorted = "zyxwvutscba";
91-
const auto value = 'x';
91+
constexpr auto value = 'x';
9292
BOOST_REQUIRE_EQUAL(binary_search(unsorted, value), -1);
9393
}
9494

@@ -173,7 +173,7 @@ BOOST_AUTO_TEST_CASE(collection__pop__empty__empty_default)
173173

174174
BOOST_AUTO_TEST_CASE(collection__pop__single__empty_expected)
175175
{
176-
const uint8_t expected = 42u;
176+
constexpr uint8_t expected = 42u;
177177
data_chunk stack{ expected };
178178
const auto value = pop(stack);
179179
BOOST_REQUIRE(stack.empty());
@@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE(collection__pop_front__empty__empty_default)
203203

204204
BOOST_AUTO_TEST_CASE(collection__pop_front__single__empty_expected)
205205
{
206-
const uint8_t expected = 42u;
206+
constexpr uint8_t expected = 42u;
207207
data_queue queue{ expected };
208208
const auto value = pop_front(queue);
209209
BOOST_REQUIRE(queue.empty());
@@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(collection__pop_front__single__empty_expected)
212212

213213
BOOST_AUTO_TEST_CASE(collection__pop_front__multiple__popped_expected)
214214
{
215-
const uint8_t expected_value = 42u;
215+
constexpr uint8_t expected_value = 42u;
216216
data_queue queue{ expected_value, 0, 1, 2, 3 };
217217
const data_queue expected_queue{ 0, 1, 2, 3 };
218218
const auto value = pop_front(queue);
@@ -435,6 +435,98 @@ BOOST_AUTO_TEST_CASE(collection__difference__subtrahend_subset__expected)
435435
BOOST_REQUIRE_EQUAL(difference(minuend, subtrahend), expected);
436436
}
437437

438+
// part
439+
440+
BOOST_AUTO_TEST_CASE(collection__part__vector__true)
441+
{
442+
std::vector<int> from = { 1, 2, 4, 7, 8, 3, 1, 5, 3 };
443+
std::vector<int> to{};
444+
BOOST_REQUIRE(part(from, to, 3));
445+
BOOST_REQUIRE_EQUAL(from, (std::vector<int>{1, 2, 4, 7, 8}));
446+
BOOST_REQUIRE_EQUAL(to, (std::vector<int>{3, 1, 5, 3}));
447+
}
448+
449+
BOOST_AUTO_TEST_CASE(collection__part__list__true)
450+
{
451+
std::list<int> from = { 1, 2, 4, 7, 8, 3, 1, 5, 3 };
452+
std::list<int> to{};
453+
BOOST_REQUIRE(part(from, to, 3));
454+
BOOST_REQUIRE(from == (std::list<int>{1, 2, 4, 7, 8}));
455+
BOOST_REQUIRE(to == (std::list<int>{3, 1, 5, 3}));
456+
}
457+
458+
BOOST_AUTO_TEST_CASE(collection__part__deque__true)
459+
{
460+
std::deque<int> from = { 1, 2, 4, 7, 8, 3, 1, 5, 3 };
461+
std::deque<int> to{};
462+
BOOST_REQUIRE(part(from, to, 3));
463+
BOOST_REQUIRE(from == (std::deque<int>{1, 2, 4, 7, 8}));
464+
BOOST_REQUIRE(to == (std::deque<int>{3, 1, 5, 3}));
465+
}
466+
467+
BOOST_AUTO_TEST_CASE(collection__part__vector_empty__false)
468+
{
469+
std::vector<int> from{};
470+
std::vector<int> to{};
471+
BOOST_REQUIRE(!part(from, to, 3));
472+
BOOST_REQUIRE_EQUAL(from, (std::vector<int>{}));
473+
BOOST_REQUIRE_EQUAL(to, (std::vector<int>{}));
474+
}
475+
476+
BOOST_AUTO_TEST_CASE(collection__part__vector_no_equal__false)
477+
{
478+
std::vector<int> from = { 1, 2, 4, 5 };
479+
std::vector<int> to{};
480+
BOOST_REQUIRE(!part(from, to, 3));
481+
BOOST_REQUIRE_EQUAL(from, (std::vector<int>{1, 2, 4, 5}));
482+
BOOST_REQUIRE_EQUAL(to, (std::vector<int>{}));
483+
}
484+
485+
BOOST_AUTO_TEST_CASE(collection__part__list_first_equal__true)
486+
{
487+
std::list<int> from = { 3, 6, 7, 8 };
488+
std::list<int> to{};
489+
BOOST_REQUIRE(part(from, to, 3));
490+
BOOST_REQUIRE(from == (std::list<int>{}));
491+
BOOST_REQUIRE(to == (std::list<int>{3, 6, 7, 8}));
492+
}
493+
494+
BOOST_AUTO_TEST_CASE(collection__part__vector_non_empty_to__true)
495+
{
496+
std::vector<int> from = { 1, 3, 4, 5 };
497+
std::vector<int> to = { 10, 11 };
498+
BOOST_REQUIRE(part(from, to, 3));
499+
BOOST_REQUIRE_EQUAL(from, (std::vector<int>{1}));
500+
BOOST_REQUIRE_EQUAL(to, (std::vector<int>{10, 11, 3, 4, 5}));
501+
}
502+
503+
BOOST_AUTO_TEST_CASE(collection__part__string_list__true)
504+
{
505+
string_list from = { "apple", "date", "banana", "cherry" };
506+
string_list to{};
507+
BOOST_REQUIRE(part(from, to, std::string("date")));
508+
BOOST_REQUIRE_EQUAL(from, (string_list{ "apple" }));
509+
BOOST_REQUIRE_EQUAL(to, (string_list{ "date", "banana", "cherry" }));
510+
}
511+
512+
BOOST_AUTO_TEST_CASE(collection__part__string_list_first_equal__true)
513+
{
514+
string_list from = { "apple", "banana", "cherry", "date" };
515+
string_list to{};
516+
BOOST_REQUIRE(part(from, to, std::string("apple")));
517+
BOOST_REQUIRE_EQUAL(from, (string_list{}));
518+
BOOST_REQUIRE_EQUAL(to, (string_list{ "apple", "banana", "cherry", "date" }));
519+
}
520+
521+
BOOST_AUTO_TEST_CASE(collection__part__string_list_last_equal__true)
522+
{
523+
string_list from = { "banana", "cherry", "date", "apple" };
524+
string_list to{};
525+
BOOST_REQUIRE(part(from, to, std::string("apple")));
526+
BOOST_REQUIRE_EQUAL(from, (string_list{ "banana", "cherry", "date" }));
527+
BOOST_REQUIRE_EQUAL(to, (string_list{ "apple" }));
528+
}
529+
438530
// reverse
439531

440532
BOOST_AUTO_TEST_CASE(collection__reverse_move__empty__empty)
@@ -444,7 +536,7 @@ BOOST_AUTO_TEST_CASE(collection__reverse_move__empty__empty)
444536

445537
BOOST_AUTO_TEST_CASE(collection__reverse_move__single__unchanged)
446538
{
447-
const uint8_t expected = 42;
539+
constexpr uint8_t expected = 42;
448540
BOOST_REQUIRE_EQUAL(reverse(data_chunk{ expected }).front(), expected);
449541
}
450542

@@ -472,7 +564,7 @@ BOOST_AUTO_TEST_CASE(collection__sort_move__empty__empty)
472564

473565
BOOST_AUTO_TEST_CASE(collection__sort_move__single__unchanged)
474566
{
475-
const uint8_t expected = 42;
567+
constexpr uint8_t expected = 42;
476568
BOOST_REQUIRE_EQUAL(sort(data_chunk{ expected }).front(), expected);
477569
}
478570

0 commit comments

Comments
 (0)