First
This commit is contained in:
@@ -0,0 +1,383 @@
|
||||
#pragma once
|
||||
|
||||
#include "tl/detail/prologue.h"
|
||||
#include <EASTL/fixed_vector.h>
|
||||
#include "tl/string.h"
|
||||
#include "tl/string.h"
|
||||
|
||||
namespace tl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace path_system
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void simple_format_rel_path(T& o_buffer, const tl::vector<string>& members, const char* separator) noexcept;
|
||||
template<typename T>
|
||||
void simple_format_abs_path(T& o_buffer, const tl::vector<string>& members, const char* root_tag, const char* separator) noexcept;
|
||||
|
||||
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 tl::vector<string> simple_parse_path(const char* path, const char* root_tag, const tl::vector<const char*>& separators) noexcept;
|
||||
|
||||
inline bool simple_match_prefix(const char* path, const char* prefix) noexcept;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename... Tail>
|
||||
struct path_system_getter
|
||||
{
|
||||
template<typename T>
|
||||
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
|
||||
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
|
||||
static 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;
|
||||
};
|
||||
|
||||
// specialization if Head element exists
|
||||
template<int Index, typename Head, typename... Tail>
|
||||
struct path_system_getter<Index, Head, Tail...>
|
||||
{
|
||||
template<typename T>
|
||||
static T format_absolute(int type_idx, const tl::vector<string>& members) noexcept;
|
||||
static void parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept;
|
||||
static 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;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename... Tail>
|
||||
struct path_systems_getter
|
||||
{
|
||||
static tl::vector<tl::vector<const char*>> get_all_parse_separators() noexcept;
|
||||
};
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
struct path_systems_getter<Head, Tail...>
|
||||
{
|
||||
static tl::vector<tl::vector<const char*>> get_all_parse_separators() noexcept;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename TypeToCheck, typename... Tail>
|
||||
struct path_system_type_checker
|
||||
{
|
||||
static bool is(int type_idx) noexcept;
|
||||
};
|
||||
|
||||
// specialization if Head element exists
|
||||
template<int Index, typename TypeToCheck, typename Head, typename... Tail>
|
||||
struct path_system_type_checker<Index, TypeToCheck, Head, Tail...>
|
||||
{
|
||||
static bool is(int type_idx) noexcept;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename parse_separators, typename format_separator>
|
||||
struct base_path_system
|
||||
{
|
||||
static const tl::vector<const char*>& get_parse_separators() noexcept;
|
||||
static const char* get_format_separator() noexcept;
|
||||
|
||||
static string format_relative(const tl::vector<string>& members) noexcept;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
namespace tl
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
namespace path_system
|
||||
{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void simple_format_rel_path(T& o_buffer, const tl::vector<string>& members, const char* separator) noexcept
|
||||
{
|
||||
//calculate the size to reserve
|
||||
size_t totalSize = 0;
|
||||
for (const string& el: members)
|
||||
totalSize += el.size() + 1; //+1 for the separator
|
||||
totalSize -= members.empty() ? 0 : 1;//remove the last separator
|
||||
|
||||
o_buffer.reserve(totalSize);
|
||||
|
||||
//append the elements and separator
|
||||
const size_t pathSize = members.size();
|
||||
for (size_t j = 0; j < pathSize; j++)
|
||||
{
|
||||
const string& member = members[j];
|
||||
o_buffer.append(member.data(), member.size());
|
||||
if (j < pathSize - 1)
|
||||
o_buffer.append(separator);
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename T>
|
||||
void simple_format_abs_path(T& o_buffer, const tl::vector<string>& members, const char* root_tag, const char* separator) noexcept
|
||||
{
|
||||
o_buffer.append(root_tag);
|
||||
detail::path_system::simple_format_rel_path(o_buffer, members, separator);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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
|
||||
{
|
||||
const size_t str_size = end - io_startIt;
|
||||
const char* bestStartIt = nullptr;
|
||||
const char* bestSeparator = nullptr;
|
||||
for (const char* const* separator_ptr = separators_begin; separator_ptr != separators_end; separator_ptr++)
|
||||
{
|
||||
const char* it = ascii::strnstr(io_startIt, *separator_ptr, str_size);
|
||||
if (it != nullptr && (bestStartIt == nullptr || it < bestStartIt))
|
||||
{
|
||||
bestStartIt = it;
|
||||
bestSeparator = *separator_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestStartIt)
|
||||
{
|
||||
io_startIt = bestStartIt;
|
||||
io_endIt = io_startIt + strlen(bestSeparator);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline void simple_parse_path(tl::vector<string>& o_elements, const char* path, size_t size, const char* root_tag, const tl::vector<const char*>& separators) noexcept
|
||||
{
|
||||
const char* pathIt = path;
|
||||
const char* start = path;
|
||||
const char* end = start + size;
|
||||
|
||||
// parse root
|
||||
if (root_tag)
|
||||
{
|
||||
const char* tagIt = root_tag;
|
||||
for (; *tagIt; ++tagIt, ++pathIt)
|
||||
{
|
||||
if (*tagIt != *pathIt)
|
||||
break;
|
||||
}
|
||||
// matched root
|
||||
if (!(*tagIt))
|
||||
start = pathIt;
|
||||
|
||||
// if not start over again
|
||||
else
|
||||
{
|
||||
pathIt = path;
|
||||
start = path;
|
||||
}
|
||||
}
|
||||
|
||||
const char* const* separators_begin = separators.data();
|
||||
const char* const* separators_end = separators_begin + separators.size();
|
||||
|
||||
// parse the rest of the path
|
||||
tl::fixed_vector<string, 64> elements;
|
||||
while (*start != 0)
|
||||
{
|
||||
const char* sepStart = start;
|
||||
const char* sepEnd = nullptr;
|
||||
|
||||
bool matchedSeparator = detail::path_system::find_next_separator(separators_begin, separators_end, sepStart, end, sepEnd);
|
||||
// if has matched separator
|
||||
if (matchedSeparator)
|
||||
{
|
||||
if (sepStart > start)
|
||||
elements.emplace_back(start, sepStart);
|
||||
|
||||
start = sepEnd;
|
||||
}
|
||||
else
|
||||
{
|
||||
//get the remainder of the string
|
||||
if (*start != 0)
|
||||
elements.emplace_back(start);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//now reserve the space and move into final place
|
||||
o_elements.clear();
|
||||
o_elements.reserve(elements.size());
|
||||
for (string& element : elements)
|
||||
o_elements.emplace_back(std::move(element));
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline bool simple_match_prefix(const char* path, size_t size, const char* prefix) noexcept
|
||||
{
|
||||
const size_t prefix_length = strlen(prefix);
|
||||
if (prefix_length > size)
|
||||
return false;
|
||||
return strncmp(path, prefix, prefix_length) == 0;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename... Tail>
|
||||
template<typename T>
|
||||
T path_system_getter<Index, Tail...>::format_absolute(int /*type_idx*/, const tl::vector<string>& /*members*/) noexcept
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed to format path. Invalid type.");
|
||||
return {};
|
||||
}
|
||||
|
||||
template<int Index, typename... Tail>
|
||||
void path_system_getter<Index, Tail...>::parse_absolute(tl::vector<string>& /*o_elements*/, int /*type_idx*/, const char* /*path*/, size_t /* size */) noexcept
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed parsing absolute path. Invalid type.");
|
||||
}
|
||||
|
||||
template<int Index, typename... Tail>
|
||||
int path_system_getter<Index, Tail...>::deduce_system_type(const char* /*path*/, size_t /* size */) noexcept
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
template<int Index, typename... Tail>
|
||||
bool path_system_getter<Index, Tail...>::validate_abs_path(int /*type_idx*/, const tl::vector<string>& /*members*/) noexcept
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed validating path system. Invalid type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename Head, typename... Tail>
|
||||
template<typename T>
|
||||
T path_system_getter<Index, Head, Tail...>::format_absolute(int type_idx, const tl::vector<string>& members) noexcept
|
||||
{
|
||||
if (type_idx == Index)
|
||||
return Head::template format_absolute<T>(members);
|
||||
|
||||
return path_system_getter<Index + 1, Tail...>::template format_absolute<T>(type_idx, members);
|
||||
}
|
||||
|
||||
template<int Index, typename Head, typename... Tail>
|
||||
void path_system_getter<Index, Head, Tail...>::parse_absolute(tl::vector<string>& o_elements, int type_idx, const char* path, size_t size) noexcept
|
||||
{
|
||||
if (type_idx == Index)
|
||||
{
|
||||
Head::parse_absolute(o_elements, path, size);
|
||||
return;
|
||||
}
|
||||
path_system_getter<Index + 1, Tail...>::parse_absolute(o_elements, type_idx, path, size);
|
||||
}
|
||||
|
||||
|
||||
template<int Index, typename Head, typename... Tail>
|
||||
int path_system_getter<Index, Head, Tail...>::deduce_system_type(const char* path, size_t size) noexcept
|
||||
{
|
||||
if (Head::match(path, size))
|
||||
return Index;
|
||||
|
||||
return path_system_getter<Index + 1, Tail...>::deduce_system_type(path, size);
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
if (type_idx == Index)
|
||||
return Head::validate_abs_path(members);
|
||||
|
||||
return path_system_getter<Index + 1, Tail...>::validate_abs_path(type_idx, members);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename... Tail>
|
||||
tl::vector<tl::vector<const char*>> path_systems_getter<Tail...>::get_all_parse_separators() noexcept
|
||||
{
|
||||
return tl::vector<tl::vector<const char*>>();
|
||||
}
|
||||
|
||||
template<typename Head, typename... Tail>
|
||||
tl::vector<tl::vector<const char*>> path_systems_getter<Head, Tail...>::get_all_parse_separators() noexcept
|
||||
{
|
||||
tl::vector<tl::vector<const char*>> separators_array;
|
||||
separators_array.reserve(32);
|
||||
separators_array.push_back(Head::get_parse_separators());
|
||||
|
||||
tl::vector<tl::vector<const char*>> tail_separators_array = path_systems_getter<Tail...>::get_all_parse_separators();
|
||||
std::copy(tail_separators_array.begin(), tail_separators_array.end(), std::back_inserter(separators_array));
|
||||
|
||||
return separators_array;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename TypeToCheck, typename... Tail>
|
||||
bool path_system_type_checker<Index, TypeToCheck, Tail...>::is(int type_idx) noexcept
|
||||
{
|
||||
TL_PLAIN_FAIL("Failed checking path type.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<int Index, typename TypeToCheck, typename Head, typename... Tail>
|
||||
bool path_system_type_checker<Index, TypeToCheck, Head, Tail...>::is(int type_idx) noexcept
|
||||
{
|
||||
if (type_idx == Index)
|
||||
return std::is_same_v<Head, TypeToCheck>;
|
||||
|
||||
return path_system_type_checker<Index + 1, TypeToCheck, Tail...>::is(type_idx);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename parse_separators, typename format_separator>
|
||||
const tl::vector<const char*>& base_path_system<parse_separators, format_separator>::get_parse_separators() noexcept
|
||||
{
|
||||
return parse_separators::vector();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template<typename parse_separators, typename format_separator>
|
||||
string base_path_system<parse_separators, format_separator>::format_relative(const tl::vector<string>& members) noexcept
|
||||
{
|
||||
eastl::string buffer;
|
||||
buffer.reserve(8192);
|
||||
detail::path_system::simple_format_rel_path(buffer, members, format_separator::value());
|
||||
if (buffer.data())
|
||||
return string(buffer.data(), buffer.size());
|
||||
|
||||
return string();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user