#pragma once #include #include #include #include #include #include template class file_id_lookup { public: using container_type = std::unordered_map; using key_type = typename container_type::key_type; using mapped_type = typename container_type::mapped_type; using value_type = typename container_type::value_type; using size_type = typename container_type::size_type; using difference_type = typename container_type::difference_type; using hasher = typename container_type::hasher; using key_equal = typename container_type::key_equal; using allocator_type = typename container_type::allocator_type; using reference = typename container_type::reference; using const_reference = typename container_type::const_reference; using pointer = typename container_type::pointer; using const_pointer = typename container_type::const_pointer; using iterator = typename container_type::iterator; using const_iterator = typename container_type::const_iterator; using local_iterator = typename container_type::local_iterator; using const_local_iterator = typename container_type::const_local_iterator; using node_type = typename container_type::node_type; using insert_return_type = typename container_type::insert_return_type; std::pair try_emplace(const key_type& path) { std::unique_lock lock(m_mutex); auto it = m_container.find(path); const auto is_new = it == m_container.end(); if (is_new) { it = m_container.emplace_hint(it, path, ID::next()); } return { it, is_new }; } [[nodiscard]] bool empty() const noexcept { std::shared_lock lock(m_mutex); return m_container.empty(); } [[nodiscard]] size_type size() const noexcept { std::shared_lock lock(m_mutex); return m_container.size(); } [[nodiscard]] size_type max_size() const noexcept { std::shared_lock lock(m_mutex); return m_container.max_size(); } void by_extension(const std::string_view extension, std::vector& dst) const { std::shared_lock lock(m_mutex); std::ranges::copy( m_container | std::views::filter([ &](const value_type& entry) { return entry.first.extension() == extension; } ) | std::views::transform([ &](const value_type& entry) { return &entry; } ), std::back_inserter(dst) ); } [[nodiscard]] bool contains(const key_type& key) const { std::shared_lock lock(m_mutex); return m_container.contains(key); } [[nodiscard]] size_type count(const key_type& key) const { std::shared_lock lock(m_mutex); return m_container.count(key); } [[nodiscard]] iterator find(const key_type& key) { std::shared_lock lock(m_mutex); return m_container.find(key); } [[nodiscard]] const_iterator find(const key_type& key) const { std::shared_lock lock(m_mutex); return m_container.find(key); } iterator erase(iterator pos) { std::unique_lock lock(m_mutex); return m_container.erase(pos); } iterator erase(const_iterator pos) { std::unique_lock lock(m_mutex); return m_container.erase(pos); } iterator erase(const_iterator first, const_iterator last) { std::unique_lock lock(m_mutex); return m_container.erase(first, last); } size_type erase(const key_type& key) { std::unique_lock lock(m_mutex); return m_container.erase(key); } void clear() noexcept { std::unique_lock lock(m_mutex); m_container.clear(); } [[nodiscard]] iterator begin() noexcept { return m_container.begin(); } [[nodiscard]] const_iterator begin() const noexcept { return m_container.begin(); } [[nodiscard]] const_iterator cbegin() const noexcept { return m_container.cbegin(); } [[nodiscard]] iterator end() noexcept { return m_container.end(); } [[nodiscard]] const_iterator end() const noexcept { return m_container.end(); } [[nodiscard]] const_iterator cend() const noexcept { return m_container.cend(); } private: static auto extension_filter(const std::string_view& extension) { return std::views::filter( [extension](const key_type& path) { return path.extension() == extension; } ); } container_type m_container; std::shared_mutex m_mutex; };