diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-24 01:30:55 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-24 01:30:55 +1000 |
commit | 2798d4bf668d74028b5c1f88ae5b7b25cd08de2d (patch) | |
tree | 4a4df7c000c2e7d8be953dcf0724aa8f4b0d2b24 /source/core/StarAssetPath.cpp | |
parent | 6832c10ed5482530b4a423a78700b279fc73212a (diff) |
what the fuck it's 1:30 AM. god
Diffstat (limited to 'source/core/StarAssetPath.cpp')
-rw-r--r-- | source/core/StarAssetPath.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/source/core/StarAssetPath.cpp b/source/core/StarAssetPath.cpp new file mode 100644 index 0000000..3a6a83e --- /dev/null +++ b/source/core/StarAssetPath.cpp @@ -0,0 +1,165 @@ +#include "StarAssetPath.hpp" +#include "StarLexicalCast.hpp" + +namespace Star { + +// The filename is everything after the last slash (excluding directives) and +// up to the first directive marker. +static Maybe<pair<size_t, size_t>> findFilenameRange(std::string const& pathUtf8) { + size_t firstDirectiveOrSubPath = pathUtf8.find_first_of(":?"); + size_t filenameStart = 0; + while (true) { + size_t find = pathUtf8.find('/', filenameStart); + if (find >= firstDirectiveOrSubPath) + break; + filenameStart = find + 1; + } + + if (filenameStart == NPos) { + return {}; + } else if (firstDirectiveOrSubPath == NPos) { + return {{filenameStart, pathUtf8.size()}}; + } else { + return {{filenameStart, firstDirectiveOrSubPath}}; + } +} + +AssetPath AssetPath::split(String const& path) { + auto i = path.begin(); + auto end = path.end(); + + AssetPath components; + + // base paths cannot have any ':' or '?' characters, stop at the first one. + while (i != end) { + String::Char c = *i; + if (c == ':' || c == '?') + break; + + components.basePath += c; + ++i; + } + + // Sub-paths must immediately follow base paths and must start with a ':', + // after this point any further ':' characters are not special. + if (i != end && *i == ':') { + ++i; + while (i != end) { + String::Char c = *i; + if (c == '?') + break; + + if (!components.subPath) + components.subPath.emplace(); + + *components.subPath += c; + ++i; + } + } + + // Directives must follow the base path and optional sub-path, and each + // directive is separated by one or more '?' characters. + while (i != end && *i == '?') { + String directives; + while (i != end) { + directives.append(*i); + ++i; + } + + if (!directives.empty()); + components.directives.append(move(directives)); + } + + starAssert(i == end); + + return components; +} + +String AssetPath::join(AssetPath const& components) { + return toString(components); +} + +String AssetPath::setSubPath(String const& path, String const& subPath) { + auto components = split(path); + components.subPath = subPath; + return join(components); +} + +String AssetPath::removeSubPath(String const& path) { + auto components = split(path); + components.subPath.reset(); + return join(components); +} + +String AssetPath::getDirectives(String const& path) { + size_t firstDirective = path.find('?'); + if (firstDirective == NPos) + return {}; + return path.substr(firstDirective + 1); +} + +String AssetPath::addDirectives(String const& path, String const& directives) { + return String::joinWith("?", path, directives); +} + +String AssetPath::removeDirectives(String const& path) { + size_t firstDirective = path.find('?'); + if (firstDirective == NPos) + return path; + return path.substr(0, firstDirective); +} + +String AssetPath::directory(String const& path) { + if (auto p = findFilenameRange(path.utf8())) { + return String(path.utf8().substr(0, p->first)); + } else { + return String(); + } +} + +String AssetPath::filename(String const& path) { + if (auto p = findFilenameRange(path.utf8())) { + return String(path.utf8().substr(p->first, p->second)); + } else { + return String(); + } +} + +String AssetPath::extension(String const& path) { + auto file = filename(path); + auto lastDot = file.findLast("."); + if (lastDot == NPos) + return ""; + + return file.substr(lastDot + 1); +} + +String AssetPath::relativeTo(String const& sourcePath, String const& givenPath) { + if (!givenPath.empty() && givenPath[0] == '/') + return givenPath; + + auto path = directory(sourcePath); + path.append(givenPath); + return path; +} + +bool AssetPath::operator==(AssetPath const& rhs) const { + return tie(basePath, subPath, directives) == tie(rhs.basePath, rhs.subPath, rhs.directives); +} + +std::ostream& operator<<(std::ostream& os, AssetPath const& rhs) { + os << rhs.basePath; + if (rhs.subPath) { + os << ":"; + os << *rhs.subPath; + } + + rhs.directives.forEach([&](ImageOperation const& operation, String const& string) { + os << "?"; + os << string; + }); + + return os; +} + +} |