Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/openxr/src/common/filesystem_utils.cpp
9903 views
1
// Copyright (c) 2017-2025 The Khronos Group Inc.
2
// Copyright (c) 2017 Valve Corporation
3
// Copyright (c) 2017 LunarG, Inc.
4
//
5
// SPDX-License-Identifier: Apache-2.0 OR MIT
6
//
7
// Initial Authors: Mark Young <[email protected]>
8
// Nat Brown <[email protected]>
9
//
10
11
#include "filesystem_utils.hpp"
12
13
#include "platform_utils.hpp"
14
15
#include <cstring>
16
#include <string>
17
18
#if defined DISABLE_STD_FILESYSTEM
19
#define USE_EXPERIMENTAL_FS 0
20
#define USE_FINAL_FS 0
21
22
#else
23
#include "stdfs_conditions.h"
24
#endif
25
26
#if USE_FINAL_FS == 1
27
#include <filesystem>
28
#define FS_PREFIX std::filesystem
29
#elif USE_EXPERIMENTAL_FS == 1
30
#include <experimental/filesystem>
31
#define FS_PREFIX std::experimental::filesystem
32
#elif defined(XR_USE_PLATFORM_WIN32)
33
// Windows fallback includes
34
#include <stdint.h>
35
#include <direct.h>
36
#else
37
// Linux/Apple fallback includes
38
#include <sys/stat.h>
39
#include <unistd.h>
40
#include <limits.h>
41
#include <stdlib.h>
42
#include <dirent.h>
43
#endif
44
45
#if defined(XR_USE_PLATFORM_WIN32)
46
#define PATH_SEPARATOR ';'
47
#define DIRECTORY_SYMBOL '\\'
48
#define ALTERNATE_DIRECTORY_SYMBOL '/'
49
#else
50
#define PATH_SEPARATOR ':'
51
#define DIRECTORY_SYMBOL '/'
52
#endif
53
54
#if (USE_FINAL_FS == 1) || (USE_EXPERIMENTAL_FS == 1)
55
// We can use one of the C++ filesystem packages
56
57
bool FileSysUtilsIsRegularFile(const std::string& path) { return FS_PREFIX::is_regular_file(path); }
58
59
bool FileSysUtilsIsDirectory(const std::string& path) { return FS_PREFIX::is_directory(path); }
60
61
bool FileSysUtilsPathExists(const std::string& path) { return FS_PREFIX::exists(path); }
62
63
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
64
FS_PREFIX::path file_path(path);
65
return file_path.is_absolute();
66
}
67
68
bool FileSysUtilsGetCurrentPath(std::string& path) {
69
FS_PREFIX::path cur_path = FS_PREFIX::current_path();
70
path = cur_path.string();
71
return true;
72
}
73
74
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
75
FS_PREFIX::path path_var(file_path);
76
parent_path = path_var.parent_path().string();
77
return true;
78
}
79
80
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
81
absolute = FS_PREFIX::absolute(path).string();
82
return true;
83
}
84
85
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
86
#if defined(XR_USE_PLATFORM_WIN32)
87
// std::filesystem::canonical fails on UWP and must be avoided. Further, PathCchCanonicalize is not available on Windows 7 and
88
// PathCanonicalizeW is not available on UWP. However, symbolic links are not important on Windows since the loader uses the
89
// registry for indirection instead, and so this function can be a no-op on Windows.
90
canonical = path;
91
#else
92
canonical = FS_PREFIX::canonical(path).string();
93
#endif
94
return true;
95
}
96
97
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
98
FS_PREFIX::path parent_path(parent);
99
FS_PREFIX::path child_path(child);
100
FS_PREFIX::path full_path = parent_path / child_path;
101
combined = full_path.string();
102
return true;
103
}
104
105
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
106
std::string::size_type start = 0;
107
std::string::size_type location = path_list.find(PATH_SEPARATOR);
108
while (location != std::string::npos) {
109
paths.push_back(path_list.substr(start, location));
110
start = location + 1;
111
location = path_list.find(PATH_SEPARATOR, start);
112
}
113
paths.push_back(path_list.substr(start, location));
114
return true;
115
}
116
117
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
118
for (auto& dir_iter : FS_PREFIX::directory_iterator(path)) {
119
files.push_back(dir_iter.path().filename().string());
120
}
121
return true;
122
}
123
124
#elif defined(XR_OS_WINDOWS)
125
126
// For pre C++17 compiler that doesn't support experimental filesystem
127
128
bool FileSysUtilsIsRegularFile(const std::string& path) {
129
const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
130
return attr != INVALID_FILE_ATTRIBUTES && !(attr & FILE_ATTRIBUTE_DIRECTORY);
131
}
132
133
bool FileSysUtilsIsDirectory(const std::string& path) {
134
const DWORD attr = GetFileAttributesW(utf8_to_wide(path).c_str());
135
return attr != INVALID_FILE_ATTRIBUTES && (attr & FILE_ATTRIBUTE_DIRECTORY);
136
}
137
138
bool FileSysUtilsPathExists(const std::string& path) {
139
return (GetFileAttributesW(utf8_to_wide(path).c_str()) != INVALID_FILE_ATTRIBUTES);
140
}
141
142
bool FileSysUtilsIsAbsolutePath(const std::string& path) {
143
bool pathStartsWithDir = (path.size() >= 1) && ((path[0] == DIRECTORY_SYMBOL) || (path[0] == ALTERNATE_DIRECTORY_SYMBOL));
144
145
bool pathStartsWithDrive =
146
(path.size() >= 3) && (path[1] == ':' && (path[2] == DIRECTORY_SYMBOL || path[2] == ALTERNATE_DIRECTORY_SYMBOL));
147
148
return pathStartsWithDir || pathStartsWithDrive;
149
}
150
151
bool FileSysUtilsGetCurrentPath(std::string& path) {
152
wchar_t tmp_path[MAX_PATH];
153
if (nullptr != _wgetcwd(tmp_path, MAX_PATH - 1)) {
154
path = wide_to_utf8(tmp_path);
155
return true;
156
}
157
return false;
158
}
159
160
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
161
std::string full_path;
162
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
163
std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
164
parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
165
return true;
166
}
167
return false;
168
}
169
170
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
171
wchar_t tmp_path[MAX_PATH];
172
if (0 != GetFullPathNameW(utf8_to_wide(path).c_str(), MAX_PATH, tmp_path, NULL)) {
173
absolute = wide_to_utf8(tmp_path);
174
return true;
175
}
176
return false;
177
}
178
179
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& absolute) {
180
// PathCchCanonicalize is not available on Windows 7 and PathCanonicalizeW is not available on UWP. However, symbolic links are
181
// not important on Windows since the loader uses the registry for indirection instead, and so this function can be a no-op on
182
// Windows.
183
absolute = path;
184
return true;
185
}
186
187
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
188
std::string::size_type parent_len = parent.length();
189
if (0 == parent_len || "." == parent || ".\\" == parent || "./" == parent) {
190
combined = child;
191
return true;
192
}
193
char last_char = parent[parent_len - 1];
194
if ((last_char == DIRECTORY_SYMBOL) || (last_char == ALTERNATE_DIRECTORY_SYMBOL)) {
195
parent_len--;
196
}
197
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
198
return true;
199
}
200
201
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
202
std::string::size_type start = 0;
203
std::string::size_type location = path_list.find(PATH_SEPARATOR);
204
while (location != std::string::npos) {
205
paths.push_back(path_list.substr(start, location));
206
start = location + 1;
207
location = path_list.find(PATH_SEPARATOR, start);
208
}
209
paths.push_back(path_list.substr(start, location));
210
return true;
211
}
212
213
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
214
std::string searchPath;
215
FileSysUtilsCombinePaths(path, "*", searchPath);
216
217
WIN32_FIND_DATAW file_data;
218
HANDLE file_handle = FindFirstFileW(utf8_to_wide(searchPath).c_str(), &file_data);
219
if (file_handle != INVALID_HANDLE_VALUE) {
220
do {
221
if (!(file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
222
files.push_back(wide_to_utf8(file_data.cFileName));
223
}
224
} while (FindNextFileW(file_handle, &file_data));
225
return true;
226
}
227
return false;
228
}
229
230
#else // XR_OS_LINUX/XR_OS_APPLE fallback
231
232
// simple POSIX-compatible implementation of the <filesystem> pieces used by OpenXR
233
234
bool FileSysUtilsIsRegularFile(const std::string& path) {
235
struct stat path_stat;
236
stat(path.c_str(), &path_stat);
237
return S_ISREG(path_stat.st_mode);
238
}
239
240
bool FileSysUtilsIsDirectory(const std::string& path) {
241
struct stat path_stat;
242
stat(path.c_str(), &path_stat);
243
return S_ISDIR(path_stat.st_mode);
244
}
245
246
bool FileSysUtilsPathExists(const std::string& path) { return (access(path.c_str(), F_OK) != -1); }
247
248
bool FileSysUtilsIsAbsolutePath(const std::string& path) { return (path[0] == DIRECTORY_SYMBOL); }
249
250
bool FileSysUtilsGetCurrentPath(std::string& path) {
251
char tmp_path[PATH_MAX];
252
if (nullptr != getcwd(tmp_path, PATH_MAX - 1)) {
253
path = tmp_path;
254
return true;
255
}
256
return false;
257
}
258
259
bool FileSysUtilsGetParentPath(const std::string& file_path, std::string& parent_path) {
260
std::string full_path;
261
if (FileSysUtilsGetAbsolutePath(file_path, full_path)) {
262
std::string::size_type lastSeparator = full_path.find_last_of(DIRECTORY_SYMBOL);
263
parent_path = (lastSeparator == 0) ? full_path : full_path.substr(0, lastSeparator);
264
return true;
265
}
266
return false;
267
}
268
269
bool FileSysUtilsGetAbsolutePath(const std::string& path, std::string& absolute) {
270
// canonical path is absolute
271
return FileSysUtilsGetCanonicalPath(path, absolute);
272
}
273
274
bool FileSysUtilsGetCanonicalPath(const std::string& path, std::string& canonical) {
275
char buf[PATH_MAX];
276
if (nullptr != realpath(path.c_str(), buf)) {
277
canonical = buf;
278
return true;
279
}
280
return false;
281
}
282
283
bool FileSysUtilsCombinePaths(const std::string& parent, const std::string& child, std::string& combined) {
284
std::string::size_type parent_len = parent.length();
285
if (0 == parent_len || "." == parent || "./" == parent) {
286
combined = child;
287
return true;
288
}
289
char last_char = parent[parent_len - 1];
290
if (last_char == DIRECTORY_SYMBOL) {
291
parent_len--;
292
}
293
combined = parent.substr(0, parent_len) + DIRECTORY_SYMBOL + child;
294
return true;
295
}
296
297
bool FileSysUtilsParsePathList(std::string& path_list, std::vector<std::string>& paths) {
298
std::string::size_type start = 0;
299
std::string::size_type location = path_list.find(PATH_SEPARATOR);
300
while (location != std::string::npos) {
301
paths.push_back(path_list.substr(start, location));
302
start = location + 1;
303
location = path_list.find(PATH_SEPARATOR, start);
304
}
305
paths.push_back(path_list.substr(start, location));
306
return true;
307
}
308
309
bool FileSysUtilsFindFilesInPath(const std::string& path, std::vector<std::string>& files) {
310
DIR* dir = opendir(path.c_str());
311
if (dir == nullptr) {
312
return false;
313
}
314
struct dirent* entry;
315
while ((entry = readdir(dir)) != nullptr) {
316
files.emplace_back(entry->d_name);
317
}
318
closedir(dir);
319
return true;
320
}
321
322
#endif
323
324