273 lines
6.8 KiB
C++
273 lines
6.8 KiB
C++
#pragma once
|
|
|
|
#include "tl/detail/prologue.h"
|
|
#include "tl/vector.h"
|
|
#include "tl/string.h"
|
|
#include "tl/hash_and_combine.h"
|
|
|
|
namespace tl
|
|
{
|
|
namespace detail
|
|
{
|
|
namespace path_system
|
|
{
|
|
|
|
template <typename PathSystems> struct path_key_less;
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
// inner path_base definition
|
|
template<typename PathSystems>
|
|
class path_base
|
|
{
|
|
public:
|
|
virtual ~path_base() noexcept = default;
|
|
using iterator = tl::vector<string>::iterator;
|
|
using const_iterator = tl::vector<string>::const_iterator;
|
|
using const_reverse_iterator = tl::vector<string>::const_reverse_iterator;
|
|
using key_less = path_key_less<PathSystems>;
|
|
using value_type = std::string;
|
|
|
|
//checked indexing
|
|
const string& at(size_t index) const noexcept;
|
|
|
|
void shrink(size_t size) noexcept;
|
|
|
|
bool empty() const noexcept;
|
|
size_t size() const noexcept;
|
|
void reserve(size_t capacity) noexcept;
|
|
|
|
// if the path is empty, these operations have no effect. They return the removed element as a string.
|
|
string pop_back() noexcept;
|
|
virtual bool push_back(string element) noexcept;
|
|
|
|
virtual void take_elements(tl::vector<string>&& elements) noexcept;
|
|
|
|
iterator begin() noexcept;
|
|
iterator end() noexcept;
|
|
const_iterator begin() const noexcept;
|
|
const_iterator end() const noexcept;
|
|
const_reverse_iterator rbegin() const noexcept;
|
|
const_reverse_iterator rend() const noexcept;
|
|
|
|
uint32_t hash() const noexcept;
|
|
|
|
protected:
|
|
bool validate_element(const string& element) noexcept;
|
|
void push_element(string element) noexcept;
|
|
|
|
tl::vector<string> m_elements;
|
|
mutable uint32_t m_hash = 0;
|
|
|
|
friend bool path_key_less<PathSystems>::operator()(const path_base<PathSystems>& a1, const path_base<PathSystems>& a2) const noexcept;
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
struct path_key_less
|
|
{
|
|
bool operator()(const path_base<PathSystems>& a1, const path_base<PathSystems>& a2) const noexcept;
|
|
};
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
namespace tl
|
|
{
|
|
namespace detail
|
|
{
|
|
namespace path_system
|
|
{
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
const string& path_base<PathSystems>::at(size_t index) const noexcept
|
|
{
|
|
return m_elements[index];
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
void path_base<PathSystems>::shrink(size_t size) noexcept
|
|
{
|
|
if (size < this->size())
|
|
{
|
|
m_elements.resize(size);
|
|
m_hash = 0;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
uint32_t path_base<PathSystems>::hash() const noexcept
|
|
{
|
|
if (m_hash == 0)
|
|
{
|
|
for (const string& e : m_elements)
|
|
hash_and_combine(m_hash, e);
|
|
}
|
|
return m_hash;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
size_t path_base<PathSystems>::size() const noexcept
|
|
{
|
|
return m_elements.size();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
bool path_base<PathSystems>::empty() const noexcept
|
|
{
|
|
return m_elements.empty();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
void path_base<PathSystems>::reserve(size_t capacity) noexcept
|
|
{
|
|
m_elements.reserve(capacity);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
string path_base<PathSystems>::pop_back() noexcept
|
|
{
|
|
if (empty())
|
|
{
|
|
TL_PLAIN_FAIL();
|
|
return string();
|
|
}
|
|
|
|
m_hash = 0;
|
|
auto res = m_elements.back();
|
|
m_elements.pop_back();
|
|
return res;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
bool path_base<PathSystems>::push_back(string element) noexcept
|
|
{
|
|
if (!validate_element(element))
|
|
{
|
|
TL_PLAIN_FAIL("Pushed an invalid path element.");
|
|
return false;
|
|
}
|
|
|
|
push_element(std::move(element));
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
bool path_base<PathSystems>::validate_element(const string& /*element*/) noexcept
|
|
{
|
|
// validate element to be added here
|
|
// if not return false
|
|
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
void path_base<PathSystems>::push_element(string element) noexcept
|
|
{
|
|
m_hash = 0;
|
|
m_elements.push_back(std::move(element));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
void path_base<PathSystems>::take_elements(tl::vector<string>&& elements) noexcept
|
|
{
|
|
m_hash = 0;
|
|
m_elements = std::move(elements);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::iterator path_base<PathSystems>::begin() noexcept
|
|
{
|
|
return m_elements.begin();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::iterator path_base<PathSystems>::end() noexcept
|
|
{
|
|
return m_elements.end();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::const_iterator path_base<PathSystems>::begin() const noexcept
|
|
{
|
|
return m_elements.cbegin();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::const_iterator path_base<PathSystems>::end() const noexcept
|
|
{
|
|
return m_elements.cend();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::const_reverse_iterator path_base<PathSystems>::rbegin() const noexcept
|
|
{
|
|
return m_elements.crbegin();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
typename path_base<PathSystems>::const_reverse_iterator path_base<PathSystems>::rend() const noexcept
|
|
{
|
|
return m_elements.crend();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
template <typename PathSystems>
|
|
bool path_key_less<PathSystems>::operator()(const path_base<PathSystems>& a1, const path_base<PathSystems>& a2) const noexcept
|
|
{
|
|
const size_t sz1 = a1.m_elements.size();
|
|
const size_t sz2 = a2.m_elements.size();
|
|
for (size_t i = 0; i < sz1 && i < sz2; ++i)
|
|
{
|
|
if (a1.m_elements[i] != a2.m_elements[i])
|
|
return a1.m_elements[i].unique_key() < a2.m_elements[i].unique_key();
|
|
}
|
|
return sz1 < sz2;
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|