Added path views for abs and rel paths
This commit is contained in:
+221
-109
@@ -2,6 +2,8 @@
|
||||
|
||||
#include "tl/detail/prologue.h"
|
||||
#include <cstddef>
|
||||
|
||||
#include "tl/rel_path_view.h"
|
||||
#include "tl/path_system.h"
|
||||
#include "tl/detail/path_base.h"
|
||||
#include "tl/plain_crash.h"
|
||||
@@ -18,7 +20,11 @@ class rel_path : public detail::path_system::path_base<PathSystems>
|
||||
{
|
||||
template<typename T> friend class abs_path;
|
||||
public:
|
||||
rel_path() noexcept;
|
||||
using path_view_type = rel_path_view<PathSystems>;
|
||||
|
||||
rel_path() noexcept = default;
|
||||
rel_path(rel_path_view<PathSystems> view) noexcept;
|
||||
rel_path(span<const string> elements) noexcept;
|
||||
explicit rel_path(const char* path) noexcept;
|
||||
rel_path(const char* path, size_t size) noexcept;
|
||||
template<typename Str>
|
||||
@@ -27,54 +33,68 @@ public:
|
||||
rel_path(const rel_path& other) noexcept;
|
||||
rel_path(rel_path&& other) noexcept;
|
||||
|
||||
// for retro-compatibility with old path system
|
||||
rel_path(const rel_path& from, const rel_path& to) noexcept;
|
||||
|
||||
// operators
|
||||
const string& operator[](size_t idx) const noexcept;
|
||||
|
||||
rel_path& operator=(const char* path) noexcept;
|
||||
rel_path& operator=(const rel_path& other) noexcept;
|
||||
rel_path& operator=(rel_path&& other) noexcept;
|
||||
template<typename Str>
|
||||
rel_path& operator=(const Str& path) noexcept;
|
||||
rel_path& operator=(const rel_path_view<PathSystems>& path) noexcept;
|
||||
|
||||
rel_path operator+(const char* path) const noexcept;
|
||||
rel_path operator+(const rel_path& path) const noexcept;
|
||||
rel_path operator+(rel_path&& path) const noexcept;
|
||||
template<typename Str>
|
||||
rel_path operator+(const Str& path) const noexcept;
|
||||
rel_path operator+(const rel_path_view<PathSystems>& path) const noexcept;
|
||||
|
||||
rel_path& operator+=(const char* path) noexcept;
|
||||
rel_path& operator+=(const rel_path& path) noexcept;
|
||||
rel_path& operator+=(rel_path&& path) noexcept;
|
||||
template<typename Str>
|
||||
rel_path& operator+=(const Str& path) noexcept;
|
||||
rel_path& operator+=(const rel_path_view<PathSystems>& path) noexcept;
|
||||
|
||||
operator rel_path_view<PathSystems>() const noexcept;
|
||||
|
||||
bool operator==(const rel_path& other) const noexcept;
|
||||
bool operator!=(const rel_path& other) const noexcept;
|
||||
auto operator<=>(const rel_path& other) const noexcept;
|
||||
|
||||
auto operator<=>(const rel_path& other) const noexcept;
|
||||
bool operator==(const rel_path_view<PathSystems>& other) const noexcept;
|
||||
bool operator!=(const rel_path_view<PathSystems>& other) const noexcept;
|
||||
auto operator<=>(const rel_path_view<PathSystems>& other) const noexcept;
|
||||
|
||||
void swap(rel_path& other) noexcept;
|
||||
void clear() noexcept;
|
||||
|
||||
template<typename FormatSystem>
|
||||
string get_as() const noexcept;
|
||||
string str() const noexcept;
|
||||
|
||||
rel_path subpath(size_t index, int count = 0) const noexcept;
|
||||
template<typename FormatSystem>
|
||||
eastl::string eastl_str() const noexcept;
|
||||
|
||||
template<typename FormatSystem>
|
||||
std::string std_str() const noexcept;
|
||||
|
||||
template<typename FormatSystem>
|
||||
rel_path_view<PathSystems> view() const noexcept;
|
||||
|
||||
|
||||
rel_path_view<PathSystems> subpath(size_t index, int count = 0) const noexcept;
|
||||
rel_path parent() const noexcept;
|
||||
|
||||
bool is_prefix_of(const rel_path& path) const noexcept;
|
||||
bool is_prefix_of(const rel_path& path) const noexcept;
|
||||
|
||||
string pop_front() noexcept;
|
||||
void push_front(string element) noexcept;
|
||||
bool push_back(string element) noexcept override;
|
||||
string pop_front() noexcept;
|
||||
void push_front(string element) noexcept;
|
||||
bool push_back(string element) noexcept override;
|
||||
|
||||
const string& front() const noexcept;
|
||||
const string& back() const noexcept;
|
||||
string& front() noexcept;
|
||||
string& back() noexcept;
|
||||
const string& front() const noexcept;
|
||||
const string& back() const noexcept;
|
||||
void replace_back(string element) noexcept;
|
||||
|
||||
void collapse_path() noexcept;
|
||||
|
||||
@@ -105,9 +125,18 @@ namespace tl
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems>::rel_path() noexcept
|
||||
rel_path<PathSystems>::rel_path(rel_path_view<PathSystems> view) noexcept
|
||||
{
|
||||
this->m_hash = 0;
|
||||
this->m_elements.insert(this->m_elements.end(), view.begin(), view.end());
|
||||
this->m_hash = view.hash();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems>::rel_path(span<const string> elements) noexcept
|
||||
{
|
||||
this->m_elements.insert(this->m_elements.end(), elements.begin(), elements.end());
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -195,14 +224,8 @@ rel_path<PathSystems>::rel_path(const rel_path& from, const rel_path& to) noexce
|
||||
|
||||
for (size_t i = last; i < to.size(); i++)
|
||||
this->push_element(to.m_elements[i]);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
const string& rel_path<PathSystems>::operator[](size_t idx) const noexcept
|
||||
{
|
||||
return this->m_elements[idx];
|
||||
collapse_path();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -237,6 +260,17 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator=(const Str& path) noexcep
|
||||
return *this;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems>& rel_path<PathSystems>::operator=(const rel_path_view<PathSystems>& path) noexcept
|
||||
{
|
||||
this->m_elements.clear();
|
||||
this->m_elements.insert(this->m_elements.end(), path.m_elements.begin(), path.m_elements.end());
|
||||
this->m_hash = path.m_hash;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
@@ -262,21 +296,9 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(const char* path) const n
|
||||
p.reserve(this->size() + 1);
|
||||
p = *this;
|
||||
|
||||
size_t old_index = p.size();
|
||||
//this will push pack in the m_elements
|
||||
PathSystems::parse_relative(p.m_elements, path, strlen(path));
|
||||
|
||||
for (size_t i = old_index; i < p.m_elements.size(); ++i)
|
||||
{
|
||||
const string& element = p.m_elements[i];
|
||||
if (!p.validate_element(element))
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed to parse path");
|
||||
p.m_elements.resize(old_index);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
p.collapse_path();
|
||||
|
||||
return p;
|
||||
@@ -296,21 +318,9 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(const Str& path) const no
|
||||
p.reserve(this->size() + 1);
|
||||
p = *this;
|
||||
|
||||
size_t old_index = p.size();
|
||||
//this will push pack in the m_elements
|
||||
PathSystems::parse_relative(p.m_elements, path.data(), path.size());
|
||||
|
||||
for (size_t i = old_index; i < p.m_elements.size(); ++i)
|
||||
{
|
||||
const string& element = p.m_elements[i];
|
||||
if (!p.validate_element(element))
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed to parse path");
|
||||
p.m_elements.resize(old_index);
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
p.collapse_path();
|
||||
|
||||
return p;
|
||||
@@ -328,7 +338,22 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(const rel_path& path) con
|
||||
rel_path p;
|
||||
p.reserve(this->size() + path.size());
|
||||
p = *this;
|
||||
p += path;
|
||||
return p;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems> rel_path<PathSystems>::operator+(const rel_path_view<PathSystems>& path) const noexcept
|
||||
{
|
||||
if (!path.empty())
|
||||
{
|
||||
rel_path p;
|
||||
p.reserve(this->size() + path.size());
|
||||
p = *this;
|
||||
p += path;
|
||||
return p;
|
||||
}
|
||||
@@ -345,7 +370,6 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(rel_path&& path) const no
|
||||
rel_path p;
|
||||
p.reserve(this->size() + path.size());
|
||||
p = *this;
|
||||
|
||||
p += std::move(path);
|
||||
return p;
|
||||
}
|
||||
@@ -359,21 +383,9 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(const char* path) noexc
|
||||
{
|
||||
if (path && path[0] != '\0')
|
||||
{
|
||||
size_t old_index = this->size();
|
||||
//this will push pack in the m_elements
|
||||
PathSystems::parse_relative(this->m_elements, path, strlen(path));
|
||||
|
||||
for (size_t i = old_index; i < this->m_elements.size(); ++i)
|
||||
{
|
||||
const string& element = this->m_elements[i];
|
||||
if (!this->validate_element(element))
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed to parse path");
|
||||
this->m_elements.resize(old_index);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_hash = 0;
|
||||
collapse_path();
|
||||
}
|
||||
@@ -388,21 +400,9 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(const Str& path) noexce
|
||||
{
|
||||
if (!path.empty())
|
||||
{
|
||||
size_t old_index = this->size();
|
||||
//this will push pack in the m_elements
|
||||
PathSystems::parse_relative(this->m_elements, path.data(), path.size());
|
||||
|
||||
for (size_t i = old_index; i < this->m_elements.size(); ++i)
|
||||
{
|
||||
const string& element = this->m_elements[i];
|
||||
if (!this->validate_element(element))
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed to parse path");
|
||||
this->m_elements.resize(old_index);
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
this->m_hash = 0;
|
||||
collapse_path();
|
||||
}
|
||||
@@ -443,6 +443,31 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(rel_path&& path) noexce
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems>& rel_path<PathSystems>::operator+=(const rel_path_view<PathSystems>& path) noexcept
|
||||
{
|
||||
if (!path.empty())
|
||||
{
|
||||
this->m_elements.reserve(this->m_elements.size() + path.m_elements.size());
|
||||
for (const string& element : path.m_elements)
|
||||
this->push_element(element);
|
||||
|
||||
this->m_hash = 0;
|
||||
this->collapse_path();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems>::operator rel_path_view<PathSystems>() const noexcept
|
||||
{
|
||||
return rel_path_view<PathSystems>(this->m_elements);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
@@ -474,7 +499,42 @@ auto rel_path<PathSystems>::operator<=>(const rel_path& other) const noexcept
|
||||
return r;
|
||||
}
|
||||
|
||||
return sz1 <=> sz2;}
|
||||
return sz1 <=> sz2;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
bool rel_path<PathSystems>::operator==(const rel_path_view<PathSystems>& other) const noexcept
|
||||
{
|
||||
return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) &&
|
||||
tl::span(this->m_elements) == other.m_elements;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
bool rel_path<PathSystems>::operator!=(const rel_path_view<PathSystems>& other) const noexcept
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
auto rel_path<PathSystems>::operator<=>(const rel_path_view<PathSystems>& other) const noexcept
|
||||
{
|
||||
const size_t sz1 = this->m_elements.size();
|
||||
const size_t sz2 = other.m_elements.size();
|
||||
for (size_t i = 0; i < sz1 && i < sz2; ++i)
|
||||
{
|
||||
auto r = this->m_elements[i] <=> other.m_elements[i];
|
||||
if (r != decltype(r)::equal)
|
||||
return r;
|
||||
}
|
||||
|
||||
return sz1 <=> sz2;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -487,15 +547,6 @@ bool rel_path<PathSystems>::parse(const char* path, size_t size) noexcept
|
||||
|
||||
PathSystems::parse_relative(this->m_elements, path, size);
|
||||
|
||||
for (const string& element : this->m_elements)
|
||||
{
|
||||
if (!this->validate_element(element))
|
||||
{
|
||||
this->clear();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
collapse_path();
|
||||
|
||||
return true;
|
||||
@@ -508,18 +559,21 @@ void rel_path<PathSystems>::collapse_path() noexcept
|
||||
{
|
||||
if (!this->empty())
|
||||
{
|
||||
this->m_hash = 0;
|
||||
for (size_t i = 0; i < this->m_elements.size();)
|
||||
{
|
||||
if (i >= 1 &&
|
||||
this->m_elements[i] == path_system::back_t::value() &&
|
||||
this->m_elements[i - 1] != path_system::back_t::value())
|
||||
{
|
||||
this->m_hash = 0;
|
||||
this->m_elements.erase(this->m_elements.begin() + i - 1, this->m_elements.begin() + i + 1); //remove the .. and the parent
|
||||
i -= 1;
|
||||
}
|
||||
else if (this->m_elements[i] == path_system::current_t::value())
|
||||
this->m_elements.erase(this->m_elements.begin() + i); //remove the .
|
||||
{
|
||||
this->m_hash = 0;
|
||||
this->m_elements.erase(this->m_elements.begin() + i); //remove the .
|
||||
}
|
||||
else
|
||||
i++;
|
||||
}
|
||||
@@ -534,7 +588,7 @@ bool rel_path<PathSystems>::is_prefix_of(const rel_path& path) const noexcept
|
||||
if (this->size() > path.size())
|
||||
return false;
|
||||
|
||||
for (size_t i = 0, _count = this->size(); i < _count; ++i)
|
||||
for (size_t i = 0, sz = this->size(); i < sz; ++i)
|
||||
{
|
||||
if (this->m_elements[i] != path[i])
|
||||
return false;
|
||||
@@ -557,7 +611,7 @@ void rel_path<PathSystems>::swap(rel_path& other) noexcept
|
||||
template <typename PathSystems>
|
||||
void rel_path<PathSystems>::clear() noexcept
|
||||
{
|
||||
this->m_elements.resize(0);
|
||||
this->m_elements.clear();
|
||||
this->m_hash = 0;
|
||||
}
|
||||
|
||||
@@ -565,17 +619,43 @@ void rel_path<PathSystems>::clear() noexcept
|
||||
|
||||
template<typename PathSystems>
|
||||
template<typename FormatSystem>
|
||||
string rel_path<PathSystems>::get_as() const noexcept
|
||||
string rel_path<PathSystems>::str() const noexcept
|
||||
{
|
||||
return FormatSystem::format_relative(this->m_elements);
|
||||
return FormatSystem::template format_rel<string>(this->m_elements);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename PathSystems>
|
||||
template<typename FormatSystem>
|
||||
eastl::string rel_path<PathSystems>::eastl_str() const noexcept
|
||||
{
|
||||
return FormatSystem::template format_rel<eastl::string>(this->m_elements);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename PathSystems>
|
||||
template<typename FormatSystem>
|
||||
std::string rel_path<PathSystems>::std_str() const noexcept
|
||||
{
|
||||
return FormatSystem::template format_rel<std::string>(this->m_elements);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path<PathSystems> rel_path<PathSystems>::subpath(size_t index, int count /* = 0 */) const noexcept
|
||||
template <typename FormatSystem>
|
||||
rel_path_view<PathSystems> rel_path<PathSystems>::view() const noexcept
|
||||
{
|
||||
return rel_path_view<PathSystems>(this->m_elements);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename PathSystems>
|
||||
rel_path_view<PathSystems> rel_path<PathSystems>::subpath(size_t index, int count /* = 0 */) const noexcept
|
||||
{
|
||||
rel_path dst;
|
||||
if (count == 0)
|
||||
count = (int)this->size() - (int)index;
|
||||
|
||||
@@ -583,12 +663,9 @@ rel_path<PathSystems> rel_path<PathSystems>::subpath(size_t index, int count /*
|
||||
count = (int)this->size() - (int)index + count;
|
||||
|
||||
if (count > 0 && index < this->size())
|
||||
{
|
||||
dst.m_elements.resize(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
dst.m_elements[i] = this->m_elements[index + i];
|
||||
}
|
||||
return dst;
|
||||
return rel_path_view<PathSystems>(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count));
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -637,21 +714,15 @@ const string& rel_path<PathSystems>::front() const noexcept
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class PathSystems>
|
||||
string& rel_path<PathSystems>::front() noexcept
|
||||
void rel_path<PathSystems>::replace_back(string element) noexcept
|
||||
{
|
||||
TL_PLAIN_ASSERT(!this->empty());
|
||||
const bool is_back_element = element == path_system::back_t::value();
|
||||
this->m_hash = 0;
|
||||
return this->m_elements.front();
|
||||
}
|
||||
this->m_elements.back() = std::move(element);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<class PathSystems>
|
||||
string& rel_path<PathSystems>::back() noexcept
|
||||
{
|
||||
TL_PLAIN_ASSERT(!this->empty());
|
||||
this->m_hash = 0;
|
||||
return this->m_elements.back();
|
||||
if (is_back_element)
|
||||
collapse_path();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -674,8 +745,12 @@ string rel_path<PathSystems>::pop_front() noexcept
|
||||
template <typename PathSystems>
|
||||
void rel_path<PathSystems>::push_front(string element) noexcept
|
||||
{
|
||||
const bool is_back_element = element == path_system::back_t::value();
|
||||
this->m_hash = 0;
|
||||
this->m_elements.insert(this->m_elements.begin(), std::move(element));
|
||||
|
||||
if (is_back_element)
|
||||
collapse_path();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -719,6 +794,43 @@ other_rel_path rel_path<PathSystems>::move_cast_to() noexcept
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<class PathSystems>
|
||||
rel_path<PathSystems> operator+(const rel_path_view<PathSystems>& a, const char* b) noexcept
|
||||
{
|
||||
rel_path<PathSystems> p;
|
||||
p.reserve(a.size() + 1);
|
||||
p = a;
|
||||
p += b;
|
||||
return p;
|
||||
}
|
||||
template<class PathSystems, typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_same_v<Str, char*>)
|
||||
rel_path<PathSystems> operator+(const rel_path_view<PathSystems>& a, const Str& b) noexcept
|
||||
{
|
||||
rel_path<PathSystems> p;
|
||||
p.reserve(a.size() + 1);
|
||||
p = a;
|
||||
p += b;
|
||||
return p;
|
||||
}
|
||||
template<class PathSystems>
|
||||
rel_path<PathSystems> operator+(const rel_path_view<PathSystems>& a, const rel_path<PathSystems>& b) noexcept
|
||||
{
|
||||
rel_path<PathSystems> p;
|
||||
p.reserve(a.size() + b.size());
|
||||
p = a;
|
||||
p += b;
|
||||
return p;
|
||||
}
|
||||
template<class PathSystems>
|
||||
rel_path<PathSystems> operator+(const rel_path_view<PathSystems>& a, const rel_path_view<PathSystems>& b) noexcept
|
||||
{
|
||||
rel_path<PathSystems> p;
|
||||
p.reserve(a.size() + b.size());
|
||||
p = a;
|
||||
p += b;
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -730,7 +842,7 @@ struct std::formatter<tl::rel_path<tl::path_systems<T>>>
|
||||
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
|
||||
auto format(const tl::rel_path<tl::path_systems<T>>& p, std::format_context& ctx) const
|
||||
{
|
||||
return format_to(ctx.out(), "{}", p.template get_as<T>());
|
||||
return format_to(ctx.out(), "{}", p.template str<T>());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user