1
0
mirror of https://github.com/rwengine/openrw.git synced 2024-11-25 03:42:48 +01:00

config: use boost::property_tree for INI read and default generation

* remove inih
* input.invert_y has now behavior as described on wiki
This commit is contained in:
Anonymous Maarten 2016-12-28 18:35:20 +01:00 committed by Daniel Evans
parent 7bc501106c
commit 65b14fcb9c
8 changed files with 78 additions and 42 deletions

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "external/inih"]
path = external/inih
url = https://github.com/benhoyt/inih.git
[submodule "external/mman-win32"]
path = external/mman-win32
url = https://github.com/witwall/mman-win32.git

View File

@ -2,7 +2,6 @@
set(EXTERNAL_PREFIX "${CMAKE_BINARY_DIR}/external")
include(inih.cmake)
if(MINGW)
include(mman-win32.cmake)
endif()

View File

@ -1,11 +0,0 @@
###### External Project: inih
include(ExternalProject)
SET(INIH_PREFIX_DIR ${PROJECT_SOURCE_DIR}/external/inih)
SET(INIH_SOURCES
${INIH_PREFIX_DIR}/ini.c)
add_library(inih
${INIH_SOURCES})
target_include_directories(inih INTERFACE SYSTEM ${INIH_PREFIX_DIR})

1
external/inih vendored

@ -1 +0,0 @@
Subproject commit 18a67c516358e2791ab720a1abe411d991774f3e

View File

@ -54,7 +54,6 @@ include_directories(
target_link_libraries(rwgame
rwengine
inih
${Boost_LIBRARIES}
${OPENGL_LIBRARIES}
${BULLET_LIBRARIES}

View File

@ -3,7 +3,9 @@
#include <cstring>
#include <rw/defines.hpp>
#include <ini.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
namespace pt = boost::property_tree;
const std::string kConfigDirectoryName("OpenRW");
@ -20,11 +22,7 @@ GameConfig::GameConfig(const std::string& configName,
// Look up the path to use
auto configFile = getConfigFile();
if (ini_parse(configFile.c_str(), handler, this) < 0) {
m_valid = false;
} else {
m_valid = true;
}
m_valid = readConfig(configFile);
}
std::string GameConfig::getConfigFile() {
@ -62,25 +60,80 @@ std::string GameConfig::getDefaultConfigPath() {
return ".";
}
int GameConfig::handler(void* user, const char* section, const char* name,
const char* value) {
auto self = static_cast<GameConfig*>(user);
#define MATCH(_s, _n) (strcmp(_s, section) == 0 && strcmp(_n, name) == 0)
std::string stripComments(const std::string &str)
{
auto s = std::string(str, 0, str.find_first_of(";#"));
return s.erase(s.find_last_not_of(" \n\r\t")+1);
}
if (MATCH("game", "path")) {
self->m_gamePath = value;
} else if (MATCH("game", "language")) {
// @todo Don't allow path seperators and relative directories
self->m_gameLanguage = value;
} else if (MATCH("input", "invert_y")) {
self->m_inputInvertY = atoi(value) > 0;
} else {
RW_MESSAGE("Unhandled config entry [" << section << "] " << name
<< " = " << value);
return 0;
struct StringTranslator {
typedef std::string internal_type;
typedef std::string external_type;
boost::optional<external_type> get_value(const internal_type &str) {
return boost::optional<external_type>(stripComments(str));
}
boost::optional<internal_type> put_value(const external_type &str) {
return boost::optional<internal_type>(str);
}
};
struct BoolTranslator {
typedef std::string internal_type;
typedef bool external_type;
boost::optional<external_type> get_value(const internal_type &str) {
return boost::optional<external_type>(std::stoi(stripComments(str)) != 0);
}
boost::optional<internal_type> put_value(const external_type &b) {
return boost::optional<internal_type>(b ? "1" : "0");
}
};
bool GameConfig::readConfig(const std::string &path) {
pt::ptree config, defaultConfig;
bool success = true;
auto read_config = [&](const std::string &key, auto &target,
const auto &defaultValue, auto &translator,
bool optional=true) {
typedef typename std::remove_reference<decltype(target)>::type targetType;
defaultConfig.put(key, defaultValue, translator);
try {
target = config.get<targetType>(key, translator);
} catch (pt::ptree_bad_path &e) {
if (optional) {
target = defaultValue;
} else {
success = false;
RW_MESSAGE(e.what());
}
}
};
try {
pt::read_ini(path, config);
} catch (pt::ini_parser_error &e) {
success = false;
RW_MESSAGE(e.what());
}
return 1;
auto deft = StringTranslator();
auto boolt = BoolTranslator();
#undef MATCH
// @todo Don't allow path seperators and relative directories
read_config("game.path", this->m_gamePath, "/opt/games/Grand Theft Auto 3", deft, false);
read_config("game.language", this->m_gameLanguage, "american", deft);
read_config("input.invert_y", this->m_inputInvertY, false, boolt);
if (!success) {
std::stringstream strstream;
pt::write_ini(strstream, defaultConfig);
RW_MESSAGE("Failed to parse configuration file (" + path + ").");
RW_MESSAGE("Create one looking like this at \"" + path + "\":");
RW_MESSAGE(strstream.str());
}
return success;
}

View File

@ -35,7 +35,8 @@ public:
private:
static std::string getDefaultConfigPath();
static int handler(void*, const char*, const char*, const char*);
bool readConfig(const std::string &path);
/* Config State */
std::string m_configName;

View File

@ -67,7 +67,6 @@ include_directories(SYSTEM
target_link_libraries(run_tests
rwengine
inih
${OPENGL_LIBRARIES}
${BULLET_LIBRARIES}
${SDL2_LIBRARY}