Files
TL/include/tl/rel_path_view.h
2024-07-10 11:52:47 +02:00

278 lines
7.0 KiB
C++

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