mirror of
https://github.com/rwengine/openrw.git
synced 2024-09-18 16:32:32 +02:00
rwgame: allow configuration files from all places (not only config path)
- add it as an argument to the rwgame executable - update the tests
This commit is contained in:
parent
6dffed543a
commit
55dd0beea0
@ -1,4 +1,8 @@
|
|||||||
#include "GameBase.hpp"
|
#include "GameBase.hpp"
|
||||||
|
|
||||||
|
#include <rw/defines.hpp>
|
||||||
|
#include <rw/filesystem.hpp>
|
||||||
|
|
||||||
#include "GitSHA1.h"
|
#include "GitSHA1.h"
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
@ -6,21 +10,19 @@
|
|||||||
// Use first 8 chars of git hash as the build string
|
// Use first 8 chars of git hash as the build string
|
||||||
const std::string kBuildStr(kGitSHA1Hash, 8);
|
const std::string kBuildStr(kGitSHA1Hash, 8);
|
||||||
const std::string kWindowTitle = "RWGame";
|
const std::string kWindowTitle = "RWGame";
|
||||||
|
const std::string kDefaultConfigFileName = "openrw.ini";
|
||||||
constexpr int kWindowWidth = 800;
|
constexpr int kWindowWidth = 800;
|
||||||
constexpr int kWindowHeight = 600;
|
constexpr int kWindowHeight = 600;
|
||||||
|
|
||||||
GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) {
|
GameBase::GameBase(Logger &inlog, int argc, char *argv[]) :
|
||||||
|
log(inlog),
|
||||||
|
config(),
|
||||||
|
window(),
|
||||||
|
options() {
|
||||||
log.info("Game", "Build: " + kBuildStr);
|
log.info("Game", "Build: " + kBuildStr);
|
||||||
|
|
||||||
if (!config.isValid()) {
|
|
||||||
log.error("Config", "Invalid INI file at \""
|
|
||||||
+ config.getConfigFile() + "\".\n"
|
|
||||||
+ "Adapt the following default INI to your configuration.\n"
|
|
||||||
+ config.getDefaultINIString());
|
|
||||||
throw std::runtime_error(config.getParseResult().what());
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t w = kWindowWidth, h = kWindowHeight;
|
size_t w = kWindowWidth, h = kWindowHeight;
|
||||||
|
rwfs::path configPath;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
bool help = false;
|
bool help = false;
|
||||||
|
|
||||||
@ -29,6 +31,7 @@ GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) {
|
|||||||
po::options_description desc("Available options");
|
po::options_description desc("Available options");
|
||||||
desc.add_options()(
|
desc.add_options()(
|
||||||
"help", "Show this help message")(
|
"help", "Show this help message")(
|
||||||
|
"config,c", po::value<rwfs::path>(), "Path of configuration file")(
|
||||||
"width,w", po::value<size_t>(), "Game resolution width in pixel")(
|
"width,w", po::value<size_t>(), "Game resolution width in pixel")(
|
||||||
"height,h", po::value<size_t>(), "Game resolution height in pixel")(
|
"height,h", po::value<size_t>(), "Game resolution height in pixel")(
|
||||||
"fullscreen,f", "Enable fullscreen mode")(
|
"fullscreen,f", "Enable fullscreen mode")(
|
||||||
@ -59,6 +62,20 @@ GameBase::GameBase(Logger &inlog, int argc, char *argv[]) : log(inlog) {
|
|||||||
if (vm.count("fullscreen")) {
|
if (vm.count("fullscreen")) {
|
||||||
fullscreen = true;
|
fullscreen = true;
|
||||||
}
|
}
|
||||||
|
if (vm.count("config")) {
|
||||||
|
configPath = vm["config"].as<rwfs::path>();
|
||||||
|
} else {
|
||||||
|
configPath = GameConfig::getDefaultConfigPath() / kDefaultConfigFileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
config.loadFile(configPath);
|
||||||
|
if (!config.isValid()) {
|
||||||
|
log.error("Config", "Invalid INI file at \""
|
||||||
|
+ config.getConfigPath().string() + "\".\n"
|
||||||
|
+ "Adapt the following default INI to your configuration.\n"
|
||||||
|
+ config.getDefaultINIString());
|
||||||
|
throw std::runtime_error(config.getParseResult().what());
|
||||||
|
}
|
||||||
|
|
||||||
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
if (SDL_Init(SDL_INIT_VIDEO) < 0)
|
||||||
throw std::runtime_error("Failed to initialize SDL2!");
|
throw std::runtime_error("Failed to initialize SDL2!");
|
||||||
|
@ -25,7 +25,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
Logger& log;
|
Logger& log;
|
||||||
GameConfig config{"openrw.ini"};
|
GameConfig config;
|
||||||
GameWindow window;
|
GameWindow window;
|
||||||
boost::program_options::variables_map options;
|
boost::program_options::variables_map options;
|
||||||
};
|
};
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <rw/defines.hpp>
|
#include <rw/defines.hpp>
|
||||||
|
#include <rw/filesystem.hpp>
|
||||||
|
|
||||||
#include <boost/property_tree/ini_parser.hpp>
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
@ -9,26 +10,21 @@ namespace pt = boost::property_tree;
|
|||||||
|
|
||||||
const std::string kConfigDirectoryName("OpenRW");
|
const std::string kConfigDirectoryName("OpenRW");
|
||||||
|
|
||||||
GameConfig::GameConfig(const std::string &configName,
|
GameConfig::GameConfig()
|
||||||
const std::string &configPath)
|
: m_configPath()
|
||||||
: m_configName(configName)
|
|
||||||
, m_configPath(configPath)
|
|
||||||
, m_parseResult()
|
, m_parseResult()
|
||||||
, m_inputInvertY(false) {
|
, m_inputInvertY(false) {
|
||||||
if (m_configPath.empty()) {
|
|
||||||
m_configPath = getDefaultConfigPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the path to use
|
|
||||||
auto configFile = getConfigFile();
|
|
||||||
|
|
||||||
std::string dummy;
|
|
||||||
m_parseResult =
|
|
||||||
parseConfig(ParseType::FILE, configFile, ParseType::CONFIG, dummy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameConfig::getConfigFile() const {
|
void GameConfig::loadFile(const rwfs::path &path) {
|
||||||
return m_configPath + "/" + m_configName;
|
m_configPath = path;
|
||||||
|
std::string dummy;
|
||||||
|
m_parseResult =
|
||||||
|
parseConfig(ParseType::FILE, path.string(), ParseType::CONFIG, dummy);
|
||||||
|
}
|
||||||
|
|
||||||
|
rwfs::path GameConfig::getConfigPath() const {
|
||||||
|
return m_configPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GameConfig::isValid() const {
|
bool GameConfig::isValid() const {
|
||||||
@ -39,31 +35,31 @@ const GameConfig::ParseResult &GameConfig::getParseResult() const {
|
|||||||
return m_parseResult;
|
return m_parseResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameConfig::getDefaultConfigPath() {
|
rwfs::path GameConfig::getDefaultConfigPath() {
|
||||||
#if defined(RW_LINUX) || defined(RW_FREEBSD) || defined(RW_NETBSD) || \
|
#if defined(RW_LINUX) || defined(RW_FREEBSD) || defined(RW_NETBSD) || \
|
||||||
defined(RW_OPENBSD)
|
defined(RW_OPENBSD)
|
||||||
char *config_home = getenv("XDG_CONFIG_HOME");
|
char *config_home = getenv("XDG_CONFIG_HOME");
|
||||||
if (config_home != nullptr) {
|
if (config_home != nullptr) {
|
||||||
return std::string(config_home) + "/" + kConfigDirectoryName;
|
return rwfs::path(config_home) / kConfigDirectoryName;
|
||||||
}
|
}
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (home != nullptr) {
|
if (home != nullptr) {
|
||||||
return std::string(home) + "/.config/" + kConfigDirectoryName;
|
return rwfs::path(home) / ".config/" / kConfigDirectoryName;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(RW_OSX)
|
#elif defined(RW_OSX)
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
if (home)
|
if (home)
|
||||||
return std::string(home) + "/Library/Preferences/" +
|
return rwfs::path(home) / "Library/Preferences/" /
|
||||||
kConfigDirectoryName;
|
kConfigDirectoryName;
|
||||||
|
|
||||||
#else
|
#else
|
||||||
return ".";
|
return rwfs::path();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Well now we're stuck.
|
// Well now we're stuck.
|
||||||
RW_ERROR("No default config path found.");
|
RW_ERROR("No default config path found.");
|
||||||
return ".";
|
return rwfs::path();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string stripComments(const std::string &str) {
|
std::string stripComments(const std::string &str) {
|
||||||
@ -71,6 +67,17 @@ std::string stripComments(const std::string &str) {
|
|||||||
return s.erase(s.find_last_not_of(" \n\r\t") + 1);
|
return s.erase(s.find_last_not_of(" \n\r\t") + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct PathTranslator {
|
||||||
|
typedef std::string internal_type;
|
||||||
|
typedef rwfs::path external_type;
|
||||||
|
boost::optional<external_type> get_value(const internal_type &str) {
|
||||||
|
return rwfs::path(str);
|
||||||
|
}
|
||||||
|
boost::optional<internal_type> put_value(const external_type &path) {
|
||||||
|
return path.string();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
struct StringTranslator {
|
struct StringTranslator {
|
||||||
typedef std::string internal_type;
|
typedef std::string internal_type;
|
||||||
typedef std::string external_type;
|
typedef std::string external_type;
|
||||||
@ -115,8 +122,8 @@ struct IntTranslator {
|
|||||||
};
|
};
|
||||||
|
|
||||||
GameConfig::ParseResult GameConfig::saveConfig() {
|
GameConfig::ParseResult GameConfig::saveConfig() {
|
||||||
auto filename = getConfigFile();
|
auto configPath = getConfigPath().string();
|
||||||
return parseConfig(ParseType::CONFIG, "", ParseType::FILE, filename);
|
return parseConfig(ParseType::CONFIG, "", ParseType::FILE, configPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GameConfig::getDefaultINIString() {
|
std::string GameConfig::getDefaultINIString() {
|
||||||
@ -210,13 +217,14 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType,
|
|||||||
|
|
||||||
auto deft = StringTranslator();
|
auto deft = StringTranslator();
|
||||||
auto boolt = BoolTranslator();
|
auto boolt = BoolTranslator();
|
||||||
|
auto patht = PathTranslator();
|
||||||
|
|
||||||
// Add new configuration parameters here.
|
// Add new configuration parameters here.
|
||||||
// Additionally, add them to the unit test.
|
// Additionally, add them to the unit test.
|
||||||
|
|
||||||
// @todo Don't allow path separators and relative directories
|
// @todo Don't allow path separators and relative directories
|
||||||
read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3",
|
read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3",
|
||||||
deft, false);
|
patht, false);
|
||||||
read_config("game.language", this->m_gameLanguage, "american", deft);
|
read_config("game.language", this->m_gameLanguage, "american", deft);
|
||||||
|
|
||||||
read_config("input.invert_y", this->m_inputInvertY, false, boolt);
|
read_config("input.invert_y", this->m_inputInvertY, false, boolt);
|
||||||
@ -273,6 +281,10 @@ GameConfig::ParseResult GameConfig::parseConfig(GameConfig::ParseType srcType,
|
|||||||
RW_MESSAGE(e.what());
|
RW_MESSAGE(e.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parseResult.type() == ParseResult::ErrorType::UNINITIALIZED) {
|
||||||
|
parseResult.markGood();
|
||||||
|
}
|
||||||
|
|
||||||
return parseResult;
|
return parseResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +319,7 @@ GameConfig::ParseResult::ParseResult(GameConfig::ParseType srcType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameConfig::ParseResult::ParseResult()
|
GameConfig::ParseResult::ParseResult()
|
||||||
: m_result(ErrorType::GOOD)
|
: m_result(ErrorType::UNINITIALIZED)
|
||||||
, m_inputfilename()
|
, m_inputfilename()
|
||||||
, m_outputfilename()
|
, m_outputfilename()
|
||||||
, m_line(0)
|
, m_line(0)
|
||||||
@ -331,6 +343,10 @@ void GameConfig::ParseResult::failInputFile(size_t line,
|
|||||||
this->m_message = message;
|
this->m_message = message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GameConfig::ParseResult::markGood() {
|
||||||
|
this-> m_result = ParseResult::ErrorType::GOOD;
|
||||||
|
}
|
||||||
|
|
||||||
void GameConfig::ParseResult::failArgument() {
|
void GameConfig::ParseResult::failArgument() {
|
||||||
this->m_result = ParseResult::ErrorType::INVALIDARGUMENT;
|
this->m_result = ParseResult::ErrorType::INVALIDARGUMENT;
|
||||||
}
|
}
|
||||||
@ -365,6 +381,9 @@ const std::vector<std::string> &GameConfig::ParseResult::getKeysInvalidData()
|
|||||||
std::string GameConfig::ParseResult::what() const {
|
std::string GameConfig::ParseResult::what() const {
|
||||||
std::ostringstream oss;
|
std::ostringstream oss;
|
||||||
switch (this->m_result) {
|
switch (this->m_result) {
|
||||||
|
case ErrorType::UNINITIALIZED:
|
||||||
|
oss << "Parsing was skipped or did not finish.";
|
||||||
|
break;
|
||||||
case ErrorType::GOOD:
|
case ErrorType::GOOD:
|
||||||
oss << "Parsing completed without errors.";
|
oss << "Parsing completed without errors.";
|
||||||
break;
|
break;
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <rw/filesystem.hpp>
|
||||||
|
|
||||||
class GameConfig {
|
class GameConfig {
|
||||||
private:
|
private:
|
||||||
enum ParseType { DEFAULT, CONFIG, FILE, STRING };
|
enum ParseType { DEFAULT, CONFIG, FILE, STRING };
|
||||||
@ -19,6 +21,8 @@ public:
|
|||||||
class ParseResult {
|
class ParseResult {
|
||||||
public:
|
public:
|
||||||
enum ErrorType {
|
enum ErrorType {
|
||||||
|
/// UNINITIALIZED: The config was not initialized
|
||||||
|
UNINITIALIZED,
|
||||||
/// GOOD: Input file/string was good
|
/// GOOD: Input file/string was good
|
||||||
GOOD,
|
GOOD,
|
||||||
/// INVALIDINPUTFILE: There was some error while reading from a file
|
/// INVALIDINPUTFILE: There was some error while reading from a file
|
||||||
@ -69,6 +73,12 @@ public:
|
|||||||
* @return A vector with all the keys
|
* @return A vector with all the keys
|
||||||
*/
|
*/
|
||||||
const std::vector<std::string> &getKeysInvalidData() const;
|
const std::vector<std::string> &getKeysInvalidData() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Mark this result as valid
|
||||||
|
*/
|
||||||
|
void markGood();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief failInputFile Fail because the input file was invalid
|
* @brief failInputFile Fail because the input file was invalid
|
||||||
* @param line Line number where the error is located
|
* @param line Line number where the error is located
|
||||||
@ -164,17 +174,20 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief GameConfig Loads a game configuration
|
* @brief GameConfig Create a game configuration (initially invalid)
|
||||||
* @param configName The configuration filename to load
|
|
||||||
* @param configPath Where to look.
|
|
||||||
*/
|
*/
|
||||||
GameConfig(const std::string &configName,
|
GameConfig();
|
||||||
const std::string &configPath = getDefaultConfigPath());
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief getFilePath Returns the system file path for the configuration
|
* @brief Initialize this object using the config file at path
|
||||||
|
* @param path Path of the configuration file
|
||||||
*/
|
*/
|
||||||
std::string getConfigFile() const;
|
void loadFile(const rwfs::path &path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief getConfigPath Returns the path for the configuration
|
||||||
|
*/
|
||||||
|
rwfs::path getConfigPath() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief writeConfig Save the game configuration
|
* @brief writeConfig Save the game configuration
|
||||||
@ -201,7 +214,7 @@ public:
|
|||||||
std::string getDefaultINIString();
|
std::string getDefaultINIString();
|
||||||
|
|
||||||
const std::string &getGameDataPath() const {
|
const std::string &getGameDataPath() const {
|
||||||
return m_gamePath;
|
return m_gamePath.string(); //FIXME: change to path
|
||||||
}
|
}
|
||||||
const std::string &getGameLanguage() const {
|
const std::string &getGameLanguage() const {
|
||||||
return m_gameLanguage;
|
return m_gameLanguage;
|
||||||
@ -210,8 +223,8 @@ public:
|
|||||||
return m_inputInvertY;
|
return m_inputInvertY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static rwfs::path getDefaultConfigPath();
|
||||||
private:
|
private:
|
||||||
static std::string getDefaultConfigPath();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief parseConfig Load data from source and write it to destination.
|
* @brief parseConfig Load data from source and write it to destination.
|
||||||
@ -230,14 +243,13 @@ private:
|
|||||||
ParseType destType, std::string &destination);
|
ParseType destType, std::string &destination);
|
||||||
|
|
||||||
/* Config State */
|
/* Config State */
|
||||||
std::string m_configName;
|
rwfs::path m_configPath;
|
||||||
std::string m_configPath;
|
|
||||||
ParseResult m_parseResult;
|
ParseResult m_parseResult;
|
||||||
|
|
||||||
/* Actual Configuration */
|
/* Actual Configuration */
|
||||||
|
|
||||||
/// Path to the game data
|
/// Path to the game data
|
||||||
std::string m_gamePath;
|
rwfs::path m_gamePath;
|
||||||
|
|
||||||
/// Language for game
|
/// Language for game
|
||||||
std::string m_gameLanguage = "american";
|
std::string m_gameLanguage = "american";
|
||||||
|
@ -12,15 +12,14 @@
|
|||||||
#include <rw/filesystem.hpp>
|
#include <rw/filesystem.hpp>
|
||||||
|
|
||||||
namespace pt = boost::property_tree;
|
namespace pt = boost::property_tree;
|
||||||
namespace fs = rwfs;
|
|
||||||
|
|
||||||
typedef std::map<std::string, std::map<std::string, std::string>>
|
typedef std::map<std::string, std::map<std::string, std::string>>
|
||||||
simpleConfig_t;
|
simpleConfig_t;
|
||||||
|
|
||||||
simpleConfig_t readConfig(const std::string &filename) {
|
simpleConfig_t readConfig(const rwfs::path &path) {
|
||||||
simpleConfig_t cfg;
|
simpleConfig_t cfg;
|
||||||
pt::ptree tree;
|
pt::ptree tree;
|
||||||
pt::read_ini(filename, tree);
|
pt::read_ini(path.string(), tree);
|
||||||
|
|
||||||
for (const auto §ion : tree) {
|
for (const auto §ion : tree) {
|
||||||
for (const auto &subKey : section.second) {
|
for (const auto &subKey : section.second) {
|
||||||
@ -67,10 +66,10 @@ public:
|
|||||||
virtual ~Temp() {
|
virtual ~Temp() {
|
||||||
}
|
}
|
||||||
bool exists() const {
|
bool exists() const {
|
||||||
return fs::exists(this->m_path);
|
return rwfs::exists(this->m_path);
|
||||||
}
|
}
|
||||||
std::string path() const {
|
const rwfs::path &path() const {
|
||||||
return this->m_path.string();
|
return this->m_path;
|
||||||
}
|
}
|
||||||
std::string filename() const {
|
std::string filename() const {
|
||||||
return this->m_path.filename().string();
|
return this->m_path.filename().string();
|
||||||
@ -86,20 +85,17 @@ protected:
|
|||||||
Temp(const Temp &) = delete;
|
Temp(const Temp &) = delete;
|
||||||
Temp() : m_path(getRandomFilePath()) {
|
Temp() : m_path(getRandomFilePath()) {
|
||||||
}
|
}
|
||||||
Temp(const fs::path &dirname) : m_path(getRandomFilePath(dirname)) {
|
Temp(const rwfs::path &dirname) : m_path(getRandomFilePath(dirname)) {
|
||||||
}
|
|
||||||
const fs::path &get_path_internal() const {
|
|
||||||
return this->m_path;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static fs::path getRandomFilePath(const fs::path &dirname) {
|
static rwfs::path getRandomFilePath(const rwfs::path &dirname) {
|
||||||
return fs::unique_path(dirname / "openrw_test_%%%%%%%%%%%%%%%%");
|
return rwfs::unique_path(dirname / "openrw_test_%%%%%%%%%%%%%%%%");
|
||||||
}
|
}
|
||||||
static fs::path getRandomFilePath() {
|
static rwfs::path getRandomFilePath() {
|
||||||
return getRandomFilePath(fs::temp_directory_path());
|
return getRandomFilePath(rwfs::temp_directory_path());
|
||||||
}
|
}
|
||||||
fs::path m_path;
|
rwfs::path m_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TempFile;
|
class TempFile;
|
||||||
@ -108,22 +104,22 @@ class TempDir : public Temp {
|
|||||||
public:
|
public:
|
||||||
TempDir() : Temp() {
|
TempDir() : Temp() {
|
||||||
}
|
}
|
||||||
TempDir(const TempDir &dirname) : Temp(dirname.get_path_internal()) {
|
TempDir(const TempDir &dirname) : Temp(dirname.path()) {
|
||||||
}
|
}
|
||||||
virtual ~TempDir() {
|
virtual ~TempDir() {
|
||||||
this->remove();
|
this->remove();
|
||||||
}
|
}
|
||||||
virtual void change_perms_readonly() const override {
|
virtual void change_perms_readonly() const override {
|
||||||
fs::permissions(this->get_path_internal(),
|
rwfs::permissions(this->path(),
|
||||||
fs::perms::owner_read | fs::perms::owner_exe |
|
rwfs::perms::owner_read | rwfs::perms::owner_exe |
|
||||||
fs::perms::group_read | fs::perms::group_exe |
|
rwfs::perms::group_read | rwfs::perms::group_exe |
|
||||||
fs::perms::others_read | fs::perms::others_exe);
|
rwfs::perms::others_read | rwfs::perms::others_exe);
|
||||||
}
|
}
|
||||||
virtual void remove() const override {
|
virtual void remove() const override {
|
||||||
fs::remove_all(this->get_path_internal());
|
rwfs::remove_all(this->path());
|
||||||
}
|
}
|
||||||
void touch() const override {
|
void touch() const override {
|
||||||
fs::create_directories(this->get_path_internal());
|
rwfs::create_directories(this->path());
|
||||||
}
|
}
|
||||||
friend class TempFile;
|
friend class TempFile;
|
||||||
};
|
};
|
||||||
@ -132,28 +128,28 @@ class TempFile : public Temp {
|
|||||||
public:
|
public:
|
||||||
TempFile() : Temp() {
|
TempFile() : Temp() {
|
||||||
}
|
}
|
||||||
TempFile(const TempDir &dirname) : Temp(dirname.get_path_internal()) {
|
TempFile(const TempDir &dirname) : Temp(dirname.path()) {
|
||||||
}
|
}
|
||||||
virtual ~TempFile() {
|
virtual ~TempFile() {
|
||||||
this->remove();
|
this->remove();
|
||||||
}
|
}
|
||||||
virtual void change_perms_readonly() const override {
|
virtual void change_perms_readonly() const override {
|
||||||
fs::permissions(this->get_path_internal(), fs::perms::owner_read |
|
rwfs::permissions(this->path(), rwfs::perms::owner_read |
|
||||||
fs::perms::group_read |
|
rwfs::perms::group_read |
|
||||||
fs::perms::others_read);
|
rwfs::perms::others_read);
|
||||||
}
|
}
|
||||||
virtual void remove() const override {
|
virtual void remove() const override {
|
||||||
fs::remove_all(this->get_path_internal());
|
rwfs::remove_all(this->path());
|
||||||
}
|
}
|
||||||
virtual void touch() const override {
|
virtual void touch() const override {
|
||||||
std::ofstream ofs(this->path(), std::ios::out | std::ios::app);
|
std::ofstream ofs(this->path().string(), std::ios::out | std::ios::app);
|
||||||
ofs.close();
|
ofs.close();
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool append(T t) const {
|
bool append(T t) const {
|
||||||
// Append argument at the end of the file.
|
// Append argument at the end of the file.
|
||||||
// File is open/closes repeatedly. Not optimal.
|
// File is open/closes repeatedly. Not optimal.
|
||||||
std::ofstream ofs(this->path(), std::ios::out | std::ios::app);
|
std::ofstream ofs(this->path().string(), std::ios::out | std::ios::app);
|
||||||
ofs << t;
|
ofs << t;
|
||||||
ofs.close();
|
ofs.close();
|
||||||
return ofs.good();
|
return ofs.good();
|
||||||
@ -162,7 +158,7 @@ public:
|
|||||||
bool write(T t) const {
|
bool write(T t) const {
|
||||||
// Write the argument to the file, discarding all contents.
|
// Write the argument to the file, discarding all contents.
|
||||||
// File is open/closes repeatedly. Not optimal.
|
// File is open/closes repeatedly. Not optimal.
|
||||||
std::ofstream ofs(this->path(), std::ios::out | std::ios::trunc);
|
std::ofstream ofs(this->path().string(), std::ios::out | std::ios::trunc);
|
||||||
ofs << t;
|
ofs << t;
|
||||||
ofs.close();
|
ofs.close();
|
||||||
return ofs.good();
|
return ofs.good();
|
||||||
@ -188,72 +184,78 @@ BOOST_AUTO_TEST_CASE(test_stripWhitespace) {
|
|||||||
BOOST_AUTO_TEST_CASE(test_TempDir) {
|
BOOST_AUTO_TEST_CASE(test_TempDir) {
|
||||||
// Check the behavior of TempFile
|
// Check the behavior of TempFile
|
||||||
TempDir tempDir;
|
TempDir tempDir;
|
||||||
BOOST_CHECK_EQUAL(tempDir.exists(), false);
|
BOOST_CHECK(!tempDir.exists());
|
||||||
tempDir.touch();
|
tempDir.touch();
|
||||||
BOOST_CHECK_EQUAL(tempDir.exists(), true);
|
BOOST_CHECK(tempDir.exists());
|
||||||
tempDir.remove();
|
tempDir.remove();
|
||||||
BOOST_CHECK_EQUAL(tempDir.exists(), false);
|
BOOST_CHECK(!tempDir.exists());
|
||||||
|
|
||||||
tempDir.touch();
|
tempDir.touch();
|
||||||
BOOST_CHECK_EQUAL(tempDir.exists(), true);
|
BOOST_CHECK(tempDir.exists());
|
||||||
|
|
||||||
TempDir tempChildDir(tempDir);
|
TempDir tempChildDir(tempDir);
|
||||||
BOOST_CHECK_EQUAL(tempChildDir.exists(), false);
|
BOOST_CHECK(!tempChildDir.exists());
|
||||||
|
|
||||||
tempChildDir.touch();
|
tempChildDir.touch();
|
||||||
BOOST_CHECK_EQUAL(tempChildDir.exists(), true);
|
BOOST_CHECK(tempChildDir.exists());
|
||||||
|
|
||||||
tempDir.remove();
|
tempDir.remove();
|
||||||
BOOST_CHECK_EQUAL(tempChildDir.exists(), false);
|
BOOST_CHECK(!tempChildDir.exists());
|
||||||
BOOST_CHECK_EQUAL(tempDir.exists(), false);
|
BOOST_CHECK(!tempDir.exists());
|
||||||
|
|
||||||
tempChildDir.touch();
|
tempChildDir.touch();
|
||||||
BOOST_CHECK_EQUAL(tempChildDir.exists(), true);
|
BOOST_CHECK(tempChildDir.exists());
|
||||||
|
|
||||||
std::string path;
|
rwfs::path path;
|
||||||
{
|
{
|
||||||
TempDir tempLocal;
|
TempDir tempLocal;
|
||||||
tempLocal.touch();
|
tempLocal.touch();
|
||||||
BOOST_CHECK_EQUAL(tempLocal.exists(), true);
|
BOOST_CHECK(tempLocal.exists());
|
||||||
path = tempLocal.path();
|
path = tempLocal.path();
|
||||||
}
|
}
|
||||||
BOOST_CHECK_EQUAL(fs::exists(path), false);
|
BOOST_CHECK(!rwfs::exists(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_TempFile) {
|
BOOST_AUTO_TEST_CASE(test_TempFile) {
|
||||||
// Check the behavior of TempFile
|
// Check the behavior of TempFile
|
||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
BOOST_CHECK_EQUAL(tempFile.exists(), false);
|
BOOST_CHECK(!tempFile.exists());
|
||||||
tempFile.touch();
|
tempFile.touch();
|
||||||
BOOST_CHECK_EQUAL(tempFile.exists(), true);
|
BOOST_CHECK(tempFile.exists());
|
||||||
tempFile.remove();
|
tempFile.remove();
|
||||||
BOOST_CHECK_EQUAL(tempFile.exists(), false);
|
BOOST_CHECK(!tempFile.exists());
|
||||||
|
|
||||||
tempFile.touch();
|
tempFile.touch();
|
||||||
BOOST_CHECK_EQUAL(tempFile.exists(), true);
|
BOOST_CHECK(tempFile.exists());
|
||||||
tempFile.remove();
|
tempFile.remove();
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(tempFile.append("abc"), true);
|
BOOST_CHECK(tempFile.append("abc"));
|
||||||
BOOST_CHECK_EQUAL(tempFile.append("def"), true);
|
BOOST_CHECK(tempFile.append("def"));
|
||||||
BOOST_CHECK_EQUAL(tempFile.exists(), true);
|
BOOST_CHECK(tempFile.exists());
|
||||||
tempFile.touch();
|
tempFile.touch();
|
||||||
std::ifstream ifs(tempFile.path());
|
std::ifstream ifs(tempFile.path().string());
|
||||||
std::string line;
|
std::string line;
|
||||||
std::getline(ifs, line);
|
std::getline(ifs, line);
|
||||||
BOOST_CHECK_EQUAL(line, "abcdef");
|
BOOST_CHECK_EQUAL(line, "abcdef");
|
||||||
|
|
||||||
tempFile.change_perms_readonly();
|
tempFile.change_perms_readonly();
|
||||||
BOOST_CHECK_EQUAL(tempFile.write("abc"), false);
|
BOOST_CHECK(!tempFile.write("abc"));
|
||||||
BOOST_CHECK_EQUAL(tempFile.append("def"), false);
|
BOOST_CHECK(!tempFile.append("def"));
|
||||||
|
|
||||||
std::string path;
|
rwfs::path path;
|
||||||
{
|
{
|
||||||
TempFile tempLocal;
|
TempFile tempLocal;
|
||||||
tempLocal.touch();
|
tempLocal.touch();
|
||||||
BOOST_CHECK_EQUAL(tempLocal.exists(), true);
|
BOOST_CHECK(tempLocal.exists());
|
||||||
path = tempLocal.path();
|
path = tempLocal.path();
|
||||||
}
|
}
|
||||||
BOOST_CHECK_EQUAL(fs::exists(path), false);
|
BOOST_CHECK(!rwfs::exists(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(test_config_initial) {
|
||||||
|
// Test an initial config
|
||||||
|
GameConfig cfg;
|
||||||
|
BOOST_CHECK(!cfg.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_config_valid) {
|
BOOST_AUTO_TEST_CASE(test_config_valid) {
|
||||||
@ -263,7 +265,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(config.isValid());
|
BOOST_CHECK(config.isValid());
|
||||||
BOOST_CHECK_EQUAL(config.getParseResult().type(),
|
BOOST_CHECK_EQUAL(config.getParseResult().type(),
|
||||||
@ -274,7 +277,7 @@ BOOST_AUTO_TEST_CASE(test_config_valid) {
|
|||||||
|
|
||||||
BOOST_CHECK_EQUAL(config.getGameDataPath(), "/dev/test");
|
BOOST_CHECK_EQUAL(config.getGameDataPath(), "/dev/test");
|
||||||
BOOST_CHECK_EQUAL(config.getGameLanguage(), "american");
|
BOOST_CHECK_EQUAL(config.getGameLanguage(), "american");
|
||||||
BOOST_CHECK_EQUAL(config.getInputInvertY(), true);
|
BOOST_CHECK(config.getInputInvertY());
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
|
BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
|
||||||
@ -286,7 +289,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(config.isValid());
|
BOOST_CHECK(config.isValid());
|
||||||
BOOST_CHECK_EQUAL(config.getParseResult().type(),
|
BOOST_CHECK_EQUAL(config.getParseResult().type(),
|
||||||
@ -295,7 +299,7 @@ BOOST_AUTO_TEST_CASE(test_config_valid_modified) {
|
|||||||
0);
|
0);
|
||||||
BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0);
|
BOOST_CHECK_EQUAL(config.getParseResult().getKeysInvalidData().size(), 0);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(config.getInputInvertY(), false);
|
BOOST_CHECK(!config.getInputInvertY());
|
||||||
BOOST_CHECK_EQUAL(config.getGameDataPath(), "Liberty City");
|
BOOST_CHECK_EQUAL(config.getGameDataPath(), "Liberty City");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,7 +311,8 @@ BOOST_AUTO_TEST_CASE(test_config_save) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(config.isValid());
|
BOOST_CHECK(config.isValid());
|
||||||
|
|
||||||
@ -318,7 +323,8 @@ BOOST_AUTO_TEST_CASE(test_config_save) {
|
|||||||
BOOST_CHECK(writeResult.isValid());
|
BOOST_CHECK(writeResult.isValid());
|
||||||
BOOST_CHECK(tempFile.exists());
|
BOOST_CHECK(tempFile.exists());
|
||||||
|
|
||||||
GameConfig config2(tempFile.filename(), tempFile.dirname());
|
GameConfig config2;
|
||||||
|
config2.loadFile(tempFile.path());
|
||||||
BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City");
|
BOOST_CHECK_EQUAL(config2.getGameDataPath(), "Liberty City");
|
||||||
|
|
||||||
simpleConfig_t cfg2 = readConfig(tempFile.path());
|
simpleConfig_t cfg2 = readConfig(tempFile.path());
|
||||||
@ -334,7 +340,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_unknown_keys) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(config.isValid());
|
BOOST_CHECK(config.isValid());
|
||||||
|
|
||||||
@ -355,7 +362,8 @@ BOOST_AUTO_TEST_CASE(test_config_valid_unknown_keys) {
|
|||||||
tempFile.remove();
|
tempFile.remove();
|
||||||
config.saveConfig();
|
config.saveConfig();
|
||||||
|
|
||||||
GameConfig config2(tempFile.filename(), tempFile.dirname());
|
GameConfig config2;
|
||||||
|
config2.loadFile(tempFile.path());
|
||||||
const auto &unknownData2 = config2.getParseResult().getUnknownData();
|
const auto &unknownData2 = config2.getParseResult().getUnknownData();
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(unknownData2.size(), 2);
|
BOOST_CHECK_EQUAL(unknownData2.size(), 2);
|
||||||
@ -379,8 +387,9 @@ BOOST_AUTO_TEST_CASE(test_config_save_readonly) {
|
|||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
tempFile.change_perms_readonly();
|
tempFile.change_perms_readonly();
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
BOOST_CHECK_EQUAL(config.isValid(), true);
|
config.loadFile(tempFile.path());
|
||||||
|
BOOST_CHECK(config.isValid());
|
||||||
|
|
||||||
auto writeResult = config.saveConfig();
|
auto writeResult = config.saveConfig();
|
||||||
BOOST_CHECK(!writeResult.isValid());
|
BOOST_CHECK(!writeResult.isValid());
|
||||||
@ -393,13 +402,15 @@ BOOST_AUTO_TEST_CASE(test_config_valid_default) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
BOOST_CHECK(!tempFile.exists());
|
BOOST_CHECK(!tempFile.exists());
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
auto defaultINI = config.getDefaultINIString();
|
auto defaultINI = config.getDefaultINIString();
|
||||||
tempFile.append(defaultINI);
|
tempFile.append(defaultINI);
|
||||||
|
BOOST_CHECK(tempFile.exists());
|
||||||
|
|
||||||
config = GameConfig(tempFile.filename(), tempFile.dirname());
|
config.loadFile(tempFile.path());
|
||||||
BOOST_CHECK(config.isValid());
|
BOOST_CHECK(config.isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,7 +422,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_emptykey) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
const auto &parseResult = config.getParseResult();
|
const auto &parseResult = config.getParseResult();
|
||||||
@ -427,7 +439,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_duplicate) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
const auto &parseResult = config.getParseResult();
|
const auto &parseResult = config.getParseResult();
|
||||||
@ -443,7 +456,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_required_missing) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
@ -465,7 +479,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_wrong_type) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
tempFile.append(cfg);
|
tempFile.append(cfg);
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
@ -487,7 +502,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_empty) {
|
|||||||
tempFile.touch();
|
tempFile.touch();
|
||||||
BOOST_CHECK(tempFile.exists());
|
BOOST_CHECK(tempFile.exists());
|
||||||
|
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
@ -504,7 +520,9 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_nodir) {
|
|||||||
|
|
||||||
BOOST_CHECK(!tempDir.exists());
|
BOOST_CHECK(!tempDir.exists());
|
||||||
BOOST_CHECK(!tempFile.exists());
|
BOOST_CHECK(!tempFile.exists());
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
|
||||||
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
@ -518,7 +536,8 @@ BOOST_AUTO_TEST_CASE(test_config_invalid_nonexisting) {
|
|||||||
TempFile tempFile;
|
TempFile tempFile;
|
||||||
|
|
||||||
BOOST_CHECK(!tempFile.exists());
|
BOOST_CHECK(!tempFile.exists());
|
||||||
GameConfig config(tempFile.filename(), tempFile.dirname());
|
GameConfig config;
|
||||||
|
config.loadFile(tempFile.path());
|
||||||
|
|
||||||
BOOST_CHECK(!config.isValid());
|
BOOST_CHECK(!config.isValid());
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
#if RW_TEST_WITH_DATA
|
#if RW_TEST_WITH_DATA
|
||||||
std::string Global::getGamePath() {
|
std::string Global::getGamePath() {
|
||||||
return GameConfig("openrw.ini").getGameDataPath();
|
GameConfig config;
|
||||||
|
config.loadFile(GameConfig::getDefaultConfigPath() / "openrw.ini");
|
||||||
|
return config.getGameDataPath();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user