--- libaitcfg/src/parse.c 2009/09/09 09:07:31 1.2 +++ libaitcfg/src/parse.c 2011/05/01 17:24:28 1.6 @@ -3,12 +3,48 @@ * by Michael Pounov * * $Author: misho $ -* $Id: parse.c,v 1.2 2009/09/09 09:07:31 misho Exp $ +* $Id: parse.c,v 1.6 2011/05/01 17:24:28 misho Exp $ * -*************************************************************************/ +************************************************************************** +The ELWIX and AITNET software is distributed under the following +terms: + +All of the documentation and software included in the ELWIX and AITNET +Releases is copyrighted by ELWIX - Sofia/Bulgaria + +Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + by Michael Pounov . All rights reserved. + +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. All advertising materials mentioning features or use of this software + must display the following acknowledgement: +This product includes software developed by Michael Pounov +ELWIX - Embedded LightWeight unIX and its contributors. +4. Neither the name of AITNET 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 AITNET 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 THE REGENTS 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 "global.h" #include "aitcfg.h" -#include "tools.h" // cfgDbg() Debug/Log operation @@ -24,8 +60,84 @@ static inline int cfgDbg(FILE *f, char *fmt, ...) return ret; } -// ----------------------------------------- +/* + * InvertQueue() InvertQueue order //{cfg} list of elements for revert + * @cfg = Head list element for revert +*/ +static inline void InvertQueue(sl_config * __restrict cfg) +{ + struct tagPair *item, *next, *prev = NULL; + for (item = cfg->slh_first; item; item = next) { + next = item->sle_next; + item->sle_next = prev; + prev = item; + } + cfg->slh_first = prev; +} + +// cfgWrite() Write to file from config list +static inline int cfgWrite(FILE *f, sl_config * __restrict cfg, int whitespace) +{ + struct tagPair *av; + time_t tim; + char szTime[MAX_STR + 1]; + u_char szSection[MAX_STR + 1]; + + bzero(szSection, MAX_STR + 1); + + bzero(szTime, MAX_STR + 1); + time(&tim); + strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim)); + if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) { + LOGERR; + return -1; + } + + InvertQueue(cfg); + for (av = cfg->slh_first; av; av = av->sle_next) { + if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) { + strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1); + if (!cfgDbg(f, "\n[%s]\n", av->psSection)) { + LOGERR; + return -1; + } + } + if (!av->psSection && *szSection) { + bzero(szSection, MAX_STR + 1); + if (!cfgDbg(f, "\n[]\n")) { + LOGERR; + return -1; + } + } + + if (whitespace) { + if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) { + LOGERR; + return -1; + } + } else { + if (!cfgDbg(f, "%s=%s\n", av->psAttribute, av->psValue)) { + LOGERR; + return -1; + } + } + } + InvertQueue(cfg); + + bzero(szTime, MAX_STR + 1); + time(&tim); + strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim)); + if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) { + LOGERR; + return -1; + } + + return 0; +} + +// --------------------------------------------------- + /* * ReadConfig() Read from file and add new item to config list * @f = file resource @@ -43,7 +155,7 @@ int ReadConfig(FILE *f, sl_config * __restrict cfg) while (!feof(f)) { memset(szLine, 0, MAX_STR + 1); fgets((char*) szLine, MAX_STR, f); - trim(szLine); + io_TrimStr(szLine); #ifdef __DEBUG cfgDbg(stdout, "DEBUG:: RAW |%s|\n", szLine); #endif @@ -109,8 +221,9 @@ int ReadConfig(FILE *f, sl_config * __restrict cfg) psAttr = szLine; psVal = (szLine + pos + 1); szLine[pos] = 0; - rtrim(psAttr); - ltrim(psVal); + io_RTrimStr(psAttr); + io_LTrimStr(psVal); + io_UnquotStr(psVal); #ifdef __DEBUG cfgDbg(stdout, "DEBUG:: Attr(%p) ->%s size=%d Value(%p) ->%s size=%d\n", psAttr, psAttr, strlen((char*) psAttr), psVal, psVal, strlen((char*) psVal)); @@ -148,50 +261,89 @@ int ReadConfig(FILE *f, sl_config * __restrict cfg) */ int WriteConfig(FILE *f, sl_config * __restrict cfg) { - struct tagPair *av; - time_t tim; - char szTime[MAX_STR + 1]; - u_char szSection[MAX_STR + 1]; + return cfgWrite(f, cfg, 1); +} - bzero(szSection, MAX_STR + 1); +/* + * cfg_WriteConfig() Write to file from items in config list without whitespaces! + * @f = file resource + * @cfg = Head list element + * return: 0 ok; -1 error:: can`t write to file +*/ +int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg) +{ + return cfgWrite(f, cfg, 0); +} - bzero(szTime, MAX_STR + 1); - time(&tim); - strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim)); - if (!cfgDbg(f, "## Write Config :: %s\n#\n", szTime)) { - LOGERR; +/* + * ConcatConfig() Concat two list in one + * @cfg = Head list element of main list + * @add_cfg = Head list element of added list + * return: 0 ok; -1 error:: can`t concat lists +*/ +int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg) +{ + struct tagPair *item; + int ret = 0; + + if (!cfg || !add_cfg) return -1; - } - for (av = cfg->slh_first; av; av = av->sle_next) { - if (av->psSection && strcmp((char*) av->psSection, (char*) szSection)) { - strlcpy((char*) szSection, (char*) av->psSection, MAX_STR + 1); - if (!cfgDbg(f, "\n[%s]\n", av->psSection)) { - LOGERR; - return -1; + for (item = cfg->slh_first; item->sle_next; item = item->sle_next); + item->sle_next = add_cfg->slh_first; + + add_cfg->slh_first = NULL; + + return ret; +} + +/* + * MergeConfig() Marge two list in one cfg and destroy add_cfg + * @cfg = Head list element of main list + * @add_cfg = Head list element of merged list (destroy after all!) + * return: 0 ok; -1 error:: can`t merge lists +*/ +int MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg) +{ + struct tagPair *item, *merge, *add_next, *next = NULL; + int flg; + + if (!cfg || !add_cfg) + return -1; + + item = add_cfg->slh_first; + while (item) { + add_next = item->sle_next; + + for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next; + merge = merge->sle_next, next = merge->sle_next) { + if (!merge->psSection && !item->psSection) { + flg = 1; + merge->sle_next = item; + item->sle_next = next; + break; } - } - if (!av->psSection && *szSection) { - bzero(szSection, MAX_STR + 1); - if (!cfgDbg(f, "\n[]\n")) { - LOGERR; - return -1; + if (merge->psSection && item->psSection && + !strcmp((char*) merge->psSection, (char*) item->psSection)) { + flg = 1; + merge->sle_next = item; + item->sle_next = next; + break; } } - if (!cfgDbg(f, "%s = %s\n", av->psAttribute, av->psValue)) { - LOGERR; - return -1; + if (!flg) { + if (!merge->sle_next) { + merge->sle_next = item; + item->sle_next = NULL; + } else + return -1; } - } - bzero(szTime, MAX_STR + 1); - time(&tim); - strftime(szTime, MAX_STR, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim)); - if (!cfgDbg(f, "\n#\n## Done. :: %s\n", szTime)) { - LOGERR; - return -1; + item = add_next; } + + add_cfg->slh_first = NULL; return 0; }