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