Removed duplicate parsing logic by extracting code into reusable parser

dev
shariq 8 years ago
parent f7ae03fb9b
commit e5f5a9399d
  1. 3
      README.md
  2. 3
      src/common/common.h
  3. 66
      src/common/parser.c
  4. 12
      src/common/parser.h
  5. 57
      src/game/config_vars.c
  6. 14
      src/game/platform.c
  7. 170
      src/libsymmetry/input.c

@ -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

@ -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

@ -0,0 +1,66 @@
#include "parser.h"
#include "hashmap.h"
#include "log.h"
#include <string.h>
#include <ctype.h>
#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;
}

@ -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

@ -4,6 +4,7 @@
#include "../common/hashmap.h"
#include "file_io.h"
#include "../common/log.h"
#include "../common/parser.h"
#include "platform.h"
#include <stdlib.h>
@ -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;
}

@ -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);
}

@ -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;

Loading…
Cancel
Save