summaryrefslogtreecommitdiffstats
path: root/Source/cmCMakePath.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'Source/cmCMakePath.cxx')
-rw-r--r--Source/cmCMakePath.cxx146
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
+}