diff options
Diffstat (limited to 'Source/cmCMakePath.cxx')
-rw-r--r-- | Source/cmCMakePath.cxx | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/Source/cmCMakePath.cxx b/Source/cmCMakePath.cxx new file mode 100644 index 0000000..b8215df --- /dev/null +++ b/Source/cmCMakePath.cxx @@ -0,0 +1,146 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmCMakePath.h" + +#include <string> + +#if defined(_WIN32) +# include <cstdlib> +#endif + +#include <cm/filesystem> +#include <cm/string_view> + +#if defined(_WIN32) +# include "cmStringAlgorithms.h" +#endif + +cmCMakePath& cmCMakePath::ReplaceWideExtension(cm::string_view extension) +{ + auto file = this->Path.filename().string(); + if (!file.empty() && file != "." && file != "..") { + auto pos = file.find('.', file[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + file.erase(pos); + } + } + if (!extension.empty()) { + if (extension[0] != '.') { + file += '.'; + } + file.append(std::string(extension)); + } + this->Path.replace_filename(file); + return *this; +} + +cmCMakePath cmCMakePath::GetWideExtension() const +{ + auto file = this->Path.filename().string(); + if (file.empty() || file == "." || file == "..") { + return cmCMakePath{}; + } + + auto pos = file.find('.', file[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + return cm::string_view(file.data() + pos, file.length() - pos); + } + + return cmCMakePath{}; +} + +cmCMakePath cmCMakePath::GetNarrowStem() const +{ + auto stem = this->Path.stem().string(); + if (!stem.empty()) { + auto pos = stem.find('.', stem[0] == '.' ? 1 : 0); + if (pos != std::string::npos) { + return stem.substr(0, pos); + } + } + return stem; +} + +cmCMakePath cmCMakePath::Absolute(const cm::filesystem::path& base) const +{ + if (this->Path.is_relative()) { + auto path = base; + path /= this->Path; + // filesystem::path::operator/= use preferred_separator ('\' on Windows) + // so converts back to '/' + return path.generic_string(); + } + return *this; +} + +bool cmCMakePath::IsPrefix(const cmCMakePath& path) const +{ + auto prefix_it = this->Path.begin(); + auto prefix_end = this->Path.end(); + auto path_it = path.Path.begin(); + auto path_end = path.Path.end(); + + while (prefix_it != prefix_end && path_it != path_end && + *prefix_it == *path_it) { + ++prefix_it; + ++path_it; + } + return prefix_it == prefix_end; +} + +std::string cmCMakePath::FormatPath(std::string path, format fmt) +{ +#if defined(_WIN32) + if (fmt == auto_format || fmt == native_format) { + auto prefix = path.substr(0, 4); + for (auto& c : prefix) { + if (c == '\\') { + c = '/'; + } + } + // remove Windows long filename marker + if (prefix == "//?/"_s) { + path.erase(0, 4); + } + if (cmHasPrefix(path, "UNC/"_s) || cmHasPrefix(path, "UNC\\"_s)) { + path.erase(0, 2); + path[0] = '/'; + } + } +#else + static_cast<void>(fmt); +#endif + return path; +} + +void cmCMakePath::GetNativePath(std::string& path) const +{ + cm::filesystem::path tmp(this->Path); + tmp.make_preferred(); + + path = tmp.string(); +} +void cmCMakePath::GetNativePath(std::wstring& path) const +{ + cm::filesystem::path tmp(this->Path); + tmp.make_preferred(); + + path = tmp.wstring(); + +#if defined(_WIN32) + // Windows long filename + static std::wstring UNC(L"\\\\?\\UNC"); + static std::wstring PREFIX(L"\\\\?\\"); + + if (this->IsAbsolute() && path.length() > _MAX_PATH - 12) { + if (this->HasRootName() && path[0] == L'\\') { + path = UNC + path.substr(1); + } else { + path = PREFIX + path; + } + } +#endif +} |