#pragma once #include "ip_range.hpp" #include #include #include namespace llarp { namespace net { /// a container that maps an ip range to a value that allows you to lookup /// key by range hit /// /// in the future we should do some kind of magic shit to ensure near constant time for lookups template struct IPRangeMap { using Range_t = IPRange; using IP_t = Range_t::Addr_t; using Entry_t = std::pair; using Container_t = std::vector; /// get a set of all values std::set Values() const { std::set all; for (const auto& entry : m_Entries) all.insert(entry.second); return all; } bool Empty() const { return m_Entries.empty(); } bool ContainsValue(const Value_t& val) const { for (const auto& entry : m_Entries) { if (entry.second == val) return true; } return false; } void ForEachValue(std::function functor) const { for (const auto& entry : m_Entries) functor(entry.second); } template void ForEachEntry(Visit_t visit) const { for (const auto& [range, value] : m_Entries) visit(range, value); } /// convert all values into type T using a transformer template std::set TransformValues(Transformer transform) const { std::set transformed; for (const auto& entry : m_Entries) { T val = transform(entry.second); transformed.insert(std::move(val)); } return transformed; } // get a value for this exact range std::optional GetExact(Range_t range) const { for (const auto& [r, value] : m_Entries) { if (r == range) return value; } return std::nullopt; } /// return a set of all entries who's range contains this IP std::set FindAllEntries(const IP_t& addr) const { std::set found; for (const auto& entry : m_Entries) { if (entry.first.Contains(addr)) found.insert(entry); } return found; } struct CompareEntry { bool operator()(const Entry_t& left, const Entry_t& right) const { return left.first < right.first; } }; void Insert(const Range_t& addr, const Value_t& val) { m_Entries.emplace_back(addr, val); } template void RemoveIf(Visit_t visit) { auto itr = m_Entries.begin(); while (itr != m_Entries.end()) { if (visit(*itr)) itr = m_Entries.erase(itr); else ++itr; } } util::StatusObject ExtractStatus() const { util::StatusObject obj; for (const auto& [range, value] : m_Entries) { obj[range.ToString()] = value.ToString(); } return obj; } private: Container_t m_Entries; }; } // namespace net } // namespace llarp