Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 0958760b69 | |||
| 25063b4f6d | |||
| 2195ccfc28 | |||
| 51cf1887cd | |||
| 7539eed0b0 | |||
| 932e770687 |
@@ -59,18 +59,7 @@ target_link_libraries(TL EASTL)
|
|||||||
#endif()
|
#endif()
|
||||||
|
|
||||||
if (0)
|
if (0)
|
||||||
#//////////////////////////////////
|
|
||||||
|
|
||||||
set(Boost_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../boost")
|
|
||||||
set(Boost_LIBRARY_DIR "${PROJECT_SOURCE_DIR}/../boost/stage/lib")
|
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
|
||||||
set(Boost_USE_MULTITHREADED ON)
|
|
||||||
set(Boost_USE_STATIC_RUNTIME OFF)
|
|
||||||
find_package(Boost 1.69 COMPONENTS unit_test_framework)
|
|
||||||
|
|
||||||
file(GLOB_RECURSE TEST_SRC "test/*.cpp" "test/*.h")
|
file(GLOB_RECURSE TEST_SRC "test/*.cpp" "test/*.h")
|
||||||
add_executable(TL_Test ${TEST_SRC})
|
add_executable(TL_Test ${TEST_SRC})
|
||||||
target_link_libraries(TL_Test TL)
|
target_link_libraries(TL_Test TL)
|
||||||
target_link_libraries(TL_Test ${Boost_LIBRARIES})
|
|
||||||
target_include_directories(TL_Test PUBLIC ${Boost_INCLUDE_DIRS})
|
|
||||||
endif()
|
endif()
|
||||||
+215
-137
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
#include "tl/detail/prologue.h"
|
#include "tl/detail/prologue.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "tl/abs_path_view.h"
|
||||||
|
#include "tl/rel_path_view.h"
|
||||||
#include "tl/path_system.h"
|
#include "tl/path_system.h"
|
||||||
#include "tl/rel_path.h"
|
#include "tl/rel_path.h"
|
||||||
#include "tl/detail/path_base.h"
|
#include "tl/detail/path_base.h"
|
||||||
@@ -23,8 +26,11 @@ class abs_path : public detail::path_system::path_base<PathSystems>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using rel_path_type = rel_path<PathSystems>;
|
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;
|
explicit abs_path(const char* path) noexcept;
|
||||||
abs_path(const char* path, size_t size) noexcept;
|
abs_path(const char* path, size_t size) noexcept;
|
||||||
|
|
||||||
@@ -35,15 +41,13 @@ public:
|
|||||||
abs_path(abs_path&& other) noexcept;
|
abs_path(abs_path&& other) noexcept;
|
||||||
|
|
||||||
// operators
|
// 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=(const abs_path& other) noexcept;
|
||||||
abs_path& operator=(abs_path&& other) noexcept;
|
abs_path& operator=(abs_path&& other) noexcept;
|
||||||
|
|
||||||
abs_path& operator=(const char* path) 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*>)
|
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 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 char* path) const noexcept;
|
||||||
abs_path operator+(const rel_path<PathSystems>& path) const noexcept;
|
abs_path operator+(const rel_path<PathSystems>& path) const noexcept;
|
||||||
@@ -56,22 +60,29 @@ public:
|
|||||||
abs_path& operator+=(rel_path<PathSystems>&& path) noexcept;
|
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*>)
|
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 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;
|
||||||
bool operator!=(const abs_path& other) const noexcept;
|
bool operator!=(const abs_path& other) const noexcept;
|
||||||
|
|
||||||
auto 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 swap(abs_path& other) noexcept;
|
||||||
|
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
string str() const noexcept;
|
string str() const noexcept;
|
||||||
eastl::string eastl_str() const noexcept;
|
eastl::string eastl_str() const noexcept;
|
||||||
std::string std_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;
|
rel_path_view<PathSystems> subpath(size_t idx, int count = 0) const noexcept;
|
||||||
abs_path parent() const noexcept;
|
abs_path_view<PathSystems> parent() const noexcept;
|
||||||
abs_path parent(size_t levels) const noexcept;
|
abs_path_view<PathSystems> parent(size_t levels) const noexcept;
|
||||||
rel_path<PathSystems> path_to(const abs_path& to) 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;
|
void path_to(rel_path<PathSystems>& dst, const abs_path& to) const noexcept;
|
||||||
bool is_prefix_of(const abs_path& path) const noexcept;
|
bool is_prefix_of(const abs_path& path) const noexcept;
|
||||||
@@ -83,19 +94,18 @@ public:
|
|||||||
bool push_back(string element) noexcept override;
|
bool push_back(string element) noexcept override;
|
||||||
const string& front() const noexcept;
|
const string& front() const noexcept;
|
||||||
const string& back() const noexcept;
|
const string& back() const noexcept;
|
||||||
string& front() noexcept;
|
void replace_back(string element) noexcept;
|
||||||
string& back() noexcept;
|
|
||||||
|
|
||||||
void take_elements(tl::vector<string>&& elements) noexcept override;
|
void take_elements(tl::vector<string>&& elements) noexcept override;
|
||||||
|
|
||||||
|
|
||||||
//Parses a string.
|
//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
|
// 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>
|
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>
|
template<typename Str>
|
||||||
static abs_path from_string(const Str& string) noexcept;
|
static abs_path from_string(const Str& string) noexcept;
|
||||||
|
|
||||||
@@ -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>
|
template <typename PathSystems>
|
||||||
abs_path<PathSystems>::abs_path(const char* path, size_t size) noexcept
|
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");
|
TL_PLAIN_CRASH("null path in abs_path constructor");
|
||||||
|
|
||||||
if (parse(path, size) == false)
|
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");
|
TL_PLAIN_CRASH("null path in abs_path constructor");
|
||||||
|
|
||||||
if (parse(path, strlen(path)) == false)
|
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
|
abs_path<PathSystems>::abs_path(const Str& path) noexcept
|
||||||
{
|
{
|
||||||
if (parse(path.data(), path.size()) == false)
|
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;
|
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>
|
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
|
abs_path<PathSystems>& abs_path<PathSystems>::operator=(const Str& path) noexcept
|
||||||
{
|
{
|
||||||
if (parse(path.data(), path.size()) == false)
|
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;
|
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>
|
template <typename PathSystems>
|
||||||
abs_path<PathSystems>& abs_path<PathSystems>::operator=(const char* path) noexcept
|
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");
|
TL_PLAIN_CRASH("null path in abs_path assignment");
|
||||||
|
|
||||||
if (parse(path, strlen(path)) == false)
|
if (parse(path, strlen(path)) == false)
|
||||||
TL_PLAIN_FAIL("Failed to parse absolute path");
|
TL_PLAIN_FAIL("Failed to parse abs path");
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -261,7 +276,6 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const char* path) const n
|
|||||||
abs_path p;
|
abs_path p;
|
||||||
p.reserve(this->size() + 1);
|
p.reserve(this->size() + 1);
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
p += path;
|
p += path;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -279,7 +293,6 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const Str& path) const no
|
|||||||
abs_path p;
|
abs_path p;
|
||||||
p.reserve(this->size() + 1);
|
p.reserve(this->size() + 1);
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
p += path;
|
p += path;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -294,9 +307,8 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(const rel_path<PathSystem
|
|||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
abs_path p;
|
abs_path p;
|
||||||
p.reserve(this->size() + 1);
|
p.reserve(this->size() + path.size());
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
p += path;
|
p += path;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -311,9 +323,8 @@ abs_path<PathSystems> abs_path<PathSystems>::operator+(rel_path<PathSystems>&& p
|
|||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
abs_path p;
|
abs_path p;
|
||||||
p.reserve(this->size() + 1);
|
p.reserve(this->size() + path.size());
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
p += std::move(path);
|
p += std::move(path);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -326,7 +337,7 @@ template <typename PathSystems>
|
|||||||
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const char* path) noexcept
|
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const char* path) noexcept
|
||||||
{
|
{
|
||||||
if (m_pathSystemId < 0 && this->empty())
|
if (m_pathSystemId < 0 && this->empty())
|
||||||
this->operator=(path);
|
*this = path;
|
||||||
else if (path && path[0] != '\0')
|
else if (path && path[0] != '\0')
|
||||||
*this += rel_path<PathSystems>(path);
|
*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
|
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const Str& path) noexcept
|
||||||
{
|
{
|
||||||
if (m_pathSystemId < 0 && this->empty())
|
if (m_pathSystemId < 0 && this->empty())
|
||||||
this->operator=(path);
|
*this = path;
|
||||||
else if (!path.empty())
|
else if (!path.empty())
|
||||||
*this += rel_path<PathSystems>(path);
|
*this += rel_path<PathSystems>(path);
|
||||||
|
|
||||||
@@ -351,13 +362,9 @@ abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const Str& path) noexce
|
|||||||
|
|
||||||
template <typename PathSystems>
|
template <typename PathSystems>
|
||||||
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const rel_path<PathSystems>& path) noexcept
|
abs_path<PathSystems>& abs_path<PathSystems>::operator+=(const rel_path<PathSystems>& path) noexcept
|
||||||
{
|
|
||||||
if (!path.empty())
|
|
||||||
{
|
{
|
||||||
//use the move version
|
//use the move version
|
||||||
*this += rel_path<PathSystems>(path);
|
*this += rel_path<PathSystems>(path);
|
||||||
this->collapse_path();
|
|
||||||
}
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,8 +381,31 @@ abs_path<PathSystems>& abs_path<PathSystems>::operator+=(rel_path<PathSystems>&&
|
|||||||
if (!push_back(std::move(e)))
|
if (!push_back(std::move(e)))
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
path.clear();
|
||||||
|
|
||||||
this->m_hash = 0;
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -403,7 +433,41 @@ bool abs_path<PathSystems>::operator!=(const abs_path& other) const noexcept
|
|||||||
template <typename PathSystems>
|
template <typename PathSystems>
|
||||||
auto abs_path<PathSystems>::operator<=>(const abs_path& other) const noexcept
|
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 sz1 = this->m_elements.size();
|
||||||
const size_t sz2 = other.m_elements.size();
|
const size_t sz2 = other.m_elements.size();
|
||||||
for (size_t i = 0; i < sz1 && i < sz2; ++i)
|
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)
|
if (m_pathSystemId < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PathSystems::parse_absolute(this->m_elements, m_pathSystemId, path, size);
|
PathSystems::parse_abs(this->m_elements, m_pathSystemId, path, size);
|
||||||
for (const string& element : this->m_elements)
|
|
||||||
{
|
|
||||||
if (!this->validate_element(element))
|
|
||||||
{
|
|
||||||
this->clear();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collapse_path() == false)
|
if (collapse_path() == false)
|
||||||
{
|
{
|
||||||
@@ -456,7 +512,7 @@ bool abs_path<PathSystems>::collapse_path() noexcept
|
|||||||
if (this->empty())
|
if (this->empty())
|
||||||
return is_valid();
|
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();)
|
for (size_t i = 0; i < this->m_elements.size();)
|
||||||
{
|
{
|
||||||
if (i >= 1 &&
|
if (i >= 1 &&
|
||||||
@@ -472,6 +528,9 @@ bool abs_path<PathSystems>::collapse_path() noexcept
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (oldSize != this->m_elements.size())
|
||||||
|
this->m_hash = 0;
|
||||||
|
|
||||||
if (!PathSystems::validate_abs_path(m_pathSystemId, this->m_elements))
|
if (!PathSystems::validate_abs_path(m_pathSystemId, this->m_elements))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -510,7 +569,7 @@ string abs_path<PathSystems>::str() const noexcept
|
|||||||
if (!is_valid() && this->empty())
|
if (!is_valid() && this->empty())
|
||||||
return {};
|
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())
|
if (!is_valid() && this->empty())
|
||||||
return {};
|
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())
|
if (!is_valid() && this->empty())
|
||||||
return {};
|
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>
|
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;
|
rel_path<PathSystems> dst;
|
||||||
if (count == 0)
|
if (count == 0)
|
||||||
count = (int)this->size() - (int)idx;
|
count = (int)this->size() - (int)index;
|
||||||
|
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
count = (int)this->size() - (int)idx + count;
|
count = (int)this->size() - (int)index + count;
|
||||||
|
|
||||||
if (count > 0 && idx < this->size())
|
if (count > 0 && index < this->size())
|
||||||
{
|
return rel_path_view<PathSystems>(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count));
|
||||||
dst.reserve(count);
|
|
||||||
for (int i = 0; i < count; i++)
|
return {};
|
||||||
dst.push_element(this->m_elements[idx + i]);
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename PathSystems>
|
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())
|
if (this->empty())
|
||||||
{
|
{
|
||||||
TL_PLAIN_FAIL("Invalid path");
|
TL_PLAIN_FAIL("Invalid path");
|
||||||
return abs_path();
|
return {};
|
||||||
}
|
}
|
||||||
|
return abs_path_view<PathSystems>(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - 1));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename PathSystems>
|
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)
|
if (this->empty() || this->size() <= levels)
|
||||||
{
|
{
|
||||||
TL_PLAIN_FAIL("Invalid path");
|
TL_PLAIN_FAIL("Invalid path");
|
||||||
return abs_path();
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
abs_path p = *this;
|
return abs_path_view<PathSystems>(m_pathSystemId, tl::span(this->m_elements.begin(), this->m_elements.end() - levels));
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -663,7 +697,7 @@ void abs_path<PathSystems>::path_to(rel_path<PathSystems>& dst, const abs_path&
|
|||||||
}
|
}
|
||||||
else if (to.empty())
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -772,21 +806,13 @@ const tl::string& abs_path<PathSystems>::front() const noexcept
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class PathSystems>
|
template<class PathSystems>
|
||||||
tl::string& abs_path<PathSystems>::front() noexcept
|
void abs_path<PathSystems>::replace_back(string element) noexcept
|
||||||
{
|
{
|
||||||
TL_PLAIN_ASSERT(!this->empty());
|
TL_PLAIN_ASSERT(!this->empty());
|
||||||
this->m_hash = 0;
|
this->m_hash = 0;
|
||||||
return this->m_elements.front();
|
this->m_elements.back() = std::move(element);
|
||||||
}
|
if (!collapse_path())
|
||||||
|
clear();
|
||||||
//////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
template<class PathSystems>
|
|
||||||
tl::string& abs_path<PathSystems>::back() noexcept
|
|
||||||
{
|
|
||||||
TL_PLAIN_ASSERT(!this->empty());
|
|
||||||
this->m_hash = 0;
|
|
||||||
return this->m_elements.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -838,6 +864,58 @@ bool abs_path<PathSystems>::has_valid_tag(const Str& string) noexcept
|
|||||||
return pathSystemId >= 0;
|
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;
|
||||||
|
}
|
||||||
|
template<class PathSystems>
|
||||||
|
bool operator==(const abs_path_view<PathSystems>& a, const abs_path<PathSystems>& b) noexcept
|
||||||
|
{
|
||||||
|
return b == a;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
@@ -28,8 +28,11 @@ public:
|
|||||||
using key_less = path_key_less<PathSystems>;
|
using key_less = path_key_less<PathSystems>;
|
||||||
using value_type = std::string;
|
using value_type = std::string;
|
||||||
|
|
||||||
//checked indexing
|
//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;
|
const string& at(size_t index) const noexcept;
|
||||||
|
string& at(size_t index) noexcept;
|
||||||
|
|
||||||
void shrink(size_t size) noexcept;
|
void shrink(size_t size) noexcept;
|
||||||
|
|
||||||
@@ -53,7 +56,6 @@ public:
|
|||||||
uint32_t hash() const noexcept;
|
uint32_t hash() const noexcept;
|
||||||
|
|
||||||
protected:
|
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;
|
tl::vector<string> m_elements;
|
||||||
@@ -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>
|
template <typename PathSystems>
|
||||||
const string& path_base<PathSystems>::at(size_t index) const noexcept
|
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];
|
return m_elements[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,25 +200,7 @@ string path_base<PathSystems>::pop_back() noexcept
|
|||||||
template <typename PathSystems>
|
template <typename PathSystems>
|
||||||
bool path_base<PathSystems>::push_back(string element) noexcept
|
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));
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <EASTL/fixed_string.h>
|
||||||
|
|
||||||
#include "tl/detail/prologue.h"
|
#include "tl/detail/prologue.h"
|
||||||
#include <EASTL/fixed_vector.h>
|
#include <EASTL/fixed_vector.h>
|
||||||
#include "tl/string.h"
|
#include "tl/string.h"
|
||||||
@@ -15,9 +17,9 @@ namespace path_system
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<typename T>
|
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>
|
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;
|
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
|
struct path_system_getter
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
|
static T format_abs(int type_idx, tl::span<const string> members) noexcept;
|
||||||
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) 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 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
|
// specialization if Head element exists
|
||||||
@@ -42,10 +44,10 @@ template<int Index, typename Head, typename... Tail>
|
|||||||
struct path_system_getter<Index, Head, Tail...>
|
struct path_system_getter<Index, Head, Tail...>
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
|
static T format_abs(int type_idx, tl::span<const string> members) noexcept;
|
||||||
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) 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 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 tl::vector<const char*>& get_parse_separators() noexcept;
|
||||||
static const char* get_format_separator() 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>
|
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
|
//calculate the size to reserve
|
||||||
size_t totalSize = 0;
|
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>
|
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);
|
o_buffer.append(root_tag);
|
||||||
detail::path_system::simple_format_rel_path(o_buffer, members, separator);
|
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<int Index, typename... Tail>
|
||||||
template<typename T>
|
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.");
|
TL_PLAIN_FAIL("Failed to format path. Invalid type.");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<int Index, typename... Tail>
|
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>
|
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>
|
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.");
|
TL_PLAIN_FAIL("Failed validating path system. Invalid type.");
|
||||||
return false;
|
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<int Index, typename Head, typename... Tail>
|
||||||
template<typename T>
|
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)
|
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>
|
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)
|
if (type_idx == Index)
|
||||||
{
|
{
|
||||||
Head::parse_absolute(o_elements, path, size);
|
Head::parse_abs(o_elements, path, size);
|
||||||
return;
|
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>
|
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)
|
if (type_idx == Index)
|
||||||
return Head::validate_abs_path(members);
|
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>
|
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;
|
T string;
|
||||||
buffer.reserve(8192);
|
detail::path_system::simple_format_rel_path(string, members, format_separator::value());
|
||||||
detail::path_system::simple_format_rel_path(buffer, members, format_separator::value());
|
return string;
|
||||||
if (buffer.data())
|
|
||||||
return string(buffer.data(), buffer.size());
|
|
||||||
|
|
||||||
return string();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef _DEBUG
|
||||||
|
#define TL_ONLY_IN_DEBUG(...) __VA_ARGS__
|
||||||
|
#else
|
||||||
|
#define TL_ONLY_IN_DEBUG(...)
|
||||||
|
#endif
|
||||||
+15
-14
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tl/detail/prologue.h"
|
#include "tl/detail/prologue.h"
|
||||||
|
#include <tl/span.h>
|
||||||
#include <tl/vector.h>
|
#include <tl/vector.h>
|
||||||
#include <tl/fixed_vector.h>
|
#include <tl/fixed_vector.h>
|
||||||
#include "tl/string.h"
|
#include "tl/string.h"
|
||||||
@@ -60,11 +61,11 @@ template <typename... Systems>
|
|||||||
struct path_systems
|
struct path_systems
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T format_absolute(int type_id, const tl::vector<string>& members) noexcept;
|
static T format_abs(int type_id, tl::span<const string> members) noexcept;
|
||||||
static void parse_absolute(tl::vector<string>& o_elements, int type_id, const char* path, size_t size) 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 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 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;
|
static const tl::vector<tl::vector<const char*> >& get_all_parse_separators() noexcept;
|
||||||
|
|
||||||
template <typename TypeToCheck>
|
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>
|
struct simple_path_system : public detail::path_system::base_path_system<parse_separators, format_separator>
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
static T format_absolute(const tl::vector<string>& members) noexcept;
|
static T format_abs(tl::span<const string> members) noexcept;
|
||||||
static void parse_absolute(tl::vector<string>& o_elements, const char* path, size_t size) noexcept;
|
static void parse_abs(tl::vector<string>& o_elements, const char* path, size_t size) noexcept;
|
||||||
static bool validate_abs_path(const tl::vector<string>& members) noexcept;
|
static bool validate_abs_path(tl::span<const string> members) noexcept;
|
||||||
static bool match(const char* path, size_t size) noexcept;
|
static bool match(const char* path, size_t size) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,19 +106,19 @@ namespace tl
|
|||||||
|
|
||||||
template <typename... Systems>
|
template <typename... Systems>
|
||||||
template<typename T>
|
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.");
|
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>
|
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.");
|
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>
|
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.");
|
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);
|
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 root_tag, typename parse_separators, typename format_separator>
|
||||||
template<typename T>
|
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>)
|
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>
|
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());
|
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>
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+219
-102
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include "tl/detail/prologue.h"
|
#include "tl/detail/prologue.h"
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
|
#include "tl/rel_path_view.h"
|
||||||
#include "tl/path_system.h"
|
#include "tl/path_system.h"
|
||||||
#include "tl/detail/path_base.h"
|
#include "tl/detail/path_base.h"
|
||||||
#include "tl/plain_crash.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;
|
template<typename T> friend class abs_path;
|
||||||
public:
|
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;
|
explicit rel_path(const char* path) noexcept;
|
||||||
rel_path(const char* path, size_t size) noexcept;
|
rel_path(const char* path, size_t size) noexcept;
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
@@ -27,42 +33,57 @@ public:
|
|||||||
rel_path(const rel_path& other) noexcept;
|
rel_path(const rel_path& other) noexcept;
|
||||||
rel_path(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;
|
rel_path(const rel_path& from, const rel_path& to) noexcept;
|
||||||
|
|
||||||
// operators
|
// operators
|
||||||
const string& operator[](size_t idx) const noexcept;
|
|
||||||
|
|
||||||
rel_path& operator=(const char* path) noexcept;
|
rel_path& operator=(const char* path) noexcept;
|
||||||
rel_path& operator=(const rel_path& other) noexcept;
|
rel_path& operator=(const rel_path& other) noexcept;
|
||||||
rel_path& operator=(rel_path&& other) noexcept;
|
rel_path& operator=(rel_path&& other) noexcept;
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
rel_path& operator=(const Str& path) noexcept;
|
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 char* path) const noexcept;
|
||||||
rel_path operator+(const rel_path& path) const noexcept;
|
rel_path operator+(const rel_path& path) const noexcept;
|
||||||
rel_path operator+(rel_path&& path) const noexcept;
|
rel_path operator+(rel_path&& path) const noexcept;
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
rel_path operator+(const Str& path) const noexcept;
|
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 char* path) noexcept;
|
||||||
rel_path& operator+=(const rel_path& path) noexcept;
|
rel_path& operator+=(const rel_path& path) noexcept;
|
||||||
rel_path& operator+=(rel_path&& path) noexcept;
|
rel_path& operator+=(rel_path&& path) noexcept;
|
||||||
template<typename Str>
|
template<typename Str>
|
||||||
rel_path& operator+=(const Str& path) noexcept;
|
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;
|
||||||
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 swap(rel_path& other) noexcept;
|
||||||
void clear() noexcept;
|
void clear() noexcept;
|
||||||
|
|
||||||
template<typename FormatSystem>
|
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;
|
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;
|
||||||
@@ -73,8 +94,7 @@ public:
|
|||||||
|
|
||||||
const string& front() const noexcept;
|
const string& front() const noexcept;
|
||||||
const string& back() const noexcept;
|
const string& back() const noexcept;
|
||||||
string& front() noexcept;
|
void replace_back(string element) noexcept;
|
||||||
string& back() noexcept;
|
|
||||||
|
|
||||||
void collapse_path() noexcept;
|
void collapse_path() noexcept;
|
||||||
|
|
||||||
@@ -105,9 +125,18 @@ namespace tl
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template <typename PathSystems>
|
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++)
|
for (size_t i = last; i < to.size(); i++)
|
||||||
this->push_element(to.m_elements[i]);
|
this->push_element(to.m_elements[i]);
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
collapse_path();
|
||||||
|
|
||||||
template <typename PathSystems>
|
|
||||||
const string& rel_path<PathSystems>::operator[](size_t idx) const noexcept
|
|
||||||
{
|
|
||||||
return this->m_elements[idx];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -237,6 +260,17 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator=(const Str& path) noexcep
|
|||||||
return *this;
|
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>
|
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.reserve(this->size() + 1);
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
size_t old_index = p.size();
|
|
||||||
//this will push pack in the m_elements
|
//this will push pack in the m_elements
|
||||||
PathSystems::parse_relative(p.m_elements, path, strlen(path));
|
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();
|
p.collapse_path();
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
@@ -296,21 +318,9 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(const Str& path) const no
|
|||||||
p.reserve(this->size() + 1);
|
p.reserve(this->size() + 1);
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
size_t old_index = p.size();
|
|
||||||
//this will push pack in the m_elements
|
//this will push pack in the m_elements
|
||||||
PathSystems::parse_relative(p.m_elements, path.data(), path.size());
|
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();
|
p.collapse_path();
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
@@ -328,7 +338,22 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(const rel_path& path) con
|
|||||||
rel_path p;
|
rel_path p;
|
||||||
p.reserve(this->size() + path.size());
|
p.reserve(this->size() + path.size());
|
||||||
p = *this;
|
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;
|
p += path;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -345,7 +370,6 @@ rel_path<PathSystems> rel_path<PathSystems>::operator+(rel_path&& path) const no
|
|||||||
rel_path p;
|
rel_path p;
|
||||||
p.reserve(this->size() + path.size());
|
p.reserve(this->size() + path.size());
|
||||||
p = *this;
|
p = *this;
|
||||||
|
|
||||||
p += std::move(path);
|
p += std::move(path);
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -359,21 +383,9 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(const char* path) noexc
|
|||||||
{
|
{
|
||||||
if (path && path[0] != '\0')
|
if (path && path[0] != '\0')
|
||||||
{
|
{
|
||||||
size_t old_index = this->size();
|
|
||||||
//this will push pack in the m_elements
|
//this will push pack in the m_elements
|
||||||
PathSystems::parse_relative(this->m_elements, path, strlen(path));
|
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;
|
this->m_hash = 0;
|
||||||
collapse_path();
|
collapse_path();
|
||||||
}
|
}
|
||||||
@@ -388,21 +400,9 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(const Str& path) noexce
|
|||||||
{
|
{
|
||||||
if (!path.empty())
|
if (!path.empty())
|
||||||
{
|
{
|
||||||
size_t old_index = this->size();
|
|
||||||
//this will push pack in the m_elements
|
//this will push pack in the m_elements
|
||||||
PathSystems::parse_relative(this->m_elements, path.data(), path.size());
|
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;
|
this->m_hash = 0;
|
||||||
collapse_path();
|
collapse_path();
|
||||||
}
|
}
|
||||||
@@ -443,6 +443,31 @@ rel_path<PathSystems>& rel_path<PathSystems>::operator+=(rel_path&& path) noexce
|
|||||||
return *this;
|
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>
|
template <typename PathSystems>
|
||||||
@@ -474,7 +499,42 @@ auto rel_path<PathSystems>::operator<=>(const rel_path& other) const noexcept
|
|||||||
return r;
|
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);
|
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();
|
collapse_path();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -508,18 +559,21 @@ void rel_path<PathSystems>::collapse_path() noexcept
|
|||||||
{
|
{
|
||||||
if (!this->empty())
|
if (!this->empty())
|
||||||
{
|
{
|
||||||
this->m_hash = 0;
|
|
||||||
for (size_t i = 0; i < this->m_elements.size();)
|
for (size_t i = 0; i < this->m_elements.size();)
|
||||||
{
|
{
|
||||||
if (i >= 1 &&
|
if (i >= 1 &&
|
||||||
this->m_elements[i] == path_system::back_t::value() &&
|
this->m_elements[i] == path_system::back_t::value() &&
|
||||||
this->m_elements[i - 1] != 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
|
this->m_elements.erase(this->m_elements.begin() + i - 1, this->m_elements.begin() + i + 1); //remove the .. and the parent
|
||||||
i -= 1;
|
i -= 1;
|
||||||
}
|
}
|
||||||
else if (this->m_elements[i] == path_system::current_t::value())
|
else if (this->m_elements[i] == path_system::current_t::value())
|
||||||
|
{
|
||||||
|
this->m_hash = 0;
|
||||||
this->m_elements.erase(this->m_elements.begin() + i); //remove the .
|
this->m_elements.erase(this->m_elements.begin() + i); //remove the .
|
||||||
|
}
|
||||||
else
|
else
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
@@ -534,7 +588,7 @@ bool rel_path<PathSystems>::is_prefix_of(const rel_path& path) const noexcept
|
|||||||
if (this->size() > path.size())
|
if (this->size() > path.size())
|
||||||
return false;
|
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])
|
if (this->m_elements[i] != path[i])
|
||||||
return false;
|
return false;
|
||||||
@@ -557,7 +611,7 @@ void rel_path<PathSystems>::swap(rel_path& other) noexcept
|
|||||||
template <typename PathSystems>
|
template <typename PathSystems>
|
||||||
void rel_path<PathSystems>::clear() noexcept
|
void rel_path<PathSystems>::clear() noexcept
|
||||||
{
|
{
|
||||||
this->m_elements.resize(0);
|
this->m_elements.clear();
|
||||||
this->m_hash = 0;
|
this->m_hash = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -565,17 +619,43 @@ void rel_path<PathSystems>::clear() noexcept
|
|||||||
|
|
||||||
template<typename PathSystems>
|
template<typename PathSystems>
|
||||||
template<typename FormatSystem>
|
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 PathSystems>
|
||||||
rel_path<PathSystems> rel_path<PathSystems>::subpath(size_t index, int count /* = 0 */) const noexcept
|
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>
|
||||||
|
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)
|
if (count == 0)
|
||||||
count = (int)this->size() - (int)index;
|
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;
|
count = (int)this->size() - (int)index + count;
|
||||||
|
|
||||||
if (count > 0 && index < this->size())
|
if (count > 0 && index < this->size())
|
||||||
{
|
return rel_path_view<PathSystems>(tl::span(this->m_elements.begin() + index, this->m_elements.begin() + index + count));
|
||||||
dst.m_elements.resize(count);
|
|
||||||
for (int i = 0; i < count; i++)
|
return {};
|
||||||
dst.m_elements[i] = this->m_elements[index + i];
|
|
||||||
}
|
|
||||||
return dst;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -637,21 +714,15 @@ const string& rel_path<PathSystems>::front() const noexcept
|
|||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
template<class PathSystems>
|
template<class PathSystems>
|
||||||
string& rel_path<PathSystems>::front() noexcept
|
void rel_path<PathSystems>::replace_back(string element) noexcept
|
||||||
{
|
{
|
||||||
TL_PLAIN_ASSERT(!this->empty());
|
TL_PLAIN_ASSERT(!this->empty());
|
||||||
|
const bool is_back_element = element == path_system::back_t::value();
|
||||||
this->m_hash = 0;
|
this->m_hash = 0;
|
||||||
return this->m_elements.front();
|
this->m_elements.back() = std::move(element);
|
||||||
}
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
if (is_back_element)
|
||||||
|
collapse_path();
|
||||||
template<class PathSystems>
|
|
||||||
string& rel_path<PathSystems>::back() noexcept
|
|
||||||
{
|
|
||||||
TL_PLAIN_ASSERT(!this->empty());
|
|
||||||
this->m_hash = 0;
|
|
||||||
return this->m_elements.back();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -674,8 +745,12 @@ string rel_path<PathSystems>::pop_front() noexcept
|
|||||||
template <typename PathSystems>
|
template <typename PathSystems>
|
||||||
void rel_path<PathSystems>::push_front(string element) noexcept
|
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_hash = 0;
|
||||||
this->m_elements.insert(this->m_elements.begin(), std::move(element));
|
this->m_elements.insert(this->m_elements.begin(), std::move(element));
|
||||||
|
|
||||||
|
if (is_back_element)
|
||||||
|
collapse_path();
|
||||||
}
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
@@ -719,6 +794,48 @@ other_rel_path rel_path<PathSystems>::move_cast_to() noexcept
|
|||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
template<class PathSystems>
|
||||||
|
bool operator==(const rel_path_view<PathSystems>& a, const rel_path<PathSystems>& b) noexcept
|
||||||
|
{
|
||||||
|
return b == a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,7 +847,7 @@ struct std::formatter<tl::rel_path<tl::path_systems<T>>>
|
|||||||
constexpr auto parse(format_parse_context& ctx) noexcept { return ctx.begin(); }
|
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
|
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>());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2013">
|
<NonUserCode xmlns="http://schemas.microsoft.com/vstudio/debugger/jmc/2013">
|
||||||
<File Name="*\jtl\*" />
|
<File Name="*\tl\*" />
|
||||||
</NonUserCode>
|
</NonUserCode>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
|
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
|
||||||
<Function><Name>jtl::.*</Name><Action>NoStepInto</Action></Function>
|
<Function><Name>tl::.*</Name><Action>NoStepInto</Action></Function>
|
||||||
</StepFilter>
|
</StepFilter>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#include "TestHelpers.h"
|
||||||
|
|
||||||
|
tl::vector<int*> ExpectedAssertGuard::s_utest_results;
|
||||||
|
tl::vector<tl::string> ExpectedAssertGuard::s_msgs;
|
||||||
|
tl::vector<tl::assert::handler> ExpectedAssertGuard::s_oldHandlers;
|
||||||
|
|
||||||
|
tl::vector<int*> NoAssertGuard::s_utest_results;
|
||||||
|
tl::vector<tl::assert::handler> NoAssertGuard::s_oldHandlers;
|
||||||
|
|
||||||
|
tl::vector<int*> ExpectedCrashGuard::s_utest_results;
|
||||||
|
tl::vector<tl::string> ExpectedCrashGuard::s_msgs;
|
||||||
|
tl::vector<tl::crash::handler> ExpectedCrashGuard::s_oldHandlers;
|
||||||
|
|
||||||
|
//tl::vector<tl::crash::handler> NoCrashesGuard::s_oldHandlers;
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "tl/string.h"
|
||||||
|
#include "tl/vector.h"
|
||||||
|
#include "tl/format.h"
|
||||||
|
#include "tl/utest.h"
|
||||||
|
|
||||||
|
struct ExpectedAssertGuard
|
||||||
|
{
|
||||||
|
ExpectedAssertGuard(tl::string msg, int* utest_result)
|
||||||
|
{
|
||||||
|
s_utest_results.push_back(utest_result);
|
||||||
|
s_msgs.push_back(std::move(msg));
|
||||||
|
s_oldHandlers.push_back(tl::assert::set_handler(assertHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
~ExpectedAssertGuard()
|
||||||
|
{
|
||||||
|
tl::assert::set_handler(s_oldHandlers.back());
|
||||||
|
s_oldHandlers.pop_back();
|
||||||
|
s_msgs.pop_back();
|
||||||
|
s_utest_results.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg)
|
||||||
|
{
|
||||||
|
int* utest_result = s_utest_results.back();
|
||||||
|
EXPECT_EQ(s_msgs.back(), msg);
|
||||||
|
return tl::assert::response::CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl::vector<int*> s_utest_results;
|
||||||
|
static tl::vector<tl::string> s_msgs;
|
||||||
|
static tl::vector<tl::assert::handler> s_oldHandlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXPECTED_ASSERT_GUARD(msg) ExpectedAssertGuard eassert##__LINE__(msg, utest_result)
|
||||||
|
|
||||||
|
struct NoAssertGuard
|
||||||
|
{
|
||||||
|
NoAssertGuard(int* utest_result)
|
||||||
|
{
|
||||||
|
s_utest_results.push_back(utest_result);
|
||||||
|
s_oldHandlers.push_back(tl::assert::set_handler(assertHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
~NoAssertGuard()
|
||||||
|
{
|
||||||
|
tl::assert::set_handler(s_oldHandlers.back());
|
||||||
|
s_oldHandlers.pop_back();
|
||||||
|
s_utest_results.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static tl::assert::response assertHandler(const char* condition, const char* file, int line, const char* msg)
|
||||||
|
{
|
||||||
|
int* utest_result = s_utest_results.back();
|
||||||
|
EXPECT_FALSE_MSG(true, tl::format("Unexpected assert: [{}] {}({}): {}", condition ? condition : "", file ? file : "", line, msg ? msg : "").c_str());
|
||||||
|
return tl::assert::response::CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl::vector<int*> s_utest_results;
|
||||||
|
static tl::vector<tl::assert::handler> s_oldHandlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NO_ASSERT_GUARD NoAssertGuard noassert##__LINE__(utest_result)
|
||||||
|
|
||||||
|
|
||||||
|
struct ExpectedCrashGuard
|
||||||
|
{
|
||||||
|
ExpectedCrashGuard(tl::string msg, int* utest_result)
|
||||||
|
{
|
||||||
|
s_utest_results.push_back(utest_result);
|
||||||
|
s_msgs.push_back(std::move(msg));
|
||||||
|
s_oldHandlers.push_back(tl::crash::set_handler(crashHandler));
|
||||||
|
}
|
||||||
|
|
||||||
|
~ExpectedCrashGuard()
|
||||||
|
{
|
||||||
|
tl::crash::set_handler(s_oldHandlers.back());
|
||||||
|
s_oldHandlers.pop_back();
|
||||||
|
s_msgs.pop_back();
|
||||||
|
s_utest_results.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static tl::crash::response crashHandler(const char* file, int line, const char* msg)
|
||||||
|
{
|
||||||
|
int* utest_result = s_utest_results.back();
|
||||||
|
EXPECT_EQ(s_msgs.back(), msg);
|
||||||
|
return tl::crash::response::CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static tl::vector<int*> s_utest_results;
|
||||||
|
static tl::vector<tl::string> s_msgs;
|
||||||
|
static tl::vector<tl::crash::handler> s_oldHandlers;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define EXPECTED_CRASH_GUARD(msg) ExpectedCrashGuard ecrash##__LINE__(msg, utest_result)
|
||||||
|
|
||||||
|
|
||||||
|
//struct NoCrashesGuard
|
||||||
|
//{
|
||||||
|
// NoCrashesGuard()
|
||||||
|
// {
|
||||||
|
// s_oldHandlers.push_back(tl::crash::set_handler(crashHandler));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// ~NoCrashesGuard()
|
||||||
|
// {
|
||||||
|
// tl::crash::set_handler(s_oldHandlers.back());
|
||||||
|
// s_oldHandlers.pop_back();
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//private:
|
||||||
|
// static tl::crash::response crashHandler(const char* file, int line, const char* msg)
|
||||||
|
// {
|
||||||
|
// EXPECT_TRUE_MSG(false, tl::format("Unexpected crash: {}({}): {}", file ? file : "", line, msg ? msg : "").c_str());
|
||||||
|
// return tl::crash::response::CONTINUE;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// static tl::vector<tl::crash::handler> s_oldHandlers;
|
||||||
|
//};
|
||||||
+2
-22
@@ -1,11 +1,6 @@
|
|||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
|
|
||||||
// each test module could contain no more then one 'main' file with init function defined
|
|
||||||
// alternatively you could define init function yourself
|
|
||||||
#define BOOST_TEST_MAIN
|
|
||||||
#include <boost/test/unit_test.hpp>
|
|
||||||
|
|
||||||
#include "tl/string.h"
|
#include "tl/string.h"
|
||||||
|
#include "tl/utest.h"
|
||||||
|
|
||||||
void* __cdecl operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line)
|
void* __cdecl operator new[](size_t size, const char* name, int flags, unsigned debugFlags, const char* file, int line)
|
||||||
{
|
{
|
||||||
@@ -16,19 +11,4 @@ void* __cdecl operator new[](size_t size, size_t, size_t, const char* name, int
|
|||||||
return new uint8_t[size];
|
return new uint8_t[size];
|
||||||
}
|
}
|
||||||
|
|
||||||
//____________________________________________________________________________//
|
UTEST_MAIN();
|
||||||
|
|
||||||
struct GlobalFixture
|
|
||||||
{
|
|
||||||
GlobalFixture()
|
|
||||||
{
|
|
||||||
std::cout << "Starting Tests\n";
|
|
||||||
}
|
|
||||||
~GlobalFixture()
|
|
||||||
{
|
|
||||||
std::cout << "Finishing Tests\n";
|
|
||||||
tl::string::free_database();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_GLOBAL_FIXTURE(GlobalFixture);
|
|
||||||
|
|||||||
@@ -0,0 +1,954 @@
|
|||||||
|
#include "StdAfx.h"
|
||||||
|
#include "tl/abs_path.h"
|
||||||
|
#include "tl/rel_path.h"
|
||||||
|
|
||||||
|
#include "tl/utest.h"
|
||||||
|
#include "TestHelpers.h"
|
||||||
|
#include "tl/abs_path_view.h"
|
||||||
|
|
||||||
|
TL_DECLARE_STRING_LITERAL(posix_root_tag, "/");
|
||||||
|
TL_DECLARE_STRING_VECTOR(posix_parse_separators, "/");
|
||||||
|
TL_DECLARE_STRING_LITERAL(posix_format_separator, "/");
|
||||||
|
using posix_system = tl::simple_path_system<posix_root_tag, posix_parse_separators, posix_format_separator>;
|
||||||
|
|
||||||
|
TL_DECLARE_STRING_LITERAL(unc_root_tag, "\\\\");
|
||||||
|
TL_DECLARE_STRING_VECTOR(unc_parse_separators, "\\", "/");
|
||||||
|
TL_DECLARE_STRING_LITERAL(unc_format_separator, "\\");
|
||||||
|
using unc_system = tl::simple_path_system<unc_root_tag, unc_parse_separators, unc_format_separator>;
|
||||||
|
|
||||||
|
using test_abs_path = tl::abs_path<tl::path_systems<posix_system, unc_system>>;
|
||||||
|
using test_rel_path = test_abs_path::rel_path_type;
|
||||||
|
|
||||||
|
using test_abs_path_view = tl::abs_path_view<tl::path_systems<posix_system, unc_system>>;
|
||||||
|
using test_rel_path_view = test_abs_path_view::rel_path_view_type;
|
||||||
|
|
||||||
|
#define PATH_TEST_EQ(a, b) EXPECT_EQ(test_abs_path(a), test_abs_path(b))
|
||||||
|
|
||||||
|
UTEST(thread_safety, thread_safety)
|
||||||
|
{
|
||||||
|
std::thread thread1;
|
||||||
|
std::thread thread2;
|
||||||
|
|
||||||
|
thread1 = std::thread([]
|
||||||
|
{
|
||||||
|
test_rel_path path;
|
||||||
|
for (volatile size_t i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
path = "a/b/c/d";
|
||||||
|
char result = 'a' + static_cast<char>(i % 20);
|
||||||
|
char buf[2] = { result , 0 };
|
||||||
|
path += (const char*)buf;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
thread2 = std::thread([]
|
||||||
|
{
|
||||||
|
test_rel_path path;
|
||||||
|
for (volatile size_t i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
path = "a/b/c/d";
|
||||||
|
char result = 'a' + static_cast<char>(i % 20);
|
||||||
|
char buf[2] = { result , 0 };
|
||||||
|
path += (const char*)buf;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (thread1.joinable())
|
||||||
|
{
|
||||||
|
thread1.join();
|
||||||
|
}
|
||||||
|
if (thread2.joinable())
|
||||||
|
{
|
||||||
|
thread2.join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UTEST(Path, Path)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
test_abs_path path;
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_TRUE(path.is<posix_system>());
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
|
||||||
|
test_abs_path path2("/a");
|
||||||
|
test_abs_path path3("/");
|
||||||
|
EXPECT_EQ(path, path2);
|
||||||
|
EXPECT_NE(path, path3);
|
||||||
|
|
||||||
|
test_abs_path path4("\\\\");
|
||||||
|
EXPECT_NE(path3, path4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_TRUE(path.is<posix_system>());
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_TRUE(path.is<unc_system>());
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a\\");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_TRUE(path.is<unc_system>());
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
//Note - Here we test that the posix path only uses / as separator
|
||||||
|
test_abs_path path("/a\\b");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_EQ(path[0], "a\\b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/");
|
||||||
|
path += "a";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 1);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path;
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
path += "a";
|
||||||
|
}
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 0);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path;
|
||||||
|
path += "/a/b";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path;
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
path += "a";
|
||||||
|
}
|
||||||
|
path += "/a/b";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\");
|
||||||
|
path += "a";
|
||||||
|
path += "b/c/d";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 4);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
EXPECT_EQ(path[3], "d");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/");
|
||||||
|
path += "a/b";
|
||||||
|
path += "c";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 3);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
EXPECT_EQ(path[2], "c");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/");
|
||||||
|
path += ("a/b" + tl::string("/df"));
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 3);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
EXPECT_EQ(path[2], "df");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
path += "a/b";
|
||||||
|
path += "c";
|
||||||
|
path += "..";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
path += "../..";
|
||||||
|
EXPECT_EQ(path.size(), 0);
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
EXPECT_TRUE(path.is<posix_system>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("\\\\"));
|
||||||
|
path += "a/b";
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path += "../../..";
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("\\\\"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path.push_back("..");
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path newPath = path + "../..";
|
||||||
|
EXPECT_TRUE(newPath.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
auto pathParent = path.parent();
|
||||||
|
EXPECT_TRUE(pathParent.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("\\\\"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
auto pathParent = path.parent();
|
||||||
|
EXPECT_TRUE(pathParent.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
auto pathParent = path.parent();
|
||||||
|
EXPECT_TRUE(pathParent.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/a/b/c/d"));
|
||||||
|
test_abs_path newPath = path.parent(2);
|
||||||
|
EXPECT_EQ(newPath, test_abs_path("/a/b"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/a"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path newPath = path.parent(2);
|
||||||
|
EXPECT_TRUE(newPath.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/c/../d");
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 3);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
EXPECT_EQ(path[2], "d");
|
||||||
|
path.push_back("..");
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
path.push_back("../..");
|
||||||
|
EXPECT_EQ(path.size(), 3);
|
||||||
|
EXPECT_TRUE(path.is<posix_system>());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a/b/c/d");
|
||||||
|
auto p = path.subpath(0, 0);
|
||||||
|
EXPECT_EQ(p, test_rel_path("a/b/c/d"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/c/d");
|
||||||
|
auto p = path.subpath(1, 0);
|
||||||
|
EXPECT_EQ(p, test_rel_path("b/c/d"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a/b/c/d");
|
||||||
|
auto p = path.subpath(0, -1);
|
||||||
|
EXPECT_EQ(p, test_rel_path("a/b/c"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/c/d");
|
||||||
|
auto p = path.subpath(0, 2);
|
||||||
|
EXPECT_EQ(p, test_rel_path("a/b"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a/b/c");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p.str(), "\\\\a\\b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p.str(), "/");
|
||||||
|
EXPECT_NE(p.str(), "\\\\");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path path("..");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path path(".");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path path("");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_TRUE(p.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/../c");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p.str(), "/a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/c/d");
|
||||||
|
path.shrink(2);
|
||||||
|
EXPECT_EQ(path, test_abs_path("/a/b"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/c/d");
|
||||||
|
EXPECT_EQ(path.back(), "d");
|
||||||
|
EXPECT_EQ(path.front(), "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path from("/a/b/c/d");
|
||||||
|
test_abs_path to("/a/b/x/y");
|
||||||
|
auto rel = from.path_to(to);
|
||||||
|
EXPECT_EQ(rel, test_rel_path("../../x/y"));
|
||||||
|
rel += "..";
|
||||||
|
rel.collapse_path();
|
||||||
|
EXPECT_EQ(rel, test_rel_path("../../x"));
|
||||||
|
|
||||||
|
test_abs_path path("/a/b/c/d");
|
||||||
|
path += rel;
|
||||||
|
EXPECT_EQ(path, test_abs_path("/a/b/c/d/../../x"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path from("/a/b");
|
||||||
|
test_abs_path to("/a/b/x/y");
|
||||||
|
auto rel = from.path_to(to);
|
||||||
|
EXPECT_EQ(rel, test_rel_path("x/y"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path from("/c/d");
|
||||||
|
test_abs_path to("/a/b/x/y");
|
||||||
|
auto rel = from.path_to(to);
|
||||||
|
EXPECT_EQ(rel, test_rel_path("../../a/b/x/y"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path p("/c/d/m/a/../s/d/a");
|
||||||
|
tl::string s = p.str();
|
||||||
|
EXPECT_EQ(s, "/c/d/m/s/d/a");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path p("/../s/d/a");
|
||||||
|
EXPECT_TRUE(p.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path p("/s/../../d/a");
|
||||||
|
EXPECT_TRUE(p.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path p("/s/d/../../../a");
|
||||||
|
EXPECT_TRUE(p.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
test_abs_path p("\\\\../a");
|
||||||
|
EXPECT_TRUE(p.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path p("/c/d/m");
|
||||||
|
tl::string s = p.str();
|
||||||
|
EXPECT_EQ(s, "/c/d/m");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path p("/foo/..bar");
|
||||||
|
tl::string s = p.str();
|
||||||
|
EXPECT_EQ(s, "/foo/..bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path p("/foo/...");
|
||||||
|
tl::string s = p.str();
|
||||||
|
EXPECT_EQ(s, "/foo/...");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "/a" }, test_abs_path("/b"));
|
||||||
|
EXPECT_EQ(test_abs_path("/a"), path);
|
||||||
|
EXPECT_NE(test_abs_path("/b"), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "a/b" }, test_abs_path("/x"));
|
||||||
|
EXPECT_EQ(test_abs_path("/x/a/b"), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ ".." }, test_abs_path("/"));
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "../.." }, test_abs_path("/a/b/d"));
|
||||||
|
EXPECT_TRUE(path.is_valid());
|
||||||
|
EXPECT_EQ(path, test_abs_path("/a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" }, test_abs_path(""));
|
||||||
|
EXPECT_TRUE(path.is_valid());
|
||||||
|
EXPECT_EQ(path, test_abs_path("/bla"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path(""));
|
||||||
|
EXPECT_TRUE(!path.is_valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" }, test_abs_path());
|
||||||
|
EXPECT_TRUE(!path.is_valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "bla" });
|
||||||
|
EXPECT_TRUE(!path.is_valid());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path = test_abs_path::from_string(tl::string_view{ "/bla" });
|
||||||
|
EXPECT_TRUE(path.is_valid());
|
||||||
|
EXPECT_EQ(path, test_abs_path("/bla"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path p1 = test_abs_path("/a/bc/d");
|
||||||
|
test_abs_path p2 = test_abs_path("/a/bd");
|
||||||
|
|
||||||
|
EXPECT_LT(p1, p2);
|
||||||
|
EXPECT_GE(p1, p1);
|
||||||
|
EXPECT_GE(p2, p1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// non_member_tests ----------------------------------------------------------------//
|
||||||
|
|
||||||
|
UTEST(non_member_tests, non_member_tests)
|
||||||
|
{
|
||||||
|
// test non-member functions, particularly operator overloads
|
||||||
|
|
||||||
|
test_abs_path e, e2;
|
||||||
|
tl::string es, es2;
|
||||||
|
|
||||||
|
char acs[] = "a";
|
||||||
|
tl::string as(acs);
|
||||||
|
test_rel_path a(as);
|
||||||
|
|
||||||
|
char acs2[] = "a";
|
||||||
|
tl::string as2(acs2);
|
||||||
|
test_rel_path a2(as2);
|
||||||
|
|
||||||
|
char bcs[] = "b";
|
||||||
|
tl::string bs(bcs);
|
||||||
|
test_rel_path b(bs);
|
||||||
|
|
||||||
|
// swap
|
||||||
|
a.swap(b);
|
||||||
|
EXPECT_EQ(a.str<posix_system>(), "b");
|
||||||
|
EXPECT_EQ(b.str<posix_system>(), "a");
|
||||||
|
std::swap(a, b);
|
||||||
|
EXPECT_EQ(a.str<posix_system>(), "a");
|
||||||
|
EXPECT_EQ(b.str<posix_system>(), "b");
|
||||||
|
|
||||||
|
// probe operator /
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + ".", "/.");
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Failed to parse abs path");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "..", "/..");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
PATH_TEST_EQ(test_abs_path("/a") + "b", "/a/b");
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "..", "");
|
||||||
|
}
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("bar"), "/foo/bar"); // path arg
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar"); // const char* arg
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + test_rel_path("woo/bar").back(), "/foo/bar"); // const std::string & arg
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "..", "/");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/f") + ".." + "b", "/b");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "..", "/foo");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "..", "/");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar" + ".." + "blah", "/foo/blah");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/f") + "b" + "..", "/f");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + "..", "/foo");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar" + "blah" + ".." + ".." + "bletch", "/foo/bletch");
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + ".", "/foo");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "." + "bar", "/foo/bar");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "." + ".", "/foo");
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "." + "..", "/");
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/."));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path += "./..";
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/."));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path += "../.";
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure basic_path overloads don't conflict with std::string overloads
|
||||||
|
|
||||||
|
//TEST_CHECK(!(as < as));
|
||||||
|
//TEST_CHECK(!(as < acs));
|
||||||
|
//TEST_CHECK(!(acs < as));
|
||||||
|
|
||||||
|
// character set reality check before lexicographical tests
|
||||||
|
EXPECT_LT(std::string("a.b"), std::string("a/b"));
|
||||||
|
// verify compare is actually lexicographical
|
||||||
|
// EXPECT_LT(path("a/b") < path("a.b"));
|
||||||
|
EXPECT_EQ(test_abs_path("/a/b"), test_abs_path("/a///b"));
|
||||||
|
EXPECT_EQ(test_abs_path("\\\\/a/b"), test_abs_path("\\\\a///b"));
|
||||||
|
|
||||||
|
// operator == and != are implemented separately, so test separately
|
||||||
|
|
||||||
|
test_abs_path p1("/fe/fi/fo/fum");
|
||||||
|
test_abs_path p2(p1);
|
||||||
|
test_abs_path p3("/fe/fi/fo/fumm");
|
||||||
|
EXPECT_NE(p1.str(), p3.str());
|
||||||
|
|
||||||
|
// check each overload
|
||||||
|
EXPECT_NE(p1, p3);
|
||||||
|
EXPECT_NE(p1.str(), p3.str());
|
||||||
|
EXPECT_NE(p1.str(), p3.str().c_str());
|
||||||
|
|
||||||
|
p3 = p2;
|
||||||
|
EXPECT_EQ(p1.str(), p3.str());
|
||||||
|
|
||||||
|
// check each overload
|
||||||
|
EXPECT_EQ(p1, p3);
|
||||||
|
EXPECT_EQ(p1.str(), p3.str());
|
||||||
|
EXPECT_EQ(p1.str(), p3.str().c_str());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
UTEST(is_prefix_tests, is_prefix_tests)
|
||||||
|
{
|
||||||
|
test_abs_path p1{ "\\\\windows" };
|
||||||
|
test_abs_path p2{ "\\\\windows\\system" };
|
||||||
|
test_abs_path p3{ "\\\\windows\\system32" };
|
||||||
|
test_abs_path p4{ "\\\\windows\\system32\\" };
|
||||||
|
test_abs_path w1{ "/windows" };
|
||||||
|
test_abs_path w2{ "/windows/" };
|
||||||
|
test_abs_path w3{ "/windows/system" };
|
||||||
|
test_abs_path w4{ "/windows/system32" };
|
||||||
|
test_abs_path w5{ "/windows/system32/" };
|
||||||
|
|
||||||
|
EXPECT_TRUE(p1.is_prefix_of(p2));
|
||||||
|
EXPECT_TRUE(!p2.is_prefix_of(p3));
|
||||||
|
EXPECT_TRUE(p3.is_prefix_of(p4));
|
||||||
|
EXPECT_TRUE(!p4.is_prefix_of(p1));
|
||||||
|
|
||||||
|
EXPECT_TRUE(w1.is_prefix_of(w2));
|
||||||
|
EXPECT_TRUE(w2.is_prefix_of(w3));
|
||||||
|
EXPECT_TRUE(w2.is_prefix_of(w4));
|
||||||
|
EXPECT_TRUE(!w3.is_prefix_of(w4));
|
||||||
|
EXPECT_TRUE(w4.is_prefix_of(w5));
|
||||||
|
}
|
||||||
|
|
||||||
|
// composition_tests ----------------------------------------------------------------//
|
||||||
|
|
||||||
|
// construction_tests ---------------------------------------------------------------//
|
||||||
|
|
||||||
|
UTEST(construction_tests, construction_tests)
|
||||||
|
{
|
||||||
|
PATH_TEST_EQ("", "");
|
||||||
|
PATH_TEST_EQ("/", "/");
|
||||||
|
PATH_TEST_EQ("\\\\", "\\\\");
|
||||||
|
|
||||||
|
PATH_TEST_EQ("/foo", "/foo");
|
||||||
|
|
||||||
|
PATH_TEST_EQ("/foo/", "/foo/");
|
||||||
|
PATH_TEST_EQ("\\\\f/", "\\\\f/");
|
||||||
|
PATH_TEST_EQ("/foo/..", "/foo/..");
|
||||||
|
PATH_TEST_EQ("/foo/../", "/foo/../");
|
||||||
|
PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../..");
|
||||||
|
PATH_TEST_EQ("/foo/bar/../../", "/foo/bar/../../");
|
||||||
|
PATH_TEST_EQ("/f", "/f");
|
||||||
|
|
||||||
|
PATH_TEST_EQ("/foo/bar/", "/foo/bar/");
|
||||||
|
PATH_TEST_EQ("//foo//bar//", "//foo//bar//");
|
||||||
|
PATH_TEST_EQ("///foo///bar///", "///foo///bar///");
|
||||||
|
PATH_TEST_EQ("\\\\/foo\\/bar\\/", "\\\\/foo\\/bar\\/");
|
||||||
|
PATH_TEST_EQ("\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//");
|
||||||
|
PATH_TEST_EQ("\\\\\\//foo\\//bar\\//", "\\\\//foo\\//bar\\//");
|
||||||
|
|
||||||
|
PATH_TEST_EQ("/foo/..", "/foo/..");
|
||||||
|
PATH_TEST_EQ("/foo/..bar", "/foo/..bar");
|
||||||
|
PATH_TEST_EQ("/f/../f", "/f/../f");
|
||||||
|
PATH_TEST_EQ("/f/..", "/f/..");
|
||||||
|
PATH_TEST_EQ("/foo/../bar", "/foo/../bar");
|
||||||
|
PATH_TEST_EQ("/foo/bar/..", "/foo/bar/..");
|
||||||
|
PATH_TEST_EQ("/foo/bar/../..", "/foo/bar/../..");
|
||||||
|
PATH_TEST_EQ("/foo/bar/../blah", "/foo/bar/../blah");
|
||||||
|
PATH_TEST_EQ("/f/../b", "/f/../b");
|
||||||
|
PATH_TEST_EQ("/f/b/..", "/f/b/..");
|
||||||
|
PATH_TEST_EQ("/f/b/../a", "/f/b/../a");
|
||||||
|
PATH_TEST_EQ("/foo/bar/blah/../..", "/foo/bar/blah/../..");
|
||||||
|
PATH_TEST_EQ("/foo/bar/blah/../../bletch", "/foo/bar/blah/../../bletch");
|
||||||
|
PATH_TEST_EQ("/...", "/...");
|
||||||
|
PATH_TEST_EQ("/....", "/....");
|
||||||
|
PATH_TEST_EQ("/foo/...", "/foo/...");
|
||||||
|
PATH_TEST_EQ("/abc.", "/abc.");
|
||||||
|
PATH_TEST_EQ("/abc..", "/abc..");
|
||||||
|
PATH_TEST_EQ("/foo/abc.", "/foo/abc.");
|
||||||
|
PATH_TEST_EQ("/foo/abc..", "/foo/abc..");
|
||||||
|
|
||||||
|
PATH_TEST_EQ("/.abc", "/.abc");
|
||||||
|
PATH_TEST_EQ("/a.c", "/a.c");
|
||||||
|
PATH_TEST_EQ("/..abc", "/..abc");
|
||||||
|
PATH_TEST_EQ("/a..c", "/a..c");
|
||||||
|
PATH_TEST_EQ("/foo/.abc", "/foo/.abc");
|
||||||
|
PATH_TEST_EQ("/foo/a.c", "/foo/a.c");
|
||||||
|
PATH_TEST_EQ("/foo/..abc", "/foo/..abc");
|
||||||
|
PATH_TEST_EQ("/foo/a..c", "/foo/a..c");
|
||||||
|
}
|
||||||
|
|
||||||
|
// append_tests --------------------------------------------------------------------//
|
||||||
|
|
||||||
|
static void append_test_aux(const test_abs_path& p, const tl::string& s, const tl::string& expect, int* utest_result)
|
||||||
|
{
|
||||||
|
PATH_TEST_EQ((p + s.c_str()).str(), expect);
|
||||||
|
PATH_TEST_EQ((p + s).str(), expect);
|
||||||
|
|
||||||
|
// path x(p);
|
||||||
|
// x.append(s.begin(), s.end());
|
||||||
|
// PATH_TEST_EQ(x.str<tl::string>(), expect);
|
||||||
|
}
|
||||||
|
|
||||||
|
UTEST(append_tests, append_tests)
|
||||||
|
{
|
||||||
|
// There are many control paths to be exercised, since empty paths and arguments,
|
||||||
|
// paths with trailing separators, arguments with leading separators, with or without
|
||||||
|
// other characters being present, are all separate cases that need to be tested.
|
||||||
|
// Furthermore, some of the code to be tested is specific to argument categories,
|
||||||
|
// so that results in further permutations to be tested.
|
||||||
|
|
||||||
|
//// code to generate test cases
|
||||||
|
////
|
||||||
|
//// expected results must be checked by hand
|
||||||
|
//// "foo\bar" expected result must be edited by hand and moved for Windows/POSIX
|
||||||
|
////
|
||||||
|
//const char* x[] = { "", "/", "foo", "foo/" };
|
||||||
|
//const char* y[] = { "", "/", "bar", "/bar" };
|
||||||
|
|
||||||
|
//for (int i = 0; i < sizeof(x)/sizeof(char*); ++i)
|
||||||
|
// for (int j = 0; j < sizeof(y)/sizeof(char*); ++j)
|
||||||
|
// {
|
||||||
|
// std::cout << "\n PATH_TEST_EQ(path(\"" << x[i] << "\") + \"" << y[j] << "\", \""
|
||||||
|
// << path(x[i]) + y[j] << "\");\n";
|
||||||
|
// std::cout << " append_test_aux(\"" << x[i] << "\", \"" << y[j] << "\", \""
|
||||||
|
// << path(x[i]) + y[j] << "\");\n";
|
||||||
|
// }
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("") + "", "");
|
||||||
|
// append_test_aux(test_abs_path(""), "", "");
|
||||||
|
|
||||||
|
test_abs_path abs = test_abs_path("") + "/";
|
||||||
|
test_abs_path abs1 = test_abs_path(abs);
|
||||||
|
test_abs_path abs2 = test_abs_path("/") + "/";
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("") + "/", "/");
|
||||||
|
append_test_aux(test_abs_path(""), "/", "/", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("") + "/bar", "/bar");
|
||||||
|
append_test_aux(test_abs_path(""), "/bar", "/bar", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "", "/");
|
||||||
|
append_test_aux(test_abs_path("/"), "", "/", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "/", "//");
|
||||||
|
append_test_aux(test_abs_path("/"), "/", "//", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "bar", "/bar");
|
||||||
|
append_test_aux(test_abs_path("/"), "bar", "/bar", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/") + "/bar", "//bar");
|
||||||
|
append_test_aux(test_abs_path("/"), "/bar", "//bar", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "", "/foo");
|
||||||
|
append_test_aux(test_abs_path("/foo"), "", "/foo", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "/", "/foo/");
|
||||||
|
append_test_aux(test_abs_path("/foo"), "/", "/foo/", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "/bar", "/foo/bar");
|
||||||
|
append_test_aux(test_abs_path("/foo"), "/bar", "/foo/bar", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo/") + "", "/foo/");
|
||||||
|
append_test_aux(test_abs_path("/foo/"), "", "/foo/", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo/") + "/", "/foo//");
|
||||||
|
append_test_aux(test_abs_path("/foo/"), "/", "/foo//", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo/") + "bar", "/foo/bar");
|
||||||
|
append_test_aux(test_abs_path("/foo/"), "bar", "/foo/bar", utest_result);
|
||||||
|
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo/") + "/bar", "/foo//bar");
|
||||||
|
append_test_aux(test_abs_path("/foo/"), "/bar", "/foo//bar", utest_result);
|
||||||
|
|
||||||
|
{
|
||||||
|
PATH_TEST_EQ(test_abs_path("/foo") + "bar", "/foo/bar");
|
||||||
|
append_test_aux(test_abs_path("/foo"), "bar", "/foo/bar", utest_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ticket #6819
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char a[1];
|
||||||
|
char b[3];
|
||||||
|
} u;
|
||||||
|
|
||||||
|
u.b[0] = '/';
|
||||||
|
u.b[1] = 'a';
|
||||||
|
u.b[2] = '\0';
|
||||||
|
|
||||||
|
test_abs_path p6819;
|
||||||
|
p6819 += (const char*)u.a;
|
||||||
|
EXPECT_EQ(p6819, test_abs_path("/a"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// self_assign_and_append_tests ------------------------------------------------------//
|
||||||
|
|
||||||
|
UTEST(self_assign_and_append_tests, self_assign_and_append_tests)
|
||||||
|
{
|
||||||
|
test_abs_path p;
|
||||||
|
|
||||||
|
p = "/snafubar";
|
||||||
|
PATH_TEST_EQ(p = p, "/snafubar");
|
||||||
|
|
||||||
|
p = "/snafubar";
|
||||||
|
p = p.str().c_str();
|
||||||
|
PATH_TEST_EQ(p, "/snafubar");
|
||||||
|
|
||||||
|
// p = "snafubar";
|
||||||
|
// p.assign(p.str<tl::string>().c_str(), path::codecvt());
|
||||||
|
// PATH_TEST_EQ(p, "snafubar");
|
||||||
|
|
||||||
|
p = "/snafu/bar";
|
||||||
|
PATH_TEST_EQ(p = p.str().c_str() + 6, "/bar");
|
||||||
|
|
||||||
|
// p = "snafubar";
|
||||||
|
// PATH_TEST_EQ(p.assign(p.c_str() + 5, p.c_str() + 7), "ba");
|
||||||
|
|
||||||
|
p = "/snafubar";
|
||||||
|
p += p.str().c_str();
|
||||||
|
PATH_TEST_EQ(p, "/snafubar/snafubar");
|
||||||
|
|
||||||
|
// p = "snafubar";
|
||||||
|
// p.append(p.c_str());
|
||||||
|
// PATH_TEST_EQ(p, "snafubar/snafubar");
|
||||||
|
|
||||||
|
// p = "snafubar";
|
||||||
|
// PATH_TEST_EQ(p.append(p.c_str() + 5, p.c_str() + 7), "snafubar" BOOST_DIR_SEP "ba");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
UTEST(PathView, PathView)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
//test_abs_path path;
|
||||||
|
//test_abs_path_view pathView = test_abs_path();
|
||||||
|
//test_abs_path_view pathView = path;
|
||||||
|
//pathView.str();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path;
|
||||||
|
test_abs_path_view pathView = path;
|
||||||
|
EXPECT_TRUE(pathView.empty());
|
||||||
|
EXPECT_FALSE(pathView.is_valid());
|
||||||
|
EXPECT_EQ(pathView.size(), 0);
|
||||||
|
EXPECT_EQ(pathView.hash(), path.hash());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/caca/maca");
|
||||||
|
test_abs_path_view pathView = path;
|
||||||
|
EXPECT_FALSE(pathView.empty());
|
||||||
|
EXPECT_TRUE(pathView.is_valid());
|
||||||
|
EXPECT_EQ(pathView.size(), path.size());
|
||||||
|
EXPECT_EQ(pathView.hash(), path.hash());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/caca/maca");
|
||||||
|
test_abs_path_view pathView = path;
|
||||||
|
pathView.pop_back();
|
||||||
|
EXPECT_FALSE(pathView.empty());
|
||||||
|
EXPECT_TRUE(pathView.is_valid());
|
||||||
|
EXPECT_EQ(pathView.size(), path.size() - 1);
|
||||||
|
EXPECT_EQ(pathView.str(), "/caca");
|
||||||
|
EXPECT_EQ(pathView.hash(), test_abs_path("/caca").hash());
|
||||||
|
EXPECT_EQ(pathView.hash(), test_abs_path(pathView).hash());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path("/a");
|
||||||
|
test_abs_path_view pathView = path;
|
||||||
|
|
||||||
|
EXPECT_TRUE(!pathView.empty());
|
||||||
|
EXPECT_EQ(pathView.size(), 1);
|
||||||
|
EXPECT_TRUE(pathView.is<posix_system>());
|
||||||
|
EXPECT_EQ(pathView[0], "a");
|
||||||
|
|
||||||
|
test_abs_path path2("/a");
|
||||||
|
test_abs_path_view pathView2 = path2;
|
||||||
|
test_abs_path path3("/");
|
||||||
|
test_abs_path_view pathView3 = path3;
|
||||||
|
EXPECT_EQ(pathView, pathView2);
|
||||||
|
EXPECT_NE(pathView, pathView3);
|
||||||
|
|
||||||
|
test_abs_path path4("\\\\");
|
||||||
|
test_abs_path_view pathView4(path4);
|
||||||
|
EXPECT_NE(pathView3, pathView4);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a");
|
||||||
|
test_abs_path_view pathView(path);
|
||||||
|
EXPECT_TRUE(!pathView.empty());
|
||||||
|
EXPECT_EQ(pathView.size(), 1);
|
||||||
|
EXPECT_TRUE(pathView.is<unc_system>());
|
||||||
|
EXPECT_EQ(pathView[0], "a");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b");
|
||||||
|
test_abs_path_view pathView(path);
|
||||||
|
EXPECT_TRUE(!pathView.empty());
|
||||||
|
EXPECT_EQ(pathView.size(), 2);
|
||||||
|
EXPECT_EQ(pathView[0], "a");
|
||||||
|
EXPECT_EQ(pathView[1], "b");
|
||||||
|
}
|
||||||
|
//xxx
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
path += "a/b";
|
||||||
|
path += "c";
|
||||||
|
path += "..";
|
||||||
|
EXPECT_TRUE(!path.empty());
|
||||||
|
EXPECT_EQ(path.size(), 2);
|
||||||
|
EXPECT_EQ(path[0], "a");
|
||||||
|
EXPECT_EQ(path[1], "b");
|
||||||
|
path += "../..";
|
||||||
|
EXPECT_EQ(path.size(), 0);
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
EXPECT_TRUE(path.is<posix_system>());
|
||||||
|
}
|
||||||
|
//xxx
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("\\\\"));
|
||||||
|
path += "a/b";
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path += "../../..";
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
//xxx
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("\\\\"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
path.push_back("..");
|
||||||
|
EXPECT_TRUE(path.empty());
|
||||||
|
}
|
||||||
|
//xxx
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path newPath = path + "../..";
|
||||||
|
EXPECT_TRUE(newPath.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path path(tl::string("/"));
|
||||||
|
test_abs_path_view pathView(path);
|
||||||
|
auto pathParentView = pathView.parent();
|
||||||
|
EXPECT_TRUE(pathParentView.empty());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path(tl::string("/a/b/c/d"));
|
||||||
|
test_abs_path_view pathView(path);
|
||||||
|
test_abs_path_view newPathView = pathView.parent(2);
|
||||||
|
EXPECT_EQ(newPathView.str(), "/a/b");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
EXPECTED_ASSERT_GUARD("Invalid path");
|
||||||
|
test_abs_path path(tl::string("/a"));
|
||||||
|
test_abs_path_view pathView(path);
|
||||||
|
test_abs_path_view newPathView = pathView.parent(2);
|
||||||
|
EXPECT_TRUE(newPathView.empty());
|
||||||
|
}
|
||||||
|
//{
|
||||||
|
// test_abs_path path("\\\\a/b/c/d");
|
||||||
|
// auto p = path.subpath(0, 0);
|
||||||
|
// EXPECT_EQ(p, test_rel_path("a/b/c/d"));
|
||||||
|
//}
|
||||||
|
//{
|
||||||
|
// test_abs_path path("/a/b/c/d");
|
||||||
|
// auto p = path.subpath(1, 0);
|
||||||
|
// EXPECT_EQ(p, test_rel_path("b/c/d"));
|
||||||
|
//}
|
||||||
|
//{
|
||||||
|
// test_abs_path path("\\\\a/b/c/d");
|
||||||
|
// auto p = path.subpath(0, -1);
|
||||||
|
// EXPECT_EQ(p, test_rel_path("a/b/c"));
|
||||||
|
//}
|
||||||
|
//{
|
||||||
|
// test_abs_path path("/a/b/c/d");
|
||||||
|
// auto p = path.subpath(0, 2);
|
||||||
|
// EXPECT_EQ(p, test_rel_path("a/b"));
|
||||||
|
//}
|
||||||
|
{
|
||||||
|
test_abs_path path("\\\\a/b/c");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p, test_abs_path("\\\\a/b"));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
test_abs_path path("/a");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p, test_abs_path("/"));
|
||||||
|
EXPECT_NE(p, test_abs_path("\\\\"));
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
test_abs_path path("/a/b/../c");
|
||||||
|
auto p = path.parent();
|
||||||
|
EXPECT_EQ(p, test_abs_path("/a"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+480
-587
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user