#include <cassert>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <glib.h>
#include <sys/queue.h>
#include "config_reader.hpp"
#include "scenario.hpp"
#define SECTION_GLOBAL "global"
#define KEY_BENCHMARK "bench"
#define KEY_GROUP "group"
struct config_reader {
GKeyFile *key_file;
};
struct config_reader *
config_reader_alloc(void)
{
struct config_reader *cr = (struct config_reader *)malloc(sizeof(*cr));
assert(cr != NULL);
cr->key_file = g_key_file_new();
if (!cr->key_file)
goto err;
return cr;
err:
free(cr);
return NULL;
}
int
config_reader_read(struct config_reader *cr, const char *fname)
{
if (g_key_file_load_from_file(cr->key_file, fname, G_KEY_FILE_NONE,
NULL) != TRUE)
return -1;
return 0;
}
void
config_reader_free(struct config_reader *cr)
{
g_key_file_free(cr->key_file);
free(cr);
}
static int
is_scenario(const char *name)
{
return strcmp(name, SECTION_GLOBAL);
}
static int
is_argument(const char *name)
{
return strcmp(name, KEY_BENCHMARK) != 0 && strcmp(name, KEY_GROUP) != 0;
}
int
config_reader_get_scenarios(struct config_reader *cr,
struct scenarios **scenarios)
{
gsize ngroups;
gsize g;
gchar **groups = g_key_file_get_groups(cr->key_file, &ngroups);
assert(NULL != groups);
if (!groups)
return -1;
int ret = 0;
int has_global =
g_key_file_has_group(cr->key_file, SECTION_GLOBAL) == TRUE;
gsize ngkeys;
gchar **gkeys = NULL;
struct scenarios *s;
if (has_global) {
gkeys = g_key_file_get_keys(cr->key_file, SECTION_GLOBAL,
&ngkeys, NULL);
assert(NULL != gkeys);
if (!gkeys) {
ret = -1;
goto err_groups;
}
}
s = scenarios_alloc();
assert(NULL != s);
if (!s) {
ret = -1;
goto err_gkeys;
}
for (g = 0; g < ngroups; g++) {
if (!is_scenario(groups[g]))
continue;
struct scenario *scenario = NULL;
if (g_key_file_has_key(cr->key_file, groups[g], KEY_BENCHMARK,
NULL) == FALSE) {
scenario = scenario_alloc(groups[g], groups[g]);
assert(scenario != NULL);
} else {
gchar *benchmark = g_key_file_get_value(
cr->key_file, groups[g], KEY_BENCHMARK, NULL);
assert(benchmark != NULL);
if (!benchmark) {
ret = -1;
goto err_scenarios;
}
scenario = scenario_alloc(groups[g], benchmark);
assert(scenario != NULL);
free(benchmark);
}
gsize k;
if (has_global) {
for (k = 0; k < ngkeys; k++) {
if (g_key_file_has_key(cr->key_file, groups[g],
gkeys[k], NULL) == TRUE)
continue;
if (!is_argument(gkeys[k]))
continue;
char *value = g_key_file_get_value(
cr->key_file, SECTION_GLOBAL, gkeys[k],
NULL);
assert(NULL != value);
if (!value) {
ret = -1;
goto err_scenarios;
}
struct kv *kv = kv_alloc(gkeys[k], value);
assert(NULL != kv);
free(value);
if (!kv) {
ret = -1;
goto err_scenarios;
}
TAILQ_INSERT_TAIL(&scenario->head, kv, next);
}
}
if (g_key_file_has_key(cr->key_file, groups[g], KEY_GROUP,
NULL) != FALSE) {
gchar *group = g_key_file_get_value(
cr->key_file, groups[g], KEY_GROUP, NULL);
assert(group != NULL);
scenario_set_group(scenario, group);
} else if (g_key_file_has_key(cr->key_file, SECTION_GLOBAL,
KEY_GROUP, NULL) != FALSE) {
gchar *group = g_key_file_get_value(
cr->key_file, SECTION_GLOBAL, KEY_GROUP, NULL);
scenario_set_group(scenario, group);
}
gsize nkeys;
gchar **keys = g_key_file_get_keys(cr->key_file, groups[g],
&nkeys, NULL);
assert(NULL != keys);
if (!keys) {
ret = -1;
goto err_scenarios;
}
for (k = 0; k < nkeys; k++) {
if (!is_argument(keys[k]))
continue;
char *value = g_key_file_get_value(
cr->key_file, groups[g], keys[k], NULL);
assert(NULL != value);
if (!value) {
ret = -1;
g_strfreev(keys);
goto err_scenarios;
}
struct kv *kv = kv_alloc(keys[k], value);
assert(NULL != kv);
free(value);
if (!kv) {
g_strfreev(keys);
ret = -1;
goto err_scenarios;
}
TAILQ_INSERT_TAIL(&scenario->head, kv, next);
}
g_strfreev(keys);
TAILQ_INSERT_TAIL(&s->head, scenario, next);
}
g_strfreev(gkeys);
g_strfreev(groups);
*scenarios = s;
return 0;
err_scenarios:
scenarios_free(s);
err_gkeys:
g_strfreev(gkeys);
err_groups:
g_strfreev(groups);
return ret;
}