#pragma once #include "tl/detail/prologue.h" #include #include #include #include "tl/string.h" #include "tl/detail/path_system_utils.h" #include "tl/toolchain.h" ////////////////////////////////////////////////////////////////////////// #define TL_DECLARE_STRING_LITERAL(struct_name, cstr_value)\ struct struct_name\ {\ static const char* value() noexcept\ {\ return cstr_value;\ }\ }; #define TL_DECLARE_STRING_VECTOR(struct_name, ...)\ struct struct_name\ {\ static const tl::vector& vector() noexcept\ {\ static tl::vector s_vector {__VA_ARGS__};\ return s_vector;\ }\ }; #define TL_DECLARE_TLSTRING_VECTOR(struct_name, ...)\ struct struct_name\ {\ static const tl::vector& vector() noexcept\ {\ static tl::vector s_vector {__VA_ARGS__};\ return s_vector;\ }\ }; ////////////////////////////////////////////////////////////////////////// namespace tl { namespace path_system { TL_DECLARE_STRING_LITERAL(back_t, ".."); TL_DECLARE_STRING_LITERAL(current_t, "."); } } ////////////////////////////////////////////////////////////////////////// namespace tl { ////////////////////////////////////////////////////////////////////////// template struct path_systems { template static T format_abs(int type_id, tl::span members) noexcept; static void parse_abs(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept; static void parse_relative(tl::vector& o_elements, const char* path, size_t size) noexcept; static int deduce_system_type(const char* path, size_t size) noexcept; static bool validate_abs_path(int type_id, tl::span members) noexcept; static const tl::vector >& get_all_parse_separators() noexcept; template static bool is(int type_id) noexcept; }; ////////////////////////////////////////////////////////////////////////// template struct custom_path_system : public custom_implementation, public detail::path_system::base_path_system { }; ////////////////////////////////////////////////////////////////////////// template struct simple_path_system : public detail::path_system::base_path_system { template static T format_abs(tl::span members) noexcept; static void parse_abs(tl::vector& o_elements, const char* path, size_t size) noexcept; static bool validate_abs_path(tl::span members) noexcept; static bool match(const char* path, size_t size) noexcept; }; ////////////////////////////////////////////////////////////////////////// } ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// namespace tl { ////////////////////////////////////////////////////////////////////////// template template T path_systems::format_abs(int type_id, tl::span members) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to format an unknown path system type."); return detail::path_system::path_system_getter<0, Systems...>::template format_abs(type_id, members); } ////////////////////////////////////////////////////////////////////////// template void path_systems::parse_abs(tl::vector& o_elements, int type_id, const char* path, size_t size) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to parse an unknown path system type."); detail::path_system::path_system_getter<0, Systems...>::parse_abs(o_elements, type_id, path, size); } ////////////////////////////////////////////////////////////////////////// template int path_systems::deduce_system_type(const char* path, size_t size) noexcept { return detail::path_system::path_system_getter<0, Systems...>::deduce_system_type(path, size); } ////////////////////////////////////////////////////////////////////////// template bool path_systems::validate_abs_path(int type_id, tl::span members) noexcept { TL_PLAIN_ASSERT(type_id >= 0, "Error: trying to validate an unknown path system type."); return detail::path_system::path_system_getter<0, Systems...>::validate_abs_path(type_id, members); } ////////////////////////////////////////////////////////////////////////// template const tl::vector >& path_systems::get_all_parse_separators() noexcept { static tl::vector> s_all_separators_cache = detail::path_system::path_systems_getter::get_all_parse_separators(); return s_all_separators_cache; } ////////////////////////////////////////////////////////////////////////// template void path_systems::parse_relative(tl::vector& o_elements, const char* path, size_t size) noexcept { const tl::vector >& all_separators = get_all_parse_separators(); const size_t path_system_count = all_separators.size(); eastl::fixed_vector elements; int systemIndex = -1; // parse the path const char* start = path; const char* const end = start + size; while (start < end) { bool matchedSeparator = false; const char* sepStart = start; const char* sepEnd = nullptr; // system hasn't been deduced yet if (systemIndex == -1) { for (size_t s = 0; s < path_system_count; ++s) { const tl::vector& separators = all_separators[s]; const char* const* separators_begin = separators.data(); const char* const* separators_end = separators_begin + separators.size(); matchedSeparator = detail::path_system::find_next_separator(separators_begin, separators_end, sepStart, end, sepEnd); if (matchedSeparator) { systemIndex = (int)s; break; } } } // path system already deduced else { const tl::vector& separators = all_separators[systemIndex]; const char* const* separators_begin = separators.data(); const char* const* separators_end = separators_begin + separators.size(); 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.reserve(o_elements.size() + elements.size()); for (string& element : elements) o_elements.emplace_back(std::move(element)); } ////////////////////////////////////////////////////////////////////////// template template bool path_systems::is(int type_id) noexcept { return detail::path_system::path_system_type_checker<0, TypeToCheck, Systems...>::is(type_id); } ////////////////////////////////////////////////////////////////////////// template template T simple_path_system::format_abs(tl::span members) noexcept { if constexpr (is_same_v) { eastl::string buffer; buffer.reserve(8192); detail::path_system::simple_format_abs_path(buffer, members, root_tag::value(), format_separator::value()); return string(buffer.data(), buffer.size()); } else { T str; detail::path_system::simple_format_abs_path(str, members, root_tag::value(), format_separator::value()); return str; } } ////////////////////////////////////////////////////////////////////////// template void simple_path_system::parse_abs(tl::vector& 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()); } ////////////////////////////////////////////////////////////////////////// template bool simple_path_system::match(const char* path, size_t size) noexcept { return detail::path_system::simple_match_prefix(path, size, root_tag::value()); } ////////////////////////////////////////////////////////////////////////// template bool simple_path_system::validate_abs_path(tl::span /*members*/) noexcept { return true; } ////////////////////////////////////////////////////////////////////////// }