#pragma once #include "tl/detail/prologue.h" #include #include "tl/path_system.h" #include "tl/rel_path_view.h" #include "tl/detail/path_view_base.h" #include "tl/plain_crash.h" #include "tl/format.h" namespace tl { template class rel_path; template class rel_path_view; template struct path_view_key_less; ////////////////////////////////////////////////////////////////////////// template class rel_path_view : public detail::path_system::path_view_base { template friend class rel_path_view; public: using rel_path_view_type = rel_path_view; rel_path_view() noexcept; rel_path_view(tl::span elements) noexcept; rel_path_view(const rel_path_view& other) noexcept; // operators rel_path_view& operator=(const rel_path_view& other) noexcept; bool operator==(const rel_path_view& other) const noexcept; bool operator!=(const rel_path_view& other) const noexcept; auto operator<=>(const rel_path_view& other) const noexcept; void clear() noexcept; template string str() const noexcept; template eastl::string eastl_str() const noexcept; template std::string std_str() const noexcept; rel_path_view subpath(size_t idx, int count = 0) const noexcept; rel_path_view parent() const noexcept; rel_path_view parent(size_t levels) const noexcept; bool is_prefix_of(const rel_path_view& path) const noexcept; template other_rel_path cast_to() const noexcept; private: friend class rel_path; }; ////////////////////////////////////////////////////////////////////////// } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// namespace tl { ////////////////////////////////////////////////////////////////////////// template rel_path_view::rel_path_view() noexcept { } ////////////////////////////////////////////////////////////////////////// template rel_path_view::rel_path_view(tl::span elements) noexcept : path_view_base(elements) { } ////////////////////////////////////////////////////////////////////////// template rel_path_view::rel_path_view(const rel_path_view& other) noexcept : path_view_base(other) { } //////////////////////////////////////////////////////////////////////////////////////////////////////////// template rel_path_view& rel_path_view::operator=(const rel_path_view& other) noexcept { m_elements = other.m_elements; m_hash = other.m_hash; return *this; } ////////////////////////////////////////////////////////////////////////// template bool rel_path_view::operator==(const rel_path_view& other) const noexcept { return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) && this->m_elements == other.m_elements; } ////////////////////////////////////////////////////////////////////////// template bool rel_path_view::operator!=(const rel_path_view& other) const noexcept { return !(*this == other); } ////////////////////////////////////////////////////////////////////////// template void rel_path_view::clear() noexcept { m_elements = {}; m_hash = 0; } ////////////////////////////////////////////////////////////////////////// template template string rel_path_view::str() const noexcept { if (this->empty()) return {}; return FormatSystem::template format_rel(this->m_elements); } ////////////////////////////////////////////////////////////////////////// template template eastl::string rel_path_view::eastl_str() const noexcept { if (this->empty()) return {}; return FormatSystem::template format_rel(this->m_elements); } ////////////////////////////////////////////////////////////////////////// template template std::string rel_path_view::std_str() const noexcept { if (this->empty()) return {}; return FormatSystem::template format_rel(this->m_elements); } ////////////////////////////////////////////////////////////////////////// template rel_path_view rel_path_view::subpath(size_t idx, int count /* = 0 */) const noexcept { if (count == 0) count = (int)this->size() - (int)idx; if (count < 0) count = (int)this->size() - (int)idx + count; if (count > 0 && idx < this->size()) return rel_path_view(tl::span(this->m_elements.begin() + idx, this->m_elements.begin() + idx + count)); return {}; } ////////////////////////////////////////////////////////////////////////// template rel_path_view rel_path_view::parent() const noexcept { if (this->empty()) { TL_PLAIN_FAIL("Invalid path"); return {}; } rel_path_view p = *this; p.pop_back(); return p; } ////////////////////////////////////////////////////////////////////////// template rel_path_view rel_path_view::parent(size_t levels) const noexcept { if (this->empty() || this->size() <= levels) { TL_PLAIN_FAIL("Invalid path"); return {}; } rel_path_view p = *this; p.shrink(p.size() - levels); return p; } ////////////////////////////////////////////////////////////////////////// template bool rel_path_view::is_prefix_of(const rel_path_view& path) const noexcept { if (this->size() > path.size()) return false; for (size_t i = 0, _count = this->size(); i < _count; ++i) { if ((*this)[i] != path[i]) return false; } return true; } ////////////////////////////////////////////////////////////////////////// template template other_rel_path rel_path_view::cast_to() const noexcept { return other_rel_path(this->m_elements); } } ////////////////////////////////////////////////////////////////////////// template struct std::formatter>> { constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); } auto format(const tl::rel_path_view>& p, std::format_context& ctx) const { return format_to(ctx.out(), "{}", p.template str()); } }; template struct std::hash> { std::size_t operator()(const tl::rel_path_view& p) const { return p.hash(); } }; template struct eastl::hash> { std::size_t operator()(const tl::rel_path_view& p) const { return p.hash(); } };