Add PlatformFolders class
This commit is contained in:
119
openVulkanoCpp/IO/PlatformFolders.cpp
Normal file
119
openVulkanoCpp/IO/PlatformFolders.cpp
Normal file
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include "PlatformFolders.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <winerror.h>
|
||||
// For SHGetFolderPathW and various CSIDL "magic numbers"
|
||||
#include <shlobj.h>
|
||||
#include <utf8.h>
|
||||
#include <memory>
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::string GetKnownWindowsFolder(REFKNOWNFOLDERID folderId, std::string name)
|
||||
{
|
||||
LPWSTR wszPath = NULL;
|
||||
HRESULT hr;
|
||||
hr = SHGetKnownFolderPath(folderId, KF_FLAG_CREATE, NULL, &wszPath);
|
||||
std::unique_ptr<wchar_t, decltype(&CoTaskMemFree)> scopeBoundMemory(wszPath, &CoTaskMemFree);
|
||||
|
||||
if (!SUCCEEDED(hr))
|
||||
{
|
||||
throw std::runtime_error("Failed to find " + name + "folder.");
|
||||
}
|
||||
std::wstring winPath(wszPath);
|
||||
std::string str;
|
||||
utf8::utf16to8(winPath.begin(), winPath.end(), std::back_inserter(str));
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::filesystem::path GetHome()
|
||||
{
|
||||
auto home = std::getenv("HOME");
|
||||
if (home == nullptr) throw std::runtime_error("HOME environment variable not set!");
|
||||
return home;
|
||||
}
|
||||
|
||||
[[nodiscard]] std::filesystem::path GetXDGFolderDefault(const char* envName, std::string_view defaultRelativePath)
|
||||
{
|
||||
#ifndef __APPLE__
|
||||
const char* envValue = std::getenv(envName);
|
||||
if (envValue)
|
||||
{
|
||||
if (envValue[0] == '/') return envValue;
|
||||
std::cerr << "Ignoring environment '" << envName << "' (value: '" << envValue << "') because it's relative! XDG specifies it should be absolute path. Falling back to default path.";
|
||||
}
|
||||
#endif
|
||||
return GetHome() / defaultRelativePath;
|
||||
}
|
||||
}
|
||||
|
||||
PlatformFolders::PlatformFolders()
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
dataHome = GetHome() + "/Documents/";
|
||||
configHome = dataHome;
|
||||
stateDir = dataHome;
|
||||
dataCache = GetHome() + "/Library/Caches/";
|
||||
tempDir = dataCache;
|
||||
#elif defined(_WIN32)
|
||||
dataHome = GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData");
|
||||
configHome = GetKnownWindowsFolder(FOLDERID_RoamingAppData, "RoamingAppData");
|
||||
stateDir = GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData");
|
||||
dataCache = GetKnownWindowsFolder(FOLDERID_LocalAppData, "LocalAppData");
|
||||
desktop = GetKnownWindowsFolder(FOLDERID_Desktop, "Desktop");
|
||||
documents = GetKnownWindowsFolder(FOLDERID_Documents, "Documents");
|
||||
downloads = GetKnownWindowsFolder(FOLDERID_Downloads, "Downloads");
|
||||
pictures = GetKnownWindowsFolder(FOLDERID_Pictures, "Pictures");
|
||||
publicDir = GetKnownWindowsFolder(FOLDERID_Public, "Public");
|
||||
music = GetKnownWindowsFolder(FOLDERID_Music, "Music");
|
||||
video = GetKnownWindowsFolder(FOLDERID_Videos, "Videos");
|
||||
savedGames = GetKnownWindowsFolder(FOLDERID_SavedGames, "Saved Games");
|
||||
#else
|
||||
dataHome = GetXDGFolderDefault("XDG_DATA_HOME", ".local/share");
|
||||
configHome = GetXDGFolderDefault("XDG_CONFIG_HOME", ".config");
|
||||
stateDir = GetXDGFolderDefault("XDG_STATE_HOME", ".local/state");
|
||||
dataCache = GetXDGFolderDefault("XDG_CACHE_HOME", ".cache");
|
||||
#endif
|
||||
#ifndef __APPLE__
|
||||
tempDir = std::filesystem::temp_directory_path();
|
||||
#endif
|
||||
|
||||
// Use XDG resolution on Linux and MacOS (will skip the env variable check on MacOS and just use the fallbacks, since they align with apple)
|
||||
#ifndef _WIN32
|
||||
desktop = GetXDGFolderDefault("XDG_DESKTOP_DIR", "Desktop");
|
||||
documents = GetXDGFolderDefault("XDG_DOCUMENTS_DIR", "Documents");
|
||||
downloads = GetXDGFolderDefault("XDG_DOWNLOAD_DIR", "Downloads");
|
||||
pictures = GetXDGFolderDefault("XDG_PICTURES_DIR", "Pictures");
|
||||
publicDir = GetXDGFolderDefault("XDG_PUBLICSHARE_DIR", "Public");
|
||||
music = GetXDGFolderDefault("XDG_MUSIC_DIR", "Music");
|
||||
#ifdef __APPLE__
|
||||
video = GetXDGFolderDefault("XDG_VIDEOS_DIR", "Movies");
|
||||
#else
|
||||
video = GetXDGFolderDefault("XDG_VIDEOS_DIR", "Videos");
|
||||
#endif
|
||||
savedGames = documents / "Saved Games";
|
||||
#endif
|
||||
}
|
||||
|
||||
PlatformFolders& PlatformFolders::GetInstance()
|
||||
{
|
||||
static PlatformFolders instance;
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
49
openVulkanoCpp/IO/PlatformFolders.hpp
Normal file
49
openVulkanoCpp/IO/PlatformFolders.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
namespace openVulkanoCpp
|
||||
{
|
||||
class PlatformFolders
|
||||
{
|
||||
std::filesystem::path dataHome, configHome, stateDir, dataCache, tempDir;
|
||||
std::filesystem::path desktop, documents, downloads, pictures, publicDir, music, video, savedGames;
|
||||
|
||||
PlatformFolders();
|
||||
|
||||
static PlatformFolders& GetInstance();
|
||||
|
||||
public:
|
||||
[[nodiscard]] static const std::filesystem::path& GetDataHomeDir() { return GetInstance().dataHome; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetConfigHomeDir() { return GetInstance().configHome; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetStateDir() { return GetInstance().stateDir; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetCacheDir() { return GetInstance().dataCache; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetTempDir() { return GetInstance().tempDir; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetDesktopDir() { return GetInstance().desktop; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetDocumentsDir() { return GetInstance().documents; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetDownloadDir() { return GetInstance().downloads; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetPicturesDir() { return GetInstance().pictures; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetPublicShareDir() { return GetInstance().publicDir; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetMusicDir() { return GetInstance().music; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetVideoDir() { return GetInstance().video; }
|
||||
|
||||
[[nodiscard]] static const std::filesystem::path& GetSaveGamesDir() { return GetInstance().savedGames; }
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user