diff --git a/lib/VCMIDirs.cpp b/lib/VCMIDirs.cpp index c35ea9913..381350f96 100644 --- a/lib/VCMIDirs.cpp +++ b/lib/VCMIDirs.cpp @@ -11,467 +11,388 @@ #include "StdInc.h" #include "VCMIDirs.h" -namespace bfs = boost::filesystem; +namespace bfs = boost::filesystem; // Should be in each cpp file + +#ifdef _WIN32 +// File: VCMIDirs_win32.h +//#include "IVCMIDirs.h" + +class VCMIDirs_win32 : public IVCMIDirs +{ + public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + boost::filesystem::path userSavePath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path clientPath() const override; + boost::filesystem::path serverPath() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; + + std::string genHelpString() const override; +}; +// End of file: VCMIDirs_win32.h + +// File: VCMIDirs_win32.cpp +//#include "StdInc.h" +//#include "VCMIDirs_win32" +// WinAPI +#include // WideCharToMultiByte +#include // SHGetSpecialFolderPathW namespace VCMIDirs { - namespace detail + const IVCMIDirs* get() { - bfs::path g_user_data_path; - bfs::path g_user_cache_path; - bfs::path g_user_config_path; - bfs::path g_user_save_path; - - bfs::path g_library_path; - bfs::path g_client_path; - bfs::path g_server_path; - - std::vector g_data_paths; - - std::string g_help_string; - - extern bfs::path GetDataPath(); - extern bfs::path GetCachePath(); - extern bfs::path GetConfigPath(); - extern bfs::path GetUserSavePath(); - - extern bfs::path GetLibraryPath(); - extern bfs::path GetClientPath(); - extern bfs::path GetServerPath(); - extern std::vector GetDataPaths(); - - extern std::string GetHelpString(); + static VCMIDirs_win32 singleton; + return &singleton; } - - void InitAllPathes(void) +} + +bfs::path VCMIDirs_win32::userDataPath() const +{ + const char* profile_dir_a; + wchar_t profile_dir_w[MAX_PATH]; + + // The user's profile folder. A typical path is C:\Users\username. + // FIXME: Applications should not create files or folders at this level; + // they should put their data under the locations referred to by CSIDL_APPDATA or CSIDL_LOCAL_APPDATA. + if (SHGetSpecialFolderPathW(nullptr, profile_dir_w, CSIDL_PROFILE, FALSE) == FALSE) // WinAPI way failed { - detail::g_user_data_path = detail::GetDataPath(); - detail::g_user_cache_path = detail::GetCachePath(); - detail::g_user_config_path = detail::GetConfigPath(); - detail::g_user_save_path = detail::GetUserSavePath(); - - detail::g_library_path = detail::GetLibraryPath(); - detail::g_client_path = detail::GetClientPath(); - detail::g_server_path = detail::GetServerPath(); - - detail::g_data_paths = detail::GetDataPaths(); - - detail::g_help_string = detail::GetHelpString(); - - // initialize local directory and create folders to which VCMI needs write access - bfs::create_directory(detail::g_user_data_path); - bfs::create_directory(detail::g_user_cache_path); - bfs::create_directory(detail::g_user_config_path); - bfs::create_directory(detail::g_user_save_path); + // FIXME: Create macro for MS Visual Studio. + if (profile_dir_a = std::getenv("userprofile")) // STL way succeed + return bfs::path(profile_dir_a) / "vcmi"; + else + return "."; // Every thing failed, return current directory. } + else + return bfs::path(profile_dir_w) / "vcmi"; - namespace detail + //return dataPaths()[0] ???; +} +bfs::path VCMIDirs_win32::userCachePath() const { return userDataPath(); } +bfs::path VCMIDirs_win32::userConfigPath() const { return userDataPath() / "config"; } +bfs::path VCMIDirs_win32::userSavePath() const { return userDataPath() / "Games"; } + +std::vector VCMIDirs_win32::dataPaths() const +{ + return std::vector(1, bfs::path(".")); +} + +bfs::path VCMIDirs_win32::clientPath() const { return binaryPath() / "VCMI_client.exe"; } +bfs::path VCMIDirs_win32::serverPath() const { return binaryPath() / "VCMI_server.exe"; } + +bfs::path VCMIDirs_win32::libraryPath() const { return "."; } +bfs::path VCMIDirs_win32::binaryPath() const { return "."; } + +std::string VCMIDirs_win32::genHelpString() const +{ + // I think this function should have multiple versions + // 1. For various arguments + // 2. Inverse functions + // and should be moved to vstd + // or use http://utfcpp.sourceforge.net/ + auto utf8_convert = [](const bfs::path& path) -> std::string { - struct InitAllPathes_ctor + const auto& path_string = path.native(); + auto perform_convert = [&path_string](LPSTR output, int output_size) { - InitAllPathes_ctor() { InitAllPathes(); } - } InitAllPathes_ctor_global_obj; + return WideCharToMultiByte( + CP_UTF8, // Use wchar_t -> utf8 char_t + WC_ERR_INVALID_CHARS, // Fails when invalid char occur + path_string.c_str(), // String to convert + path_string.size(), // String to convert size + output, // Result + output_size, // Result size + nullptr, nullptr); // For the ... CP_UTF8 settings for CodePage, this parameter must be set to NULL + }; + + int char_count = perform_convert(nullptr, 0); // Result size (0 - obtain size) + if (char_count > 0) + { + std::unique_ptr buffer(new char[char_count]); + if ((char_count = perform_convert(buffer.get(), char_count)) > 0) + return std::string(buffer.get(), char_count); + } + + // Conversion failed :C + return path.string(); }; - // TODO: Remove _VCMIDirs - static _VCMIDirs _VCMIDirsGlobal; - _VCMIDirs & get() - { - puts("VCMIDirs::get() - used of deprecated function :#"); - return _VCMIDirsGlobal; - } + std::vector temp_vec; + for (const bfs::path& path : dataPaths()) + temp_vec.push_back(utf8_convert(path)); + std::string gd_string_a = boost::algorithm::join(temp_vec, L";"); + + + return + " game data: " + gd_string_a + "\n" + + " libraries: " + utf8_convert(libraryPath()) + "\n" + + " server: " + utf8_convert(serverPath()) + "\n" + + "\n" + + " user data: " + utf8_convert(userDataPath()) + "\n" + + " user cache: " + utf8_convert(userCachePath()) + "\n" + + " user config: " + utf8_convert(userConfigPath()) + "\n" + + " user saves: " + utf8_convert(userSavePath()) + "\n"; // Should end without new-line? } -// FIXME: find way to at least decrease size of this ifdef (along with cleanup in CMake) -#ifdef _WIN32 -// This part should be moved into separate file (for example: VCMIDirs_win32.cpp) -// WinAPI -#include -#include +std::string libraryName(const std::string& basename) { return basename + ".dll"; } +// End of file: VCMIDirs_win32.cpp +#else // UNIX +// File: IVCMIDirs_unix.h +//#include "IVCMIDirs.h" + +class IVCMIDirs_unix : public IVCMIDirs +{ + public: + boost::filesystem::path clientPath() const override; + boost::filesystem::path serverPath() const override; + + std::string genHelpString() const override; +}; +// End of file: IVCMIDirs_unix.h + +// File: IVCMIDirs_unix.cpp +//#include "StdInc.h" +//#include "IVCMIDirs_unix.h" + +bfs::path IVCMIDirs_unix::clientPath() const { return binaryPath() / "vcmiclient"; } +bfs::path IVCMIDirs_unix::clientPath() const { return binaryPath() / "vcmiserver"; } + +std::string IVCMIDirs_unix::genHelpString() const +{ + std::vector temp_vec; + for (const bfs::path& path : dataPaths()) + temp_vec.push_back(path.string()); + std::string gd_string_a = boost::algorithm::join(temp_vec, L";"); + + + return + " game data: " + gd_string_a + "\n" + + " libraries: " + libraryPath().string() + "\n" + + " server: " + serverPath().string() + "\n" + + "\n" + + " user data: " + userDataPath().string() + "\n" + + " user cache: " + userCachePath().string() + "\n" + + " user config: " + userConfigPath().string() + "\n" + + " user saves: " + userSavePath().string() + "\n"; // Should end without new-line? +} +// End of file: IVCMIDirs_unix.cpp + +#ifdef __APPLE__ +// File: VCMIDirs_OSX.h +//#include "IVCMIDirs_unix.h" + +class VCMIDirs_OSX : public IVCMIDirs_unix +{ + public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + boost::filesystem::path userSavePath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; +}; +// End of file: VCMIDirs_OSX.h + +// File: VCMIDirs_OSX.cpp +//#include "StdInc.h" +//#include "VCMIDirs_OSX.h" namespace VCMIDirs { - namespace detail + const IVCMIDirs* get() { - bfs::path GetDataPath() - { - const char* profile_dir_a; - wchar_t profile_dir_w[MAX_PATH]; - - // The user's profile folder. A typical path is C:\Users\username. - // FIXME: Applications should not create files or folders at this level; - // they should put their data under the locations referred to by CSIDL_APPDATA or CSIDL_LOCAL_APPDATA. - if (SHGetSpecialFolderPathW(nullptr, profile_dir_w, CSIDL_PROFILE, FALSE) == FALSE) // WinAPI way failed - { - if (profile_dir_a = std::getenv("userprofile")) // STL way succeed - return bfs::path(profile_dir_a) / "vcmi"; - else - return "."; // Every thing failed, return current directory. - } - else - return bfs::path(profile_dir_w) / "vcmi"; - - //return dataPaths()[0] ???; - } - - bfs::path GetCachePath() - { - return GetDataPath(); - } - - bfs::path GetConfigPath() - { - return GetDataPath() / "config"; - } - - bfs::path GetUserSavePath() - { - return GetDataPath() / "Games"; - } - - bfs::path GetLibraryPath() - { - return "."; - } - - bfs::path GetClientPath() - { - return GetLibraryPath() / "VCMI_client.exe"; - } - - bfs::path GetServerPath() - { - return GetLibraryPath() / "VCMI_server.exe"; - } - - std::vector GetDataPaths() - { - return std::vector(1, bfs::path(".")); - } - - std::string GetHelpString() - { - // I think this function should have multiple versions - // 1. For various arguments - // 2. Inverse functions - // and should be moved to vstd - // or use http://utfcpp.sourceforge.net/ - auto utf8_convert = [](const bfs::path& path) -> std::string - { - const auto& path_string = path.native(); - auto perform_convert = [&path_string](LPSTR output, int output_size) - { - return WideCharToMultiByte( - CP_UTF8, // Use wchar_t -> utf8 char_t - WC_ERR_INVALID_CHARS, // Fails when invalid char occur - path_string.c_str(), // String to convert - path_string.size(), // String to convert size - output, // Result - output_size, // Result size - nullptr, nullptr); // For the ... CP_UTF8 settings for CodePage, this parameter must be set to NULL - }; - - int char_count = perform_convert(nullptr, 0); // Result size (0 - obtain size) - if (char_count > 0) - { - std::unique_ptr buffer(new char[char_count]); - if ((char_count = perform_convert(buffer.get(), char_count)) > 0) - return std::string(buffer.get(), char_count); - } - - // Conversion failed :C - return path.string(); - }; - - std::vector temp_vec; - for (const bfs::path& path : GetDataPaths()) - temp_vec.push_back(utf8_convert(path)); - std::string gd_string_a = boost::algorithm::join(temp_vec, L";"); - - - return - " game data: " + gd_string_a + "\n" + - " libraries: " + utf8_convert(GetLibraryPath()) + "\n" + - " server: " + utf8_convert(GetServerPath()) + "\n" + - "\n" + - " user data: " + utf8_convert(GetDataPath()) + "\n" + - " user cache: " + utf8_convert(GetCachePath()) + "\n" + - " user config: " + utf8_convert(GetConfigPath()) + "\n" + - " user saves: " + utf8_convert(GetUserSavePath()) + "\n"; // Should end without new-line? - } - } - - std::string libraryName(const std::string& basename) - { - return basename + ".dll"; + static VCMIDirs_OSX singleton; + return &singleton; } } -#elif defined (__APPLE__) -// This part should be moved to separate file (for example: VCMIDirs_apple.cpp) - -namespace VCMIDirs +bfs::path VCMIDirs_OSX::userDataPath() const { - namespace detail - { - bfs::path GetDataPath() - { - // This is Cocoa code that should be normally used to get path to Application Support folder but can't use it here for now... - // NSArray* urls = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask]; - // UserPath = path([urls[0] path] + "/vcmi").string(); + // This is Cocoa code that should be normally used to get path to Application Support folder but can't use it here for now... + // NSArray* urls = [[NSFileManager defaultManager] URLsForDirectory:NSApplicationSupportDirectory inDomains:NSUserDomainMask]; + // UserPath = path([urls[0] path] + "/vcmi").string(); - // ...so here goes a bit of hardcode instead + // ...so here goes a bit of hardcode instead - const char* home_dir = getenv("HOME"); // Should be std::getenv? - if (home_dir == nullptr) - home_dir = "."; - return bfs::path(home_dir) / "Library" / "Application Support" / "vcmi"; - } - - bfs::path GetCachePath() - { - return GetDataPath(); - } - - bfs::path GetConfigPath() - { - return GetDataPath() / "config"; - } - - bfs::path GetUserSavePath() - { - return GetDataPath() / "Games"; - } - - bfs::path GetLibraryPath() - { - return "."; - } - - bfs::path GetClientPath() - { - return "./vcmiclient"; - } - - bfs::path GetServerPath() - { - return "./vcmiserver"; - } - - std::vector GetDataPaths() - { - return std::vector(1, "../Data"); - } - - std::string GetHelpString() - { - std::vector temp_vec; - for (const bfs::path& path : GetDataPaths()) - temp_vec.push_back(path.string()); - - return - " game data: " + boost::algorithm::join(temp_vec, ":") + "\n" + - " libraries: " + GetLibraryPath().string() + "\n" + - " server: " + GetServerPath().string() + "\n" + - "\n" + - " user data: " + GetDataPath().string() + "\n" + - " user cache: " + GetCachePath().string() + "\n" + - " user config: " + GetConfigPath().string() + "\n" + - " user saves: " + GetUserSavePath().string() + "\n"; // Should end without new-line? - } - } - - std::string libraryName(const std::string& basename) - { - return "lib" + basename + ".dylib"; - } + const char* home_dir = getenv("HOME"); // Should be std::getenv? + if (home_dir == nullptr) + home_dir = "."; + return bfs::path(home_dir) / "Library" / "Application Support" / "vcmi"; } -#elif defined __ANDROID__ -// This part should be moved to separate file (for example: VCMIDirs_android.cpp) +bfs::path VCMIDirs_OSX::userCachePath() const { return userDataPath(); } +bfs::path VCMIDirs_OSX::userConfigPath() const { return userDataPath() / "config"; } +bfs::path VCMIDirs_OSX::userSavePath() const { return userDataPath() / "Games"; } -namespace VCMIDirs +std::vector VCMIDirs_OSX::dataPaths() const { - namespace detail - { - bfs::path GetDataPath() - { - // on Android HOME will be set to something like /sdcard/data/Android/is.xyz.vcmi/files/ - return getenv("HOME"); - } - - bfs::path GetCachePath() - { - return GetDataPath() / "cache"; - } - - bfs::path GetConfigPath() - { - return GetDataPath() / "config"; - } - - bfs::path GetUserSavePath() - { - return GetDataPath() / "Saves"; // Why different than other platforms??? - } - - bfs::path GetLibraryPath() - { - return M_LIB_DIR; - } - - bfs::path GetClientPath() - { - return bfs::path(M_BIN_DIR) / "vcmiclient"; - } - - bfs::path GetServerPath() - { - return bfs::path(M_BIN_DIR) / "vcmiserver"; - } - - std::vector GetDataPaths() - { - return std::vector(1, GetDataPath()); - } - - std::string GetHelpString() - { - std::vector temp_vec; - for (const bfs::path& path : GetDataPaths()) - temp_vec.push_back(path.string()); - - return - " game data: " + boost::algorithm::join(temp_vec, ":") + "\n" + - " libraries: " + GetLibraryPath().string() + "\n" + - " server: " + GetServerPath().string() + "\n" + - "\n" + - " user data: " + GetDataPath().string() + "\n" + - " user cache: " + GetCachePath().string() + "\n" + - " user config: " + GetConfigPath().string() + "\n" + - " user saves: " + GetUserSavePath().string() + "\n"; // Should end without new-line? - } - } - - std::string libraryName(const std::string& basename) - { - return "lib" + basename + ".so"; - } + return std::vector(1, "../Data"); } + +bfs::path VCMIDirs_OSX::libraryPath() const { return "."; } +bfs::path VCMIDirs_OSX::binaryPath() const { return "."; } + +std::string libraryName(const std::string& basename) { return "lib" + basename + ".dylib"; } +// End of file: VCMIDirs_OSX.cpp #else -// This part should be moved to separate file (for example: VCMIDirs_default.cpp) +// File: VCMIDirs_Linux.h +//#include "IVCMIDirs_unix.h" + +class VCMIDirs_Linux : public IVCMIDirs_unix +{ +public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + boost::filesystem::path userSavePath() const override; + + std::vector dataPaths() const override; + + boost::filesystem::path libraryPath() const override; + boost::filesystem::path binaryPath() const override; + + std::string libraryName(const std::string& basename) const override; +}; +// End of file: VCMIDirs_Linux.h + +// File: VCMIDirs_Linux.cpp +//#include "StdInc.h" +//#include "VCMIDirs_Linux.h" namespace VCMIDirs { - namespace detail + const IVCMIDirs* get() { - // $XDG_DATA_HOME, default: $HOME/.local/share - bfs::path GetDataPath() - { - const char* home_dir; - if (home_dir = getenv("XDG_DATA_HOME")) - return = home_dir; - else if (home_dir = getenv("HOME")) - return = bfs::path(home_dir) / ".local" / "share" / "vcmi"; - else - return "."; - } - - // $XDG_CACHE_HOME, default: $HOME/.cache - bfs::path GetCachePath() - { - const char* home_dir; - if (home_dir = getenv("XDG_CACHE_HOME")) - return bfs::path(home_dir) / "vcmi"; - else if (home_dir = getenv("HOME")) - return bfs::path(home_dir) / ".cache" / "vcmi"; - else - return "."; - } - - // $XDG_CONFIG_HOME, default: $HOME/.config - bfs::path GetConfigPath() - { - const char* home_dir; - if (home_dir = getenv("XDG_CONFIG_HOME")) - return bfs:path(home_dir) / "vcmi"; - else if (home_dir = getenv("HOME")) - return bfs::path(home_dir) / ".config" / "vcmi"; - else - return "."; - } - - bfs::path GetUserSavePath() - { - return GetDataPath() / "Saves"; // Why different than other platforms??? - } - - bfs::path GetLibraryPath() - { - return M_LIB_DIR; - } - - bfs::path GetClientPath() - { - return bfs::path(M_BIN_DIR) / "vcmiclient"; - } - - bfs::path GetServerPath() - { - return bfs::path(M_BIN_DIR) / "vcmiserver"; - } - - std::vector GetDataPaths() - { - // $XDG_DATA_DIRS, default: /usr/local/share/:/usr/share/ - - // construct list in reverse. - // in specification first directory has highest priority - // in vcmi fs last directory has highest priority - std::vector ret; - - const char* home_dir; - if (home_dir = getenv("HOME")) // compatibility, should be removed after 0.96 - ret.push_back(bfs::path(home_dir) / ".vcmi"); - ret.push_back(M_DATA_DIR); - - if (home_dir = getenv("XDG_DATA_DIRS") != nullptr) - { - std::string dataDirsEnv = home_dir; - std::vector dataDirs; - boost::split(dataDirs, dataDirsEnv, boost::is_any_of(":")); - for (auto & entry : boost::adaptors::reverse(dataDirs)) - ret.push_back(entry + "/vcmi"); - } - else - { - ret.push_back("/usr/share/"); - ret.push_back("/usr/local/share/"); - } - - return ret; - } - - std::string GetHelpString() - { - std::vector temp_vec; - for (const bfs::path& path : GetDataPaths()) - temp_vec.push_back(path.string()); - - return - " game data: " + boost::algorithm::join(temp_vec, ":") + "\n" + - " libraries: " + GetLibraryPath().string() + "\n" + - " server: " + GetServerPath().string() + "\n" + - "\n" + - " user data: " + GetDataPath().string() + "\n" + - " user cache: " + GetCachePath().string() + "\n" + - " user config: " + GetConfigPath().string() + "\n" + - " user saves: " + GetUserSavePath().string() + "\n"; // Should end without new-line? - } - } - - std::string libraryName(const std::string& basename) - { - return "lib" + basename + ".so"; + static VCMIDirs_Linux singleton; + return &singleton; } } + +bfs::path VCMIDirs_Linux::userDataPath() const +{ + // $XDG_DATA_HOME, default: $HOME/.local/share + const char* home_dir; + if (home_dir = getenv("XDG_DATA_HOME")) + return home_dir; + else if (home_dir = getenv("HOME")) + return bfs::path(home_dir) / ".local" / "share" / "vcmi"; + else + return "."; +} +bfs::path VCMIDirs_Linux::userCachePath() const +{ + // $XDG_CACHE_HOME, default: $HOME/.cache + const char* home_dir; + if (home_dir = getenv("XDG_CACHE_HOME")) + return bfs::path(home_dir) / "vcmi"; + else if (home_dir = getenv("HOME")) + return bfs::path(home_dir) / ".cache" / "vcmi"; + else + return "."; +} +bfs::path VCMIDirs_Linux::userConfigPath() const +{ + // $XDG_CONFIG_HOME, default: $HOME/.config + const char* home_dir; + if (home_dir = getenv("XDG_CONFIG_HOME")) + return bfs::path(home_dir) / "vcmi"; + else if (home_dir = getenv("HOME")) + return bfs::path(home_dir) / ".config" / "vcmi"; + else + return "."; +} +bfs::path VCMIDirs_Linux::userSavePath() const +{ + return userDataPath() / "Saves"; +} + +std::vector VCMIDirs_Linux::dataPaths() const +{ + // $XDG_DATA_DIRS, default: /usr/local/share/:/usr/share/ + + // construct list in reverse. + // in specification first directory has highest priority + // in vcmi fs last directory has highest priority + std::vector ret; + + const char* home_dir; + if (home_dir = getenv("HOME")) // compatibility, should be removed after 0.96 + ret.push_back(bfs::path(home_dir) / ".vcmi"); + ret.push_back(M_DATA_DIR); + + if ((home_dir = getenv("XDG_DATA_DIRS")) != nullptr) + { + std::string dataDirsEnv = home_dir; + std::vector dataDirs; + boost::split(dataDirs, dataDirsEnv, boost::is_any_of(":")); + for (auto & entry : boost::adaptors::reverse(dataDirs)) + ret.push_back(entry + "/vcmi"); + } + else + { + ret.push_back("/usr/share/"); + ret.push_back("/usr/local/share/"); + } + + return ret; +} + +bfs::path VCMIDirs_Linux::libraryPath() const { return M_LIB_PATH; } +bfs::path VCMIDirs_Linux::binaryPath() const { return M_BIN_DIR; } + +std::string VCMIDirs_Linux::libraryName(const std::string& basename) const { return "lib" + basename + ".so"; } +// End of file VCMIDirs_Linux.cpp +#ifdef __ANDROID__ +// File: VCMIDirs_Android.h +//#include "VCMIDirs_Linux.h" +class VCMIDirs_Android : public VCMIDirs_Linux +{ +public: + boost::filesystem::path userDataPath() const override; + boost::filesystem::path userCachePath() const override; + boost::filesystem::path userConfigPath() const override; + boost::filesystem::path userSavePath() const override; + + std::vector dataPaths() const override; +}; +// End of file: VCMIDirs_Android.h + +// File: VCMIDirs_Android.cpp +//#include "StdInc.h" +//#include "VCMIDirs_Android.h" + +namespace VCMIDirs +{ + const IVCMIDirs* get() + { + static VCMIDirs_Android singleton; + return &singleton; + } +} + +// on Android HOME will be set to something like /sdcard/data/Android/is.xyz.vcmi/files/ +bfs::path VCMIDirs_Android::userDataPath() const { return getenv("HOME"); } +bfs::path VCMIDirs_Android::userCachePath() const { return userDataPath() / "cache"; } +bfs::path VCMIDirs_Android::userConfigPath() const { return userDataPath() / "config"; } +bfs::path VCMIDirs_Android::userSavePath() const { return userDataPath() / "Saves"; } + +std::vector VCMIDirs_Android::dataPaths() const +{ + return std::vector(1, userDataPath()); +} +// End of file: VCMIDirs_Android.cpp +#endif +#endif #endif \ No newline at end of file diff --git a/lib/VCMIDirs.h b/lib/VCMIDirs.h index 28b5f72c1..3a563beae 100644 --- a/lib/VCMIDirs.h +++ b/lib/VCMIDirs.h @@ -7,112 +7,56 @@ * Full text of license available in license.txt file, in main folder * */ - #pragma once -// Boost -#include - // STL C++ #include #include -// TODO: Remove _VCMIDirs -class _VCMIDirs; +// Boost +#include + +// TODO: File should be rename to IVCMIDirs.h + +class IVCMIDirs +{ + public: + // Path to user-specific data directory + virtual boost::filesystem::path userDataPath() const = 0; + + // Path to "cache" directory, can be used for any non-essential files + virtual boost::filesystem::path userCachePath() const = 0; + + // Path to writeable directory with user configs + virtual boost::filesystem::path userConfigPath() const = 0; + + // Path to saved games + virtual boost::filesystem::path userSavePath() const = 0; + + // Paths to global system-wide data directories. First items have higher priority + virtual std::vector dataPaths() const = 0; + + // Full path to client executable, including server name (e.g. /usr/bin/vcmiclient) + virtual boost::filesystem::path clientPath() const = 0; + + // Full path to server executable, including server name (e.g. /usr/bin/vcmiserver) + virtual boost::filesystem::path serverPath() const = 0; + + // Path where vcmi libraries can be found (in AI and Scripting subdirectories) + virtual boost::filesystem::path libraryPath() const = 0; + + // Path where vcmi binaries can be found + virtual boost::filesystem::path binaryPath() const = 0; + + // Returns system-specific name for dynamic libraries ( StupidAI => "libStupidAI.so" or "StupidAI.dll") + virtual std::string libraryName(const std::string& basename) const = 0; + // virtual std::string libraryName(const char* basename) const = 0; ? + // virtual std::string libraryName(std::string&& basename) const = 0;? + + virtual std::string genHelpString() const = 0; +}; -// Where to find the various VCMI files. This is mostly useful for linux. namespace VCMIDirs { - namespace detail - { - extern DLL_LINKAGE boost::filesystem::path g_user_data_path; - extern DLL_LINKAGE boost::filesystem::path g_user_cache_path; - extern DLL_LINKAGE boost::filesystem::path g_user_config_path; - extern DLL_LINKAGE boost::filesystem::path g_user_save_path; - - extern DLL_LINKAGE boost::filesystem::path g_library_path; - extern DLL_LINKAGE boost::filesystem::path g_client_path; - extern DLL_LINKAGE boost::filesystem::path g_server_path; - - extern DLL_LINKAGE std::vector g_data_paths; - - extern DLL_LINKAGE std::string g_help_string; - } - - /// deprecated: get singleton instance - extern DLL_LINKAGE _VCMIDirs & get(); - - // Path to user-specific data directory - inline const boost::filesystem::path& userDataPath() { return detail::g_user_data_path; } - - // Path to "cache" directory, can be used for any non-essential files - inline const boost::filesystem::path& userCachePath() { return detail::g_user_cache_path; } - - // Path to writeable directory with user configs - inline const boost::filesystem::path& userConfigPath() { return detail::g_user_config_path; } - - // Path to saved games - inline const boost::filesystem::path& userSavePath() { return detail::g_user_save_path; } - - // Paths to global system-wide data directories. First items have higher priority - inline const std::vector& dataPaths() { return detail::g_data_paths; } - - // Full path to client executable, including server name (e.g. /usr/bin/vcmiclient) - inline const boost::filesystem::path& clientPath() { return detail::g_client_path; } - - // Full path to server executable, including server name (e.g. /usr/bin/vcmiserver) - inline const boost::filesystem::path& serverPath() { return detail::g_server_path; } - - // Path where vcmi libraries can be found (in AI and Scripting subdirectories) - inline const boost::filesystem::path& libraryPath() { return detail::g_library_path; } - - // Returns system-specific name for dynamic libraries ( StupidAI => "libStupidAI.so" or "StupidAI.dll") - extern DLL_LINKAGE std::string libraryName(const std::string& basename); - //extern DLL_LINKAGE std::string libraryName(const char* basename); - //extern DLL_LINKAGE std::string libraryName(std::string&& basename); - - - inline const std::string& genHelpString() { return detail::g_help_string; } -} - -// TODO: Remove _VCMIDirs -// This class is deprecated -class DLL_LINKAGE _VCMIDirs -{ -public: - /// deprecated: Path to user-specific data directory - std::string userDataPath() const { return VCMIDirs::userDataPath().string(); } - - /// deprecated: Path to "cache" directory, can be used for any non-essential files - std::string userCachePath() const { return VCMIDirs::userCachePath().string(); } - - /// deprecated: Path to writeable directory with user configs - std::string userConfigPath() const { return VCMIDirs::userConfigPath().string(); } - - /// deprecated: Path to saved games - std::string userSavePath() const { return VCMIDirs::userSavePath().string(); } - - /// deprecated: Paths to global system-wide data directories. First items have higher priority - std::vector dataPaths() const - { - std::vector result; - for (const auto& path : VCMIDirs::dataPaths()) - result.push_back(path.string()); - return result; - } - - /// deprecated: Full path to client executable, including server name (e.g. /usr/bin/vcmiclient) - std::string clientPath() const { return VCMIDirs::clientPath().string(); } - - /// deprecated: Full path to server executable, including server name (e.g. /usr/bin/vcmiserver) - std::string serverPath() const { return VCMIDirs::serverPath().string(); } - - /// deprecated: Path where vcmi libraries can be found (in AI and Scripting subdirectories) - std::string libraryPath() const { return VCMIDirs::libraryPath().string(); } - - /// deprecated: Returns system-specific name for dynamic libraries ( StupidAI => "libStupidAI.so" or "StupidAI.dll") - std::string libraryName(std::string basename) const { return VCMIDirs::libraryName(basename); } - - /// deprecated: - std::string genHelpString() const { return VCMIDirs::genHelpString(); } -}; \ No newline at end of file + extern DLL_LINKAGE const IVCMIDirs* get(); +} \ No newline at end of file