From e5f5a9399dfd4df66d6c5e5aea99da045101f39d Mon Sep 17 00:00:00 2001 From: shariq Date: Sat, 9 Sep 2017 03:29:16 +0500 Subject: [PATCH] Removed duplicate parsing logic by extracting code into reusable parser --- README.md | 3 + src/common/common.h | 3 +- src/common/parser.c | 66 ++++++++++++++++ src/common/parser.h | 12 +++ src/game/config_vars.c | 57 +++++--------- src/game/platform.c | 14 ++-- src/libsymmetry/input.c | 170 ++++++++++++++++++---------------------- 7 files changed, 186 insertions(+), 139 deletions(-) create mode 100644 src/common/parser.c create mode 100644 src/common/parser.h diff --git a/README.md b/README.md index e220781..ff12a72 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,8 @@ - ## TODO + - Fix bugs in stripping key name for input map + - Modify entity loading logic to use the new parsing code - Implement sound/listener loading from scene file - Finish loading scene from file - Update makefiles to be able to compile the code in it's current state @@ -316,3 +318,4 @@ * Fixed error caused by the way eof was checked in scene file * Camera fbo params are now written to file when entity is saved * Fixed several bugs with entity loading + * Removed duplicate parsing logic diff --git a/src/common/common.h b/src/common/common.h index 0c00c13..a4a9b86 100644 --- a/src/common/common.h +++ b/src/common/common.h @@ -93,7 +93,7 @@ struct Log_Api struct Platform_Api { // General platform api - void (*poll_events)(bool *out_quit); + void (*poll_events)(bool* out_quit); void (*keyboard_callback_set)(Keyboard_Event_Func func); void (*mousebutton_callback_set)(Mousebutton_Event_Func func); void (*mousemotion_callback_set)(Mousemotion_Event_Func func); @@ -131,5 +131,4 @@ struct Game_Api void (*cleanup)(void); }; - #endif diff --git a/src/common/parser.c b/src/common/parser.c new file mode 100644 index 0000000..b156a33 --- /dev/null +++ b/src/common/parser.c @@ -0,0 +1,66 @@ +#include "parser.h" +#include "hashmap.h" +#include "log.h" + +#include +#include + +#define MAX_LINE_LEN 512 +#define QUOTE(str) #str +#define KEY_LEN_STR(LEN) QUOTE(LEN) + +bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line) +{ + if(!file) + { + log_error("parser:load", "Invalid file handle for file %s", filename); + return false; + } + + if(!assign_func) + { + log_error("parser:load", "No assign function provided to load file %s", filename); + return false; + } + + /* Read line by line, ignore comments */ + char key_str[HASH_MAX_KEY_LEN]; + char line_buffer[MAX_LINE_LEN]; + memset(key_str, '\0', HASH_MAX_KEY_LEN); + memset(line_buffer, '\0', MAX_LINE_LEN); + + while(fgets(line_buffer, MAX_LINE_LEN - 1, file)) + { + current_line++; + memset(key_str, '\0', HASH_MAX_KEY_LEN); + + if(strlen(line_buffer) == 0 || isspace(line_buffer[0]) != 0) + { + if(return_on_emptyline) + return true; + else + continue; + } + + if(line_buffer[0] == '#') + continue; + + char* value_str = strstr(line_buffer, ":"); + if(!value_str) + { + log_warning("Malformed value in config file %s, line %d", filename, current_line); + continue; + } + + value_str++; /* Ignore the colon(:) and set the pointer after it */ + + if(sscanf(line_buffer, " %" KEY_LEN_STR(HASH_MAX_KEY_LEN) "[^: ] : %*s", key_str) != 1) + { + log_warning("Parser unable to read key in file %s, line %d", filename, current_line); + continue; + } + + assign_func(key_str, value_str, filename, current_line); + } + return true; +} diff --git a/src/common/parser.h b/src/common/parser.h new file mode 100644 index 0000000..5ea0300 --- /dev/null +++ b/src/common/parser.h @@ -0,0 +1,12 @@ +#ifndef PARSER_H +#define PARSER_H + +#include "common.h" + +struct Hashmap; + +typedef void (*Parser_Assign_Func)(const char* key, const char* value, const char* filename, int current_line); + +bool parser_load(FILE* file, const char* filename, Parser_Assign_Func assign_func, bool return_on_emptyline, int current_line); + +#endif diff --git a/src/game/config_vars.c b/src/game/config_vars.c index d48cb07..5ad4876 100644 --- a/src/game/config_vars.c +++ b/src/game/config_vars.c @@ -4,6 +4,7 @@ #include "../common/hashmap.h" #include "file_io.h" #include "../common/log.h" +#include "../common/parser.h" #include "platform.h" #include @@ -13,6 +14,8 @@ static struct Hashmap* cvars = NULL; +static void config_on_parser_assign(const char* key, const char* value, const char* filename, int current_line); + void config_vars_init(void) { cvars = hashmap_new(); @@ -43,6 +46,17 @@ struct Hashmap* config_vars_get(void) return cvars; } +void config_on_parser_assign(const char* key, const char* value, const char* filename, int current_line) +{ + struct Variant* cvar = hashmap_value_get(cvars, key); + if(!cvar) + { + log_warning("Unknown config key '%s' in file %s, line %d", key, filename, current_line); + return; + } + variant_from_str(cvar, value, cvar->type); +} + bool config_vars_load(const char* filename, int directory_type) { bool success = false; @@ -53,45 +67,16 @@ bool config_vars_load(const char* filename, int directory_type) return success; } - /* Read line by line, ignore comments */ - char key_str[HASH_MAX_KEY_LEN]; - char line_buffer[MAX_LINE_LEN]; - memset(key_str, '\0', HASH_MAX_KEY_LEN); - memset(line_buffer, '\0', MAX_LINE_LEN); - int current_line = 0; - while(fgets(line_buffer, MAX_LINE_LEN - 1, config_file)) + if(!parser_load(config_file, filename, &config_on_parser_assign, false, 0)) { - current_line++; - memset(key_str, '\0', HASH_MAX_KEY_LEN); - - if(line_buffer[0] == '#' || strlen(line_buffer) == 0) - continue; - - char* value_str = strstr(line_buffer, ":"); - if(!value_str) - { - log_warning("Malformed value in config file %s, line %d", filename, current_line); - continue; - } - - value_str++; /* Ignore the colon(:) and set the pointer after it */ - - if(sscanf(line_buffer, " %1024[^: ] : %*s", key_str) != 1) - { - log_warning("Unable to read key in config file %s, line %d", filename, current_line); - continue; - } - - struct Variant* value = hashmap_value_get(cvars, key_str); - if(!value) - { - log_warning("Unknown value in config file %s, line %d", filename, current_line); - continue; - } - variant_from_str(value, value_str, value->type); + log_error("config_vars:load", "Failed to parse config file %s", filename); + } + else + { + log_message("Loaded config from %s", filename); + success = true; } - success = true; fclose(config_file); return success; } diff --git a/src/game/platform.c b/src/game/platform.c index 3cceced..d466afc 100644 --- a/src/game/platform.c +++ b/src/game/platform.c @@ -422,13 +422,13 @@ int platform_key_from_name(const char* key_name) #define max_name_len 30 char trimmed_key_name[max_name_len] = {'\0'}; - const char* start_ptr = &key_name[0]; - while(isspace(start_ptr[0])) start_ptr++; - - const char* end_ptr = &key_name[strlen(key_name)]; - while(isspace(end_ptr[0])) end_ptr--; - - strncpy(trimmed_key_name, start_ptr, (end_ptr - start_ptr)); + int start = 0; + while(isspace(key_name[start]) != 0) start++; + + int end = strlen(key_name); + while(isspace(key_name[end]) != 0) end--; + + strncpy(trimmed_key_name, &key_name[start], (end - start)); return SDL_GetKeyFromName(trimmed_key_name); } diff --git a/src/libsymmetry/input.c b/src/libsymmetry/input.c index ef7a992..2fcddc8 100644 --- a/src/libsymmetry/input.c +++ b/src/libsymmetry/input.c @@ -7,6 +7,7 @@ #include "gui.h" #include "../common/string_utils.h" #include "../common/common.h" +#include "../common/parser.h" struct Input_Map { @@ -20,7 +21,7 @@ static void input_on_mousebutton(int button, int state, int x, int y, int8 num_c static void input_on_mousemotion(int x, int y, int xrel, int yrel); static void input_on_mousewheel(int x, int y); static int map_find(const char* name); - +static void on_parser_assign(const char* key, const char* value, const char* filename, int current_line); static struct Input_Map* input_map_list = NULL; void input_init(void) @@ -90,117 +91,98 @@ void input_cleanup(void) input_map_list = NULL; } -bool input_keybinds_load(const char* filename, int directory_type) +void on_parser_assign(const char* key, const char* value, const char* filename, int current_line) { - bool success = false; - #define MAX_KEYBIND_LEN 128 - #define MAX_LINE_LEN 512 - FILE* config_file = platform->file.open(directory_type, filename, "r"); - if(!config_file) + char* value_copy = str_new(value); + //value_copy[strlen(value_copy) - 1] = '\0'; + char* val = strtok(value_copy, ","); + if(!val) { - log_error("input:keybinds_load", "Could not open %s", filename); - return success; + log_warning("Unable to parse keys for keybinding %s in file %s, line %d", key, filename, current_line); + free(value_copy); + return; } - /* Read line by line, ignore comments */ - char key_str[MAX_KEYBIND_LEN]; - char line_buffer[MAX_LINE_LEN]; - memset(key_str, '\0', MAX_KEYBIND_LEN); - memset(line_buffer, '\0', MAX_LINE_LEN); - int current_line = 0; - while(fgets(line_buffer, MAX_LINE_LEN - 1, config_file)) + while(val) { - current_line++; - line_buffer[strcspn(line_buffer, "\r\n")] = '\0'; - - if(line_buffer[0] == '#' || strlen(line_buffer) == 0) - continue; - - //log_message("Line : %s", line_buffer); - memset(key_str, '\0', MAX_KEYBIND_LEN); - char* value_str = strstr(line_buffer, ":"); - if(!value_str) +#define max_key_str_len 20 + /* Check if there are any Modifiers */ + int modifiers = KMD_NONE; + char* keys = strstr(val, "-"); + char* start_loc = val; + char key_name[max_key_str_len]; + int skip_to_next = 0; + while(keys) { - log_warning("Malformed value in config file %s, line %d", filename, current_line); - continue; + memset(key_name, '\0', max_key_str_len); + strncpy(key_name, start_loc, (keys - start_loc)); + log_message("key_name : %s", key_name); + + int key_modifier = platform->key_from_name(key_name); + + if(key_modifier == KEY_UNKNOWN) + { + log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); + skip_to_next = true; + break; + } + + switch(key_modifier) + { + case KEY_LSHIFT: case KEY_RSHIFT: modifiers |= KMD_SHIFT; break; + case KEY_LCTRL: case KEY_RCTRL: modifiers |= KMD_CTRL; break; + case KEY_LALT: case KEY_RALT: modifiers |= KMD_ALT; break; + }; + + ++keys; + start_loc = keys; + keys = strstr(keys, "-"); } - value_str++; /* Ignore the colon(:) and set the pointer after it */ - - if(sscanf(line_buffer, " %1024[^: ] : %*s", key_str) != 1) + if(skip_to_next) { - log_warning("Unable to read key in keybindings file %s, line %d", filename, current_line); + val = strtok(NULL, ","); continue; } - - char* val = strtok(value_str, ","); - if(!val) + + /* Copy the last key after the hyphen */ + strncpy(key_name, start_loc, max_key_str_len); + int key_code = platform->key_from_name(key_name); + if(key_code == KEY_UNKNOWN) { - log_warning("Unable to parse keys for keybinding %s in file %s, line %d", key_str, filename, current_line); + log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); + val = strtok(NULL, ","); continue; } - while(val) - { - //log_message("Key read : %s", val); - - #define max_key_str_len 20 - /* Check if there are any Modifiers */ - int modifiers = KMD_NONE; - char* keys = strstr(val, "-"); - char* start_loc = val; - char key_name[max_key_str_len]; - int skip_to_next = 0; - while(keys) - { - memset(key_name, '\0', max_key_str_len); - strncpy(key_name, start_loc, (keys - start_loc)); - //log_message("key_name : %s", key_name); - - int key_modifier = platform->key_from_name(key_name); - - if(key_modifier == KEY_UNKNOWN) - { - log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); - skip_to_next = 1; - break; - } - - switch(key_modifier) - { - case KEY_LSHIFT: case KEY_RSHIFT: modifiers |= KMD_SHIFT; break; - case KEY_LCTRL: case KEY_RCTRL: modifiers |= KMD_CTRL; break; - case KEY_LALT: case KEY_RALT: modifiers |= KMD_ALT; break; - }; - - ++keys; - start_loc = keys; - keys = strstr(keys, "-"); - } - if(skip_to_next) - { - val = strtok(NULL, ","); - continue; - } + struct Key_Combination key_comb = { .key = key_code, .mods = modifiers}; + input_map_create(key, &key_comb, 1); - /* Copy the last key after the hyphen */ - strncpy(key_name, start_loc, max_key_str_len); - int key = platform->key_from_name(key_name); - if(key == KEY_UNKNOWN) - { - log_warning("Unrecognized key %s in keybindings file %s, at line %d", key_name, filename, current_line); - val = strtok(NULL, ","); - continue; - } + val = strtok(NULL, ","); + } + free(value_copy); +} - struct Key_Combination key_comb = { .key = key, .mods = modifiers}; - input_map_create(key_str, &key_comb, 1); - - val = strtok(NULL, ","); - } +bool input_keybinds_load(const char* filename, int directory_type) +{ + bool success = false; + FILE* config_file = platform->file.open(directory_type, filename, "r"); + if(!config_file) + { + log_error("input:keybinds_load", "Could not open %s", filename); + return success; + } + + if(!parser_load(config_file, filename, &on_parser_assign, false, 0)) + { + log_error("input:keybinds_load", "Failed to parse file %s", filename); + } + else + { + log_message("Loaded keybindings from %s", filename); + success = true; } - success = true; fclose(config_file); return success; } @@ -231,7 +213,7 @@ bool input_keybinds_save(const char* filename) } fprintf(config_file, "\n"); } - + fprintf(config_file, "\n"); fclose(config_file); log_message("Keybindings saved to %s", filename); success = true;