* This file is part of the MindStudio project.
* Copyright (c) 2025 Huawei Technologies Co.,Ltd.
*
* MindStudio is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* ------------------------------------------------------------------------- */
#include "Path.h"
#include <unistd.h>
#include <sys/stat.h>
#include <linux/limits.h>
#include "Ustring.h"
constexpr char const *PATH_SEP = "/";
constexpr char const *CURRENT_SEGMENT = ".";
constexpr char const *PARENT_SEGMENT = "..";
Path::Path(void) noexcept : absolute_{false} { }
* 构造函数中的核心逻辑为将一个路径字符串解析为一系列由 PATH_SEP 分隔的构件(components)组成,
* 由 std::vector<std::string> 表示。路径可分为相对路径和绝对路径。相对路径在 Path 中表示为第一
* 个构件不以分隔符开头,如 `["test", "test.cpp"]`;绝对路径的第一个构件以分隔符开头,如
* `["/test", "test.cpp"]`。
*/
Path::Path(std::string path) noexcept : absolute_{false}
{
path = Strip(path);
if (path.empty()) {
return;
}
if (path[0] == PATH_SEP[0]) {
absolute_ = true;
}
size_t j = 0;
for (size_t i = 0; i < path.size(); i = j) {
j = i + 1;
if (path[i] == PATH_SEP[0]) {
continue;
}
while (j < path.size() && path[j] != PATH_SEP[0]) {
j++;
}
std::string route = path.substr(i, j - i);
if (route != CURRENT_SEGMENT) {
route_.emplace_back(route);
}
}
}
std::string Path::ToString(void) const
{
std::string raw;
if (absolute_) {
raw = PATH_SEP;
} else if (route_.empty()) {
return CURRENT_SEGMENT;
}
raw.append(Join(route_.cbegin(), route_.cend(), PATH_SEP));
return raw;
}
std::string Path::Name(void) const
{
if (route_.empty()) {
return "";
}
return route_.back();
}
Path Path::Parent(void) const &
{
return Path(*this).Parent();
}
Path Path::Parent(void) &&
{
if (!route_.empty()) {
route_.pop_back();
}
return std::move(*this);
}
Path Path::Absolute(void) const &
{
return Path(*this).Absolute();
}
Path Path::Absolute(void) &&
{
char buf[PATH_MAX] = {0};
std::string cwd;
if (getcwd(buf, sizeof(buf))) {
cwd = buf;
}
return Path(cwd) / std::move(*this);
}
Path Path::Resolved(void) const &
{
return Path(*this).Resolved();
}
Path Path::Resolved(void) &&
{
Path path = std::move(*this).Absolute();
auto fast = path.route_.cbegin();
auto slow = path.route_.begin();
for (; fast != path.route_.cend(); ++fast) {
if (*fast != PARENT_SEGMENT) {
*slow++ = *fast;
} else if (slow > path.route_.begin()) {
--slow;
}
}
path.route_.erase(slow, path.route_.end());
return path;
}
Path Path::operator/(Path rhs) const &
{
return Path(*this) / rhs;
}
Path Path::operator/(Path rhs) &&
{
if (rhs.absolute_) {
return std::move(rhs);
}
for (auto &r : rhs.route_) {
route_.emplace_back(std::move(r));
}
return std::move(*this);
}
bool Path::GetStat(struct stat &st) const
{
return stat(this->ToString().c_str(), &st) == 0;
}
bool Path::Exists(void) const
{
struct stat st{};
return stat(this->ToString().c_str(), &st) == 0;
}