-
Notifications
You must be signed in to change notification settings - Fork 0
/
data_path.cpp
133 lines (124 loc) · 3.83 KB
/
data_path.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include "data_path.hpp"
#include <iostream>
#include <vector>
#include <sstream>
#if defined(_WIN32)
#include <windows.h>
#include <Knownfolders.h>
#include <Shlobj.h>
#include <direct.h>
#include <io.h>
#elif defined(__APPLE__)
#include <mach-o/dyld.h>
#elif defined(__linux__)
#include <unistd.h>
#include <sys/stat.h>
#endif //WINDOWS
#ifndef __ANDROID__
//This function gets the path to the current executable in various os-specific ways:
static std::string get_exe_path() {
#if defined(_WIN32)
//See: https://stackoverflow.com/questions/1023306/finding-current-executables-path-without-proc-self-exe
TCHAR buffer[MAX_PATH];
GetModuleFileName(NULL, buffer, MAX_PATH);
std::string ret = buffer;
ret = ret.substr(0, ret.rfind('\\'));
return ret;
#elif defined(__linux__)
//From: https://stackoverflow.com/questions/933850/how-do-i-find-the-location-of-the-executable-in-c
std::vector< char > buffer(1000);
while (1) {
ssize_t got = readlink("/proc/self/exe", &buffer[0], buffer.size());
if (got <= 0) {
return "";
} else if (got < (ssize_t)buffer.size()) {
std::string ret = std::string(buffer.begin(), buffer.begin() + got);
return ret.substr(0, ret.rfind('/'));
}
buffer.resize(buffer.size() + 4000);
}
#elif defined(__APPLE__)
//From: https://stackoverflow.com/questions/799679/programmatically-retrieving-the-absolute-path-of-an-os-x-command-line-app/1024933
uint32_t bufsize = 0;
std::vector< char > buffer;
_NSGetExecutablePath(&buffer[0], &bufsize);
buffer.resize(bufsize, '\0');
bufsize = buffer.size();
if (_NSGetExecutablePath(&buffer[0], &bufsize) != 0) {
throw std::runtime_error("Call to _NSGetExecutablePath failed for mysterious reasons.");
}
std::string ret = std::string(&buffer[0]);
return ret.substr(0, ret.rfind('/'));
#else
#error "No idea what the OS is."
#endif
}
#endif
std::string data_path(std::string const &suffix) {
#ifdef __ANDROID__
std::cout << "Reading from " << suffix << std::endl; //DEBUG
return suffix; //since assets are handled by asset manager and don't have filenames per se
#else
static std::string path = get_exe_path(); //cache result of get_exe_path()
return path + "/" + suffix;
#endif
}
/* From Rktcr; to be used eventually!
static std::string make_user_dir(std::string const &app_name) {
std::string ret = "";
#if defined(_WIN32)
PWSTR path = NULL;
if (S_OK == SHGetKnownFolderPath(FOLDERID_Documents, 0, NULL, &path)) {
int needed = WideCharToMultiByte(CP_UTF8, 0, path, -1, NULL, 0, NULL, NULL);
if (needed != 0) {
std::unique_ptr< char[] > temp(new char[needed]);
memset(temp.get(), 0, needed);
if (WideCharToMultiByte(CP_UTF8, 0, path, -1, temp.get(), needed, NULL, NULL) != 0) {
if (temp.get()[needed-1] != '\0') {
temp.get()[needed-1] = '\0'; //"fix it"
LOG_ERROR("!!!! Woah, missing '\\0' terminator in converted string: " << temp.get());
} else {
ret = temp.get();
}
}
}
CoTaskMemFree(path);
path = NULL;
} else {
LOG_WARNING("Unable to locate FOLDERID_Documents.");
ret = ".";
}
if (ret.empty() || ret[ret.size()-1] != '/') {
ret += '/';
}
ret = ret + app_name;
#elif defined(__APPLE__) || defined(__linux__)
char *var = getenv("HOME");
if (var == NULL) {
std::cerr << "Environment variable 'HOME' is not set; using current directory as data directory" << std::endl;
ret = ".";
} else {
ret = var;
}
if (ret.empty() || ret[ret.size()-1] != '/') {
ret += '/';
}
ret = ret + "." + app_name;
#else
#error "Unsure of the what OS we're on; so can't generate home-directory code"
#endif
//Make sure directory exists... or at least try to!
#ifdef WINDOWS
_mkdir(ret.c_str());
#elif defined(MINGW)
mkdir(ret.c_str());
#else
mkdir(ret.c_str(), 0755);
#endif
return ret;
}
std::string user_path(std::string const &suffix) {
static std::string path = make_user_dir( ... TODO ... );
return path + '/' + suffix;
}
*/