// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2024 // // 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 add_to_top(V &v, size_t max_size, T value) { size_t size = v.size(); size_t i; for (i = 0; i < size; i++) { if (v[i] == value) { value = std::move(v[i]); break; } } if (i == size) { if (size < max_size || i == 0) { v.emplace_back(value); } else { i--; } } while (i > 0) { v[i] = std::move(v[i - 1]); i--; } v[0] = std::move(value); } template void add_to_top_if(V &v, size_t max_size, T value, const F &is_equal_to_value) { size_t size = v.size(); size_t i; for (i = 0; i < size; i++) { if (is_equal_to_value(v[i])) { value = std::move(v[i]); break; } } if (i == size) { if (size < max_size || i == 0) { v.emplace_back(value); } else { i--; } } while (i > 0) { v[i] = std::move(v[i - 1]); i--; } v[0] = std::move(value); } 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[j - 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 bool any_of(const V &v, F &&f) { for (const auto &x : v) { if (f(x)) { return true; } } return false; } template bool all_of(const V &v, F &&f) { for (const auto &x : v) { if (!f(x)) { return false; } } return true; } 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}; } template void table_remove_if(TableT &table, FuncT &&func) { for (auto it = table.begin(); it != table.end();) { if (func(*it)) { it = table.erase(it); } else { ++it; } } } template class FlatHashTable; template void table_remove_if(FlatHashTable &table, FuncT &&func) { table.remove_if(func); } } // namespace td