Kurlyk
Loading...
Searching...
No Matches
path_utils.hpp
Go to the documentation of this file.
1#pragma once
2#ifndef KURLYK_HEADER_KURLYK_UTILS_PATH_UTILS_HPP_INCLUDED
3#define KURLYK_HEADER_KURLYK_UTILS_PATH_UTILS_HPP_INCLUDED
4
7
8#include <cstdint>
9#include <cstdlib>
10#include <stdexcept>
11#include <string>
12#include <vector>
13
14#if defined(_WIN32)
15#include <windows.h>
16#include <locale>
17#include <codecvt>
18#elif defined(__APPLE__)
19#include <limits.h>
20#include <mach-o/dyld.h>
21#include <unistd.h>
22#else
23#include <limits.h>
24#include <unistd.h>
25#endif
26
27#if __cplusplus >= 201703L
28#include <filesystem>
29#endif
30
31namespace kurlyk {
32namespace utils {
33
36 inline std::string get_exec_dir() {
37# if defined(_WIN32)
38 std::vector<wchar_t> buffer(MAX_PATH);
39 HMODULE hModule = GetModuleHandle(NULL);
40
41 // Пробуем получить путь
42 DWORD size = GetModuleFileNameW(hModule, buffer.data(), buffer.size());
43
44 // Если путь слишком длинный, увеличиваем буфер
45 while (size == buffer.size() && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
46 buffer.resize(buffer.size() * 2); // Увеличиваем буфер в два раза
47 size = GetModuleFileNameW(hModule, buffer.data(), buffer.size());
48 }
49
50 if (size == 0) throw std::runtime_error("Failed to get executable path.");
51 std::wstring exe_path(buffer.begin(), buffer.begin() + size);
52 std::wstring::size_type pos = exe_path.find_last_of(L"\\/");
53 if (pos != std::wstring::npos) {
54 exe_path = exe_path.substr(0, pos);
55 }
56
57# if __cplusplus >= 201703L
58 auto utf8_path = std::filesystem::path(exe_path).u8string();
59# if defined(__cpp_char8_t)
60 return std::string(reinterpret_cast<const char*>(utf8_path.data()), utf8_path.size());
61# else
62 return utf8_path;
63# endif
64# else
65 std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
66 return converter.to_bytes(exe_path);
67# endif
68
69# elif defined(__APPLE__)
70 uint32_t path_size = 0;
71 if (_NSGetExecutablePath(NULL, &path_size) != -1 || path_size == 0) {
72 throw std::runtime_error("Failed to determine executable path size.");
73 }
74
75 std::vector<char> buffer(path_size + 1, '\0');
76 if (_NSGetExecutablePath(buffer.data(), &path_size) != 0) {
77 throw std::runtime_error("Failed to get executable path.");
78 }
79
80 std::string exe_path(buffer.data());
81 std::vector<char> resolved_path(PATH_MAX, '\0');
82 if (realpath(exe_path.c_str(), resolved_path.data()) != NULL) {
83 exe_path.assign(resolved_path.data());
84 }
85
86 const size_t pos = exe_path.find_last_of("/");
87 if (pos != std::string::npos) {
88 exe_path.erase(pos);
89 }
90 return exe_path;
91
92# else
93 char result[PATH_MAX];
94 ssize_t count = readlink("/proc/self/exe", result, PATH_MAX);
95
96 if (count == -1) throw std::runtime_error("Failed to get executable path.");
97
98 std::string exe_path(result, count);
99
100 // Обрезаем путь до директории (удаляем имя файла, оставляем только путь к папке)
101 size_t pos = exe_path.find_last_of("\\/");
102 if (pos != std::string::npos) {
103 exe_path = exe_path.substr(0, pos);
104 }
105
106 return exe_path;
107# endif
108 }
109
110} // namespace utils
111} // namespace kurlyk
112
113#endif // KURLYK_HEADER_KURLYK_UTILS_PATH_UTILS_HPP_INCLUDED
std::string get_exec_dir()
Retrieves the directory of the executable file.
Primary namespace for the Kurlyk library, encompassing initialization, request management,...