33 const char* userprofile = std::getenv(
"USERPROFILE");
34 if (userprofile && *userprofile) {
35 return std::filesystem::path(userprofile);
39 const char* homedrive = std::getenv(
"HOMEDRIVE");
40 const char* homepath = std::getenv(
"HOMEPATH");
41 if (homedrive && homepath) {
42 return std::filesystem::path(std::string(homedrive) +
43 std::string(homepath));
48 auto temp = std::filesystem::temp_directory_path(ec);
52 return std::filesystem::path(
".");
53#elif defined(__EMSCRIPTEN__)
55 return std::filesystem::path(
"/home/web_user");
58 const char* home = std::getenv(
"HOME");
60 return std::filesystem::path(home);
64 struct passwd* pw = getpwuid(getuid());
65 if (pw && pw->pw_dir) {
66 return std::filesystem::path(pw->pw_dir);
71 auto cwd = std::filesystem::current_path(ec);
75 return std::filesystem::path(
".");
79 return std::filesystem::path(
".");
84#if defined(YAZE_IOS) || defined(YAZE_APPLE_MOBILE)
86 if (home.empty() || home ==
".") {
88 auto temp = std::filesystem::temp_directory_path(ec);
94 std::filesystem::path app_data =
95 home /
"Library" /
"Application Support" /
"yaze";
98 app_data = home /
"Documents" /
"yaze";
106 wchar_t path[MAX_PATH];
107 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, 0, path))) {
108 std::filesystem::path app_data = std::filesystem::path(path) /
"yaze";
117 std::filesystem::path app_data = home /
"yaze_data";
123#elif defined(__EMSCRIPTEN__)
133 std::filesystem::path app_data(
"/config");
140 std::filesystem::path app_data = home /
".yaze";
156#if defined(YAZE_IOS) || defined(YAZE_APPLE_MOBILE)
158 std::filesystem::path docs_dir = home /
"Documents" /
"Yaze";
161 docs_dir = home /
"Yaze";
169 wchar_t path[MAX_PATH];
170 if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PERSONAL, NULL, 0, path))) {
171 std::filesystem::path docs_dir = std::filesystem::path(path) /
"Yaze";
180 std::filesystem::path docs_dir = home /
"Documents" /
"Yaze";
186#elif defined(__EMSCRIPTEN__)
188 std::filesystem::path docs_dir(
"/projects");
193 std::filesystem::path docs_dir = home /
"Documents" /
"Yaze";
197 docs_dir = home /
"Yaze";
301 const std::string& relative_path) {
302 std::vector<std::filesystem::path> search_paths;
306#ifdef YAZE_ASSETS_PATH
308 search_paths.push_back(std::filesystem::path(YAZE_ASSETS_PATH) /
316 static std::filesystem::path cached_cwd;
317 static bool cwd_cached =
false;
321 cached_cwd = std::filesystem::current_path(ec);
325 if (!cached_cwd.empty()) {
327 search_paths.push_back(cached_cwd /
"assets" / relative_path);
334 static std::filesystem::path cached_exe_dir;
335 static bool exe_dir_cached =
false;
337 if (!exe_dir_cached) {
340 char exe_path[PATH_MAX];
341 uint32_t size =
sizeof(exe_path);
342 if (_NSGetExecutablePath(exe_path, &size) == 0) {
343 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
345#elif defined(__linux__)
346 char exe_path[PATH_MAX];
348 readlink(
"/proc/self/exe", exe_path,
sizeof(exe_path) - 1);
350 exe_path[len] =
'\0';
351 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
354 wchar_t exe_path[MAX_PATH];
355 if (GetModuleFileNameW(NULL, exe_path, MAX_PATH) != 0) {
356 cached_exe_dir = std::filesystem::path(exe_path).parent_path();
362 exe_dir_cached =
true;
365 if (!cached_exe_dir.empty()) {
367 search_paths.push_back(cached_exe_dir /
"assets" / relative_path);
369 search_paths.push_back(cached_exe_dir.parent_path() /
"assets" /
375 auto contents_dir = cached_exe_dir.parent_path();
376 auto bundle_dir = contents_dir.parent_path();
377 auto bundle_parent = bundle_dir.parent_path();
378 search_paths.push_back(contents_dir /
"Resources" /
"assets" /
380 search_paths.push_back(bundle_parent /
"assets" / relative_path);
388 if (!cached_cwd.empty()) {
390 auto parent = cached_cwd.parent_path();
391 if (!parent.empty() && parent != cached_cwd) {
392 search_paths.push_back(parent /
"assets" / relative_path);
393 auto grandparent = parent.parent_path();
394 if (!grandparent.empty() && grandparent != parent) {
395 search_paths.push_back(grandparent /
"assets" / relative_path);
404 static std::filesystem::path cached_home;
405 static bool home_cached =
false;
416 if (!cached_home.empty() && cached_home !=
".") {
418 search_paths.push_back(cached_home /
".yaze" /
"assets" /
428 search_paths.push_back(
429 std::filesystem::path(
"/usr/local/share/yaze/assets") /
431 search_paths.push_back(std::filesystem::path(
"/usr/share/yaze/assets") /
440 const size_t max_paths_to_check = 20;
443 for (
const auto& candidate : search_paths) {
444 if (++checked > max_paths_to_check) {
450 std::error_code exists_ec;
451 if (std::filesystem::exists(candidate, exists_ec) && !exists_ec) {
453 auto status = std::filesystem::status(candidate, exists_ec);
455 status.type() != std::filesystem::file_type::not_found) {
466 return absl::NotFoundError(
467 absl::StrCat(
"Asset not found: ", relative_path));
469 }
catch (
const std::exception& e) {
470 return absl::InternalError(
471 absl::StrCat(
"Exception while searching for asset: ", e.what()));
473 return absl::InternalError(
"Unknown exception while searching for asset");