diff options
author | Maxim Pimenov <m@maps.me> | 2018-09-12 14:22:15 +0300 |
---|---|---|
committer | Vlad Mihaylenko <vxmihaylenko@gmail.com> | 2018-09-14 15:14:36 +0300 |
commit | c7e09657fa5cc6fd5600252b41e9774b83c0a45d (patch) | |
tree | 0c1636a81a6afba6ae87b3040096bb86bf862c81 /base | |
parent | 4a44e1d009cf30dbb9fe759260aeef221a7be561 (diff) |
[base] Unified stl_add and stl_helpers.
Diffstat (limited to 'base')
-rw-r--r-- | base/CMakeLists.txt | 1 | ||||
-rw-r--r-- | base/base_tests/CMakeLists.txt | 3 | ||||
-rw-r--r-- | base/base_tests/cache_test.cpp | 5 | ||||
-rw-r--r-- | base/base_tests/regexp_test.cpp | 14 | ||||
-rw-r--r-- | base/base_tests/stl_helpers_test.cpp | 152 | ||||
-rw-r--r-- | base/base_tests/stl_helpers_tests.cpp (renamed from base/base_tests/stl_add_test.cpp) | 161 | ||||
-rw-r--r-- | base/levenshtein_dfa.cpp | 4 | ||||
-rw-r--r-- | base/stl_add.hpp | 246 | ||||
-rw-r--r-- | base/stl_helpers.hpp | 245 | ||||
-rw-r--r-- | base/string_utils.hpp | 4 |
10 files changed, 396 insertions, 439 deletions
diff --git a/base/CMakeLists.txt b/base/CMakeLists.txt index 0c97898372..1365ea8f88 100644 --- a/base/CMakeLists.txt +++ b/base/CMakeLists.txt @@ -63,7 +63,6 @@ set( src_point.cpp src_point.hpp stats.hpp - stl_add.hpp stl_helpers.hpp stl_iterator.hpp string_format.cpp diff --git a/base/base_tests/CMakeLists.txt b/base/base_tests/CMakeLists.txt index 56257580aa..500b9cae61 100644 --- a/base/base_tests/CMakeLists.txt +++ b/base/base_tests/CMakeLists.txt @@ -30,8 +30,7 @@ set( rolling_hash_test.cpp scope_guard_test.cpp small_set_test.cpp - stl_add_test.cpp - stl_helpers_test.cpp + stl_helpers_tests.cpp string_format_test.cpp string_utils_test.cpp suffix_array_tests.cpp diff --git a/base/base_tests/cache_test.cpp b/base/base_tests/cache_test.cpp index 8e9ae4dc52..5c1322b33d 100644 --- a/base/base_tests/cache_test.cpp +++ b/base/base_tests/cache_test.cpp @@ -1,7 +1,8 @@ #include "testing/testing.hpp" + #include "base/cache.hpp" #include "base/macros.hpp" -#include "base/stl_add.hpp" +#include "base/stl_helpers.hpp" #include <functional> @@ -86,7 +87,7 @@ UNIT_TEST(CacheSmoke_0) cache.Find(0, found); TEST(!found, ()); std::vector<char> v; - cache.ForEachValue(MakeBackInsertFunctor(v)); + cache.ForEachValue(base::MakeBackInsertFunctor(v)); TEST_EQUAL(v, std::vector<char>(8, 0), ()); } diff --git a/base/base_tests/regexp_test.cpp b/base/base_tests/regexp_test.cpp index 06e0f2921f..6c4fa912a0 100644 --- a/base/base_tests/regexp_test.cpp +++ b/base/base_tests/regexp_test.cpp @@ -1,6 +1,6 @@ #include "testing/testing.hpp" -#include "base/stl_add.hpp" +#include "base/stl_helpers.hpp" #include "base/string_utils.hpp" #include <regex> @@ -29,7 +29,7 @@ UNIT_TEST(RegExp_ForEachMatched) { std::string const s = "6.66, 9.99"; std::vector<std::string> v; - strings::ForEachMatched(s, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 1, ()); TEST_EQUAL(v[0], s, ()); } @@ -38,7 +38,7 @@ UNIT_TEST(RegExp_ForEachMatched) std::string const s1 = "6.66, 9.99"; std::string const s2 = "-5.55, -7.77"; std::vector<std::string> v; - strings::ForEachMatched(s1 + " 180 , bfuewib 365@" + s2, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s1 + " 180 , bfuewib 365@" + s2, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 2, ()); TEST_EQUAL(v[0], s1, ()); TEST_EQUAL(v[1], s2, ()); @@ -47,7 +47,7 @@ UNIT_TEST(RegExp_ForEachMatched) { std::string const s = "X6.66, 9.99"; std::vector<std::string> v; - strings::ForEachMatched(s, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 1, ()); TEST_EQUAL(v[0], std::string(s.begin() + 1, s.end()), ()); } @@ -55,7 +55,7 @@ UNIT_TEST(RegExp_ForEachMatched) { std::string const s = "6.66, 9.99X"; std::vector<std::string> v; - strings::ForEachMatched(s, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 1, ()); TEST_EQUAL(v[0], std::string(s.begin(), s.end() - 1), ()); } @@ -63,14 +63,14 @@ UNIT_TEST(RegExp_ForEachMatched) { std::string const s = "6.66X, 9.99"; std::vector<std::string> v; - strings::ForEachMatched(s, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 0, ()); } { std::string const s = "6.66, X9.99"; std::vector<std::string> v; - strings::ForEachMatched(s, exp, MakeBackInsertFunctor(v)); + strings::ForEachMatched(s, exp, base::MakeBackInsertFunctor(v)); TEST_EQUAL(v.size(), 0, ()); } } diff --git a/base/base_tests/stl_helpers_test.cpp b/base/base_tests/stl_helpers_test.cpp deleted file mode 100644 index 12ebe85699..0000000000 --- a/base/base_tests/stl_helpers_test.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "testing/testing.hpp" - -#include "base/stl_helpers.hpp" - -#include <algorithm> -#include <deque> -#include <utility> -#include <vector> - -namespace -{ -class Int -{ -public: - explicit Int(int v) : m_v(v) {} - - inline int Get() const { return m_v; } - -private: - int m_v; -}; - -template <template <typename...> class Cont> -void TestSortUnique() -{ - { - Cont<int> actual = {1, 2, 1, 4, 3, 5, 2, 7, 1}; - my::SortUnique(actual); - Cont<int> const expected = {1, 2, 3, 4, 5, 7}; - TEST_EQUAL(actual, expected, ()); - } - { - using Value = int; - using Pair = std::pair<Value, int>; - Cont<Pair> d = - {{1, 22}, {2, 33}, {1, 23}, {4, 54}, {3, 34}, {5, 23}, {2, 23}, {7, 32}, {1, 12}}; - - my::SortUnique(d, my::LessBy(&Pair::first), my::EqualsBy(&Pair::first)); - - Cont<Value> const expected = {1, 2, 3, 4, 5, 7}; - TEST_EQUAL(d.size(), expected.size(), ()); - for (size_t i = 0; i < d.size(); ++i) - TEST_EQUAL(d[i].first, expected[i], (i)); - } - { - using Value = double; - using Pair = std::pair<Value, int>; - Cont<Pair> d = - {{0.5, 11}, {1000.99, 234}, {0.5, 23}, {1234.56789, 54}, {1000.99, 34}}; - - my::SortUnique(d, my::LessBy(&Pair::first), my::EqualsBy(&Pair::first)); - - Cont<Value> const expected = {0.5, 1000.99, 1234.56789}; - TEST_EQUAL(d.size(), expected.size(), ()); - for (size_t i = 0; i < d.size(); ++i) - TEST_EQUAL(d[i].first, expected[i], (i)); - } -} - -template <template <typename...> class Cont> -void TestEqualsBy() -{ - { - using Value = std::pair<int, int>; - Cont<Value> actual = {{1, 2}, {1, 3}, {2, 100}, {3, 7}, {3, 8}, {2, 500}}; - actual.erase(std::unique(actual.begin(), actual.end(), my::EqualsBy(&Value::first)), actual.end()); - - Cont<int> const expected = {{1, 2, 3, 2}}; - TEST_EQUAL(expected.size(), actual.size(), ()); - for (size_t i = 0; i < actual.size(); ++i) - TEST_EQUAL(expected[i], actual[i].first, ()); - } - - { - Cont<Int> actual; - for (auto const v : {0, 0, 1, 2, 2, 0}) - actual.emplace_back(v); - actual.erase(std::unique(actual.begin(), actual.end(), my::EqualsBy(&Int::Get)), actual.end()); - - Cont<int> const expected = {{0, 1, 2, 0}}; - TEST_EQUAL(expected.size(), actual.size(), ()); - for (size_t i = 0; i < actual.size(); ++i) - TEST_EQUAL(expected[i], actual[i].Get(), ()); - } -} - -UNIT_TEST(LessBy) -{ - { - using Value = std::pair<int, int>; - - std::vector<Value> v = {{2, 2}, {0, 4}, {3, 1}, {4, 0}, {1, 3}}; - std::sort(v.begin(), v.end(), my::LessBy(&Value::first)); - for (size_t i = 0; i < v.size(); ++i) - TEST_EQUAL(i, static_cast<size_t>(v[i].first), ()); - - std::vector<Value const *> pv; - for (auto const & p : v) - pv.push_back(&p); - - std::sort(pv.begin(), pv.end(), my::LessBy(&Value::second)); - for (size_t i = 0; i < pv.size(); ++i) - TEST_EQUAL(i, static_cast<size_t>(pv[i]->second), ()); - } - - { - std::vector<Int> v; - for (int i = 9; i >= 0; --i) - v.emplace_back(i); - - std::sort(v.begin(), v.end(), my::LessBy(&Int::Get)); - for (size_t i = 0; i < v.size(); ++i) - TEST_EQUAL(v[i].Get(), static_cast<int>(i), ()); - } -} - -UNIT_TEST(EqualsBy_VectorTest) -{ - TestEqualsBy<std::vector>(); - TestEqualsBy<std::deque>(); -} - -UNIT_TEST(SortUnique_VectorTest) -{ - TestSortUnique<std::vector>(); - TestSortUnique<std::deque>(); -} - -UNIT_TEST(IgnoreFirstArgument) -{ - { - int s = 0; - auto f1 = [&](int a, int b) { s += a + b; }; - auto f2 = [&](int a, int b) { s -= a + b; }; - auto f3 = my::MakeIgnoreFirstArgument(f2); - - f1(2, 3); - TEST_EQUAL(s, 5, ()); - f3(1, 2, 3); - TEST_EQUAL(s, 0, ()); - } - - { - auto f1 = [](int a, int b) -> int { return a + b; }; - auto f2 = my::MakeIgnoreFirstArgument(f1); - - auto const x = f1(2, 3); - auto const y = f2("ignored", 2, 3); - TEST_EQUAL(x, y, ()); - } -} -} // namespace diff --git a/base/base_tests/stl_add_test.cpp b/base/base_tests/stl_helpers_tests.cpp index 82ff469580..cc76540a42 100644 --- a/base/base_tests/stl_add_test.cpp +++ b/base/base_tests/stl_helpers_tests.cpp @@ -1,22 +1,156 @@ #include "testing/testing.hpp" #include "base/macros.hpp" +#include "base/stl_helpers.hpp" -#include "base/stl_add.hpp" - +#include <algorithm> #include <deque> +#include <utility> +#include <vector> + +using namespace base; + +namespace +{ +class Int +{ +public: + explicit Int(int v) : m_v(v) {} + + inline int Get() const { return m_v; } + +private: + int m_v; +}; + +template <template <typename...> class Cont> +void TestSortUnique() +{ + { + Cont<int> actual = {1, 2, 1, 4, 3, 5, 2, 7, 1}; + SortUnique(actual); + Cont<int> const expected = {1, 2, 3, 4, 5, 7}; + TEST_EQUAL(actual, expected, ()); + } + { + using Value = int; + using Pair = std::pair<Value, int>; + Cont<Pair> d = + {{1, 22}, {2, 33}, {1, 23}, {4, 54}, {3, 34}, {5, 23}, {2, 23}, {7, 32}, {1, 12}}; + + SortUnique(d, LessBy(&Pair::first), EqualsBy(&Pair::first)); + Cont<Value> const expected = {1, 2, 3, 4, 5, 7}; + TEST_EQUAL(d.size(), expected.size(), ()); + for (size_t i = 0; i < d.size(); ++i) + TEST_EQUAL(d[i].first, expected[i], (i)); + } + { + using Value = double; + using Pair = std::pair<Value, int>; + Cont<Pair> d = + {{0.5, 11}, {1000.99, 234}, {0.5, 23}, {1234.56789, 54}, {1000.99, 34}}; -UNIT_TEST(STLAdd_IsSorted) + SortUnique(d, LessBy(&Pair::first), EqualsBy(&Pair::first)); + + Cont<Value> const expected = {0.5, 1000.99, 1234.56789}; + TEST_EQUAL(d.size(), expected.size(), ()); + for (size_t i = 0; i < d.size(); ++i) + TEST_EQUAL(d[i].first, expected[i], (i)); + } +} + +template <template <typename...> class Cont> +void TestEqualsBy() { - TEST(IsSorted(static_cast<int*>(0), static_cast<int*>(0)), ()); - int v1[] = { 1, 3, 5 }; - int const v2[] = { 1, 3, 2 }; - TEST(!IsSorted(&v2[0], &v2[0] + ARRAY_SIZE(v2)), ()); - TEST(IsSorted(&v1[0], &v1[0] + ARRAY_SIZE(v1)), ()); - TEST(IsSorted(&v1[0], &v1[0] + 0), ()); - TEST(IsSorted(&v1[0], &v1[0] + 1), ()); - TEST(IsSorted(&v1[0], &v1[0] + 2), ()); + { + using Value = std::pair<int, int>; + Cont<Value> actual = {{1, 2}, {1, 3}, {2, 100}, {3, 7}, {3, 8}, {2, 500}}; + actual.erase(std::unique(actual.begin(), actual.end(), EqualsBy(&Value::first)), actual.end()); + + Cont<int> const expected = {{1, 2, 3, 2}}; + TEST_EQUAL(expected.size(), actual.size(), ()); + for (size_t i = 0; i < actual.size(); ++i) + TEST_EQUAL(expected[i], actual[i].first, ()); + } + + { + Cont<Int> actual; + for (auto const v : {0, 0, 1, 2, 2, 0}) + actual.emplace_back(v); + actual.erase(std::unique(actual.begin(), actual.end(), EqualsBy(&Int::Get)), actual.end()); + + Cont<int> const expected = {{0, 1, 2, 0}}; + TEST_EQUAL(expected.size(), actual.size(), ()); + for (size_t i = 0; i < actual.size(); ++i) + TEST_EQUAL(expected[i], actual[i].Get(), ()); + } +} + +UNIT_TEST(LessBy) +{ + { + using Value = std::pair<int, int>; + + std::vector<Value> v = {{2, 2}, {0, 4}, {3, 1}, {4, 0}, {1, 3}}; + std::sort(v.begin(), v.end(), LessBy(&Value::first)); + for (size_t i = 0; i < v.size(); ++i) + TEST_EQUAL(i, static_cast<size_t>(v[i].first), ()); + + std::vector<Value const *> pv; + for (auto const & p : v) + pv.push_back(&p); + + std::sort(pv.begin(), pv.end(), LessBy(&Value::second)); + for (size_t i = 0; i < pv.size(); ++i) + TEST_EQUAL(i, static_cast<size_t>(pv[i]->second), ()); + } + + { + std::vector<Int> v; + for (int i = 9; i >= 0; --i) + v.emplace_back(i); + + std::sort(v.begin(), v.end(), LessBy(&Int::Get)); + for (size_t i = 0; i < v.size(); ++i) + TEST_EQUAL(v[i].Get(), static_cast<int>(i), ()); + } +} + +UNIT_TEST(EqualsBy_VectorTest) +{ + TestEqualsBy<std::vector>(); + TestEqualsBy<std::deque>(); +} + +UNIT_TEST(SortUnique_VectorTest) +{ + TestSortUnique<std::vector>(); + TestSortUnique<std::deque>(); +} + +UNIT_TEST(IgnoreFirstArgument) +{ + { + int s = 0; + auto f1 = [&](int a, int b) { s += a + b; }; + auto f2 = [&](int a, int b) { s -= a + b; }; + auto f3 = MakeIgnoreFirstArgument(f2); + + f1(2, 3); + TEST_EQUAL(s, 5, ()); + f3(1, 2, 3); + TEST_EQUAL(s, 0, ()); + } + + { + auto f1 = [](int a, int b) -> int { return a + b; }; + auto f2 = MakeIgnoreFirstArgument(f1); + + auto const x = f1(2, 3); + auto const y = f2("ignored", 2, 3); + TEST_EQUAL(x, y, ()); + } } namespace @@ -33,7 +167,7 @@ namespace } } -UNIT_TEST(STLAdd_RemoveIfKeepValid) +UNIT_TEST(RemoveIfKeepValid) { { std::vector<int> v; @@ -103,7 +237,7 @@ namespace } } -UNIT_TEST(STLAdd_AccumulateIntervals) +UNIT_TEST(AccumulateIntervals) { typedef std::pair<int, int> T; size_t idTest = 0; @@ -192,3 +326,4 @@ UNIT_TEST(STLAdd_AccumulateIntervals) CheckAccumulateIntervals(idTest, arr1, arr2, res); } } +} // namespace diff --git a/base/levenshtein_dfa.cpp b/base/levenshtein_dfa.cpp index b6bae3928b..9d1a5cf7b3 100644 --- a/base/levenshtein_dfa.cpp +++ b/base/levenshtein_dfa.cpp @@ -189,7 +189,7 @@ void LevenshteinDFA::State::Normalize() } m_positions.erase(m_positions.begin() + j, m_positions.end()); - my::SortUnique(m_positions); + base::SortUnique(m_positions); } // LevenshteinDFA ---------------------------------------------------------------------------------- @@ -211,7 +211,7 @@ LevenshteinDFA::LevenshteinDFA(UniString const & s, size_t prefixSize, m_alphabet.insert(m_alphabet.end(), misprints.begin(), misprints.end()); } } - my::SortUnique(m_alphabet); + base::SortUnique(m_alphabet); UniChar missed = 0; for (size_t i = 0; i < m_alphabet.size() && missed >= m_alphabet[i]; ++i) diff --git a/base/stl_add.hpp b/base/stl_add.hpp deleted file mode 100644 index 2eb4909014..0000000000 --- a/base/stl_add.hpp +++ /dev/null @@ -1,246 +0,0 @@ -#pragma once - -#include <algorithm> -#include <functional> -#include <initializer_list> -#include <iterator> -#include <memory> - -namespace my -{ -using StringIL = std::initializer_list<char const *>; -} // namespace my - -template <class ContainerT> class BackInsertFunctor -{ - ContainerT & m_Container; -public: - explicit BackInsertFunctor(ContainerT & container) : m_Container(container) - { - } - void operator() (typename ContainerT::value_type const & t) const - { - m_Container.push_back(t); - } -}; - -template <class ContainerT> -BackInsertFunctor<ContainerT> MakeBackInsertFunctor(ContainerT & container) -{ - return BackInsertFunctor<ContainerT>(container); -} - -template <class ContainerT> class InsertFunctor -{ - ContainerT & m_Container; -public: - explicit InsertFunctor(ContainerT & container) : m_Container(container) - { - } - void operator() (typename ContainerT::value_type const & t) const - { - m_Container.insert(end(m_Container), t); - } -}; - -template <class ContainerT> -InsertFunctor<ContainerT> MakeInsertFunctor(ContainerT & container) -{ - return InsertFunctor<ContainerT>(container); -} - -template <class IterT, class CompareT> inline bool IsSorted(IterT beg, IterT end, CompareT comp) -{ - if (beg == end) - return true; - IterT prev = beg; - for (++beg; beg != end; ++beg, ++prev) - { - if (comp(*beg, *prev)) - return false; - } - return true; -} - -template <class IterT, class CompareT> -inline bool IsSortedAndUnique(IterT beg, IterT end, CompareT comp) -{ - if (beg == end) - return true; - IterT prev = beg; - for (++beg; beg != end; ++beg, ++prev) - { - if (!comp(*prev, *beg)) - return false; - } - return true; -} - -template <class IterT, class CompareT> -IterT RemoveIfKeepValid(IterT beg, IterT end, CompareT comp) -{ - while (beg != end) - { - if (comp(*beg)) - { - while (beg != --end) - { - if (!comp(*end)) - { - std::swap(*beg, *end); - ++beg; - break; - } - } - } - else - ++beg; - } - - return end; -} - - -template <class IterT> inline bool IsSorted(IterT beg, IterT end) -{ - return IsSorted(beg, end, std::less<typename std::iterator_traits<IterT>::value_type>()); -} - -template <class IterT> inline bool IsSortedAndUnique(IterT beg, IterT end) -{ - return IsSortedAndUnique(beg, end, std::less<typename std::iterator_traits<IterT>::value_type>()); -} - -struct DeleteFunctor -{ - template <typename T> void operator() (T const * p) const - { - delete p; - } -}; - -namespace impl -{ - template <class TContainer, class TDeletor> class DeleteRangeFunctor - { - TContainer & m_cont; - TDeletor m_deletor; - - public: - DeleteRangeFunctor(TContainer & cont, TDeletor const & deletor) - : m_cont(cont), m_deletor(deletor) - { - } - - void operator() () - { - for_each(m_cont.begin(), m_cont.end(), m_deletor); - m_cont.clear(); - } - }; -} - -template <class TContainer, class TDeletor> -impl::DeleteRangeFunctor<TContainer, TDeletor> -GetRangeDeletor(TContainer & cont, TDeletor const & deletor) -{ - return impl::DeleteRangeFunctor<TContainer, TDeletor>(cont, deletor); -} - -template <class TContainer, class TDeletor> -void DeleteRange(TContainer & cont, TDeletor const & deletor) -{ - (void)GetRangeDeletor(cont, deletor)(); -} - -struct IdFunctor -{ - template <typename T> inline T operator () (T const & x) const - { - return x; - } -}; - -template <class T> struct EqualFunctor -{ - T const & m_t; - explicit EqualFunctor(T const & t) : m_t(t) {} - inline bool operator() (T const & t) const { return (t == m_t); } -}; - -template <typename IterT> IterT NextIterInCycle(IterT it, IterT beg, IterT end) -{ - if (++it == end) - return beg; - return it; -} - -template <typename IterT> IterT PrevIterInCycle(IterT it, IterT beg, IterT end) -{ - if (it == beg) - it = end; - return --it; -} - -template <class IterT1, class IterT2, class InsertIterT> -void AccumulateIntervals1With2(IterT1 b1, IterT1 e1, IterT2 b2, IterT2 e2, InsertIterT res) -{ - //typedef typename iterator_traits<InsertIterT>::value_type T; - typedef typename std::iterator_traits<IterT1>::value_type T; - - T prev; - bool validPrev = false; - - while (b1 != e1 || b2 != e2) - { - // Try to continue previous range. - if (validPrev) - { - // add b1 range to prev if needed - if (b1 != e1 && b1->first < prev.second) - { - // correct only second if needed - if (prev.second < b1->second) - prev.second = b1->second; - ++b1; - continue; - } - - // add b2 range to prev if needed - if (b2 != e2 && b2->first < prev.second) - { - // check that intervals are overlapped - if (prev.first < b2->second) - { - // correct first and second if needed - if (b2->first < prev.first) - prev.first = b2->first; - if (prev.second < b2->second) - prev.second = b2->second; - } - - ++b2; - continue; - } - - // if nothing to add - push to results - *res++ = prev; - validPrev = false; - } - - if (b1 != e1) - { - // start new range - prev = *b1++; - validPrev = true; - } - else - { - // go to exit - break; - } - } - - if (validPrev) - *res++ = prev; -} diff --git a/base/stl_helpers.hpp b/base/stl_helpers.hpp index 7296daabc9..4ad67bed8a 100644 --- a/base/stl_helpers.hpp +++ b/base/stl_helpers.hpp @@ -2,13 +2,18 @@ #include <algorithm> #include <functional> +#include <initializer_list> +#include <iterator> +#include <memory> #include <tuple> #include <type_traits> #include <utility> #include <vector> -namespace my +namespace base { +using StringIL = std::initializer_list<char const *>; + namespace impl { // When isField is true, following functors operate on a @@ -22,9 +27,9 @@ struct Less<true, T, C> { Less(T(C::*p)) : m_p(p) {} - inline bool operator()(C const & lhs, C const & rhs) const { return lhs.*m_p < rhs.*m_p; } + bool operator()(C const & lhs, C const & rhs) const { return lhs.*m_p < rhs.*m_p; } - inline bool operator()(C const * const lhs, C const * const rhs) const + bool operator()(C const * const lhs, C const * const rhs) const { return lhs->*m_p < rhs->*m_p; } @@ -37,9 +42,9 @@ struct Less<false, T, C> { Less(T (C::*p)() const) : m_p(p) {} - inline bool operator()(C const & lhs, C const & rhs) const { return (lhs.*m_p)() < (rhs.*m_p)(); } + bool operator()(C const & lhs, C const & rhs) const { return (lhs.*m_p)() < (rhs.*m_p)(); } - inline bool operator()(C const * const lhs, C const * const rhs) const + bool operator()(C const * const lhs, C const * const rhs) const { return (lhs->*m_p)() < (rhs->*m_p)(); } @@ -55,9 +60,9 @@ struct Equals<true, T, C> { Equals(T(C::*p)) : m_p(p) {} - inline bool operator()(C const & lhs, C const & rhs) const { return lhs.*m_p == rhs.*m_p; } + bool operator()(C const & lhs, C const & rhs) const { return lhs.*m_p == rhs.*m_p; } - inline bool operator()(C const * const lhs, C const * const rhs) const + bool operator()(C const * const lhs, C const * const rhs) const { return lhs->*m_p == rhs->*m_p; } @@ -70,15 +75,34 @@ struct Equals<false, T, C> { Equals(T (C::*p)() const) : m_p(p) {} - inline bool operator()(C const & lhs, C const & rhs) const { return (lhs.*m_p)() == (rhs.*m_p)(); } + bool operator()(C const & lhs, C const & rhs) const { return (lhs.*m_p)() == (rhs.*m_p)(); } - inline bool operator()(C const * const lhs, C const * const rhs) const + bool operator()(C const * const lhs, C const * const rhs) const { return (lhs->*m_p)() == (rhs->*m_p)(); } T (C::*m_p)() const; }; + +template <typename Container, typename Deletor> +class DeleteRangeFunctor +{ +public: + DeleteRangeFunctor(Container & cont, Deletor const & deletor) : m_cont(cont), m_deletor(deletor) + { + } + + void operator()() + { + for_each(m_cont.begin(), m_cont.end(), m_deletor); + m_cont.clear(); + } + +private: + Container & m_cont; + Deletor m_deletor; +}; } // namespace impl // Sorts and removes duplicate entries from |c|. @@ -92,14 +116,14 @@ void SortUnique(Cont & c) // Sorts according to |less| and removes duplicate entries according to |equals| from |c|. // Note. If several entries are equal according to |less| an arbitrary entry of them // is left in |c| after a call of this function. -template <class Cont, typename Less, typename Equals> +template <typename Cont, typename Less, typename Equals> void SortUnique(Cont & c, Less && less, Equals && equals) { sort(c.begin(), c.end(), std::forward<Less>(less)); c.erase(unique(c.begin(), c.end(), std::forward<Equals>(equals)), c.end()); } -template <class Cont, class Fn> +template <typename Cont, typename Fn> void EraseIf(Cont & c, Fn && fn) { c.erase(remove_if(c.begin(), c.end(), std::forward<Fn>(fn)), c.end()); @@ -193,4 +217,201 @@ for_each_in_tuple_const(std::tuple<Tp...> const & t, Fn && fn) for_each_in_tuple_const<I + 1, Fn, Tp...>(t, std::forward<Fn>(fn)); } -} // namespace my +template <typename Container> +class BackInsertFunctor +{ +public: + explicit BackInsertFunctor(Container & container) : m_Container(container) {} + void operator()(typename Container::value_type const & t) const { m_Container.push_back(t); } + +private: + Container & m_Container; +}; + +template <typename Container> +BackInsertFunctor<Container> MakeBackInsertFunctor(Container & container) +{ + return BackInsertFunctor<Container>(container); +} + +template <typename Container> +class InsertFunctor +{ +public: + explicit InsertFunctor(Container & container) : m_Container(container) {} + void operator()(typename Container::value_type const & t) const + { + m_Container.insert(end(m_Container), t); + } + +private: + Container & m_Container; +}; + +template <typename Container> +InsertFunctor<Container> MakeInsertFunctor(Container & container) +{ + return InsertFunctor<Container>(container); +} + +template <typename Iter, typename Compare> +bool IsSortedAndUnique(Iter beg, Iter end, Compare comp) +{ + if (beg == end) + return true; + Iter prev = beg; + for (++beg; beg != end; ++beg, ++prev) + { + if (!comp(*prev, *beg)) + return false; + } + return true; +} + +template <typename Iter, typename Compare> +Iter RemoveIfKeepValid(Iter beg, Iter end, Compare comp) +{ + while (beg != end) + { + if (comp(*beg)) + { + while (beg != --end) + { + if (!comp(*end)) + { + std::swap(*beg, *end); + ++beg; + break; + } + } + } + else + ++beg; + } + + return end; +} + +template <typename Iter> +bool IsSortedAndUnique(Iter beg, Iter end) +{ + return IsSortedAndUnique(beg, end, std::less<typename std::iterator_traits<Iter>::value_type>()); +} + +struct DeleteFunctor +{ + template <typename T> + void operator()(T const * p) const + { + delete p; + } +}; + +template <typename Container, typename Deletor> +impl::DeleteRangeFunctor<Container, Deletor> GetRangeDeletor(Container & cont, + Deletor const & deletor) +{ + return impl::DeleteRangeFunctor<Container, Deletor>(cont, deletor); +} + +template <typename Container, typename Deletor> +void DeleteRange(Container & cont, Deletor const & deletor) +{ + (void)GetRangeDeletor(cont, deletor)(); +} + +struct IdFunctor +{ + template <typename T> + T operator()(T const & x) const + { + return x; + } +}; + +template <typename T> +struct EqualFunctor +{ + T const & m_t; + explicit EqualFunctor(T const & t) : m_t(t) {} + bool operator()(T const & t) const { return (t == m_t); } +}; + +template <typename Iter> +Iter NextIterInCycle(Iter it, Iter beg, Iter end) +{ + if (++it == end) + return beg; + return it; +} + +template <typename Iter> +Iter PrevIterInCycle(Iter it, Iter beg, Iter end) +{ + if (it == beg) + it = end; + return --it; +} + +template <typename Iter1, typename Iter2, typename InsertIter> +void AccumulateIntervals1With2(Iter1 b1, Iter1 e1, Iter2 b2, Iter2 e2, InsertIter res) +{ + using T = typename std::iterator_traits<Iter1>::value_type; + + T prev; + bool validPrev = false; + + while (b1 != e1 || b2 != e2) + { + // Try to continue previous range. + if (validPrev) + { + // add b1 range to prev if needed + if (b1 != e1 && b1->first < prev.second) + { + // correct only second if needed + if (prev.second < b1->second) + prev.second = b1->second; + ++b1; + continue; + } + + // add b2 range to prev if needed + if (b2 != e2 && b2->first < prev.second) + { + // check that intervals are overlapped + if (prev.first < b2->second) + { + // correct first and second if needed + if (b2->first < prev.first) + prev.first = b2->first; + if (prev.second < b2->second) + prev.second = b2->second; + } + + ++b2; + continue; + } + + // if nothing to add - push to results + *res++ = prev; + validPrev = false; + } + + if (b1 != e1) + { + // start new range + prev = *b1++; + validPrev = true; + } + else + { + // go to exit + break; + } + } + + if (validPrev) + *res++ = prev; +} +} // namespace base diff --git a/base/string_utils.hpp b/base/string_utils.hpp index 3fe0807500..778818b018 100644 --- a/base/string_utils.hpp +++ b/base/string_utils.hpp @@ -2,7 +2,7 @@ #include "base/buffer_vector.hpp" #include "base/macros.hpp" -#include "base/stl_add.hpp" +#include "base/stl_helpers.hpp" #include <algorithm> #include <cstdint> @@ -317,7 +317,7 @@ template <template <typename ...> class Collection = std::vector> Collection<std::string> Tokenize(std::string const & str, char const * delims) { Collection<std::string> c; - Tokenize(str, delims, MakeInsertFunctor(c)); + Tokenize(str, delims, base::MakeInsertFunctor(c)); return c; } |