diff --git a/src/common/container_helpers.h b/src/common/container_helpers.h new file mode 100644 index 000000000..cd74b1ada --- /dev/null +++ b/src/common/container_helpers.h @@ -0,0 +1,106 @@ +// Copyright (c) 2022, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF +// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Miscellaneous container helpers. + +#pragma once + +//local headers + +//third party headers + +//standard headers +#include +#include +#include +#include +#include + +//forward declarations + + +namespace tools +{ + +/// use operator< to get operator== +/// WARNING: equality is not always implied by operator<, depending on implementation +struct equals_from_less final +{ + template + bool operator()(const T &a, const T &b) { return !(a < b) && !(b < a); } +}; +/// note: uniqueness uses 'equals_from_less' to match the use of operator< when testing if sorted +template +bool is_sorted_and_unique(const T& container) +{ + if (!std::is_sorted(container.begin(), container.end())) + return false; + + if (std::adjacent_find(container.begin(), container.end(), equals_from_less{}) != container.end()) + return false; + + return true; +} +/// convenience wrapper for checking if a mapped object is mapped to a key embedded in that object +template +bool keys_match_internal_values(const std::unordered_map &map, + const std::function< + const typename std::unordered_map::key_type& + (const typename std::unordered_map::mapped_type&) + > &get_internal_key_func) +{ + for (const auto &map_element : map) + { + if (!(map_element.first == get_internal_key_func(map_element.second))) + return false; + } + + return true; +} +/// convenience wrapper for getting the last element after emplacing back +template +typename ContainerT::value_type& add_element(ContainerT &container) +{ + container.emplace_back(); + return container.back(); +} +/// convenience erasor for unordered maps: std::erase_if(std::unordered_map) is C++20 +template +void for_all_in_map_erase_if(std::unordered_map &map_inout, + const std::function::value_type&)> &predicate) +{ + for (auto map_it = map_inout.begin(); map_it != map_inout.end();) + { + if (predicate(*map_it)) + map_it = map_inout.erase(map_it); + else + ++map_it; + } +} + +} //namespace tools