From a2fd2983b22ab9234490d9cc2bfdb5d8e085aaf2 Mon Sep 17 00:00:00 2001 From: Agent X <44549182+Agent-11@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:54:24 -0400 Subject: [PATCH] Add crash preventions to DynOS_Tex_Get --- data/dynos.cpp.h | 6 +- data/dynos_bin_actor.cpp | 2 +- data/dynos_bin_behavior.cpp | 2 +- data/dynos_bin_col.cpp | 2 +- data/dynos_bin_lvl.cpp | 2 +- data/dynos_mgr_tex.cpp | 13 + src/pc/configini.c | 1224 ----------------------------------- src/pc/configini.h | 110 ---- 8 files changed, 20 insertions(+), 1341 deletions(-) delete mode 100644 src/pc/configini.c delete mode 100644 src/pc/configini.h diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index e30bcf2b..cd26a4b8 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -734,10 +734,10 @@ void Print(const char *aFmt, Args... aArgs) { } template -void PrintConsole(const char *aFmt, Args... aArgs) { +void PrintConsole(enum ConsoleMessageLevel level, const char *aFmt, Args... aArgs) { snprintf(gDjuiConsoleTmpBuffer, CONSOLE_MAX_TMP_BUFFER, aFmt, aArgs...); sys_swap_backslashes(gDjuiConsoleTmpBuffer); - djui_console_message_create(gDjuiConsoleTmpBuffer, CONSOLE_MESSAGE_INFO); + djui_console_message_create(gDjuiConsoleTmpBuffer, level); } template @@ -750,7 +750,7 @@ void PrintError(const char *aFmt, Args... aArgs) { #define PrintDataError(...) { \ if (aGfxData->mErrorCount == 0) Print(" ERROR!"); \ Print(__VA_ARGS__); \ - PrintConsole(__VA_ARGS__); \ + PrintConsole(CONSOLE_MESSAGE_ERROR, __VA_ARGS__); \ aGfxData->mErrorCount++; \ } diff --git a/data/dynos_bin_actor.cpp b/data/dynos_bin_actor.cpp index 01fc2862..149b1e98 100644 --- a/data/dynos_bin_actor.cpp +++ b/data/dynos_bin_actor.cpp @@ -188,7 +188,7 @@ static void DynOS_Actor_Generate(const SysPath &aPackFolder, ArraymModelIdentifier); - PrintConsole("%s.bin: Model identifier: %X - Processing... ", _GeoRootName.begin(), _GfxData->mModelIdentifier); + PrintConsole(CONSOLE_MESSAGE_INFO, "%s.bin: Model identifier: %X - Processing... ", _GeoRootName.begin(), _GfxData->mModelIdentifier); DynOS_Geo_Parse(_GfxData, _GeoNode, true); // Init animation data diff --git a/data/dynos_bin_behavior.cpp b/data/dynos_bin_behavior.cpp index 82886daa..6a5e756c 100644 --- a/data/dynos_bin_behavior.cpp +++ b/data/dynos_bin_behavior.cpp @@ -2626,7 +2626,7 @@ static void DynOS_Bhv_Generate(const SysPath &aPackFolder, ArraymModelIdentifier); - PrintConsole("%s.bhv: Model identifier: %X - Processing... ", _BhvRootName.begin(), _GfxData->mModelIdentifier); + PrintConsole(CONSOLE_MESSAGE_INFO, "%s.bhv: Model identifier: %X - Processing... ", _BhvRootName.begin(), _GfxData->mModelIdentifier); DynOS_Bhv_Parse(_GfxData, _BhvNode, true); // Write if no error diff --git a/data/dynos_bin_col.cpp b/data/dynos_bin_col.cpp index 3fe618c5..43222721 100644 --- a/data/dynos_bin_col.cpp +++ b/data/dynos_bin_col.cpp @@ -706,7 +706,7 @@ void DynOS_Col_Generate(const SysPath &aPackFolder, Array> _Ac // Parse data PrintNoNewLine("%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); - PrintConsole("%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); + PrintConsole(CONSOLE_MESSAGE_INFO, "%s.col: Model identifier: %X - Processing... ", _ColRootName.begin(), _GfxData->mModelIdentifier); DynOS_Col_Parse(_GfxData, _ColNode, true); // Write if no error diff --git a/data/dynos_bin_lvl.cpp b/data/dynos_bin_lvl.cpp index b13118e3..d55e4db9 100644 --- a/data/dynos_bin_lvl.cpp +++ b/data/dynos_bin_lvl.cpp @@ -1097,7 +1097,7 @@ static bool DynOS_Lvl_GeneratePack_Internal(const SysPath &aPackFolder, ArraymModelIdentifier); - PrintConsole("%s.lvl: Model identifier: %X - Processing... ", _LvlRootName.begin(), _GfxData->mModelIdentifier); + PrintConsole(CONSOLE_MESSAGE_INFO, "%s.lvl: Model identifier: %X - Processing... ", _LvlRootName.begin(), _GfxData->mModelIdentifier); DynOS_Lvl_Parse(_GfxData, _LvlRoot, true); // Force all of the movtexs, collisions, and trajectories into the compiled lvl diff --git a/data/dynos_mgr_tex.cpp b/data/dynos_mgr_tex.cpp index d36da4f3..fe645247 100644 --- a/data/dynos_mgr_tex.cpp +++ b/data/dynos_mgr_tex.cpp @@ -462,6 +462,19 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) { // load the texture if it hasn't been yet if (_Data->mRawData.begin() == NULL) { u8 *_RawData = stbi_load_from_memory(_Data->mPngData.begin(), _Data->mPngData.Count(), &_Data->mRawWidth, &_Data->mRawHeight, NULL, 4); + // texture data is corrupted + if (_RawData == NULL) { + PrintError("Attempted to load corrupted tex file: %s", aTexName); + PrintConsole(CONSOLE_MESSAGE_ERROR, "Attempted to load corrupted tex file: %s", aTexName); + return false; + } + // texture width or height is NPOT + if (!(_Data->mRawWidth > 0 && _Data->mRawWidth & (_Data->mRawWidth - 1) == 0) || + !(_Data->mRawHeight > 0 && _Data->mRawHeight & (_Data->mRawHeight - 1) == 0)) { + PrintError("Attempted to load tex file with non power of two width or height: %s", aTexName); + PrintConsole(CONSOLE_MESSAGE_ERROR, "Attempted to load tex file with non power of two width or height: %s", aTexName); + return false; + } _Data->mRawFormat = G_IM_FMT_RGBA; _Data->mRawSize = G_IM_SIZ_32b; _Data->mRawData = Array(_RawData, _RawData + (_Data->mRawWidth * _Data->mRawHeight * 4)); diff --git a/src/pc/configini.c b/src/pc/configini.c deleted file mode 100644 index 2d87830c..00000000 --- a/src/pc/configini.c +++ /dev/null @@ -1,1224 +0,0 @@ -/* - libconfigini - an ini formatted configuration parser library - Copyright (C) 2013-present Taner YILMAZ - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of copyright holders nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include - -#include "configini.h" -#include "queue.h" - - -#define COMMENT_CHARS "#" /* default comment chars */ -#define KEYVAL_SEP '=' /* default key-val seperator character */ -#define STR_TRUE "1" /* default string valu of true */ -#define STR_FALSE "0" /* default string valu of false */ - -#define CONFIG_INIT_MAGIC 0x12F0ED1 - -#define UNUSED __attribute__((unused)) - -/** - * \brief Configuration key-value - */ -typedef struct ConfigKeyValue -{ - char *key; - char *value; - TAILQ_ENTRY(ConfigKeyValue) next; -} ConfigKeyValue; - -/** - * \brief Configuration section - */ -typedef struct ConfigSection -{ - char *name; - int numofkv; - TAILQ_HEAD(, ConfigKeyValue) kv_list; - TAILQ_ENTRY(ConfigSection) next; -} ConfigSection; - -/** - * \brief Configuration handle - */ -struct Config -{ - char *comment_chars; - char keyval_sep; - char *true_str; - char *false_str; - int initnum; - int numofsect; - TAILQ_HEAD(, ConfigSection) sect_list; -}; - - - - -static int StrSafeCopy(char *dst, const char *src, int size) -{ - char *d = dst; - const char *s = src; - int n = size; - - if (n != 0 && --n != 0) { - do { - if ((*d++ = *s++) == 0) - break; - } while (--n != 0); - } - - if (n == 0) { - if (size != 0) - *d = '\0'; - while (*s++) - ; - } - - return (s - src - 1); -} - -static bool StrIsTypeOfTrue(const char *s) -{ - if ( !strcasecmp(s, "true") || !strcasecmp(s, "yes") || !strcasecmp(s, "1") ) - return true; - return false; -} - -static bool StrIsTypeOfFalse(const char *s) -{ - if ( !strcasecmp(s, "false") || !strcasecmp(s, "no") || !strcasecmp(s, "0") ) - return true; - return false; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -const char *ConfigRetToString(ConfigRet ret) -{ - switch(ret) { - case CONFIG_OK: return "OK"; - case CONFIG_ERR_FILE: return "File IO error"; - case CONFIG_ERR_NO_SECTION: return "No section"; - case CONFIG_ERR_NO_KEY: return "No key"; - case CONFIG_ERR_MEMALLOC: return "Memory allocation failed"; - case CONFIG_ERR_INVALID_PARAM: return "Invalid parameter"; - case CONFIG_ERR_INVALID_VALUE: return "Invalid value"; - case CONFIG_ERR_PARSING: return "Parse error"; - default: return NULL; - } -} - -/** - * \brief ConfigSetCommentCharset() sets comment characters - * - * \param cfg config handle - * \param comment_ch charaters to consider as comments - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigSetCommentCharset(Config *cfg, const char *comment_ch) -{ - char *p; - - if (!cfg || !comment_ch) - return CONFIG_ERR_INVALID_PARAM; - - if ((p = strdup(comment_ch)) == NULL) - return CONFIG_ERR_MEMALLOC; - - if (cfg->comment_chars) - free(cfg->comment_chars); - cfg->comment_chars = p; - - return CONFIG_OK; -} - -/** - * \brief ConfigSetCommentCharset() sets comment characters - * - * \param cfg config handle - * \param ch charater to consider as key-value seperator - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigSetKeyValSepChar(Config *cfg, char ch) -{ - if (!cfg) - return CONFIG_ERR_INVALID_PARAM; - - cfg->keyval_sep = ch; - - return CONFIG_OK; -} - -/** - * \brief ConfigSetCommentCharset() sets comment characters - * - * \param cfg config handle - * \param true_str string value of boolean true (must be one of these: "true", "yes", "1") - * \param false_str string value of boolean false (must be one of these: "false", "no", "0") - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigSetBoolString(Config *cfg, const char *true_str, const char *false_str) -{ - char *t, *f; - - if ( !cfg || - !true_str || !*true_str || !StrIsTypeOfTrue(true_str) || - !false_str || !*false_str || !StrIsTypeOfFalse(false_str) ) - return CONFIG_ERR_INVALID_PARAM; - - if ((t = strdup(true_str)) == NULL) - return CONFIG_ERR_MEMALLOC; - - if ((f = strdup(false_str)) == NULL) { - free(t); - return CONFIG_ERR_MEMALLOC; - } - - if (cfg->true_str) - free(cfg->true_str); - if (cfg->false_str) - free(cfg->false_str); - - cfg->true_str = t; - cfg->false_str = f; - - return CONFIG_OK; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -/** - * \brief ConfigGetSection() gets the requested section - * - * \param cfg config handle to search in - * \param section section name to search for - * \param sect pointer to ConfigSection* searched for to save - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -static ConfigRet ConfigGetSection(const Config *cfg, const char *section, ConfigSection **sect) -{ - if (!cfg || !sect) - return CONFIG_ERR_INVALID_PARAM; - - TAILQ_FOREACH(*sect, &cfg->sect_list, next) { - if ( (section && (*sect)->name && !strcmp((*sect)->name, section)) || - (!section && !(*sect)->name) ) { - return CONFIG_OK; - } - } - - return CONFIG_ERR_NO_SECTION; -} - -/** - * \brief Checks whether section exists - * - * \param cfg config handle to search in - * \param section section name to search for - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -bool ConfigHasSection(const Config *cfg, const char *section) -{ - ConfigSection *sect = NULL; - - return ( (ConfigGetSection(cfg, section, §) == CONFIG_OK) ? true : false ); -} - -/** - * \brief ConfigGetKeyValue() gets the ConfigKeyValue * - * - * \param cfg config handle - * \param sect section to search in - * \param key key to search for - * \param kv pointer to ConfigKeyValue* searched for to save - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -static ConfigRet ConfigGetKeyValue(UNUSED const Config *cfg, ConfigSection *sect, const char *key, - ConfigKeyValue **kv) -{ - if (!sect || !key || !kv) - return CONFIG_ERR_INVALID_PARAM; - - TAILQ_FOREACH(*kv, §->kv_list, next) { - if (!strcmp((*kv)->key, key)) - return CONFIG_OK; - } - - return CONFIG_ERR_NO_KEY; -} - -/** - * \brief ConfigGetSectionCount() gets number of sections - * - * \param cfg config handle to search in - * - * \return Returns number of sections on success, -1 on failure. - */ -int ConfigGetSectionCount(const Config *cfg) -{ - if (!cfg) - return -1; - - return (TAILQ_FIRST(&cfg->sect_list)->numofkv > 0 ? cfg->numofsect : cfg->numofsect - 1); -} - -/** - * \brief ConfigGetKeyCount() gets number of keys - * - * \param cfg config handle to search in - * \param section section name to search for - * - * \return Returns number of keys on success, -1 on failure. - */ -int ConfigGetKeyCount(const Config *cfg, const char *section) -{ - ConfigSection *sect = NULL; - - if (!cfg) - return -1; - - if (ConfigGetSection(cfg, section, §) != CONFIG_OK) - return -1; - - return sect->numofkv; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -/** - * \brief ConfigReadString() reads a string value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param size value buffer size - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadString(const Config *cfg, const char *section, const char *key, - char *value, int size, const char *dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg || !key || !value || (size < 1)) - return CONFIG_ERR_INVALID_PARAM; - - *value = '\0'; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - if (dfl_value) - StrSafeCopy(value, dfl_value, size); - return ret; - } - - StrSafeCopy(value, kv->value, size); - - return CONFIG_OK; -} - -/** - * \brief ConfigReadInt() reads an integer value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadInt(const Config *cfg, const char *section, const char *key, - int *value, int dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - char *p = NULL; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - *value = dfl_value; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - return ret; - } - - *value = (int) strtol(kv->value, &p, 10); - if (*p || (errno == ERANGE)) - return CONFIG_ERR_INVALID_VALUE; - - return CONFIG_OK; -} - -/** - * \brief ConfigReadUnsignedInt() reads an unsigned integer value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadUnsignedInt(const Config *cfg, const char *section, const char *key, - unsigned int *value, unsigned int dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - char *p = NULL; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - *value = dfl_value; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - return ret; - } - - *value = (unsigned int) strtoul(kv->value, &p, 10); - if (*p || (errno == ERANGE)) - return CONFIG_ERR_INVALID_VALUE; - - return CONFIG_OK; -} - -/** - * \brief ConfigReadFloat() reads a float value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadFloat(const Config *cfg, const char *section, const char *key, - float *value, float dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - char *p = NULL; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - *value = dfl_value; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - return ret; - } - - *value = strtof(kv->value, &p); - if (*p || (errno == ERANGE)) - return CONFIG_ERR_INVALID_VALUE; - - return CONFIG_OK; -} - -/** - * \brief ConfigReadDouble() reads a double value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadDouble(const Config *cfg, const char *section, const char *key, - double *value, double dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - char *p = NULL; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - *value = dfl_value; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - return ret; - } - - *value = strtod(kv->value, &p); - if (*p || (errno == ERANGE)) - return CONFIG_ERR_INVALID_VALUE; - - return CONFIG_OK; -} - -/** - * \brief ConfigReadBool() reads a boolean value from the cfg. - * If any error occurs default value is copied to 'value' buffer and - * returns reason. If key is optional and does not exists in config, - * the 'value' is default value and return is CONFIG_ERR_NO_KEY - * - * \param cfg config handle - * \param section section to search in - * \param key key to search for - * \param value value to save in - * \param dfl_value default value to copy back if any error occurs - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadBool(const Config *cfg, const char *section, const char *key, - bool *value, bool dfl_value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - *value = dfl_value; - - if ( ((ret = ConfigGetSection(cfg, section, §)) != CONFIG_OK) || - ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) != CONFIG_OK) ) { - return ret; - } - - if (StrIsTypeOfTrue(kv->value)) - *value = true; - else if (StrIsTypeOfFalse(kv->value)) - *value = false; - else - return CONFIG_ERR_INVALID_VALUE; - - return CONFIG_OK; -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -/** - * \brief ConfigAddSection() creates a section in the cfg - * - * \param cfg config handle - * \param section section to add - * \param sect pointer to added ConfigSection* or NULL if not needed - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -static ConfigRet ConfigAddSection(Config *cfg, const char *section, ConfigSection **sect) -{ - ConfigSection *_sect = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg) - return CONFIG_ERR_INVALID_PARAM; - - if (!sect) - sect = &_sect; - - if ((ret = ConfigGetSection(cfg, section, sect)) != CONFIG_ERR_NO_SECTION) - return ret; - - *sect = calloc(1, sizeof(ConfigSection)); - if (*sect == NULL) - return CONFIG_ERR_MEMALLOC; - - if (section) { - if (((*sect)->name = strdup(section)) == NULL) { - free(*sect); - return CONFIG_ERR_MEMALLOC; - } - } - - TAILQ_INIT(&(*sect)->kv_list); - TAILQ_INSERT_TAIL(&cfg->sect_list, *sect, next); - ++(cfg->numofsect); - - return CONFIG_OK; -} - -/** - * \brief ConfigAddString() adds the key with string value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddString(Config *cfg, const char *section, const char *key, const char *value) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - const char *p = NULL; - const char *q = NULL; - - if (!cfg || !key || !value) - return CONFIG_ERR_INVALID_PARAM; - - if ((ret = ConfigAddSection(cfg, section, §)) != CONFIG_OK) - return ret; - - switch (ret = ConfigGetKeyValue(cfg, sect, key, &kv)) { - case CONFIG_OK: - if (kv->value) { - free(kv->value); - kv->value = NULL; - } - break; - - case CONFIG_ERR_NO_KEY: - if ((kv = calloc(1, sizeof(ConfigKeyValue))) == NULL) - return CONFIG_ERR_MEMALLOC; - if ((kv->key = strdup(key)) == NULL) { - free(kv); - return CONFIG_ERR_MEMALLOC; - } - TAILQ_INSERT_TAIL(§->kv_list, kv, next); - ++(sect->numofkv); - break; - - default: - return ret; - } - - for (p = value; *p && isspace(*p); ++p) - ; - for (q = p; *q && (*q != '\r') && (*q != '\n') && !strchr(cfg->comment_chars, *q); ++q) - ; - while (*q && (q > p) && isspace(*(q - 1))) - --q; - - kv->value = (char *) malloc(q - p + 1); - if (kv->value == NULL) { - TAILQ_REMOVE(§->kv_list, kv, next); - --(sect->numofkv); - free(kv->key); - free(kv); - return CONFIG_ERR_MEMALLOC; - } - memcpy(kv->value, p, q - p); - kv->value[q - p] = '\0'; - - return CONFIG_OK; -} - -/** - * \brief ConfigAddInt() adds the key with integer value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddInt(Config *cfg, const char *section, const char *key, int value) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "%d", value); - - return ConfigAddString(cfg, section, key, buf); -} - -/** - * \brief ConfigAddUnsignedInt() adds the key with unsigned integer value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddUnsignedInt(Config *cfg, const char *section, const char *key, unsigned int value) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "%u", value); - - return ConfigAddString(cfg, section, key, buf); -} - -/** - * \brief ConfigAddFloat() adds the key with float value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddFloat(Config * cfg, const char *section, const char *key, float value) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "%f", value); - - return ConfigAddString(cfg, section, key, buf); -} - -/** - * \brief ConfigAddDouble() adds the key with double value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddDouble(Config *cfg, const char *section, const char *key, double value) -{ - char buf[64]; - - snprintf(buf, sizeof(buf), "%f", value); - - return ConfigAddString(cfg, section, key, buf); -} - -/** - * \brief ConfigAddBool() adds the key with blooean value to the cfg - * - * \param cfg config handle - * \param section section to add in - * \param key key to save as - * \param value value to save as - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigAddBool(Config * cfg, const char *section, const char *key, bool value) -{ - return ConfigAddString(cfg, section, key, value ? cfg->true_str : cfg->false_str); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -static void _ConfigRemoveKey(ConfigSection *sect, ConfigKeyValue *kv) -{ - TAILQ_REMOVE(§->kv_list, kv, next); - --(sect->numofkv); - - if (kv->key) - free(kv->key); - if (kv->value) - free(kv->value); - free(kv); -} - -/** - * \brief ConfigRemoveKey() removes the key which exists under section from the cfg - * - * \param cfg config handle - * \param section section to seach in - * \param key key to remove - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigRemoveKey(Config *cfg, const char *section, const char *key) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg || !key) - return CONFIG_ERR_INVALID_PARAM; - - if ((ret = ConfigGetSection(cfg, section, §)) == CONFIG_OK) { - if ((ret = ConfigGetKeyValue(cfg, sect, key, &kv)) == CONFIG_OK) - _ConfigRemoveKey(sect, kv); - } - - return ret; -} - -static void _ConfigRemoveSection(Config *cfg, ConfigSection *sect) -{ - ConfigKeyValue *kv, *t_kv; - - if (!cfg || !sect) - return; - - TAILQ_REMOVE(&cfg->sect_list, sect, next); - --(cfg->numofsect); - - TAILQ_FOREACH_SAFE(kv, §->kv_list, next, t_kv) { - _ConfigRemoveKey(sect, kv); - } - - if (sect->name) - free(sect->name); - free(sect); -} - -/** - * \brief ConfigRemoveSection() removes section from the cfgfile - * - * \param cfg config handle - * \param section section to remove - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigRemoveSection(Config *cfg, const char *section) -{ - ConfigSection *sect = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg) - return CONFIG_ERR_INVALID_PARAM; - - if ((ret = ConfigGetSection(cfg, section, §)) == CONFIG_OK) - _ConfigRemoveSection(cfg, sect); - - return ret; -} - -/** - * \brief ConfigNew() creates a cfg handle with - * default section which has no section name - * - * \return Config* handle on success, NULL on failure - */ -Config *ConfigNew() -{ - Config *cfg = NULL; - - cfg = calloc(1, sizeof(Config)); - if (cfg == NULL) - return NULL; - - TAILQ_INIT(&cfg->sect_list); - - /* add default section */ - if (ConfigAddSection(cfg, CONFIG_SECTION_FLAT, NULL) != CONFIG_OK) { - free(cfg); - return NULL; - } - - cfg->comment_chars = strdup(COMMENT_CHARS); - cfg->keyval_sep = KEYVAL_SEP; - cfg->true_str = strdup(STR_TRUE); - cfg->false_str = strdup(STR_FALSE); - cfg->initnum = CONFIG_INIT_MAGIC; - - return cfg; -} - -/** - * \brief ConfigFree() frees the memory for the cfg handle - * - * \param cfg config handle - */ -void ConfigFree(Config *cfg) -{ - ConfigSection *sect, *t_sect; - - if (cfg == NULL) - return; - - TAILQ_FOREACH_SAFE(sect, &cfg->sect_list, next, t_sect) { - _ConfigRemoveSection(cfg, sect); - } - - if (cfg->comment_chars) free(cfg->comment_chars); - if (cfg->true_str) free(cfg->true_str); - if (cfg->false_str) free(cfg->false_str); - - free(cfg); -} - - -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// -/////////////////////////////////////////////////////////////////////////////////////////////////// - - -/** - * \brief Gets section name on the buffer p - * - * \param cfg config handle - * \param p read buffer - * \param section pointer address to section - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -static ConfigRet GetSectName(Config *cfg, char *p, char **section) -{ - char *q, *r; - - if (!cfg || !p || !*p || !section) - return CONFIG_ERR_INVALID_PARAM; - - *section = NULL; - - /* get section name */ - while (*p && isspace(*p)) - ++p; - - if (*p != '[') - return CONFIG_ERR_PARSING; - - ++p; - while (*p && isspace(*p)) - ++p; - - for (q = p; - *q && (*q != '\r') && (*q != '\n') && (*q != ']') && !strchr(cfg->comment_chars, *q); - ++q) - ; - - if (*q != ']') - return CONFIG_ERR_PARSING; - - r = q + 1; - - while (*q && (q > p) && isspace(*(q - 1))) - --q; - - if (q == p) /* section has no name */ - return CONFIG_ERR_PARSING; - - *q = '\0'; - *section = p; - - /* check rest of section */ - while (*r && isspace(*r)) - ++r; - - /* there are unrecognized trailing data */ - if (*r && !strchr(cfg->comment_chars, *r)) - return CONFIG_ERR_PARSING; - - return CONFIG_OK; -} - -/** - * \brief Gets key and value on the buffer p - * - * \param cfg config handle - * \param p read buffer - * \param key pointer address to key - * \param val pointer address to value - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -static ConfigRet GetKeyVal(Config *cfg, char *p, char **key, char **val) -{ - char *q, *v; - - if (!cfg || !p || !*p || !key || !val) - return CONFIG_ERR_INVALID_PARAM; - - *key = *val = NULL; - - /* get key */ - while (*p && isspace(*p)) - ++p; - - for (q = p; - *q && (*q != '\r') && (*q != '\n') && (*q != cfg->keyval_sep) && !strchr(cfg->comment_chars, *q); - ++q) - ; - - if (*q != cfg->keyval_sep) - return CONFIG_ERR_PARSING; - - v = q + 1; - - while (*q && (q > p) && isspace(*(q - 1))) - --q; - - if (q == p) /* no key name */ - return CONFIG_ERR_PARSING; - - *q = '\0'; - *key = p; - - /* get value */ - while (*v && isspace(*v)) - ++v; - - for (q = v; - *q && (*q != '\r') && (*q != '\n') && !strchr(cfg->comment_chars, *q); - ++q) - ; - - while (*q && (q > v) && isspace(*(q - 1))) - --q; - - if (q == v) /* no value */ - return CONFIG_ERR_INVALID_VALUE; - - *q = '\0'; - *val = v; - - return CONFIG_OK; -} - -/** - * \brief ConfigRead() reads the stream and populates the entire content to cfg handle - * - * \param fp FILE handle to read - * \param cfg pointer to config handle. - * If not NULL a handle created with ConfigNew() must be given. - * If cfg is NULL a new one is created and saved to cfg. - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigRead(FILE *fp, Config **cfg) -{ - ConfigSection *sect = NULL; - char *p = NULL; - char *section = NULL; - char *key = NULL; - char *val = NULL; - char buf[4096]; - Config *_cfg = NULL; - bool newcfg = false; - ConfigRet ret = CONFIG_OK; - - if ( !fp || !cfg || (*cfg && ((*cfg)->initnum != CONFIG_INIT_MAGIC)) ) - return CONFIG_ERR_INVALID_PARAM; - - if (*cfg == NULL) { - _cfg = ConfigNew(); - if (_cfg == NULL) - return CONFIG_ERR_MEMALLOC; - *cfg = _cfg; - newcfg = true; - } - else - _cfg = *cfg; - - while (!feof(fp)) { - if (fgets(buf, sizeof(buf), fp) == NULL) - continue; - - for (p = buf; *p && isspace(*p) ; ++p) - ; - if (!*p || strchr(_cfg->comment_chars, *p)) - continue; - - if (*p == '[') { - if ((ret = GetSectName(_cfg, p, §ion)) != CONFIG_OK) - goto error; - - if ((ret = ConfigAddSection(_cfg, section, §)) != CONFIG_OK) - goto error; - } - else { - if ((ret = GetKeyVal(_cfg, p, &key, &val)) != CONFIG_OK) - goto error; - if (!sect) - goto error; - if ((ret = ConfigAddString(_cfg, sect->name, key, val)) != CONFIG_OK) - goto error; - } - } - - return CONFIG_OK; - -error: - if (newcfg) { - ConfigFree(_cfg); - *cfg = NULL; - } - - return ret; -} - -/** - * \brief ConfigReadFile() opens and reads the file and populates the - * entire content to cfg handle - * - * \param filename name of file to open and load - * \param cfg pointer to config handle. - * If not NULL a handle created with ConfigNew() must be given. - * If cfg is NULL a new one is created and saved to cfg. - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigReadFile(const char *filename, Config **cfg) -{ - FILE *fp = NULL; - ConfigRet ret = CONFIG_OK; - - if ( !filename || !cfg || (*cfg && ((*cfg)->initnum != CONFIG_INIT_MAGIC)) ) - return CONFIG_ERR_INVALID_PARAM; - - if ((fp = fopen(filename, "r")) == NULL) - return CONFIG_ERR_FILE; - - ret = ConfigRead(fp, cfg); - - fclose(fp); - - return ret; -} - -/** - * \brief ConfigPrint() prints all cfg content to the stream - * - * \param cfg config handle - * \param stream stream to print - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigPrint(const Config *cfg, FILE *stream) -{ - ConfigSection *sect = NULL; - ConfigKeyValue *kv = NULL; - - if (!cfg || !stream) - return CONFIG_ERR_INVALID_PARAM; - - TAILQ_FOREACH(sect, &cfg->sect_list, next) { - if (sect->name) - fprintf(stream, "[%s]\n", sect->name); - - TAILQ_FOREACH(kv, §->kv_list, next) - fprintf(stream, "%s=%s\n", kv->key, kv->value); - - fprintf(stream, "\n"); - } - - return CONFIG_OK; -} - -/** - * \brief ConfigPrintToFile() prints (saves) all cfg content to the file - * - * \param cfg config handle - * \param filename filename to save in - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigPrintToFile(const Config *cfg, char *filename) -{ - FILE *fp = NULL; - ConfigRet ret = CONFIG_OK; - - if (!cfg || !filename) - return CONFIG_ERR_INVALID_PARAM; - - if ((fp = fopen(filename, "wb")) == NULL) - return CONFIG_ERR_FILE; - - ret = ConfigPrint(cfg, fp); - - fclose(fp); - - return ret; -} - -/** - * \brief ConfigPrintSettings() prints settings to the stream - * - * \param cfg config handle - * \param stream stream to print - * - * \return Returns CONFIG_RET_OK as success, otherwise is an error. - */ -ConfigRet ConfigPrintSettings(const Config *cfg, FILE *stream) -{ - if (!cfg || !stream) - return CONFIG_ERR_INVALID_PARAM; - - fprintf(stream, "\n"); - fprintf(stream, "Configuration settings: \n"); - fprintf(stream, " Comment characters : %s\n", cfg->comment_chars); - fprintf(stream, " Key-Value seperator: %c\n", cfg->keyval_sep); - fprintf(stream, " True-False strings : %s-%s\n", cfg->true_str, cfg->false_str); - fprintf(stream, "\n"); - - return CONFIG_OK; -} - diff --git a/src/pc/configini.h b/src/pc/configini.h deleted file mode 100644 index e46aa455..00000000 --- a/src/pc/configini.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - libconfigini - an ini formatted configuration parser library - Copyright (C) 2013-present Taner YILMAZ - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of copyright holders nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS OR CONTRIBUTORS - BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef CONFIGINI_H_ -#define CONFIGINI_H_ - -#include -#include - - -typedef struct Config Config; - - -#define CONFIG_SECTION_FLAT NULL /* config is flat data (has no section) */ - - -/** - * \brief Return types - */ -typedef enum -{ - CONFIG_OK, /* ok (no error) */ - CONFIG_ERR_FILE, /* file io error (file not exists, cannot open file, ...) */ - CONFIG_ERR_NO_SECTION, /* section does not exist */ - CONFIG_ERR_NO_KEY, /* key does not exist */ - CONFIG_ERR_MEMALLOC, /* memory allocation failed */ - CONFIG_ERR_INVALID_PARAM, /* invalid parametrs (as NULL) */ - CONFIG_ERR_INVALID_VALUE, /* value of key is invalid (inconsistent data, empty data) */ - CONFIG_ERR_PARSING, /* parsing error of data (does not fit to config format) */ -} ConfigRet; - - - -#ifdef __cplusplus -extern "C" { -#endif - - - -Config* ConfigNew (void); -void ConfigFree (Config *cfg); - -const char *ConfigRetToString (ConfigRet ret); - -ConfigRet ConfigRead (FILE *fp, Config **cfg); -ConfigRet ConfigReadFile (const char *filename, Config **cfg); - -ConfigRet ConfigPrint (const Config *cfg, FILE *stream); -ConfigRet ConfigPrintToFile (const Config *cfg, char *filename); -ConfigRet ConfigPrintSettings (const Config *cfg, FILE *stream); - -int ConfigGetSectionCount (const Config *cfg); -int ConfigGetKeyCount (const Config *cfg, const char *sect); - -ConfigRet ConfigSetCommentCharset(Config *cfg, const char *comment_ch); -ConfigRet ConfigSetKeyValSepChar (Config *cfg, char ch); -ConfigRet ConfigSetBoolString (Config *cfg, const char *true_str, const char *false_str); - -ConfigRet ConfigReadString (const Config *cfg, const char *sect, const char *key, char * val, int size, const char * dfl_val); -ConfigRet ConfigReadInt (const Config *cfg, const char *sect, const char *key, int * val, int dfl_val); -ConfigRet ConfigReadUnsignedInt (const Config *cfg, const char *sect, const char *key, unsigned int *val, unsigned int dfl_val); -ConfigRet ConfigReadFloat (const Config *cfg, const char *sect, const char *key, float * val, float dfl_val); -ConfigRet ConfigReadDouble (const Config *cfg, const char *sect, const char *key, double * val, double dfl_val); -ConfigRet ConfigReadBool (const Config *cfg, const char *sect, const char *key, bool * val, bool dfl_val); - -ConfigRet ConfigAddString (Config *cfg, const char *sect, const char *key, const char *val); -ConfigRet ConfigAddInt (Config *cfg, const char *sect, const char *key, int val); -ConfigRet ConfigAddUnsignedInt (Config *cfg, const char *sect, const char *key, unsigned int val); -ConfigRet ConfigAddFloat (Config *cfg, const char *sect, const char *key, float val); -ConfigRet ConfigAddDouble (Config *cfg, const char *sect, const char *key, double val); -ConfigRet ConfigAddBool (Config *cfg, const char *sect, const char *key, bool val); - -bool ConfigHasSection (const Config *cfg, const char *sect); - -ConfigRet ConfigRemoveSection (Config *cfg, const char *sect); -ConfigRet ConfigRemoveKey (Config *cfg, const char *sect, const char *key); - - -#ifdef __cplusplus -} -#endif - - -#endif /* CONFIGINI_H_ */