#pragma region CPL License /* Nuclex Native Framework Copyright (C) 2002-2021 Nuclex Development Labs This library is free software; you can redistribute it and/or modify it under the terms of the IBM Common Public License as published by the IBM Corporation; either version 1.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the IBM Common Public License for more details. You should have received a copy of the IBM Common Public License along with this library */ #pragma endregion // CPL License #ifndef NUCLEX_PLATFORM_LOCATIONS_XDGDIRECTORYRESOLVER_H #define NUCLEX_PLATFORM_LOCATIONS_XDGDIRECTORYRESOLVER_H #include "Nuclex/Platform/Config.h" #if defined(NUCLEX_PLATFORM_LINUX) #include // for std::string namespace Nuclex { namespace Platform { namespace Locations { // ------------------------------------------------------------------------------------------- // /// Resolves standard paths for a user according to the xdg specification /// /// /// The xdg specification defines a set of directories and the data they should be /// used for as well as a mechanism (a configuration file) for users to customize /// these directories. It has been adopted by all Linux distributions I'm aware of. /// /// /// If you're a Windows developer, this is similar to Microsoft's "known folders" /// and even defines several directories with identical purposes. /// /// /// See https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html /// /// class XdgDirectoryResolver { /// Signature of a method that reads an environment variable /// Name of the environment variable that will be read /// The value of the specified environment variable or an empty string public: typedef bool GetEnvironmentVariableMethod( const std::string &name, std::string &value ); /// /// Signature of a method that reads the entire ~/.config/user-dirs.dirs file /// /// The full contents of the users-dirs.dirs file as a string /// /// True if the file was found and successfully read, false if anything went wrong /// public: typedef bool ReadEntireXdgUserDirsFileMethod(std::string &contents); /// Initializes a new directory resolver /// /// Method to use for reading environment variables, leave empty for default. /// Mainly provided to isolate the class with mocks for unit testing. /// /// /// Method to use for reading the whole contents of the user-dirs.dirs file, /// leave empty for default. Intended to aid in mocking for unit tests. /// public: XdgDirectoryResolver( GetEnvironmentVariableMethod *getEnvironmentVariable = nullptr, ReadEntireXdgUserDirsFileMethod *readEntireXdgUserDirsFile = nullptr ); /// Looks up the user's home directory /// The home directory of the user running the application /// /// No data should be stored directory under the user's home directory, /// but this is a good starting point for accessing user-specific configuration files. /// public: static std::string GetHomeDirectory(); /// Looks up the directory for user-specific configuration files /// The directory to use for user-specific configuration files /// /// This usually points to $HOME/.config/ and has been widely adopted. Any user-specific /// configuration data is stored inside this folder. The established convention is to /// create one subdirectory for each application (i.e. $HOME/.config/awesome-game/). /// public: std::string GetConfigHomeDirectory(); /// Looks up the directory for user-specific data /// The directory to use for user-specific data /// /// /// This usually points to $HOME/.local/share/ and should be used to store /// user-specific data (anything that's not pure configuration - screenshots, /// user-created maps, etc.). The established convention is to create one /// subdirectory for each application (i.e. $HOME/.local/share/awesome-game/). /// /// /// If a user moved to a different system (or had a Windows-style roaming profile /// downloaded upon login from a server), this would be a directory that would be /// moved to the new system (whereas its sibling, the 'state' directory, woudln't). /// /// public: std::string GetDataHomeDirectory(); /// Looks up the directory for persistent application states /// The directory to use for application state data /// /// /// This usually points to $HOME/.local/state/ and should be used to store data /// by which an application remembers its state - a list of recently used files, /// view layout, undo history or such. The established convention is to create /// one subdirectory for each application (i.e. $HOME/.local/share/awesome-game/). /// /// /// As per the XDG Base Directory Specification, this should be used for state /// data that is just for convenience or data that is non-portable. Compare this /// with the method where information that /// is considered permanent and portable. /// /// public: std::string GetStateHomeDirectory(); /// Looks up the directory for cached, non-essential files /// The directory to use for cached, non-essential files /// /// This usually points to $HOME/.cache/. It can be used to store intermediate /// (and recreatable) files that should - maybe - stay around across multiple /// starts of your appliation (think compiled shaders or indexes that the game /// can recreate when needed) /// public: std::string GetCacheHomeDirectory(); /// /// Looks up a user-specific directory using the behavior described in /// the xdg specification /// /// Name of the user-specific directory /// String that will receive the looked-up path /// /// True if the path was successfully looked up, false if the path was not /// defined for the user and the parameter is unchanged /// /// /// Name should be the full variable name, i.e. 'XDG_CUSTOM_DIR', not just 'CUSTOM'. /// The resulting string can contain '$HOME' to reference to the home directory. /// This is the only substitution supported by xdg. /// public: bool GetUserDirectory(const std::string &name, std::string &path); /// Reads a path assignment from the 'user-dirs.dirs' file /// Name of the path assignment that will be read /// Receives the path if an assignment could be found /// /// True if the path was successfully looked up, false if the path had no /// assignment and the parameter is unchanged /// private: bool readUserDirectoryAssignment(const std::string &name, std::string &path); /// Method used to read environment variables private: GetEnvironmentVariableMethod *getEnvironmentVariable; /// Method used to read the entire user-dirs.dirs file private: ReadEntireXdgUserDirsFileMethod *readEntireXdgUserDirsFile; }; // ------------------------------------------------------------------------------------------- // }}} // namespace Nuclex::Platform::Locations #endif // defined(NUCLEX_PLATFORM_LINUX) #endif // NUCLEX_PLATFORM_LOCATIONS_XDGDIRECTORYRESOLVER_H