#pragma once #include "tl/detail/prologue.h" #include "tl/span.h" #include "tl/string.h" #include "tl/hash_and_combine.h" namespace tl { namespace detail { namespace path_system { class path_view_base; struct path_view_key_less { bool operator()(const path_view_base& a1, const path_view_base& a2) const noexcept; }; ////////////////////////////////////////////////////////////////////////// // inner path_view_base definition class path_view_base { public: path_view_base() noexcept; path_view_base(tl::span elements) noexcept; virtual ~path_view_base() noexcept = default; using iterator = tl::span::iterator; using const_iterator = tl::span::const_iterator; using const_reverse_iterator = tl::span::const_reverse_iterator; using key_less = path_view_key_less; using value_type = std::string; //both have checked indexing const string& at(size_t index) const noexcept; const string& operator[](size_t index) const noexcept; void shrink(size_t size) noexcept; bool empty() const noexcept; size_t size() const noexcept; void pop_back() noexcept; iterator begin() noexcept; iterator end() noexcept; const_iterator begin() const noexcept; const_iterator end() const noexcept; const string& front() const noexcept; const string& back() const noexcept; uint32_t hash() const noexcept; protected: tl::span m_elements; mutable uint32_t m_hash = 0; friend bool path_view_key_less::operator()(const path_view_base& a1, const path_view_base& a2) const noexcept; }; ////////////////////////////////////////////////////////////////////////// } } } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// namespace tl { namespace detail { namespace path_system { ////////////////////////////////////////////////////////////////////////// inline path_view_base::path_view_base() noexcept { } ////////////////////////////////////////////////////////////////////////// inline path_view_base::path_view_base(tl::span elements) noexcept : m_elements(elements) { } ////////////////////////////////////////////////////////////////////////// inline const string& path_view_base::operator[](size_t index) const noexcept { if (index >= m_elements.size()) TL_PLAIN_CRASH("Illegal access"); return m_elements[index]; } ////////////////////////////////////////////////////////////////////////// inline const string& path_view_base::at(size_t index) const noexcept { if (index >= m_elements.size()) TL_PLAIN_CRASH("Illegal access"); return m_elements[index]; } ////////////////////////////////////////////////////////////////////////// inline void path_view_base::shrink(size_t size) noexcept { if (size < this->size()) { m_elements = tl::span(m_elements.data(), size); m_hash = 0; } } ////////////////////////////////////////////////////////////////////////// inline uint32_t path_view_base::hash() const noexcept { if (m_hash == 0) { for (const string& e : *this) hash_and_combine(m_hash, e); } return m_hash; } ////////////////////////////////////////////////////////////////////////// inline size_t path_view_base::size() const noexcept { return m_elements.size(); } ////////////////////////////////////////////////////////////////////////// inline bool path_view_base::empty() const noexcept { return m_elements.empty(); } ////////////////////////////////////////////////////////////////////////// inline void path_view_base::pop_back() noexcept { if (empty()) { TL_PLAIN_FAIL(); return; } m_hash = 0; m_elements = tl::span(m_elements.data(), m_elements.size() - 1); } ////////////////////////////////////////////////////////////////////////// inline path_view_base::iterator path_view_base::begin() noexcept { return m_elements.begin(); } ////////////////////////////////////////////////////////////////////////// inline path_view_base::iterator path_view_base::end() noexcept { return m_elements.end(); } ////////////////////////////////////////////////////////////////////////// inline path_view_base::const_iterator path_view_base::begin() const noexcept { return m_elements.cbegin(); } ////////////////////////////////////////////////////////////////////////// inline path_view_base::const_iterator path_view_base::end() const noexcept { return m_elements.cend(); } inline const string& path_view_base::front() const noexcept { return m_elements.front(); } inline const string& path_view_base::back() const noexcept { return m_elements.back(); } ////////////////////////////////////////////////////////////////////////// inline bool path_view_key_less::operator()(const path_view_base& a1, const path_view_base& a2) const noexcept { const size_t sz1 = a1.size(); const size_t sz2 = a2.size(); for (size_t i = 0; i < sz1 && i < sz2; ++i) { if (a1[i] != a2[i]) return a1[i].unique_key() < a2[i].unique_key(); } return sz1 < sz2; } } } }