Added path views for abs and rel paths

This commit is contained in:
catalinvasile
2024-07-10 11:52:47 +02:00
parent 51cf1887cd
commit 2195ccfc28
15 changed files with 4637 additions and 957 deletions
+227 -154
View File
@@ -2,6 +2,9 @@
#include "tl/detail/prologue.h"
#include <cstddef>
#include "tl/abs_path_view.h"
#include "tl/rel_path_view.h"
#include "tl/path_system.h"
#include "tl/rel_path.h"
#include "tl/detail/path_base.h"
@@ -23,8 +26,11 @@ class abs_path : public detail::path_system::path_base<PathSystems>
public:
using rel_path_type = rel_path<PathSystems>;
using path_view_type = abs_path_view<PathSystems>;
abs_path() noexcept;
abs_path() noexcept = default;
abs_path(abs_path_view<PathSystems> view) noexcept;
abs_path(int path_system_id, span<const string> elements) noexcept;
explicit abs_path(const char* path) noexcept;
abs_path(const char* path, size_t size) noexcept;
@@ -35,15 +41,13 @@ public:
abs_path(abs_path&& other) noexcept;
// operators
const string& operator[](size_t idx) const noexcept;
string& operator[](size_t idx) noexcept;
abs_path& operator=(const abs_path& other) noexcept;
abs_path& operator=(abs_path&& other) noexcept;
abs_path& operator=(const char* path) noexcept;
template<typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_same_v<Str, char*>)
abs_path& operator=(const Str& path) noexcept;
abs_path& operator=(const abs_path_view<PathSystems>& path) noexcept;
abs_path operator+(const char* path) const noexcept;
abs_path operator+(const rel_path<PathSystems>& path) const noexcept;
@@ -56,58 +60,64 @@ public:
abs_path& operator+=(rel_path<PathSystems>&& path) noexcept;
template<typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_same_v<Str, char*>)
abs_path& operator+=(const Str& path) noexcept;
abs_path& operator+=(const rel_path_view<PathSystems>& path) noexcept;
operator abs_path_view<PathSystems>() const noexcept;
bool operator==(const abs_path& other) const noexcept;
bool operator!=(const abs_path& other) const noexcept;
auto operator<=>(const abs_path& other) const noexcept;
bool operator==(const abs_path_view<PathSystems>& other) const noexcept;
bool operator!=(const abs_path_view<PathSystems>& other) const noexcept;
auto operator<=>(const abs_path_view<PathSystems>& other) const noexcept;
void swap(abs_path& other) noexcept;
void clear() noexcept;
string str() const noexcept;
eastl::string eastl_str() const noexcept;
std::string std_str() const noexcept;
abs_path_view<PathSystems> view() const noexcept;
rel_path<PathSystems> subpath(size_t idx, int count = 0) const noexcept;
abs_path parent() const noexcept;
abs_path parent(size_t levels) const noexcept;
rel_path_view<PathSystems> subpath(size_t idx, int count = 0) const noexcept;
abs_path_view<PathSystems> parent() const noexcept;
abs_path_view<PathSystems> parent(size_t levels) const noexcept;
rel_path<PathSystems> path_to(const abs_path& to) const noexcept;
void path_to(rel_path<PathSystems>& dst, const abs_path& to) const noexcept;
bool is_prefix_of(const abs_path& path) const noexcept;
void path_to(rel_path<PathSystems>& dst, const abs_path& to) const noexcept;
bool is_prefix_of(const abs_path& path) const noexcept;
template <typename T>
bool is() const noexcept;
bool is_valid() const noexcept;
bool is() const noexcept;
bool is_valid() const noexcept;
bool push_back(string element) noexcept override;
const string& front() const noexcept;
const string& back() const noexcept;
string& front() noexcept;
string& back() noexcept;
bool push_back(string element) noexcept override;
const string& front() const noexcept;
const string& back() const noexcept;
void replace_back(string element) noexcept;
void take_elements(tl::vector<string>&& elements) noexcept override;
void take_elements(tl::vector<string>&& elements) noexcept override;
//Parses a string.
// 1st attempt is done to parse it as an absolute path. If it succeeds, it returns the path.
// 1st attempt is done to parse it as an abs path. If it succeeds, it returns the path.
// 2nd attempt is done to parse it as a relative path and if it succeeds, it returns it as fallbackRoot + relative path. This happens ONLY if the fallbackRoot is valid
template<typename Str>
static abs_path from_string(const Str& string, const abs_path& fallbackRoot) noexcept;
static abs_path from_string(const Str& string, const abs_path& fallbackRoot) noexcept;
//Parses a string as an absolute path. If it fails it returns an invalid path.
//Parses a string as an abs path. If it fails it returns an invalid path.
template<typename Str>
static abs_path from_string(const Str& string) noexcept;
static abs_path from_string(const Str& string) noexcept;
template<typename Str>
static bool is_valid_string(const Str& string) noexcept;
static bool is_valid_string(const Str& string) noexcept;
template<typename Str>
static bool has_valid_tag(const Str& string) noexcept;
static bool has_valid_tag(const Str& string) noexcept;
bool parse(const char* path, size_t size) noexcept;
bool parse(const char* path, size_t size) noexcept;
private:
bool collapse_path() noexcept;
bool collapse_path() noexcept;
int m_pathSystemId = -1;
};
@@ -124,15 +134,6 @@ namespace tl
{
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>::abs_path() noexcept
{
m_pathSystemId = -1;
this->m_hash = 0;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>::abs_path(const char* path, size_t size) noexcept
{
@@ -140,7 +141,26 @@ abs_path<PathSystems>::abs_path(const char* path, size_t size) noexcept
TL_PLAIN_CRASH("null path in abs_path constructor");
if (parse(path, size) == false)
TL_PLAIN_FAIL("Failed to parse absolute path");
TL_PLAIN_FAIL("Failed to parse abs path");
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>::abs_path(abs_path_view<PathSystems> view) noexcept
: m_pathSystemId(view.m_pathSystemId)
{
this->m_elements.insert(this->m_elements.end(), view.begin(), view.end());
this->m_hash = view.hash();
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>::abs_path(int path_system_id, span<const string> elements) noexcept
: m_pathSystemId(path_system_id)
{
this->m_elements.insert(this->m_elements.end(), elements.begin(), elements.end());
}
//////////////////////////////////////////////////////////////////////////
@@ -152,7 +172,7 @@ abs_path<PathSystems>::abs_path(const char* path) noexcept
TL_PLAIN_CRASH("null path in abs_path constructor");
if (parse(path, strlen(path)) == false)
TL_PLAIN_FAIL("Failed to parse absolute path");
TL_PLAIN_FAIL("Failed to parse abs path");
}
//////////////////////////////////////////////////////////////////////////
@@ -162,7 +182,7 @@ template <typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_
abs_path<PathSystems>::abs_path(const Str& path) noexcept
{
if (parse(path.data(), path.size()) == false)
TL_PLAIN_FAIL("Failed to parse absolute path");
TL_PLAIN_FAIL("Failed to parse abs path");
}
//////////////////////////////////////////////////////////////////////////
@@ -186,23 +206,6 @@ abs_path<PathSystems>::abs_path(abs_path&& other) noexcept
other.m_hash = 0;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
const string& abs_path<PathSystems>::operator[](size_t idx) const noexcept
{
return this->m_elements[idx];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
string& abs_path<PathSystems>::operator[](size_t idx) noexcept
{
this->m_hash = 0;
return this->m_elements[idx];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
@@ -232,13 +235,25 @@ template<typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_s
abs_path<PathSystems>& abs_path<PathSystems>::operator=(const Str& path) noexcept
{
if (parse(path.data(), path.size()) == false)
TL_PLAIN_FAIL("Failed to parse absolute path");
TL_PLAIN_FAIL("Failed to parse abs path");
return *this;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>& abs_path<PathSystems>::operator=(const abs_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;
m_pathSystemId = path.m_pathSystemId;
return *this;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>& abs_path<PathSystems>::operator=(const char* path) noexcept
{
@@ -246,7 +261,7 @@ abs_path<PathSystems>& abs_path<PathSystems>::operator=(const char* path) noexce
TL_PLAIN_CRASH("null path in abs_path assignment");
if (parse(path, strlen(path)) == false)
TL_PLAIN_FAIL("Failed to parse absolute path");
TL_PLAIN_FAIL("Failed to parse abs path");
return *this;
}
@@ -261,7 +276,6 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const char* path) const n
abs_path p;
p.reserve(this->size() + 1);
p = *this;
p += path;
return p;
}
@@ -279,7 +293,6 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const Str& path) const no
abs_path p;
p.reserve(this->size() + 1);
p = *this;
p += path;
return p;
}
@@ -294,9 +307,8 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const rel_path<PathSystem
if (!path.empty())
{
abs_path p;
p.reserve(this->size() + 1);
p.reserve(this->size() + path.size());
p = *this;
p += path;
return p;
}
@@ -311,9 +323,8 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(rel_path<PathSystems>&& p
if (!path.empty())
{
abs_path p;
p.reserve(this->size() + 1);
p.reserve(this->size() + path.size());
p = *this;
p += std::move(path);
return p;
}
@@ -326,7 +337,7 @@ template <typename PathSystems>
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const char* path) noexcept
{
if (m_pathSystemId < 0 && this->empty())
this->operator=(path);
*this = path;
else if (path && path[0] != '\0')
*this += rel_path<PathSystems>(path);
@@ -340,7 +351,7 @@ template<typename Str> requires (!std::is_same_v<Str, const char*> && !std::is_s
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const Str& path) noexcept
{
if (m_pathSystemId < 0 && this->empty())
this->operator=(path);
*this = path;
else if (!path.empty())
*this += rel_path<PathSystems>(path);
@@ -352,12 +363,8 @@ abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const Str& path) noexce
template <typename PathSystems>
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const rel_path<PathSystems>& path) noexcept
{
if (!path.empty())
{
//use the move version
*this += rel_path<PathSystems>(path);
this->collapse_path();
}
//use the move version
*this += rel_path<PathSystems>(path);
return *this;
}
@@ -374,8 +381,31 @@ abs_path<PathSystems>& abs_path<PathSystems>::operator+=(rel_path<PathSystems>&&
if (!push_back(std::move(e)))
return *this;
}
path.clear();
this->m_hash = 0;
this->collapse_path();
if (!this->collapse_path())
this->clear();
}
return *this;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const rel_path_view<PathSystems>& path) noexcept
{
if (!path.empty())
{
this->m_elements.reserve(this->m_elements.size() + path.size());
for (auto& e : path)
{
if (!push_back(std::move(e)))
return *this;
}
this->m_hash = 0;
if (!this->collapse_path())
this->clear();
}
return *this;
}
@@ -403,7 +433,41 @@ bool abs_path<PathSystems>::operator!=(const abs_path& other) const noexcept
template <typename PathSystems>
auto abs_path<PathSystems>::operator<=>(const abs_path& other) const noexcept
{
// return std::compare_three_way{}(this->m_elements, other.m_elements);
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;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
bool abs_path<PathSystems>::operator==(const abs_path_view<PathSystems>& other) const noexcept
{
return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) &&
this->m_pathSystemId == other.m_pathSystemId &&
tl::span(this->m_elements) == other.m_elements;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
bool abs_path<PathSystems>::operator!=(const abs_path_view<PathSystems>& other) const noexcept
{
return !(*this == other);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
auto abs_path<PathSystems>::operator<=>(const abs_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)
@@ -429,15 +493,7 @@ bool abs_path<PathSystems>::parse(const char* path, size_t size) noexcept
if (m_pathSystemId < 0)
return false;
PathSystems::parse_absolute(this->m_elements, m_pathSystemId, path, size);
for (const string& element : this->m_elements)
{
if (!this->validate_element(element))
{
this->clear();
return false;
}
}
PathSystems::parse_abs(this->m_elements, m_pathSystemId, path, size);
if (collapse_path() == false)
{
@@ -456,7 +512,7 @@ bool abs_path<PathSystems>::collapse_path() noexcept
if (this->empty())
return is_valid();
this->m_hash = 0;
const size_t oldSize = this->m_elements.size();
for (size_t i = 0; i < this->m_elements.size();)
{
if (i >= 1 &&
@@ -467,11 +523,14 @@ bool abs_path<PathSystems>::collapse_path() noexcept
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_elements.erase(this->m_elements.begin() + i); //remove the .
else
i++;
}
if (oldSize != this->m_elements.size())
this->m_hash = 0;
if (!PathSystems::validate_abs_path(m_pathSystemId, this->m_elements))
return false;
@@ -510,7 +569,7 @@ string abs_path<PathSystems>::str() const noexcept
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_absolute<string>(m_pathSystemId, this->m_elements);
return PathSystems::template format_abs<string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
@@ -521,7 +580,7 @@ eastl::string abs_path<PathSystems>::eastl_str() const noexcept
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_absolute<eastl::string>(m_pathSystemId, this->m_elements);
return PathSystems::template format_abs<eastl::string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
@@ -532,93 +591,68 @@ std::string abs_path<PathSystems>::std_str() const noexcept
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_absolute<std::string>(m_pathSystemId, this->m_elements);
return PathSystems::template format_abs<std::string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
rel_path<PathSystems> abs_path<PathSystems>::subpath(size_t idx, int count /* = 0 */) const noexcept
abs_path_view<PathSystems> abs_path<PathSystems>::view() const noexcept
{
return abs_path_view<PathSystems>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems>::operator abs_path_view<PathSystems>() const noexcept
{
return abs_path_view<PathSystems>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
rel_path_view<PathSystems> abs_path<PathSystems>::subpath(size_t index, int count /* = 0 */) const noexcept
{
rel_path<PathSystems> dst;
if (count == 0)
count = (int)this->size() - (int)idx;
count = (int)this->size() - (int)index;
if (count < 0)
count = (int)this->size() - (int)idx + count;
count = (int)this->size() - (int)index + count;
if (count > 0 && idx < this->size())
{
dst.reserve(count);
for (int i = 0; i < count; i++)
dst.push_element(this->m_elements[idx + i]);
}
return dst;
if (count > 0 && index < this->size())
return rel_path_view<PathSystems>(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count));
return {};
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems> abs_path<PathSystems>::parent() const noexcept
abs_path_view<PathSystems> abs_path<PathSystems>::parent() const noexcept
{
if (this->empty())
{
TL_PLAIN_FAIL("Invalid path");
return abs_path();
return {};
}
abs_path p = *this;
if (p.back() == path_system::back_t::value())
{
//do not do a pop_back here!!
//The parent of '/..' is '/../..'!!!
p.push_back(path_system::back_t::value());
}
else
p.pop_back();
if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements))
{
TL_PLAIN_FAIL("Invalid path");
return abs_path();
}
return p;
return abs_path_view<PathSystems>(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - 1));
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path<PathSystems> abs_path<PathSystems>::parent(size_t levels) const noexcept
abs_path_view<PathSystems> abs_path<PathSystems>::parent(size_t levels) const noexcept
{
if (this->empty() || this->size() <= levels)
{
TL_PLAIN_FAIL("Invalid path");
return abs_path();
return {};
}
abs_path p = *this;
if (p.back() == path_system::back_t::value())
{
//The parent of '/..' is '/../..'!!!
while (levels > 0)
{
levels--;
p.push_back(path_system::back_t::value());
}
}
else
p.shrink(p.size() - levels);
if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements))
{
TL_PLAIN_FAIL("Invalid path");
return abs_path();
}
return p;
return abs_path_view<PathSystems>(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - levels));
}
//////////////////////////////////////////////////////////////////////////
@@ -663,7 +697,7 @@ void abs_path<PathSystems>::path_to(rel_path<PathSystems>& dst, const abs_path&
}
else if (to.empty())
{
//ms relative path from an absolute path to an empty path should be an empty path
//ms relative path from an abs path to an empty path should be an empty path
}
else
{
@@ -772,21 +806,13 @@ const tl::string& abs_path<PathSystems>::front() const noexcept
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
tl::string& abs_path<PathSystems>::front() noexcept
void abs_path<PathSystems>::replace_back(string element) noexcept
{
TL_PLAIN_ASSERT(!this->empty());
this->m_hash = 0;
return this->m_elements.front();
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
tl::string& abs_path<PathSystems>::back() noexcept
{
TL_PLAIN_ASSERT(!this->empty());
this->m_hash = 0;
return this->m_elements.back();
this->m_elements.back() = std::move(element);
if (!collapse_path())
clear();
}
//////////////////////////////////////////////////////////////////////////
@@ -838,6 +864,53 @@ bool abs_path<PathSystems>::has_valid_tag(const Str& string) noexcept
return pathSystemId >= 0;
}
template<class PathSystems>
abs_path<PathSystems> operator+(const abs_path_view<PathSystems>& a, const char* b) noexcept
{
abs_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*>)
abs_path<PathSystems> operator+(const abs_path_view<PathSystems>& a, const Str& b) noexcept
{
abs_path<PathSystems> p;
p.reserve(a.size() + 1);
p = a;
p += b;
return p;
}
template<class PathSystems>
abs_path<PathSystems> operator+(const abs_path_view<PathSystems>& a, const rel_path<PathSystems>& b) noexcept
{
abs_path<PathSystems> p;
p.reserve(a.size() + b.size());
p = a;
p += b;
return p;
}
template<class PathSystems>
abs_path<PathSystems> operator+(const abs_path_view<PathSystems>& a, const rel_path_view<PathSystems>& b) noexcept
{
abs_path<PathSystems> p;
p.reserve(a.size() + b.size());
p = a;
p += b;
return p;
}
template<class PathSystems>
abs_path<PathSystems> operator+(const abs_path_view<PathSystems>& a, const abs_path_view<PathSystems>& b) noexcept
{
abs_path<PathSystems> p;
p.reserve(a.size() + b.size());
p = a;
p += b;
return p;
}
}
//////////////////////////////////////////////////////////////////////////
+322
View File
@@ -0,0 +1,322 @@
#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 abs_path;
template<typename PathSystems> class abs_path_view;
template<typename PathSystems> struct path_view_key_less;
//////////////////////////////////////////////////////////////////////////
template<typename PathSystems>
class abs_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>;
abs_path_view() noexcept;
abs_path_view(int pathSystemId, tl::span<const string> elements) noexcept;
abs_path_view(const abs_path_view& other) noexcept;
// operators
abs_path_view& operator=(const abs_path_view& other) noexcept;
bool operator==(const abs_path_view& other) const noexcept;
bool operator!=(const abs_path_view& other) const noexcept;
auto operator<=>(const abs_path_view& other) const noexcept;
void swap(abs_path_view& other) noexcept;
void clear() noexcept;
string str() const noexcept;
eastl::string eastl_str() const noexcept;
std::string std_str() const noexcept;
rel_path_view<PathSystems> subpath(size_t idx, int count = 0) const noexcept;
abs_path_view parent() const noexcept;
abs_path_view parent(size_t levels) const noexcept;
bool is_prefix_of(const abs_path_view& path) const noexcept;
//This only works if `this` is a prefix of `to`, in other words, only if the resultant path can be expressed as a view of the `to` path
// This is true when going from a parent to a subfolder
//Example:
//Good: ("/a/b/c").prefix_path_to("/a/b/c/d") == ("d")
//Bad: ("/a/b/c").prefix_path_to("/a/b") == ("") will assert and return empty. It should return ".." but it cannot
rel_path_view<PathSystems> prefix_path_to(const abs_path_view& to) const noexcept;
template <typename T>
bool is() const noexcept;
bool is_valid() const noexcept;
private:
int m_pathSystemId = -1;
friend class abs_path<PathSystems>;
};
//////////////////////////////////////////////////////////////////////////
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
namespace tl
{
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path_view<PathSystems>::abs_path_view() noexcept
{
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path_view<PathSystems>::abs_path_view(int pathSystemId, tl::span<const string> elements) noexcept
: path_view_base(elements)
, m_pathSystemId(pathSystemId)
{
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path_view<PathSystems>::abs_path_view(const abs_path_view& other) noexcept
: path_view_base(other)
, m_pathSystemId(other.m_pathSystemId)
{
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path_view<PathSystems>& abs_path_view<PathSystems>::operator=(const abs_path_view& other) noexcept
{
m_elements = other.m_elements;
m_hash = other.m_hash;
m_pathSystemId = other.m_pathSystemId;
return *this;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
bool abs_path_view<PathSystems>::operator==(const abs_path_view& other) const noexcept
{
return (!this->m_hash || !other.m_hash || this->m_hash == other.m_hash) &&
this->m_pathSystemId == other.m_pathSystemId &&
this->m_elements == other.m_elements;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
bool abs_path_view<PathSystems>::operator!=(const abs_path_view& other) const noexcept
{
return !(*this == other);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
void abs_path_view<PathSystems>::clear() noexcept
{
m_elements = {};
m_hash = 0;
m_pathSystemId = -1;
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
string abs_path_view<PathSystems>::str() const noexcept
{
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_abs<string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
eastl::string abs_path_view<PathSystems>::eastl_str() const noexcept
{
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_abs<eastl::string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
std::string abs_path_view<PathSystems>::std_str() const noexcept
{
if (!is_valid() && this->empty())
return {};
return PathSystems::template format_abs<std::string>(m_pathSystemId, this->m_elements);
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
rel_path_view<PathSystems> abs_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>
abs_path_view<PathSystems> abs_path_view<PathSystems>::parent() const noexcept
{
if (this->empty())
{
TL_PLAIN_FAIL("Invalid path");
return {};
}
abs_path_view p = *this;
p.pop_back();
if (!PathSystems::validate_abs_path(p.m_pathSystemId, p.m_elements))
{
TL_PLAIN_FAIL("Invalid path");
return {};
}
return p;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
abs_path_view<PathSystems> abs_path_view<PathSystems>::parent(size_t levels) const noexcept
{
if (this->empty() || this->size() <= levels)
{
TL_PLAIN_FAIL("Invalid path");
return {};
}
abs_path_view<PathSystems> p = *this;
p.shrink(p.size() - levels);
return p;
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
template <typename T>
bool abs_path_view<PathSystems>::is() const noexcept
{
return PathSystems::template is<T>(m_pathSystemId);
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
bool abs_path_view<PathSystems>::is_valid() const noexcept
{
return m_pathSystemId >= 0;
}
//////////////////////////////////////////////////////////////////////////
template<class PathSystems>
bool abs_path_view<PathSystems>::is_prefix_of(const abs_path_view& path) const noexcept
{
if (m_pathSystemId != path.m_pathSystemId)
return false;
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<class PathSystems>
rel_path_view<PathSystems> abs_path_view<PathSystems>::prefix_path_to(const abs_path_view& to) const noexcept
{
if (this->empty())
return rel_path_view<PathSystems>(to.m_elements);
if (!is_prefix_of(to))
{
TL_PLAIN_FAIL("Invalid path");
return {};
}
return rel_path_view<PathSystems>(tl::span(to.m_elements.begin() + size(), to.m_elements.end()));
}
}
//////////////////////////////////////////////////////////////////////////
template <class PathSystems>
struct std::formatter<tl::abs_path_view<PathSystems>>
{
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
auto format(const tl::abs_path_view<PathSystems>& p, std::format_context& ctx) const
{
return format_to(ctx.out(), "{}", p.str());
}
};
template <typename T>
struct std::hash<tl::abs_path_view<T>>
{
std::size_t operator()(const tl::abs_path_view<T>& p) const
{
return p.hash();
}
};
template <typename T>
struct eastl::hash<tl::abs_path_view<T>>
{
std::size_t operator()(const tl::abs_path_view<T>& p) const
{
return p.hash();
}
};
+48 -30
View File
@@ -28,36 +28,38 @@ public:
using key_less = path_key_less<PathSystems>;
using value_type = std::string;
//checked indexing
const string& at(size_t index) const noexcept;
//both have checked indexing
const string& operator[](size_t index) const noexcept;
string& operator[](size_t index) noexcept;
const string& at(size_t index) const noexcept;
string& at(size_t index) noexcept;
void shrink(size_t size) noexcept;
bool empty() const noexcept;
size_t size() const noexcept;
size_t size() const noexcept;
void reserve(size_t capacity) noexcept;
// if the path is empty, these operations have no effect. They return the removed element as a string.
string pop_back() noexcept;
virtual bool push_back(string element) noexcept;
string pop_back() noexcept;
virtual bool push_back(string element) noexcept;
virtual void take_elements(tl::vector<string>&& elements) noexcept;
virtual void take_elements(tl::vector<string>&& elements) noexcept;
iterator begin() noexcept;
iterator end() noexcept;
iterator begin() noexcept;
iterator end() noexcept;
const_iterator begin() const noexcept;
const_iterator end() const noexcept;
const_reverse_iterator rbegin() const noexcept;
const_reverse_iterator rend() const noexcept;
uint32_t hash() const noexcept;
uint32_t hash() const noexcept;
protected:
bool validate_element(const string& element) noexcept;
void push_element(string element) noexcept;
void push_element(string element) noexcept;
tl::vector<string> m_elements;
mutable uint32_t m_hash = 0;
mutable uint32_t m_hash = 0;
friend bool path_key_less<PathSystems>::operator()(const path_base<PathSystems>& a1, const path_base<PathSystems>& a2) const noexcept;
};
@@ -87,9 +89,43 @@ namespace path_system
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
const string& path_base<PathSystems>::operator[](size_t index) const noexcept
{
if (index >= m_elements.size())
TL_PLAIN_CRASH("Illegal access");
return m_elements[index];
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
string& path_base<PathSystems>::operator[](size_t index) noexcept
{
if (index >= m_elements.size())
TL_PLAIN_CRASH("Illegal access");
m_hash = 0;
return m_elements[index];
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
const string& path_base<PathSystems>::at(size_t index) const noexcept
{
if (index >= m_elements.size())
TL_PLAIN_CRASH("Illegal access");
return m_elements[index];
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
string& path_base<PathSystems>::at(size_t index) noexcept
{
if (index >= m_elements.size())
TL_PLAIN_CRASH("Illegal access");
m_hash = 0;
return m_elements[index];
}
@@ -164,25 +200,7 @@ string path_base<PathSystems>::pop_back() noexcept
template <typename PathSystems>
bool path_base<PathSystems>::push_back(string element) noexcept
{
if (!validate_element(element))
{
TL_PLAIN_FAIL("Pushed an invalid path element.");
return false;
}
push_element(std::move(element));
return true;
}
//////////////////////////////////////////////////////////////////////////
template <typename PathSystems>
bool path_base<PathSystems>::validate_element(const string& /*element*/) noexcept
{
// validate element to be added here
// if not return false
return true;
}
+40 -30
View File
@@ -1,5 +1,7 @@
#pragma once
#include <EASTL/fixed_string.h>
#include "tl/detail/prologue.h"
#include <EASTL/fixed_vector.h>
#include "tl/string.h"
@@ -15,9 +17,9 @@ namespace path_system
//////////////////////////////////////////////////////////////////////////
template<typename T>
void simple_format_rel_path(T& o_buffer, const tl::vector<string>& members, const char* separator) noexcept;
void simple_format_rel_path(T& o_buffer, tl::span<const string> members, const char* separator) noexcept;
template<typename T>
void simple_format_abs_path(T& o_buffer, const tl::vector<string>& members, const char* root_tag, const char* separator) noexcept;
void simple_format_abs_path(T& o_buffer, tl::span<const string> members, const char* root_tag, const char* separator) noexcept;
inline bool find_next_separator(const char* const* separators_begin, const char* const* separators_end, const char*& io_startIt, const char* end, const char*& io_endIt) noexcept;
@@ -31,10 +33,10 @@ template<int Index, typename... Tail>
struct path_system_getter
{
template<typename T>
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
static T format_abs(int type_idx, tl::span<const string> members) noexcept;
static void parse_abs(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
static int deduce_system_type(const char* path, size_t size) noexcept;
static bool validate_abs_path(int type_idx, const tl::vector<string>& members) noexcept;
static bool validate_abs_path(int type_idx, tl::span<const string> members) noexcept;
};
// specialization if Head element exists
@@ -42,10 +44,10 @@ template<int Index, typename Head, typename... Tail>
struct path_system_getter<Index, Head, Tail...>
{
template<typename T>
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
static T format_abs(int type_idx, tl::span<const string> members) noexcept;
static void parse_abs(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
static int deduce_system_type(const char* path, size_t size) noexcept;
static bool validate_abs_path(int type_idx, const tl::vector<string>& members) noexcept;
static bool validate_abs_path(int type_idx, tl::span<const string> members) noexcept;
};
//////////////////////////////////////////////////////////////////////////
@@ -85,7 +87,8 @@ struct base_path_system
static const tl::vector<const char*>& get_parse_separators() noexcept;
static const char* get_format_separator() noexcept;
static string format_relative(const tl::vector<string>& members) noexcept;
template<typename T>
static T format_rel(tl::span<const string> members) noexcept;
};
//////////////////////////////////////////////////////////////////////////
@@ -110,7 +113,7 @@ namespace path_system
//////////////////////////////////////////////////////////////////////////
template<typename T>
void simple_format_rel_path(T& o_buffer, const tl::vector<string>& members, const char* separator) noexcept
void simple_format_rel_path(T& o_buffer, tl::span<const string> members, const char* separator) noexcept
{
//calculate the size to reserve
size_t totalSize = 0;
@@ -133,8 +136,18 @@ void simple_format_rel_path(T& o_buffer, const tl::vector<string>& members, cons
//////////////////////////////////////////////////////////////////////////
template<>
inline void simple_format_rel_path(string& o_buffer, tl::span<const string> members, const char* separator) noexcept
{
tl::fixed_string<char, 1024> temp;
simple_format_rel_path(temp, members, separator);
o_buffer = string(temp);
}
//////////////////////////////////////////////////////////////////////////
template<typename T>
void simple_format_abs_path(T& o_buffer, const tl::vector<string>& members, const char* root_tag, const char* separator) noexcept
void simple_format_abs_path(T& o_buffer, tl::span<const string> members, const char* root_tag, const char* separator) noexcept
{
o_buffer.append(root_tag);
detail::path_system::simple_format_rel_path(o_buffer, members, separator);
@@ -246,16 +259,16 @@ inline bool simple_match_prefix(const char* path, size_t size, const char* prefi
template<int Index, typename... Tail>
template<typename T>
T path_system_getter<Index, Tail...>::format_absolute(int /*type_idx*/, const tl::vector<string>& /*members*/) noexcept
T path_system_getter<Index, Tail...>::format_abs(int /*type_idx*/, tl::span<const string> /*members*/) noexcept
{
TL_PLAIN_FAIL("Failed to format path. Invalid type.");
return {};
}
template<int Index, typename... Tail>
void path_system_getter<Index, Tail...>::parse_absolute(tl::vector<string>& /*o_elements*/, int /*type_idx*/, const char* /*path*/, size_t /* size */) noexcept
void path_system_getter<Index, Tail...>::parse_abs(tl::vector<string>& /*o_elements*/, int /*type_idx*/, const char* /*path*/, size_t /* size */) noexcept
{
TL_PLAIN_FAIL("Failed parsing absolute path. Invalid type.");
TL_PLAIN_FAIL("Failed parsing abs path. Invalid type.");
}
template<int Index, typename... Tail>
@@ -265,7 +278,7 @@ int path_system_getter<Index, Tail...>::deduce_system_type(const char* /*path*/,
}
template<int Index, typename... Tail>
bool path_system_getter<Index, Tail...>::validate_abs_path(int /*type_idx*/, const tl::vector<string>& /*members*/) noexcept
bool path_system_getter<Index, Tail...>::validate_abs_path(int /*type_idx*/, tl::span<const string> /*members*/) noexcept
{
TL_PLAIN_FAIL("Failed validating path system. Invalid type.");
return false;
@@ -275,23 +288,23 @@ bool path_system_getter<Index, Tail...>::validate_abs_path(int /*type_idx*/, con
template<int Index, typename Head, typename... Tail>
template<typename T>
T path_system_getter<Index, Head, Tail...>::format_absolute(int type_idx, const tl::vector<string>& members) noexcept
T path_system_getter<Index, Head, Tail...>::format_abs(int type_idx, tl::span<const string> members) noexcept
{
if (type_idx == Index)
return Head::template format_absolute<T>(members);
return Head::template format_abs<T>(members);
return path_system_getter<Index + 1, Tail...>::template format_absolute<T>(type_idx, members);
return path_system_getter<Index + 1, Tail...>::template format_abs<T>(type_idx, members);
}
template<int Index, typename Head, typename... Tail>
void path_system_getter<Index, Head, Tail...>::parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept
void path_system_getter<Index, Head, Tail...>::parse_abs(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept
{
if (type_idx == Index)
{
Head::parse_absolute(o_elements, path, size);
Head::parse_abs(o_elements, path, size);
return;
}
path_system_getter<Index + 1, Tail...>::parse_absolute(o_elements, type_idx, path, size);
path_system_getter<Index + 1, Tail...>::parse_abs(o_elements, type_idx, path, size);
}
@@ -305,7 +318,7 @@ int path_system_getter<Index, Head, Tail...>::deduce_system_type(const char* pat
}
template<int Index, typename Head, typename... Tail>
bool path_system_getter<Index, Head, Tail...>::validate_abs_path(int type_idx, const tl::vector<string>& members) noexcept
bool path_system_getter<Index, Head, Tail...>::validate_abs_path(int type_idx, tl::span<const string> members) noexcept
{
if (type_idx == Index)
return Head::validate_abs_path(members);
@@ -365,15 +378,12 @@ const tl::vector<const char*>& base_path_system<parse_separators, format_separat
//////////////////////////////////////////////////////////////////////////
template<typename parse_separators, typename format_separator>
string base_path_system<parse_separators, format_separator>::format_relative(const tl::vector<string>& members) noexcept
template<typename T>
T base_path_system<parse_separators, format_separator>::format_rel(tl::span<const string> members) noexcept
{
eastl::string buffer;
buffer.reserve(8192);
detail::path_system::simple_format_rel_path(buffer, members, format_separator::value());
if (buffer.data())
return string(buffer.data(), buffer.size());
return string();
T string;
detail::path_system::simple_format_rel_path(string, members, format_separator::value());
return string;
}
//////////////////////////////////////////////////////////////////////////
+219
View File
@@ -0,0 +1,219 @@
#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<const string> elements) noexcept;
virtual ~path_view_base() noexcept = default;
using iterator = tl::span<const string>::iterator;
using const_iterator = tl::span<const string>::const_iterator;
using const_reverse_iterator = tl::span<const string>::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<const string> 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<const string> 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<const string>(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<const string>(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;
}
}
}
}
+15 -14
View File
@@ -1,6 +1,7 @@
#pragma once
#include "tl/detail/prologue.h"
#include <tl/span.h>
#include <tl/vector.h>
#include <tl/fixed_vector.h>
#include "tl/string.h"
@@ -60,11 +61,11 @@ template <typename... Systems>
struct path_systems
{
template<typename T>
static T format_absolute(int type_id, const tl::vector<string>& members) noexcept;
static void parse_absolute(tl::vector<string>& o_elements, int type_id, const char* path, size_t size) noexcept;
static T format_abs(int type_id, tl::span<const string> members) noexcept;
static void parse_abs(tl::vector<string>& o_elements, int type_id, const char* path, size_t size) noexcept;
static void parse_relative(tl::vector<string>& o_elements, const char* path, size_t size) noexcept;
static int deduce_system_type(const char* path, size_t size) noexcept;
static bool validate_abs_path(int type_id, const tl::vector<string>& members) noexcept;
static bool validate_abs_path(int type_id, tl::span<const string> members) noexcept;
static const tl::vector<tl::vector<const char*> >& get_all_parse_separators() noexcept;
template <typename TypeToCheck>
@@ -84,9 +85,9 @@ template<typename root_tag, typename parse_separators, typename format_separator
struct simple_path_system : public detail::path_system::base_path_system<parse_separators, format_separator>
{
template<typename T>
static T format_absolute(const tl::vector<string>& members) noexcept;
static void parse_absolute(tl::vector<string>& o_elements, const char* path, size_t size) noexcept;
static bool validate_abs_path(const tl::vector<string>& members) noexcept;
static T format_abs(tl::span<const string> members) noexcept;
static void parse_abs(tl::vector<string>& o_elements, const char* path, size_t size) noexcept;
static bool validate_abs_path(tl::span<const string> members) noexcept;
static bool match(const char* path, size_t size) noexcept;
};
@@ -105,19 +106,19 @@ namespace tl
template <typename... Systems>
template<typename T>
T path_systems<Systems...>::format_absolute(int type_id, const tl::vector<string>& members) noexcept
T path_systems<Systems...>::format_abs(int type_id, tl::span<const string> members) noexcept
{
TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to format an unknown path system type.");
return detail::path_system::path_system_getter<0, Systems...>::template format_absolute<T>(type_id, members);
return detail::path_system::path_system_getter<0, Systems...>::template format_abs<T>(type_id, members);
}
//////////////////////////////////////////////////////////////////////////
template <typename... Systems>
void path_systems<Systems...>::parse_absolute(tl::vector<string>& o_elements, int type_id, const char* path, size_t size) noexcept
void path_systems<Systems...>::parse_abs(tl::vector<string>& o_elements, int type_id, const char* path, size_t size) noexcept
{
TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to parse an unknown path system type.");
detail::path_system::path_system_getter<0, Systems...>::parse_absolute(o_elements, type_id, path, size);
detail::path_system::path_system_getter<0, Systems...>::parse_abs(o_elements, type_id, path, size);
}
//////////////////////////////////////////////////////////////////////////
@@ -131,7 +132,7 @@ int path_systems<Systems...>::deduce_system_type(const char* path, size_t size)
//////////////////////////////////////////////////////////////////////////
template <typename... Systems>
bool path_systems<Systems...>::validate_abs_path(int type_id, const tl::vector<string>& members) noexcept
bool path_systems<Systems...>::validate_abs_path(int type_id, tl::span<const string> members) noexcept
{
TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to validate an unknown path system type.");
return detail::path_system::path_system_getter<0, Systems...>::validate_abs_path(type_id, members);
@@ -232,7 +233,7 @@ bool path_systems<Systems...>::is(int type_id) noexcept
template<typename root_tag, typename parse_separators, typename format_separator>
template<typename T>
T simple_path_system<root_tag, parse_separators, format_separator>::format_absolute(const tl::vector<string>& members) noexcept
T simple_path_system<root_tag, parse_separators, format_separator>::format_abs(tl::span<const string> members) noexcept
{
if constexpr (is_same_v<T, string>)
{
@@ -252,7 +253,7 @@ T simple_path_system<root_tag, parse_separators, format_separator>::format_absol
//////////////////////////////////////////////////////////////////////////
template<typename root_tag, typename parse_separators, typename format_separator>
void simple_path_system<root_tag, parse_separators, format_separator>::parse_absolute(tl::vector<string>& o_elements, const char* path, size_t size) noexcept
void simple_path_system<root_tag, parse_separators, format_separator>::parse_abs(tl::vector<string>& o_elements, const char* path, size_t size) noexcept
{
detail::path_system::simple_parse_path(o_elements, path, size, root_tag::value(), parse_separators::vector());
}
@@ -268,7 +269,7 @@ bool simple_path_system<root_tag, parse_separators, format_separator>::match(con
//////////////////////////////////////////////////////////////////////////
template<typename root_tag, typename parse_separators, typename format_separator>
bool simple_path_system<root_tag, parse_separators, format_separator>::validate_abs_path(const tl::vector<string>& /*members*/) noexcept
bool simple_path_system<root_tag, parse_separators, format_separator>::validate_abs_path(tl::span<const string> /*members*/) noexcept
{
return true;
}
+221 -109
View File
@@ -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>());
}
};
+277
View File
@@ -0,0 +1,277 @@
#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();
}
};
+1700
View File
File diff suppressed because it is too large Load Diff