/* * clone_scenario -- alloc a new scenario and copy all data from src scenario */ struct scenario * clone_scenario(struct scenario *src_scenario) { assert(src_scenario != NULL); struct scenario *new_scenario = scenario_alloc(src_scenario->name, src_scenario->benchmark); assert(new_scenario != NULL); struct kv *src_kv; FOREACH_KV(src_kv, src_scenario) { struct kv *new_kv = kv_alloc(src_kv->key, src_kv->value); assert(new_kv != NULL); TAILQ_INSERT_TAIL(&new_scenario->head, new_kv, next); } return new_scenario; }
/* * config_reader_get_scenarios -- return scenarios from config file * * This function reads the config file and returns a list of scenarios. * Each scenario contains a list of key/value arguments. * The scenario's arguments are merged with arguments from global section. */ int config_reader_get_scenarios(struct config_reader *cr, struct scenarios **scenarios) { /* * Read all groups. * The config file must have at least one group, otherwise * it is considered as invalid. */ gsize ngroups; gsize g; gchar **groups = g_key_file_get_groups(cr->key_file, &ngroups); assert(nullptr != groups); if (!groups) return -1; /* * Check if global section is present and read keys from it. */ int ret = 0; int has_global = g_key_file_has_group(cr->key_file, SECTION_GLOBAL) == TRUE; gsize ngkeys; gchar **gkeys = nullptr; struct scenarios *s; if (has_global) { gkeys = g_key_file_get_keys(cr->key_file, SECTION_GLOBAL, &ngkeys, nullptr); assert(nullptr != gkeys); if (!gkeys) { ret = -1; goto err_groups; } } s = scenarios_alloc(); assert(nullptr != s); if (!s) { ret = -1; goto err_gkeys; } for (g = 0; g < ngroups; g++) { /* * Check whether a group is a scenario * or global section. */ if (!is_scenario(groups[g])) continue; /* * Check for KEY_BENCHMARK which contains benchmark name. * If not present the benchmark name is the same as the * name of the section. */ struct scenario *scenario = nullptr; if (g_key_file_has_key(cr->key_file, groups[g], KEY_BENCHMARK, nullptr) == FALSE) { scenario = scenario_alloc(groups[g], groups[g]); assert(scenario != nullptr); } else { gchar *benchmark = g_key_file_get_value(cr->key_file, groups[g], KEY_BENCHMARK, nullptr); assert(benchmark != nullptr); if (!benchmark) { ret = -1; goto err_scenarios; } scenario = scenario_alloc(groups[g], benchmark); assert(scenario != nullptr); free(benchmark); } gsize k; if (has_global) { /* * Merge key/values from global section. */ for (k = 0; k < ngkeys; k++) { if (g_key_file_has_key(cr->key_file, groups[g], gkeys[k], nullptr) == TRUE) continue; if (!is_argument(gkeys[k])) continue; char *value = g_key_file_get_value( cr->key_file, SECTION_GLOBAL, gkeys[k], nullptr); assert(nullptr != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc(gkeys[k], value); assert(nullptr != kv); free(value); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } } /* check for group name */ if (g_key_file_has_key(cr->key_file, groups[g], KEY_GROUP, nullptr) != FALSE) { gchar *group = g_key_file_get_value( cr->key_file, groups[g], KEY_GROUP, nullptr); assert(group != nullptr); scenario_set_group(scenario, group); } else if (g_key_file_has_key(cr->key_file, SECTION_GLOBAL, KEY_GROUP, nullptr) != FALSE) { gchar *group = g_key_file_get_value(cr->key_file, SECTION_GLOBAL, KEY_GROUP, nullptr); scenario_set_group(scenario, group); } gsize nkeys; gchar **keys = g_key_file_get_keys(cr->key_file, groups[g], &nkeys, nullptr); assert(nullptr != keys); if (!keys) { ret = -1; goto err_scenarios; } /* * Read key/values from the scenario's section. */ 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], nullptr); assert(nullptr != value); if (!value) { ret = -1; g_strfreev(keys); goto err_scenarios; } struct kv *kv = kv_alloc(keys[k], value); assert(nullptr != 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; }
/* * config_reader_get_scenarios -- return scenarios from config file * * This function reads the config file and returns a list of scenarios. * Each scenario contains a list of key/value arguments. * The scenario's arguments are merged with arguments from global section. */ int config_reader_get_scenarios(struct config_reader *cr, struct scenarios **scenarios) { /* * Read all groups. * The config file must have at least one group, otherwise * it is considered as invalid. */ int ret = 0; TCHAR *sections = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!sections) return -1; GetPrivateProfileSectionNames(sections, SIZEOF_SECTION, cr->lpFileName); if (NULL_LIST_EMPTY(sections)) { ret = -1; goto err_sections; } /* * Check if global section is present and read it. */ TCHAR *global = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!global) return -1; GetPrivateProfileSection(SECTION_GLOBAL, global, SIZEOF_SECTION, cr->lpFileName); KV_LIST global_kv = KV_LIST_INIT(global); int has_global = !KV_LIST_EMPTY(global_kv); struct scenarios *s = scenarios_alloc(); assert(NULL != s); if (!s) { ret = -1; goto err_gkeys; } LPTSTR global_group = NULL; for (KV_LIST it = global_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { if (_tcscmp(KV_LIST_KEY(it), KEY_GROUP) == 0) { global_group = KV_LIST_VALUE(it); break; } } TCHAR *section; for (LPTSTR group_name = sections; !NULL_LIST_EMPTY(group_name); group_name = NULL_LIST_NEXT(group_name)) { /* * Check whether a group is a scenario * or global section. */ if (!is_scenario(group_name)) continue; /* * Check for KEY_BENCHMARK which contains benchmark name. * If not present the benchmark name is the same as the * name of the section. */ section = (TCHAR *)malloc(sizeof(TCHAR) * SIZEOF_SECTION); if (!section) ret = -1; GetPrivateProfileSection(group_name, section, SIZEOF_SECTION, cr->lpFileName); KV_LIST section_kv = KV_LIST_INIT(section); struct scenario *scenario = NULL; LPTSTR name = NULL; LPTSTR group = NULL; for (KV_LIST it = section_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { if (_tcscmp(KV_LIST_KEY(it), KEY_BENCHMARK) == 0) { name = KV_LIST_VALUE(it); } if (_tcscmp(KV_LIST_KEY(it), KEY_GROUP) == 0) { group = KV_LIST_VALUE(it); } } if (name == NULL) { scenario = scenario_alloc((const char *)group_name, (const char *)group_name); } else { scenario = scenario_alloc((const char *)group_name, (const char *)name); } assert(scenario != NULL); if (has_global) { /* * Merge key/values from global section. */ for (KV_LIST it = global_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { LPTSTR key = KV_LIST_KEY(it); if (!is_argument(key)) continue; LPTSTR value = KV_LIST_VALUE(it); assert(NULL != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc((const char *)key, (const char *)value); assert(NULL != kv); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } } /* check for group name */ if (group) { scenario_set_group(scenario, (const char *)group); } else if (global_group) { scenario_set_group(scenario, (const char *)global_group); } for (KV_LIST it = section_kv; !KV_LIST_EMPTY(it); KV_LIST_NEXT(it)) { LPTSTR key = KV_LIST_KEY(it); if (!is_argument(key)) continue; LPTSTR value = KV_LIST_VALUE(it); assert(NULL != value); if (!value) { ret = -1; goto err_scenarios; } struct kv *kv = kv_alloc((const char *)key, (const char *)value); assert(NULL != kv); if (!kv) { ret = -1; goto err_scenarios; } TAILQ_INSERT_TAIL(&scenario->head, kv, next); } TAILQ_INSERT_TAIL(&s->head, scenario, next); free(section); } *scenarios = s; free(global); free(sections); return 0; err_scenarios: free(section); scenarios_free(s); err_gkeys: free(global); err_sections: free(sections); return ret; }