1 /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
2 file Copyright.txt or https://cmake.org/licensing for details. */
4 #include "cmConfigure.h" // IWYU pragma: keep
6 #include "cmCMakePath.h"
14 #include <cm/filesystem>
15 #include <cm/string_view>
18 # include "cmStringAlgorithms.h"
21 cmCMakePath& cmCMakePath::ReplaceWideExtension(cm::string_view extension)
23 auto file = this->Path.filename().string();
24 if (!file.empty() && file != "." && file != "..") {
25 auto pos = file.find('.', file[0] == '.' ? 1 : 0);
26 if (pos != std::string::npos) {
30 if (!extension.empty()) {
31 if (extension[0] != '.') {
34 file.append(std::string(extension));
36 this->Path.replace_filename(file);
40 cmCMakePath cmCMakePath::GetWideExtension() const
42 auto file = this->Path.filename().string();
43 if (file.empty() || file == "." || file == "..") {
47 auto pos = file.find('.', file[0] == '.' ? 1 : 0);
48 if (pos != std::string::npos) {
49 return cm::string_view(file.data() + pos, file.length() - pos);
55 cmCMakePath cmCMakePath::GetNarrowStem() const
57 auto stem = this->Path.stem().string();
59 auto pos = stem.find('.', stem[0] == '.' ? 1 : 0);
60 if (pos != std::string::npos) {
61 return stem.substr(0, pos);
67 cmCMakePath cmCMakePath::Absolute(const cm::filesystem::path& base) const
69 if (this->Path.is_relative()) {
72 // filesystem::path::operator/= use preferred_separator ('\' on Windows)
73 // so converts back to '/'
74 return path.generic_string();
79 bool cmCMakePath::IsPrefix(const cmCMakePath& path) const
81 auto prefix_it = this->Path.begin();
82 auto prefix_end = this->Path.end();
83 auto path_it = path.Path.begin();
84 auto path_end = path.Path.end();
86 while (prefix_it != prefix_end && path_it != path_end &&
87 *prefix_it == *path_it) {
91 return (prefix_it == prefix_end) ||
92 (prefix_it->empty() && path_it != path_end);
95 std::string cmCMakePath::FormatPath(std::string path, format fmt)
98 if (fmt == auto_format || fmt == native_format) {
99 auto prefix = path.substr(0, 4);
100 for (auto& c : prefix) {
105 // remove Windows long filename marker
106 if (prefix == "//?/"_s) {
109 if (cmHasPrefix(path, "UNC/"_s) || cmHasPrefix(path, "UNC\\"_s)) {
115 static_cast<void>(fmt);
120 void cmCMakePath::GetNativePath(std::string& path) const
122 cm::filesystem::path tmp(this->Path);
123 tmp.make_preferred();
127 void cmCMakePath::GetNativePath(std::wstring& path) const
129 cm::filesystem::path tmp(this->Path);
130 tmp.make_preferred();
132 path = tmp.wstring();
135 // Windows long filename
136 static std::wstring UNC(L"\\\\?\\UNC");
137 static std::wstring PREFIX(L"\\\\?\\");
139 if (this->IsAbsolute() && path.length() > _MAX_PATH - 12) {
140 if (this->HasRootName() && path[0] == L'\\') {
141 path = UNC + path.substr(1);
143 path = PREFIX + path;