mirror of
https://github.com/lifegpc/c-utils.git
synced 2026-06-06 05:08:45 +08:00
Update
This commit is contained in:
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "googletest"]
|
||||
path = googletest
|
||||
url = https://github.com/google/googletest
|
||||
124
fileop.cpp
124
fileop.cpp
@@ -419,7 +419,6 @@ bool fileop::mkdirs(std::string path, int mode, bool allow_exists) {
|
||||
}
|
||||
|
||||
bool fileop::get_file_size(std::string path, size_t& size) {
|
||||
if (!exists(path)) return false;
|
||||
#if _WIN32
|
||||
UINT cp[] = { CP_UTF8, CP_OEMCP, CP_ACP };
|
||||
int i;
|
||||
@@ -545,3 +544,126 @@ int fileop::fcloseall() {
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
std::string fileop::relpath(std::string path, std::string start) {
|
||||
// 如果 start 为空,使用当前目录
|
||||
if (start.empty()) {
|
||||
start = ".";
|
||||
}
|
||||
|
||||
// 将 Windows 风格的路径分隔符统一转换为 '/'
|
||||
auto normalize_path = [](std::string& p) {
|
||||
std::string result = p;
|
||||
for (auto& c : result) {
|
||||
if (c == '\\') c = '/';
|
||||
}
|
||||
// 确保路径末尾没有斜杠
|
||||
if (!result.empty() && result.back() == '/') {
|
||||
result.pop_back();
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
std::string norm_path = normalize_path(path);
|
||||
std::string norm_start = normalize_path(start);
|
||||
|
||||
// 如果两个路径相同,返回当前目录
|
||||
if (norm_path == norm_start) {
|
||||
return ".";
|
||||
}
|
||||
|
||||
// 如果 path 是绝对路径但 start 不是,或者反之,无法计算相对路径
|
||||
#ifdef _WIN32
|
||||
bool path_is_abs = isabs(path);
|
||||
bool start_is_abs = isabs(start);
|
||||
|
||||
// 在 Windows 上,还要检查驱动器号是否相同
|
||||
if (path_is_abs && start_is_abs) {
|
||||
if (norm_path.length() >= 2 && norm_start.length() >= 2) {
|
||||
// 如果驱动器号不同,无法计算相对路径
|
||||
if (tolower(norm_path[0]) != tolower(norm_start[0]) || norm_path[1] != ':') {
|
||||
return path; // 返回原路径
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
bool path_is_abs = !norm_path.empty() && norm_path[0] == '/';
|
||||
bool start_is_abs = !norm_start.empty() && norm_start[0] == '/';
|
||||
#endif
|
||||
|
||||
if (path_is_abs != start_is_abs) {
|
||||
return path; // 无法计算相对路径,返回原路径
|
||||
}
|
||||
|
||||
// 分割路径为组件
|
||||
auto split_path = [](const std::string& p) {
|
||||
std::vector<std::string> components;
|
||||
std::string::size_type start = 0;
|
||||
std::string::size_type end = 0;
|
||||
|
||||
while ((end = p.find('/', start)) != std::string::npos) {
|
||||
if (end != start) {
|
||||
components.push_back(p.substr(start, end - start));
|
||||
}
|
||||
start = end + 1;
|
||||
}
|
||||
|
||||
if (start < p.length()) {
|
||||
components.push_back(p.substr(start));
|
||||
}
|
||||
|
||||
return components;
|
||||
};
|
||||
|
||||
auto path_components = split_path(norm_path);
|
||||
auto start_components = split_path(norm_start);
|
||||
|
||||
// 找到公共前缀
|
||||
size_t i = 0;
|
||||
while (i < path_components.size() && i < start_components.size()) {
|
||||
#ifdef _WIN32
|
||||
// Windows 路径不区分大小写
|
||||
if (str_util::tolower(path_components[i]) != str_util::tolower(start_components[i])) {
|
||||
break;
|
||||
}
|
||||
#else
|
||||
if (path_components[i] != start_components[i]) {
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
i++;
|
||||
}
|
||||
|
||||
// 构建相对路径
|
||||
std::string result;
|
||||
|
||||
// 添加 ".." 以表示上级目录
|
||||
for (size_t j = i; j < start_components.size(); j++) {
|
||||
if (!result.empty()) {
|
||||
result += "/";
|
||||
}
|
||||
result += "..";
|
||||
}
|
||||
|
||||
// 添加目标路径的非共享部分
|
||||
for (size_t j = i; j < path_components.size(); j++) {
|
||||
if (!result.empty()) {
|
||||
result += "/";
|
||||
}
|
||||
result += path_components[j];
|
||||
}
|
||||
|
||||
// 如果结果为空,表示当前目录
|
||||
if (result.empty()) {
|
||||
return ".";
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
// 在 Windows 上,将斜杠转换回反斜杠
|
||||
for (auto& c : result) {
|
||||
if (c == '/') c = '\\';
|
||||
}
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
7
fileop.h
7
fileop.h
@@ -175,5 +175,12 @@ namespace fileop {
|
||||
* @return 0(>=0) succeed. EOF error happened.
|
||||
*/
|
||||
int fcloseall();
|
||||
/**
|
||||
* @brief Return a relative path
|
||||
* @param path Path
|
||||
* @param start Start path
|
||||
* @return Result
|
||||
*/
|
||||
std::string relpath(std::string path, std::string start = "");
|
||||
}
|
||||
#endif
|
||||
|
||||
Submodule googletest updated: 1d17ea141d...0bdccf4aa2
12
str_util.cpp
12
str_util.cpp
@@ -30,6 +30,18 @@ bool str_util::touppercase(std::string ori, std::string& result) {
|
||||
}
|
||||
}
|
||||
|
||||
std::string str_util::tolower(std::string ori) {
|
||||
std::string result;
|
||||
tolowercase(ori, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string str_util::toupper(std::string ori) {
|
||||
std::string result;
|
||||
touppercase(ori, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string str_util::str_replace(std::string input, std::string pattern, std::string new_content) {
|
||||
auto loc = input.find(pattern, 0);
|
||||
auto len = pattern.length();
|
||||
|
||||
@@ -19,6 +19,8 @@ namespace str_util {
|
||||
* @return true if successed.
|
||||
*/
|
||||
bool touppercase(std::string ori, std::string& result);
|
||||
std::string tolower(std::string ori);
|
||||
std::string toupper(std::string ori);
|
||||
/**
|
||||
* @brief Replace all pattern to new_content
|
||||
* @param input Input string
|
||||
|
||||
Reference in New Issue
Block a user