|
4 | 4 | #pragma once |
5 | 5 | #include <ice/string.hxx> |
6 | 6 | #include <ice/heap_string.hxx> |
| 7 | +#include <ice/log_formatters.hxx> |
7 | 8 |
|
8 | | -namespace ice::path |
| 9 | +namespace ice |
9 | 10 | { |
10 | 11 |
|
11 | | - //! \note On windows: starts with a drive letter, on linux: checks for starting backslash. |
12 | | - //! \return true If the path is absolute. |
13 | | - bool is_absolute(ice::String path) noexcept; |
| 12 | + struct PathString |
| 13 | + { |
| 14 | + template<ice::concepts::SupportedCharType CharT> |
| 15 | + static constexpr ice::BasicString<CharT> Separator_Dot; |
| 16 | + template<ice::concepts::SupportedCharType CharT> |
| 17 | + static constexpr ice::BasicString<CharT> Separator_Drive; |
| 18 | + template<ice::concepts::SupportedCharType CharT> |
| 19 | + static constexpr ice::BasicString<CharT> Separator_Directory; |
| 20 | + |
| 21 | + template<> constexpr ice::BasicString<char> Separator_Dot<char> = "."; |
| 22 | + template<> constexpr ice::BasicString<char> Separator_Drive<char> = ":"; |
| 23 | + template<> constexpr ice::BasicString<char> Separator_Directory<char> = "\\/"; |
| 24 | + template<> constexpr ice::BasicString<ice::wchar> Separator_Dot<ice::wchar> = L"."; |
| 25 | + template<> constexpr ice::BasicString<ice::wchar> Separator_Drive<ice::wchar> = L":"; |
| 26 | + template<> constexpr ice::BasicString<ice::wchar> Separator_Directory<ice::wchar> = L"\\/"; |
| 27 | + |
| 28 | + template<typename Self> |
| 29 | + bool is_absolute(this Self const& self) noexcept |
| 30 | + { |
| 31 | + using CharType = ice::string::CharType<Self>; |
| 32 | + |
| 33 | + if constexpr (ice::build::is_windows) |
| 34 | + { |
| 35 | + if (self.size() >= 3_count) |
| 36 | + { |
| 37 | + return self[1] == Separator_Drive<CharType>[0] && Separator_Directory<CharType>.find_first_of(self[2]) != ice::nindex_none; |
| 38 | + } |
| 39 | + return false; |
| 40 | + } |
| 41 | + else |
| 42 | + { |
| 43 | + return self.not_empty() && self.front() == Separator_Directory<CharType>[1]; |
| 44 | + } |
| 45 | + } |
| 46 | + |
| 47 | + template<typename Self> |
| 48 | + bool is_relative(this Self const& self) noexcept |
| 49 | + { |
| 50 | + return self.is_absolute() == false; |
| 51 | + } |
| 52 | + }; |
| 53 | + |
| 54 | + template<ice::concepts::SupportedCharType CharT> |
| 55 | + struct BasicPath : public ice::BasicString<CharT>, public ice::PathString |
| 56 | + { |
| 57 | + using BasicString<CharT>::BasicString; |
| 58 | + using BasicString<CharT>::operator std::basic_string_view<CharT>; |
| 59 | + |
| 60 | + constexpr BasicPath(ice::BasicString<CharT> str) noexcept |
| 61 | + : BasicString<CharT>{ str } |
| 62 | + { } |
| 63 | + }; |
| 64 | + |
| 65 | + using Path = ice::BasicPath<char>; |
| 66 | + |
| 67 | +} // namespace |
| 68 | + |
| 69 | +namespace ice::path |
| 70 | +{ |
14 | 71 |
|
15 | 72 | //! \return true If the path is just the root part. (ex. 'C:/' or '/') |
16 | 73 | bool is_absolute_root(ice::String path) noexcept; |
@@ -71,3 +128,13 @@ namespace ice::path |
71 | 128 | auto replace_extension(ice::HeapString<ice::wchar>& path, ice::WString extension) noexcept -> ice::WString; |
72 | 129 |
|
73 | 130 | } // namespace ice::path |
| 131 | + |
| 132 | +template<typename CharType> |
| 133 | +struct fmt::formatter<ice::BasicPath<CharType>> : public fmt::formatter<std::basic_string_view<CharType>> |
| 134 | +{ |
| 135 | + template<typename FormatContext> |
| 136 | + constexpr auto format(ice::BasicPath<CharType> value, FormatContext& ctx) const noexcept |
| 137 | + { |
| 138 | + return fmt::formatter<std::basic_string_view<CharType>>::format(value, ctx); |
| 139 | + } |
| 140 | +}; |
0 commit comments