You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
150 lines
3.4 KiB
150 lines
3.4 KiB
/* 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 <cmext/string_view>
|
|
|
|
# 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) ||
|
|
(prefix_it->empty() && path_it != path_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
|
|
}
|