From 7271dd9f331b00533ccaab01f62c7693377bbdc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rn=20Lomax?= Date: Sat, 3 May 2014 15:59:23 +0200 Subject: [PATCH 1/3] cleaned new config functions. Removed memory leak --- src/config.c | 23 +++++++++++++---------- src/config.h | 1 + 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/config.c b/src/config.c index bab8fd2c67..ce3aff43cb 100644 --- a/src/config.c +++ b/src/config.c @@ -176,6 +176,8 @@ void config_init() } config_parse_settings(fp); + + fclose(fp); } } @@ -236,14 +238,12 @@ static void config_parse_settings(FILE *fp) int c = NULL, pos = 0; char *setting; char *value; - setting = (char *)malloc(128); - value = (char *)malloc(128); - - int size = 256; + setting = (char *)malloc(MAX_CONFIG_LENGTH); + value = (char *)malloc(MAX_CONFIG_LENGTH); while (config_get_line(fp, setting, value) > 0) { if (strcmp(setting, "game_path") == 0){ - strcpy(gConfig.game_path, value); // TODO: change to copy correct amount of bytes + strcpy(gConfig.game_path, value); } else if(strcmp(setting, "screenshot_format") == 0) { if (strcmp(value, "1") == 0) { gConfig.screenshot_format = 1; @@ -252,6 +252,8 @@ static void config_parse_settings(FILE *fp) } } } + free(setting); + free(value); } /** @@ -264,15 +266,14 @@ static void config_parse_settings(FILE *fp) static int config_get_line(FILE *fp, char *setting, char *value) { long start = ftell(fp); - long end; - int c; - int pos = 0; - long size; + long end, size; + int c, pos = 0; + c = fgetc(fp); if (c == EOF) return -1; while (isalpha(c) || c == '_'){ - c = fgetc(fp); // find size of setting + c = fgetc(fp); if (c == EOF) return -1; } @@ -293,6 +294,8 @@ static int config_get_line(FILE *fp, char *setting, char *value) return 1; } + + while (isalpha(c) || c == '_'){ setting[pos] = (char)c; pos++; diff --git a/src/config.h b/src/config.h index c5cfccf276..8b8ce8bcf1 100644 --- a/src/config.h +++ b/src/config.h @@ -74,6 +74,7 @@ void config_save(); // New config format +#define MAX_CONFIG_LENGTH 256 typedef struct configuration { uint8 screenshot_format; From dc26319694a2adac1805a16a0486efe13b591b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rn=20Lomax?= Date: Sun, 4 May 2014 12:14:18 +0200 Subject: [PATCH 2/3] intermidiate commit --- src/config.c | 39 +++++++++++++++++++++++++-------------- src/config.h | 5 ++++- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/config.c b/src/config.c index ce3aff43cb..030b7648b1 100644 --- a/src/config.c +++ b/src/config.c @@ -78,7 +78,7 @@ void config_reset_shortcut_keys() } /** - * + * Reads the config file data/config.cfg * rct2: 0x006752D5 */ void config_load() @@ -86,6 +86,7 @@ void config_load() HANDLE hFile; DWORD bytesRead; + char* path = get_file_path(PATH_ID_GAMECFG); hFile = CreateFile(get_file_path(PATH_ID_GAMECFG), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { @@ -98,14 +99,15 @@ void config_load() if (RCT2_GLOBAL(0x009AB4C6, sint8) == 1) return; RCT2_GLOBAL(0x009AB4C6, sint8) = 1; - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = 0; - RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FAHRENHEIT, sint8) = 1; - RCT2_GLOBAL(0x009AACBB, sint8) = 1; - RCT2_GLOBAL(0x009AACBD, sint16) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) = 0; + RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FAHRENHEIT, sint8) = 1; + RCT2_GLOBAL(0x009AACBB, sint8) = 1; + RCT2_GLOBAL(0x009AACBD, sint16) = 0; if (!(RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_FLAGS, uint8) & CONFIG_FLAG_SHOW_HEIGHT_AS_UNITS)) RCT2_GLOBAL(0x009AACBD, sint16) = (RCT2_GLOBAL(RCT2_ADDRESS_CONFIG_METRIC, sint8) + 1) * 256; RCT2_GLOBAL(0x009AA00D, sint8) = 1; } + } RCT2_GLOBAL(0x009AAC77, sint8) = 0; @@ -124,7 +126,7 @@ void config_load() } /** - * + * Save configuration to the data/config.cfg file * rct2: 0x00675487 */ void config_save() @@ -238,10 +240,16 @@ static void config_parse_settings(FILE *fp) int c = NULL, pos = 0; char *setting; char *value; + char *section; setting = (char *)malloc(MAX_CONFIG_LENGTH); value = (char *)malloc(MAX_CONFIG_LENGTH); while (config_get_line(fp, setting, value) > 0) { + if (strcmp(value, "\0")){ //if value is a null string, we assume new section + strcpy(section, setting); + continue; + } + if (strcmp(setting, "game_path") == 0){ strcpy(gConfig.game_path, value); } else if(strcmp(setting, "screenshot_format") == 0) { @@ -283,16 +291,19 @@ static int config_get_line(FILE *fp, char *setting, char *value) realloc(setting, size); fseek(fp, start, SEEK_SET); c = fgetc(fp); - if (c == '[') { - // TODO support categories - setting[0] = '\0'; - value[0] = '\0'; - while (c != '\n' && c != EOF) { - pos++; - c = fgetc(fp); + if (c == '[' ) { + + while (c != ']' && c != EOF){ + c = fgetc(fp); + setting[pos] = (char)c; + pos++; } - return 1; + realloc(value, 1); + value[0] = '\0'; + c = fgetc(fp); + + return } diff --git a/src/config.h b/src/config.h index 8b8ce8bcf1..b38c309316 100644 --- a/src/config.h +++ b/src/config.h @@ -76,11 +76,14 @@ void config_save(); // New config format #define MAX_CONFIG_LENGTH 256 -typedef struct configuration { +typedef struct general_configuration { uint8 screenshot_format; char game_path[MAX_PATH]; } configuration_t; +//typedef struct hotkey_configuration{ + +//}; extern configuration_t gConfig; void config_init(); From 4e13b24104f9d33f82714a426ead2328599f4f54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rn=20Lomax?= Date: Thu, 8 May 2014 11:05:07 +0200 Subject: [PATCH 3/3] Revamped the config system. Now enables sections and comments. Also enables some validation checking of the config file --- src/config.c | 209 +++++++++++++++++++++++++++++++++++++++------------ src/config.h | 5 ++ 2 files changed, 166 insertions(+), 48 deletions(-) diff --git a/src/config.c b/src/config.c index 1d43f108ff..332a05f3f0 100644 --- a/src/config.c +++ b/src/config.c @@ -148,7 +148,11 @@ configuration_t gConfig; static void config_parse_settings(FILE *fp); static int config_get_line(FILE *fp, char *setting, char *value); +static int config_parse_setting(FILE *fp, char *setting); +static int config_parse_value(FILE *fp, char *value); +static int config_parse_section(FILE *fp, char *setting, char *value); static void config_create_default(char *path); +static void config_error(char *msg); /** * Initilise the settings. @@ -165,7 +169,7 @@ void config_init() DWORD dwAttrib = GetFileAttributes(path); if (dwAttrib == INVALID_FILE_ATTRIBUTES || !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) { // folder does not exist if (!CreateDirectory(path, NULL)) { - return NULL; // error creating path + config_error("Could not create config file (do you have write acces to you documents folder?)"); } } strcat(path, "\\config.ini"); @@ -174,7 +178,7 @@ void config_init() config_create_default(path); fp = fopen(path, "r"); if (!fp) - return NULL; + config_error("Could not create config file"); } config_parse_settings(fp); @@ -228,6 +232,7 @@ static void config_create_default(char *path) fprintf(fp, "[general]\n"); fprintf(fp, "game_path = %s\n", gConfig.game_path); fprintf(fp, "screenshot_format = PNG\n"); + fprintf(fp, "temperature_format = C\n"); fclose(fp); } @@ -243,19 +248,22 @@ static void config_parse_settings(FILE *fp) char *section; setting = (char *)malloc(MAX_CONFIG_LENGTH); value = (char *)malloc(MAX_CONFIG_LENGTH); + section = (char*)malloc(MAX_CONFIG_LENGTH); while (config_get_line(fp, setting, value) > 0) { - if (strcmp(value, "\0")){ //if value is a null string, we assume new section - strcpy(section, setting); + if (strcmp(setting, "section") == 0){ + strcpy(section, value); continue; } - if (strcmp(setting, "game_path") == 0){ + + + if (strcmp(setting, "game_path") == 0){ strcpy(gConfig.game_path, value); } else if(strcmp(setting, "screenshot_format") == 0) { if (strcmp(value, "png") == 0 || strcmp(value, "PNG") == 0) { gConfig.screenshot_format = SCREENSHOT_FORMAT_PNG; - } else if (strcmp(value, "1") == 0) { // Maybe remove that? WARNING: Breaks existing config files + } else if (strcmp(value, "1") == 0) { //TODO: REMOVE LINE AT LATER DATE WHEN EVERYONE HAS NEW CONFIG FORMAT gConfig.screenshot_format = SCREENSHOT_FORMAT_PNG; } else { gConfig.screenshot_format = SCREENSHOT_FORMAT_BMP; @@ -264,82 +272,187 @@ static void config_parse_settings(FILE *fp) } free(setting); free(value); + free(section); } /** * Read one line in the settings file - * @param fp filepointer to the settings file + * @param fp filepointer to the config file * @param setting pointer where to to store the setting * @param value pointer to where to store the value - * @return < 0 on error + * @return < 0 if EOF file is reached or other error */ static int config_get_line(FILE *fp, char *setting, char *value) { - long start = ftell(fp); - long end, size; - int c, pos = 0; + int c; + + c = fgetc(fp); + while (isspace(c)){ + c = getc(fp); + } + + if (c == '['){ + return config_parse_section(fp, setting, value); + } + else if(c == '#'){ + while (c != '\n'){ + c = fgetc(fp); + } + return 1; + } + if (c == EOF){ + return -1; + } + + while (!isalpha(c)){ + c = fgetc(fp); + } + + //if the first char is not the '[' char, it belongs to the setting name. We want to leave that for the next fn + fseek(fp, -1, SEEK_CUR); + + config_parse_setting(fp, setting); c = fgetc(fp); - if (c == EOF) + while (isspace(c)){ + c = getc(fp); + } + + if (c != '='){ + config_error("There is an error in your configuration file"); return -1; + } + + config_parse_value(fp, value); + return 1; + + +} + +/** +* Parse the value of a setting +* @param fp a filepointer to the config file +* @param value a pointer to where to store the setting +* @return < 0 if EOF is reached +*/ +static int config_parse_setting(FILE *fp, char *setting){ + long start, end; + int size, c, pos = 0; + + + start = ftell(fp); + c = fgetc(fp); + + while (isspace(c)){ + start = ftell(fp); + c = fgetc(fp); + + } + if (c == EOF){ + return -1; + } + while (isalpha(c) || c == '_'){ c = fgetc(fp); - if (c == EOF) - return -1; } end = ftell(fp); size = end - start; - realloc(setting, size); + + fseek(fp, start, SEEK_SET); c = fgetc(fp); - if (c == '[' ) { - - while (c != ']' && c != EOF){ - c = fgetc(fp); - setting[pos] = (char)c; - pos++; - } - - realloc(value, 1); - value[0] = '\0'; - c = fgetc(fp); - - return - } - - while (isalpha(c) || c == '_'){ setting[pos] = (char)c; - pos++; c = fgetc(fp); + pos++; } setting[pos] = '\0'; - while (c != '=') { - if (c == EOF || c == '\n') { // this is not a valid setting - return -1; - } - c = fgetc(fp); - } - c = fgetc(fp); - while (isspace(c)) { - c = fgetc(fp); - } + return 1; +} + +/** + * Parse the value of a setting + * @param fp a filepointer to the config file + * @param value a pointer to where to store the value + * @return < 0 if EOF is reached + */ +static int config_parse_value(FILE *fp, char *value){ + long start, end; + int size, c, pos = 0; start = ftell(fp); - while (c != '\n' && c!= EOF) { + c = fgetc(fp); + while (isspace(c)){ + start = ftell(fp); + c = fgetc(fp); + + } + + while (c != EOF && c != '\n'){ + c = fgetc(fp); + } + end = ftell(fp); + size = end - start; + if (size > MAX_CONFIG_LENGTH){ + config_error("One of your settings is too long"); + } + fseek(fp, start, SEEK_SET); + c = fgetc(fp); + while (c != EOF && c != '\n'){ + + value[pos] = (char)c; + c = fgetc(fp); + pos++; + } + value[pos] = '\0'; + return; +} + +/** + * Parse the current section + * @param fp Filepointer to the config file + * @param setting This is set to contain the string "section" + * @param value Pointer to where the section name should be put + * @return < 0 if EOF is reached + */ +static int config_parse_section(FILE *fp, char *setting, char *value){ + int size, c, pos = 0; + long start, end; + + strcpy(setting, "section\0"); + c = fgetc(fp); + start = ftell(fp); + while (c != ']' && c != EOF){ c = fgetc(fp); } end = ftell(fp); size = end - start; - realloc(value, size); fseek(fp, start - 1, SEEK_SET); - pos = 0; c = fgetc(fp); - while (c != '\n' && c != EOF) { + while (c != ']' && c != EOF){ value[pos] = (char)c; - pos++; c = fgetc(fp); + pos++; } + value[pos] = '\0'; -} \ No newline at end of file + if (c != ']'){ + config_error("There is an error with the section headers"); + } + c = fgetc(fp); //devour ']' + + return 1; +} + + +/** + * Error with config file. Print error message an quit the game + * @param msg Message to print in message box + */ +static void config_error(char *msg){ + MessageBox(NULL, msg, "OpenRCT2", MB_OK); + //TODO:SHUT DOWN EVERYTHING! +} + + diff --git a/src/config.h b/src/config.h index d413bb85f6..398eca343f 100644 --- a/src/config.h +++ b/src/config.h @@ -71,6 +71,11 @@ enum { SCREENSHOT_FORMAT_PNG }; +enum { + TEMPERATURE_FORMAT_C, + TEMPERATURE_FORMAT_F +}; + extern uint16 gShortcutKeys[SHORTCUT_COUNT]; void config_reset_shortcut_keys();