mirror of
https://github.com/ondra-novak/gates_of_skeldal.git
synced 2025-07-13 01:41:59 -04:00
new ini support proposal
This commit is contained in:
parent
ab4a08ada5
commit
2de58233c4
4 changed files with 318 additions and 2 deletions
|
@ -1,7 +1,14 @@
|
|||
SET(files error.cpp legacy_coroutines.cpp platform.cpp int2ascii.c istr.c file_access.cpp)
|
||||
SET(files error.cpp
|
||||
legacy_coroutines.cpp
|
||||
platform.cpp
|
||||
int2ascii.c
|
||||
istr.c
|
||||
file_access.cpp
|
||||
config.cpp
|
||||
)
|
||||
|
||||
add_library(skeldal_platform_libs ${files})
|
||||
set_property(TARGET skeldal_platform_libs PROPERTY CXX_STANDARD 20)
|
||||
|
||||
add_subdirectory(sdl)
|
||||
add_subdirectory(linux)
|
||||
add_subdirectory(linux)
|
||||
|
|
170
platform/config.cpp
Normal file
170
platform/config.cpp
Normal file
|
@ -0,0 +1,170 @@
|
|||
#include "config.h"
|
||||
#include "platform.h"
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
typedef struct ini_config_tag {
|
||||
|
||||
using Section = std::map<std::string, std::string, std::less<>>;
|
||||
using Config = std::map<std::string, Section , std::less<>>;
|
||||
Config data;
|
||||
|
||||
} INI_CONFIG;
|
||||
|
||||
|
||||
|
||||
// Trim whitespace z obou stran pro string_view
|
||||
static inline std::string_view trim(std::string_view str) {
|
||||
const size_t first = str.find_first_not_of(" \t");
|
||||
if (first == std::string_view::npos) return {};
|
||||
const size_t last = str.find_last_not_of(" \t");
|
||||
return str.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
// Parser INI souboru
|
||||
template<std::invocable<std::string_view, std::string_view, std::string_view> Callback >
|
||||
void parseIniStream(std::istream& input, Callback &&callback) {
|
||||
std::string line;
|
||||
std::string currentSection;
|
||||
|
||||
while (std::getline(input, line)) {
|
||||
std::string_view line_view = trim(line);
|
||||
|
||||
// Ignoruj prázdné řádky nebo komentáře
|
||||
if (line_view.empty() || line_view.front() == '#') continue;
|
||||
|
||||
// Detekce sekce [sekce]
|
||||
if (line_view.front() == '[' && line_view.back() == ']') {
|
||||
currentSection = std::string(trim(line_view.substr(1, line_view.size() - 2)));
|
||||
} else {
|
||||
// Zpracuj klíč = hodnota
|
||||
size_t eqPos = line_view.find('=');
|
||||
if (eqPos != std::string_view::npos) {
|
||||
std::string_view key_view = trim(line_view.substr(0, eqPos));
|
||||
std::string_view value_view = trim(line_view.substr(eqPos + 1));
|
||||
callback(currentSection, std::string(key_view), std::string(value_view));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const INI_CONFIG* ini_open(const char *filename) {
|
||||
INI_CONFIG *c = new INI_CONFIG;
|
||||
|
||||
std::fstream input(filename);
|
||||
if (!input) return c;
|
||||
parseIniStream(input, [&](std::string_view section, std::string_view key, std::string_view value) {
|
||||
INI_CONFIG::Config::iterator iter = c->data.find(section);
|
||||
if (iter == c->data.end()) {
|
||||
iter = c->data.emplace(std::string(section), INI_CONFIG::Section()).first;
|
||||
}
|
||||
iter->second.emplace(std::string(key), std::string(value));
|
||||
});
|
||||
return c;
|
||||
}
|
||||
|
||||
void ini_close(const INI_CONFIG *config) {
|
||||
delete config;
|
||||
}
|
||||
|
||||
const INI_CONFIG_SECTION* ini_section_open(const INI_CONFIG *cfg, const char *section) {
|
||||
auto iter = cfg->data.find(std::string_view(section));
|
||||
if (iter == cfg->data.end()) return NULL;
|
||||
else return reinterpret_cast<const INI_CONFIG_SECTION *>(&iter->second);
|
||||
}
|
||||
|
||||
const char* ini_find_key(const INI_CONFIG_SECTION *section,
|
||||
const char *key) {
|
||||
if (section == NULL) return NULL;
|
||||
const INI_CONFIG::Section *s = reinterpret_cast<const INI_CONFIG::Section *>(section);
|
||||
auto iter = s->find(std::string_view(key));
|
||||
if (iter == s->end()) return NULL;
|
||||
return iter->second.c_str();
|
||||
}
|
||||
|
||||
|
||||
long ini_get_value_int(const char *value, int *conv_ok) {
|
||||
char *out = NULL;
|
||||
if (value != NULL) {
|
||||
long ret = strtol(value, &out, 10);
|
||||
if (*out == 0) {
|
||||
if (*conv_ok) *conv_ok = 1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (*conv_ok) *conv_ok = 0;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
double ini_get_value_double(const char *value, int *conv_ok) {
|
||||
char *out = NULL;
|
||||
if (value != NULL) {
|
||||
double ret = strtod(value, &out);
|
||||
if (*out == 0) {
|
||||
if (*conv_ok) *conv_ok = 1;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (*conv_ok) *conv_ok = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ini_get_value_boolean(const char *value) {
|
||||
int r = -1;
|
||||
if (value != NULL) {
|
||||
if (stricmp(value, "true") == 0
|
||||
|| stricmp(value, "1") == 0
|
||||
|| stricmp(value, "on") == 0
|
||||
|| stricmp(value, "yes") == 0) {
|
||||
r = 1;
|
||||
} else if (stricmp(value, "false") == 0
|
||||
|| stricmp(value, "0") == 0
|
||||
|| stricmp(value, "off") == 0
|
||||
|| stricmp(value, "no") == 0) {
|
||||
r = 0;
|
||||
} else {
|
||||
r = -1;
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
const char* ini_get_string(
|
||||
const INI_CONFIG_SECTION *section, const char *key, const char *defval) {
|
||||
const char *k = ini_find_key(section, key);
|
||||
return k?k:defval;
|
||||
}
|
||||
|
||||
long ini_get_int(const INI_CONFIG_SECTION *section, const char *key, long defval) {
|
||||
const char *k = ini_find_key(section, key);
|
||||
if (k) {
|
||||
int ok;
|
||||
long r = ini_get_value_int(k, &ok);
|
||||
return ok?r:defval;
|
||||
}
|
||||
return defval;
|
||||
}
|
||||
|
||||
int ini_get_double(const INI_CONFIG_SECTION *section, const char *key,
|
||||
double defval) {
|
||||
const char *k = ini_find_key(section, key);
|
||||
if (k) {
|
||||
int ok;
|
||||
double r = ini_get_value_double(k, &ok);
|
||||
return ok?r:defval;
|
||||
}
|
||||
return defval;
|
||||
}
|
||||
|
||||
int ini_get_boolean(const INI_CONFIG_SECTION *section, const char *key,
|
||||
int defval) {
|
||||
const char *k = ini_find_key(section, key);
|
||||
if (k) {
|
||||
int r = ini_get_value_boolean(k);
|
||||
return r>=0?r:defval;
|
||||
}
|
||||
return defval;
|
||||
}
|
97
platform/config.h
Normal file
97
platform/config.h
Normal file
|
@ -0,0 +1,97 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct ini_config_tag INI_CONFIG;
|
||||
typedef struct ini_config_section_tag INI_CONFIG_SECTION;
|
||||
|
||||
///Opens config, returns handle
|
||||
const INI_CONFIG *ini_open(const char *filename);
|
||||
///closes the config and frees memory
|
||||
void ini_close(const INI_CONFIG *config);
|
||||
|
||||
///Opens section
|
||||
/**
|
||||
*
|
||||
* @param cfg ini config
|
||||
* @param section section name
|
||||
* @return if section exists, return handle to section otherwise returns NULL.
|
||||
* The section don't need to be closed, however it is tied to INI_CONFIG handle, so
|
||||
* one the config is closed, the section becomes invalid
|
||||
*/
|
||||
const INI_CONFIG_SECTION *ini_section_open(const INI_CONFIG *cfg, const char *section);
|
||||
///Finds key in section
|
||||
/**
|
||||
* @param section handle to section
|
||||
* @param key name of key
|
||||
* @return handle of key if found, or NULL if not. The returned pointer points
|
||||
* to string representation of the value (so you can use it as string value)
|
||||
*/
|
||||
const char *ini_find_key(const INI_CONFIG_SECTION *section, const char *key);
|
||||
///retrieves value as integer
|
||||
/**
|
||||
* @param value found value
|
||||
* @param conv_error (optional, can be NULL) - retrieves 1 if conversion succes, 0 if failed
|
||||
* @return if conversion successed, returns value, otherwise returns -1
|
||||
*/
|
||||
long ini_get_value_int(const char *value, int *conv_ok);
|
||||
///retrieves value as double
|
||||
/**
|
||||
* @param value found value
|
||||
* @param conv_error (optional, can be NULL) - retrieves 1 if conversion succes, 0 if failed
|
||||
* @return if conversion successed, returns value, otherwise returns -1
|
||||
*/
|
||||
double ini_get_value_double(const char *value, int *conv_ok);
|
||||
///retrieves value as boolean
|
||||
/**
|
||||
* @param value found value
|
||||
* @param conv_error (optional, can be NULL) - retrieves 1 if conversion succes, 0 if failed
|
||||
* @retval 1 value is true, nonzero, yes or on
|
||||
* @retval 0 value is false, zero, no, or off
|
||||
* @retval -1 cannot convert value
|
||||
*
|
||||
*/
|
||||
int ini_get_value_boolean(const char *value);
|
||||
|
||||
|
||||
///retrieve string from ini
|
||||
/**
|
||||
* @param section section
|
||||
* @param key key
|
||||
* @param defval default value
|
||||
* @return if key doesn't exits or parse error, returns defval, otherwise returns value
|
||||
*/
|
||||
const char *ini_get_string(const INI_CONFIG_SECTION *section, const char *key, const char *defval);
|
||||
///retrieve int from ini
|
||||
/**
|
||||
* @param section section
|
||||
* @param key key
|
||||
* @param defval default value
|
||||
* @return if key doesn't exits or parse error, returns defval, otherwise returns value
|
||||
*/
|
||||
long ini_get_int(const INI_CONFIG_SECTION *section, const char *key, long defval);
|
||||
///retrieve double from ini
|
||||
/**
|
||||
* @param section section
|
||||
* @param key key
|
||||
* @param defval default value
|
||||
* @return if key doesn't exits or parse error, returns defval, otherwise returns value
|
||||
*/
|
||||
int ini_get_double(const INI_CONFIG_SECTION *section, const char *key, double defval);
|
||||
///retrieve boolean from ini
|
||||
/**
|
||||
* @param section section
|
||||
* @param key key
|
||||
* @param defval default value
|
||||
* @return if key doesn't exits or parse error, returns defval, otherwise returns value
|
||||
*/
|
||||
int ini_get_boolean(const INI_CONFIG_SECTION *section, const char *key, int defval);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
42
skeldal.ini
Normal file
42
skeldal.ini
Normal file
|
@ -0,0 +1,42 @@
|
|||
##### path
|
||||
#
|
||||
# game_path = path to root of the game
|
||||
# maps = relative path to maps
|
||||
# video = relative path to videp
|
||||
# data = relative path to skeldal.ddl
|
||||
# savegame = path to savegame, if not defined, retrieved from platform settings
|
||||
|
||||
|
||||
[path]
|
||||
game_path=/home/ondra/skeldal_game/
|
||||
# maps=./maps/
|
||||
# video=./video/
|
||||
# data=./
|
||||
# savegame = determine default
|
||||
|
||||
|
||||
#### video settings
|
||||
#
|
||||
# fullscreen = run game in fullscreen mode
|
||||
# window_width = set window with (in windowed mode)
|
||||
# window_height = set window height (in windowed mode)
|
||||
# crt_filter = enable filter simmulates lowres CRT monitor for higher resolution
|
||||
# composer = auto - choose best supported driver
|
||||
# hardware,hw - use hardware for composition
|
||||
# software,sw - use software for composition
|
||||
# scale_quality = auto - best for hardware composer, nearest for software comporser
|
||||
# best - best scale quality (SDL = linear)
|
||||
# linear - use linear filtering (Direct3D and OpenGL)
|
||||
# nearest - use nearest filtering
|
||||
#
|
||||
[video]
|
||||
fullscreen=on
|
||||
#window_width=640
|
||||
#window_height=480
|
||||
#crt_filter=on
|
||||
#smooth_scale=auto
|
||||
#composer=auto
|
||||
#scale_quality
|
||||
|
||||
|
||||
[audio]
|
Loading…
Add table
Add a link
Reference in a new issue