63 using String = std::basic_string<CharT>;
65 using StringView = std::basic_string_view<CharT>;
67 constexpr static CharT preferredSep =
'\\';
69 static inline bool isPathSep(CharT c)
71 return c ==
'/' || c == preferredSep;
74 static size_t findPathSep(StringView path,
size_t from = 0)
76 size_t p1 = path.find(
'/',
from);
77 size_t p2 = path.find(preferredSep,
from);
78 return p1 == String::npos ? p2 :
79 p2 == String::npos ? p1 :
83 static size_t rfindPathSep(StringView path,
size_t from = String::npos)
85 size_t p1 = path.rfind(
'/',
from);
86 size_t p2 = path.rfind(preferredSep,
from);
87 return p1 == String::npos ? p2 :
88 p2 == String::npos ? p1 :
120 typename PathDict::StringView remaining,
121 auto && hookComponent)
123 assert(remaining !=
"");
125 typename PathDict::String result;
131 while (!remaining.empty() && PathDict::isPathSep(remaining[0]))
132 remaining.remove_prefix(1);
134 if (remaining.empty())
break;
137 auto nextPathSep = PathDict::findPathSep(remaining);
138 nextPathSep == remaining.npos ? remaining : remaining.substr(0, nextPathSep);
143 remaining.remove_prefix(1);
146 else if (nextComp ==
"..")
148 if (!result.empty()) result.erase(PathDict::rfindPathSep(result));
149 remaining.remove_prefix(2);
154 result += PathDict::preferredSep;
155 if (
const auto slash = PathDict::findPathSep(remaining); slash == result.npos) {
159 result += remaining.substr(0, slash);
160 remaining = remaining.substr(slash);
163 hookComponent(result, remaining);
168 result =
typename PathDict::String { PathDict::preferredSep };