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

220 lines
5.0 KiB
C++

#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;
}
}
}
}