// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #pragma once #include "td/utils/common.h" #include #include #include namespace td { namespace detail { template struct transform_helper { template auto transform(const V &v, const Func &f) { vector result; result.reserve(v.size()); for (auto &x : v) { result.push_back(f(x)); } return result; } template auto transform(V &&v, const Func &f) { vector result; result.reserve(v.size()); for (auto &x : v) { result.push_back(f(std::move(x))); } return result; } }; } // namespace detail template auto transform(V &&v, const Func &f) { return detail::transform_helper>().transform(std::forward(v), f); } template bool remove_if(V &v, const Func &f) { size_t i = 0; while (i != v.size() && !f(v[i])) { i++; } if (i == v.size()) { return false; } size_t j = i; while (++i != v.size()) { if (!f(v[i])) { v[j++] = std::move(v[i]); } } v.erase(v.begin() + j, v.end()); return true; } template bool remove(V &v, const T &value) { size_t i = 0; while (i != v.size() && v[i] != value) { i++; } if (i == v.size()) { return false; } size_t j = i; while (++i != v.size()) { if (v[i] != value) { v[j++] = std::move(v[i]); } } v.erase(v.begin() + j, v.end()); return true; } template void unique(V &v) { if (v.empty()) { return; } // use ADL to find std::sort // caller will need to #include sort(v.begin(), v.end(), std::less()); size_t j = 1; for (size_t i = 1; i < v.size(); i++) { if (v[i] != v[i - 1]) { if (i != j) { v[j] = std::move(v[i]); } j++; } } v.resize(j); } template bool contains(const V &v, const T &value) { for (auto &x : v) { if (x == value) { return true; } } return false; } template void reset_to_empty(T &value) { using std::swap; std::decay_t tmp; swap(tmp, value); } template void append(vector &destination, const vector &source) { destination.insert(destination.end(), source.begin(), source.end()); } template void append(vector &destination, vector &&source) { if (destination.empty()) { destination.swap(source); return; } destination.reserve(destination.size() + source.size()); for (auto &elem : source) { destination.push_back(std::move(elem)); } reset_to_empty(source); } template void combine(vector &destination, const vector &source) { append(destination, source); } template void combine(vector &destination, vector &&source) { if (destination.size() < source.size()) { destination.swap(source); } if (source.empty()) { return; } destination.reserve(destination.size() + source.size()); for (auto &elem : source) { destination.push_back(std::move(elem)); } reset_to_empty(source); } namespace detail { template struct reversion_wrapper { T &iterable; }; template auto begin(reversion_wrapper w) { return w.iterable.rbegin(); } template auto end(reversion_wrapper w) { return w.iterable.rend(); } } // namespace detail template detail::reversion_wrapper reversed(T &iterable) { return {iterable}; } } // namespace td