diff --git a/source/code/sago/platform_folders.cpp b/source/code/sago/platform_folders.cpp index 004ceac..34e6bae 100644 --- a/source/code/sago/platform_folders.cpp +++ b/source/code/sago/platform_folders.cpp @@ -30,17 +30,14 @@ SOFTWARE. #include #include #include -#include +#include #include #if defined(_WIN32) #include #include -#define strtok_r strtok_s - -static std::string win32_utf16_to_utf8(const wchar_t* wstr) -{ +static std::string win32_utf16_to_utf8(const wchar_t* wstr) { std::string res; // If the 6th parameter is 0 then WideCharToMultiByte returns the number of bytes needed to store the result. int actualSize = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL); @@ -52,7 +49,7 @@ static std::string win32_utf16_to_utf8(const wchar_t* wstr) } if (actualSize == 0) { // WideCharToMultiByte return 0 for errors. - std::string errorMsg = "UTF16 to UTF8 failed with error code: " + GetLastError(); + const std::string errorMsg = "UTF16 to UTF8 failed with error code: " + GetLastError(); throw std::runtime_error(errorMsg.c_str()); } return res; @@ -61,8 +58,7 @@ static std::string win32_utf16_to_utf8(const wchar_t* wstr) static std::string GetWindowsFolder(int folderId, const char* errorMsg) { wchar_t szPath[MAX_PATH]; szPath[0] = 0; - if ( !SUCCEEDED( SHGetFolderPathW( NULL, folderId, NULL, 0, szPath ) ) ) - { + if ( !SUCCEEDED( SHGetFolderPathW( NULL, folderId, NULL, 0, szPath ) ) ) { throw std::runtime_error(errorMsg); } return win32_utf16_to_utf8(szPath); @@ -101,12 +97,14 @@ static std::string GetMacFolder(OSType folderType, const char* errorMsg) { #include #include #include +// For strlen and strtok +#include //Typically Linux. For easy reading the comments will just say Linux but should work with most *nixes static void throwOnRelative(const char* envName, const char* envValue) { if (envValue[0] != '/') { char buffer[200]; - snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue); + std::snprintf(buffer, sizeof(buffer), "Environment \"%s\" does not start with an '/'. XDG specifies that the value must be absolute. The current value is: \"%s\"", envName, envValue); throw std::runtime_error(buffer); } } @@ -120,13 +118,13 @@ static void throwOnRelative(const char* envName, const char* envValue) { static std::string getHome() { std::string res; int uid = getuid(); - const char* homeEnv = getenv("HOME"); + const char* homeEnv = std::getenv("HOME"); if ( uid != 0 && homeEnv) { //We only acknowlegde HOME if not root. res = homeEnv; return res; } - struct passwd *pw = getpwuid(uid); + struct passwd* pw = getpwuid(uid); if (!pw) { throw std::runtime_error("Unable to get passwd struct."); } @@ -140,7 +138,7 @@ static std::string getHome() { static std::string getLinuxFolderDefault(const char* envName, const char* defaultRelativePath) { std::string res; - const char* tempRes = getenv(envName); + const char* tempRes = std::getenv(envName); if (tempRes) { throwOnRelative(envName, tempRes); res = tempRes; @@ -151,9 +149,8 @@ static std::string getLinuxFolderDefault(const char* envName, const char* defaul } static void appendExtraFoldersTokenizer(const char* envName, const char* envValue, std::vector& folders) { - std::vector buffer(envValue, envValue + strlen(envValue) + 1); - char *saveptr; - const char* p = strtok_r ( &buffer[0], ":", &saveptr); + std::vector buffer(envValue, envValue + std::strlen(envValue) + 1); + char* p = std::strtok ( &buffer[0], ":"); while (p != NULL) { if (p[0] == '/') { folders.push_back(p); @@ -163,12 +160,12 @@ static void appendExtraFoldersTokenizer(const char* envName, const char* envValu //The XDG documentation indicates that the folder should be ignored but that the program should continue. std::cerr << "Skipping path \"" << p << "\" in \"" << envName << "\" because it does not start with a \"/\"\n"; } - p = strtok_r (NULL, ":", &saveptr); + p = std::strtok (NULL, ":"); } } static void appendExtraFolders(const char* envName, const char* defaultValue, std::vector& folders) { - const char* envValue = getenv(envName); + const char* envValue = std::getenv(envName); if (!envValue) { envValue = defaultValue; } @@ -206,7 +203,7 @@ std::string getCacheDir() { #elif defined(__APPLE__) return GetMacFolder(kCachedDataFolderType, "Failed to find the Application Support Folder"); #else - return getLinuxFolderDefault("XDG_CONFIG_HOME", ".cache"); + return getLinuxFolderDefault("XDG_CACHE_HOME", ".cache"); #endif } @@ -276,7 +273,8 @@ PlatformFolders::PlatformFolders() { this->data = new PlatformFolders::PlatformFoldersData(); try { PlatformFoldersFillData(data->folders); - } catch (...) { + } + catch (...) { delete this->data; throw; } @@ -364,6 +362,33 @@ std::string PlatformFolders::getSaveGamesFolder1() const { #endif } +std::string getDesktopFolder() { + return PlatformFolders().getDesktopFolder(); +} + +std::string getDocumentsFolder() { + return PlatformFolders().getDocumentsFolder(); +} + +std::string getDownloadFolder1() { + return PlatformFolders().getDownloadFolder1(); +} + +std::string getPicturesFolder() { + return PlatformFolders().getPicturesFolder(); +} + +std::string getMusicFolder() { + return PlatformFolders().getMusicFolder(); +} + +std::string getVideoFolder() { + return PlatformFolders().getVideoFolder(); +} + +std::string getSaveGamesFolder1() { + return PlatformFolders().getSaveGamesFolder1(); +} } //namespace sago diff --git a/source/code/sago/platform_folders.h b/source/code/sago/platform_folders.h index 73fba85..bd6c0d5 100644 --- a/source/code/sago/platform_folders.h +++ b/source/code/sago/platform_folders.h @@ -48,6 +48,7 @@ namespace sago { * @return The base folder for storring program data. */ std::string getDataHome(); + /** * Retrives the base folder for storring config files. * You must add the program name yourself like this: @@ -59,6 +60,7 @@ std::string getDataHome(); * @return The base folder for storring config data. */ std::string getConfigHome(); + /** * Retrives the base folder for storring cache files. * You must add the program name yourself like this: @@ -70,6 +72,7 @@ std::string getConfigHome(); * @return The base folder for storring data that do not need to be backed up. */ std::string getCacheDir(); + /** * This will append extra folders that your program should be looking for data files in. * This does not normally include the path returned by GetDataHome(). @@ -87,6 +90,7 @@ std::string getCacheDir(); * @param homes A vector that extra folders will be appended to. */ void appendAdditionalDataDirectories(std::vector& homes); + /** * This will append extra folders that your program should be looking for config files in. * This does not normally include the path returned by GetConfigHome(). @@ -106,6 +110,58 @@ void appendAdditionalDataDirectories(std::vector& homes); void appendAdditionalConfigDirectories(std::vector& homes); /** + * The folder that represents the desktop. + * Normally you should try not to use this folder. + * @return Absolute path to the user's desktop + */ +std::string getDesktopFolder(); + +/** + * The folder to store user documents to + * @return Absolute path to the "Documents" folder + */ +std::string getDocumentsFolder(); + +/** + * The folder where files are downloaded. + * @note Windows: This version is XP compatible and returns the Desktop. Vista and later has a dedicated folder. + * @return Absolute path to the folder where files are downloaded to. + */ +std::string getDownloadFolder1(); + +/** + * The folder for storring the user's pictures. + * @return Absolute path to the "Picture" folder + */ +std::string getPicturesFolder(); + +/** + * The folder where music is stored + * @return Absolute path to the music folder + */ +std::string getMusicFolder(); + +/** + * The folder where video is stored + * @return Absolute path to the video folder + */ +std::string getVideoFolder(); + +/** + * The base folder for storring saved games. + * You must add the program name to it like this: + * @code{.cpp} + * string saved_games_folder = sago::getSaveGamesFolder1()+"/My Program Name/"; + * @endcode + * @note Windows: This is an XP compatible version and returns the path to "My Games" in Documents. Vista and later has an official folder. + * @note Linux: XDF does not define a folder for saved games. This will just return the same as GetDataHome() + * @return The folder base folder for storring save games. + */ +std::string getSaveGamesFolder1(); + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +/** * This class contains methods for finding the system depended special folders. * For Windows these folders are either by convention or given by CSIDL. * For Linux XDG convention is used. @@ -166,10 +222,13 @@ private: #elif defined(__APPLE__) #else struct PlatformFoldersData; - PlatformFoldersData *data; + PlatformFoldersData* data; #endif }; +#endif // skip doxygen + + } //namespace sago #endif /* PLATFORM_FOLDERS_H */