2#ifndef _MDBX_CONTAINERS_PATH_UTILS_HPP_INCLUDED
3#define _MDBX_CONTAINERS_PATH_UTILS_HPP_INCLUDED
10#if __cplusplus >= 201703L
22#if __cplusplus < 202002L
36# if __cplusplus >= 201703L
37 namespace fs = std::filesystem;
44# if __cplusplus >= 201703L
45 return fs::u8path(path).is_absolute();
49 return (path.size() >= 2 && std::isalpha(path[0]) && path[1] ==
':') ||
50 (path.size() >= 2 && path[0] ==
'\\' && path[1] ==
'\\') ||
51 (path.size() >= 2 && path[0] ==
'/' && path[1] ==
'/');
54 return !path.empty() && path[0] ==
'/';
63# if __cplusplus >= 201703L
64 return fs::u8path(file_path).parent_path().u8string();
66 size_t pos = file_path.find_last_of(
"/\\");
67 if (pos == std::string::npos)
69 return file_path.substr(0, pos);
77 std::vector<wchar_t> buffer(MAX_PATH);
78 HMODULE hModule = GetModuleHandle(NULL);
81 std::size_t size =
static_cast<std::size_t
>(GetModuleFileNameW(hModule, buffer.data(),
static_cast<DWORD
>(buffer.size())));
84 while (size == buffer.size() && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
85 buffer.resize(buffer.size() * 2);
86 size =
static_cast<std::size_t
>(GetModuleFileNameW(hModule, buffer.data(),
static_cast<DWORD
>(buffer.size())));
90 throw std::runtime_error(
"Failed to get executable path.");
93 std::wstring exe_path(buffer.begin(), buffer.begin() + size);
96 size_t pos = exe_path.find_last_of(L
"\\/");
97 if (pos != std::wstring::npos) {
98 exe_path = exe_path.substr(0, pos);
101# if __cplusplus >= 202002L
102 fs::path path_wide = exe_path;
103 return path_wide.u8string();
106 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
107 return converter.to_bytes(exe_path);
111 char result[PATH_MAX];
112 ssize_t count = readlink(
"/proc/self/exe", result, PATH_MAX);
115 throw std::runtime_error(
"Failed to get executable path.");
118 std::string exe_path(result, count);
121 size_t pos = exe_path.find_last_of(
"\\/");
122 if (pos != std::string::npos) {
123 exe_path = exe_path.substr(0, pos);
134# if __cplusplus >= 201703L
135 return fs::u8path(file_path).filename().u8string();
137 size_t pos = file_path.find_last_of(
"/\\");
138 if (pos == std::string::npos)
return file_path;
139 return file_path.substr(pos + 1);
143#if __cplusplus >= 201703L
149 inline std::string make_relative(
const std::string& file_path,
const std::string& base_path) {
150 if (base_path.empty())
return file_path;
151 fs::path fileP = fs::u8path(file_path);
152 fs::path baseP = fs::u8path(base_path);
154 fs::path relativeP = fs::relative(fileP, baseP, ec);
159 return relativeP.u8string();
168# if __cplusplus >= 202002L
172 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
174 fs::path parent_dir = fs::path(wide_path);
179 if (parent_dir.empty()) parent_dir = fs::current_path();
180 if (!fs::exists(parent_dir)) {
182 if (!std::filesystem::create_directories(parent_dir, ec)) {
183 throw std::runtime_error(
"Failed to create directories for path: " + parent_dir.u8string());
203 size_t n = path.size();
206 if (n >= 1 && (path[0] ==
'/' || path[0] ==
'\\')) {
210 }
else if (n >= 2 && std::isalpha(path[0]) && path[1] ==
':') {
212 result.
root = path.substr(0, 2);
214 if (n >= 3 && (path[2] ==
'/' || path[2] ==
'\\')) {
223 while (i < n && (path[i] ==
'/' || path[i] ==
'\\')) {
228 while (j < n && path[j] !=
'/' && path[j] !=
'\\') {
232 result.
components.push_back(path.substr(i, j - i));
244 int n_len = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);
245 if (n_len == 0)
return {};
247 std::wstring wide_string(n_len + 1, L
'\0');
248 MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, &wide_string[0], n_len);
250 n_len = WideCharToMultiByte(CP_ACP, 0, wide_string.c_str(), -1, NULL, 0, NULL, NULL);
251 if (n_len == 0)
return {};
253 std::string ansi_string(n_len - 1,
'\0');
254 WideCharToMultiByte(CP_ACP, 0, wide_string.c_str(), -1, &ansi_string[0], n_len, NULL, NULL);
262 if (path.empty())
return;
265 size_t components_size = components.size();
268 std::string current_path = path_pc.
root;
269 for (
size_t i = 0; i < components_size; ++i) {
270 if (!current_path.empty() && current_path.back() !=
'/' && current_path.back() !=
'\\') {
273 current_path += components[i];
276 if (components[i] ==
".." ||
277 components[i] ==
"/" ||
278 components[i] ==
"~/")
continue;
282 int ret = mkdir(current_path.c_str(), 0755);
285 if (ret != 0 && errnum != EEXIST) {
286 throw std::runtime_error(
"Failed to create directory: " + current_path);
std::string get_parent_path(const std::string &file_path)
Extracts the parent directory from a full file path.
PathComponents split_path(const std::string &path)
Splits a path into its root and components.
void create_directories(const std::string &path)
Creates directories recursively for the given path.
std::string get_exec_dir()
Retrieves the directory of the executable file.
bool is_absolute_path(const std::string &path)
Checks whether the given path is absolute (cross-platform).
std::string utf8_to_ansi(const std::string &utf8) noexcept
Converts a UTF-8 string to an ANSI string (Windows-specific).
std::string get_file_name(const std::string &file_path)
Extracts the file name from a full file path.
Structure to hold the root and components of a path.
std::vector< std::string > components
The components of the path.
std::string root
The root part of the path (e.g., "/", "C:")