Diff for /libaitcfg/src/parse.c between versions 1.6.4.2 and 1.18.4.1

version 1.6.4.2, 2012/04/03 09:21:06 version 1.18.4.1, 2021/11/25 23:44:52
Line 12  terms: Line 12  terms:
 All of the documentation and software included in the ELWIX and AITNET  All of the documentation and software included in the ELWIX and AITNET
 Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>  Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
   
Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012Copyright 2004 - 2021
         by Michael Pounov <misho@elwix.org>.  All rights reserved.          by Michael Pounov <misho@elwix.org>.  All rights reserved.
   
 Redistribution and use in source and binary forms, with or without  Redistribution and use in source and binary forms, with or without
Line 44  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF TH Line 44  OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF TH
 SUCH DAMAGE.  SUCH DAMAGE.
 */  */
 #include "global.h"  #include "global.h"
 #include "aitcfg.h"  
   
   
 static inline int  
 cfg_Write(FILE *f, char *fmt, ...)  
 {  
         int ret = 0;  
         va_list lst;  
   
         va_start(lst, fmt);  
         ret = vfprintf(f, fmt, lst);  
         va_end(lst);  
   
         return ret;  
 }  
   
 static inline void  
 _invertQueue(cfg_root_t * __restrict cfg)  
 {  
         struct tagCfg *item, *next, *prev = NULL;  
   
         SLIST_FOREACH_SAFE(item, cfg, cfg_next, next) {  
                 item->cfg_next.sle_next = prev;  
                 prev = item;  
         }  
         cfg->slh_first = prev;  
 }  
   
   
 /*  /*
  * cfgReadConfig() - Read file and add new item at config root   * cfgReadConfig() - Read file and add new item at config root
  *   *
Line 80  _invertQueue(cfg_root_t * __restrict cfg) Line 53  _invertQueue(cfg_root_t * __restrict cfg)
  * @cfg = Config root   * @cfg = Config root
  * return: -1 error or 0 ok   * return: -1 error or 0 ok
  */   */
int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg)int
 cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg)
 {  {
        char line[BUFSIZ];        char line[BUFSIZ], origin[BUFSIZ];
         struct tagCfg *av = NULL;          struct tagCfg *av = NULL;
         int flg = 0;          int flg = 0;
         char *psAttr, *psVal, szSection[STRSIZ] = { 0 };          char *psAttr, *psVal, szSection[STRSIZ] = { 0 };
           FILE *ff;
   
           if (!f || !cfg) {
                   cfg_SetErr(EINVAL, "Invalid parameter(s)");
                   return -1;
           }
   
         while (!feof(f)) {          while (!feof(f)) {
                 memset(line, 0, sizeof line);                  memset(line, 0, sizeof line);
                 fgets(line, sizeof line - 1, f);                  fgets(line, sizeof line - 1, f);
Line 100  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 80  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
                         continue;                          continue;
                 } else {                  } else {
                         *psAttr = 0;                          *psAttr = 0;
                        io_TrimStr(line);                        strlcpy(origin, line, sizeof origin);
                         str_Trim(line);
                 }                  }
   
                 if (flg) {                  if (flg) {
Line 115  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 96  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
                                 flg = 0;                                  flg = 0;
                         /* concat line to value */                          /* concat line to value */
                         AIT_SET_STRCAT(&av->cfg_val, line);                          AIT_SET_STRCAT(&av->cfg_val, line);
                        if (!flg)                        if (!flg && AIT_ADDR(&av->cfg_val))
                                io_UnquotStr((char*) AIT_GET_STR(&av->cfg_val));                                str_Unquot((char*) AIT_GET_STR(&av->cfg_val));
 
                         /* read include file */
                         if (!flg && AIT_ADDR(&av->cfg_val) && 
                                         *AIT_GET_STR(&av->cfg_attr) == '%' && 
                                         !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) {
                                 ff = fopen(AIT_GET_STR(&av->cfg_val), "r");
                                 if (ff) {
                                         cfgReadConfig(ff, cfg);
                                         fclose(ff);
                                 } else
                                         EDEBUG(7, "Error:: Can't open %s file", 
                                                         AIT_GET_STR(&av->cfg_val));
                         }
                         continue;                          continue;
                 }                  }
   
                 /* *NEW PAIR* alloc new pair element */                  /* *NEW PAIR* alloc new pair element */
                av = malloc(sizeof(struct tagCfg));                av = e_malloc(sizeof(struct tagCfg));
                 if (!av) {                  if (!av) {
                        LOGERR;                        cfg_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                         return -1;                          return -1;
                 } else {                  } else {
                         memset(av, 0, sizeof(struct tagCfg));                          memset(av, 0, sizeof(struct tagCfg));
                         CFG_RC_LOCK(cfg);                          CFG_RC_LOCK(cfg);
                        SLIST_INSERT_HEAD(cfg, av, cfg_next);                        TAILQ_INSERT_TAIL(cfg, av, cfg_next);
                         CFG_RC_UNLOCK(cfg);                          CFG_RC_UNLOCK(cfg);
                 }                  }
   
                   /* check for comment or empty line */
                   if (!*line || *line == '#' || *line == ';') {
                           AIT_SET_STR(&av->cfg_val, line);
                           continue;
                   }
   
                 /* check for continues line */                  /* check for continues line */
                psAttr = line + strlen(line) - 1;                psAttr = line + (*line ? strlen(line) : 1) - 1;
                 if (*psAttr == '\\') {                  if (*psAttr == '\\') {
                         *psAttr = 0;                          *psAttr = 0;
                         flg = 1;                          flg = 1;
                 }                  }
   
                 /* check for comment or empty line */  
                 if (!*line || *line == '#' || *line == ';') {  
                         AIT_SET_STR(&av->cfg_val, line);  
                         continue;  
                 }  
                 /* section */                  /* section */
                 if (*line == '[') {                  if (*line == '[') {
                         AIT_SET_STR(&av->cfg_val, line);  
                         psAttr = line + strlen(line) - 1;                          psAttr = line + strlen(line) - 1;
                         if (*psAttr == ']') {                          if (*psAttr == ']') {
                                 *psAttr = 0;                                   *psAttr = 0; 
                                 flg = 0;                                  flg = 0;
                                 strlcpy(szSection, line + 1, sizeof szSection);                                  strlcpy(szSection, line + 1, sizeof szSection);
                                   AIT_SET_STR(&av->cfg_sec, line);
                         } else                          } else
                                ioDEBUG(7, "Ignore section '%s' ... not found ']'", line);                                EDEBUG(7, "Ignore section '%s' ... not found ']'", line);
                         continue;                          continue;
                 }                  }
                 /* parse pair */                  /* parse pair */
                 if (!(psAttr = strchr(line, '='))) {                  if (!(psAttr = strchr(line, '='))) {
                        AIT_SET_STR(&av->cfg_val, line);                        AIT_SET_STR(&av->cfg_val, origin);
                        ioDEBUG(7, "Ignore a/v '%s' ... not found '='", line);                        EDEBUG(7, "Ignore a/v '%s' ... not found '='", line);
                         continue;                          continue;
                 } else {                  } else {
                         *psAttr = 0;                          *psAttr = 0;
Line 171  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 166  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
                 if (*szSection) {                  if (*szSection) {
                         AIT_SET_STR(&av->cfg_sec, szSection);                          AIT_SET_STR(&av->cfg_sec, szSection);
                         AIT_KEY(&av->cfg_sec) = crcFletcher16(AIT_GET_LIKE(&av->cfg_sec, u_short*),                           AIT_KEY(&av->cfg_sec) = crcFletcher16(AIT_GET_LIKE(&av->cfg_sec, u_short*), 
                                        io_align(AIT_LEN(&av->cfg_sec) - 1, 1) / 2);                                        E_ALIGN(AIT_LEN(&av->cfg_sec) - 1, 2) / 2);
                 }                  }
   
                io_RTrimStr(psAttr);                str_RTrim(psAttr);
                io_LTrimStr(psVal);                str_LTrim(psVal);
                 if (!flg)                  if (!flg)
                        io_UnquotStr(psVal);                        str_Unquot(psVal);
                 AIT_SET_STR(&av->cfg_val, psVal);                  AIT_SET_STR(&av->cfg_val, psVal);
                 AIT_SET_STR(&av->cfg_attr, psAttr);                  AIT_SET_STR(&av->cfg_attr, psAttr);
                 AIT_KEY(&av->cfg_attr) = crcFletcher16(AIT_GET_LIKE(&av->cfg_attr, u_short*),                   AIT_KEY(&av->cfg_attr) = crcFletcher16(AIT_GET_LIKE(&av->cfg_attr, u_short*), 
                                io_align(AIT_LEN(&av->cfg_attr) - 1, 1) / 2);                                E_ALIGN(AIT_LEN(&av->cfg_attr) - 1, 2) / 2);
   
                 CFG_RC_LOCK(cfg);                  CFG_RC_LOCK(cfg);
                 RB_INSERT(tagRC, cfg, av);                  RB_INSERT(tagRC, cfg, av);
                 CFG_RC_UNLOCK(cfg);                  CFG_RC_UNLOCK(cfg);
   
                   /* read include file */
                   if (!flg && *AIT_GET_STR(&av->cfg_attr) == '%' && 
                                   !strcmp(AIT_GET_STR(&av->cfg_attr), "%include")) {
                           ff = fopen(AIT_GET_STR(&av->cfg_val), "r");
                           if (ff) {
                                   cfgReadConfig(ff, cfg);
                                   fclose(ff);
                           } else
                                   EDEBUG(7, "Error:: Can't open %s file", 
                                                   AIT_GET_STR(&av->cfg_val));
                   }
         }          }
   
         return 0;          return 0;
Line 203  int Line 210  int
 cfgWriteConfig(FILE *f, cfg_root_t * __restrict cfg, int whitespace)  cfgWriteConfig(FILE *f, cfg_root_t * __restrict cfg, int whitespace)
 {  {
         struct tagCfg *av;          struct tagCfg *av;
        time_t tim;        char line[BUFSIZ] = { 0 }, szSection[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
        char szTime[STRSIZ] = { 0 }, szSection[STRSIZ] = { 0 }; 
   
        time(&tim);        if (!f || !cfg) {
        strftime(szTime, sizeof szTime, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));                cfg_SetErr(EINVAL, "Invalid parameter(s)");
        if (!cfg_Write(f, "## Write Config :: %s\n#\n", szTime)) { 
                LOGERR; 
                 return -1;                  return -1;
         }          }
   
         CFG_RC_LOCK(cfg);          CFG_RC_LOCK(cfg);
        _invertQueue(cfg);        RB_FOREACH(av, tagRC, cfg) {
        SLIST_FOREACH(av, cfg, cfg_next) {                /* empty lines or comment */
                if (!AIT_ISEMPTY(&av->cfg_sec) &&                 if (AIT_ISEMPTY(&av->cfg_attr)) {
                                strcmp(AIT_GET_STR(&av->cfg_sec), szSection)) {                        if (AIT_ISEMPTY(&av->cfg_val))
                                 continue;
                         strlcpy(line, AIT_GET_STR(&av->cfg_val), sizeof line);
                         goto skip_sec;
                 }
 
                 /* section [] */
                 if (!AIT_ISEMPTY(&av->cfg_sec) && AIT_ADDR(&av->cfg_sec) && 
                                 strcmp(AIT_GET_STRZ(&av->cfg_sec), szSection)) {
                         strlcpy(szSection, AIT_GET_STR(&av->cfg_sec), sizeof szSection);                          strlcpy(szSection, AIT_GET_STR(&av->cfg_sec), sizeof szSection);
                         if (!cfg_Write(f, "\n[%s]\n", AIT_GET_STR(&av->cfg_sec))) {                          if (!cfg_Write(f, "\n[%s]\n", AIT_GET_STR(&av->cfg_sec))) {
                                 LOGERR;                                  LOGERR;
                                 CFG_RC_UNLOCK(cfg);                                  CFG_RC_UNLOCK(cfg);
                                 return -1;                                  return -1;
                         }                          }
                }                } else if (AIT_ISEMPTY(&av->cfg_sec) && *szSection) {
                if (AIT_ISEMPTY(&av->cfg_sec) && *szSection) { 
                         memset(szSection, 0, sizeof szSection);                          memset(szSection, 0, sizeof szSection);
                         if (!cfg_Write(f, "\n[]\n")) {                          if (!cfg_Write(f, "\n[]\n")) {
                                 LOGERR;                                  LOGERR;
Line 234  cfgWriteConfig(FILE *f, cfg_root_t * __restrict cfg, i Line 245  cfgWriteConfig(FILE *f, cfg_root_t * __restrict cfg, i
                         }                          }
                 }                  }
   
                if (!cfg_Write(f, ((whitespace) ? "%s = %s\n" : "%s=%s\n"),                 /* build line */
                                        AIT_GET_STR(&av->cfg_attr), AIT_GET_STR(&av->cfg_val))) {                memset(line, 0, sizeof line);
                 if (!AIT_ISEMPTY(&av->cfg_attr) && AIT_TYPE(&av->cfg_attr) == string) {
                         strlcpy(line, AIT_GET_STRZ(&av->cfg_attr), sizeof line);
                         if (whitespace)
                                 strlcat(line, " = ", sizeof line);
                         else
                                 strlcat(line, "=", sizeof line);
                 }
                 if (!AIT_ISEMPTY(&av->cfg_val) && AIT_TYPE(&av->cfg_val) == string)
                         strlcat(line, AIT_GET_STRZ(&av->cfg_val), sizeof line);
 skip_sec:
                 /* write */
                 if (!cfg_Write(f, "%s\n", line)) {
                         LOGERR;                          LOGERR;
                         CFG_RC_UNLOCK(cfg);                          CFG_RC_UNLOCK(cfg);
                         return -1;                          return -1;
                 }                  }
         }          }
         _invertQueue(cfg);  
         CFG_RC_UNLOCK(cfg);          CFG_RC_UNLOCK(cfg);
   
         memset(szTime, 0, sizeof szTime);  
         time(&tim);  
         strftime(szTime, sizeof szTime, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));  
         if (!cfg_Write(f, "\n#\n## Done. :: %s\n", szTime)) {  
                 LOGERR;  
                 return -1;  
         }  
   
         return 0;          return 0;
 }  }
   
 #if 0  
 /*  /*
 * WriteConfig() Write to file from items in config list * cfgWriteConfigRaw() - Write config from memory by list
 * @f = file resource *
 * @cfg = Head list element * @f = File handle
 * return: 0 ok; -1 error:: can`t write to file * @cfg = Config root
*/ * @whitespace = Additional whitespace characters to file
int WriteConfig(FILE *f, sl_config * __restrict cfg) * return: -1 error or 0 ok
  */
 int
 cfgWriteConfigRaw(FILE *f, cfg_root_t * __restrict cfg, int whitespace)
 {  {
        return cfgWrite(f, cfg, 1);        struct tagCfg *av, *nxt;
}        char line[BUFSIZ] = { 0 }, szSection[STRSIZ] = { [0 ... STRSIZ - 1] = 0 };
   
/*        if (!f || !cfg) {
 * cfg_WriteConfig() Write to file from items in config list without whitespaces!                cfg_SetErr(EINVAL, "Invalid parameter(s)");
 * @f = file resource                return -1;
 * @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); 
} 
   
           CFG_RC_LOCK(cfg);
           TAILQ_FOREACH_SAFE(av, cfg, cfg_next, nxt) {
                   /* empty lines or comment */
                   if (AIT_ISEMPTY(&av->cfg_attr)) {
                           if (AIT_ISEMPTY(&av->cfg_val))
                                   continue;
                           strlcpy(line, AIT_GET_STR(&av->cfg_val), sizeof line);
                           goto skip_sec;
                   }
   
                   /* section [] */
                   if (!AIT_ISEMPTY(&av->cfg_sec) && AIT_ADDR(&av->cfg_sec) && 
                                   strcmp(AIT_GET_STRZ(&av->cfg_sec), szSection)) {
                           strlcpy(szSection, AIT_GET_STR(&av->cfg_sec), sizeof szSection);
                           if (!cfg_Write(f, "\n[%s]\n", AIT_GET_STR(&av->cfg_sec))) {
                                   LOGERR;
                                   CFG_RC_UNLOCK(cfg);
                                   return -1;
                           }
                   } else if (AIT_ISEMPTY(&av->cfg_sec) && *szSection) {
                           memset(szSection, 0, sizeof szSection);
                           if (!cfg_Write(f, "\n[]\n")) {
                                   LOGERR;
                                   CFG_RC_UNLOCK(cfg);
                                   return -1;
                           }
                   }
   
                   /* build line */
                   memset(line, 0, sizeof line);
                   if (!AIT_ISEMPTY(&av->cfg_attr) && AIT_TYPE(&av->cfg_attr) == string) {
                           strlcpy(line, AIT_GET_STRZ(&av->cfg_attr), sizeof line);
                           if (whitespace)
                                   strlcat(line, " = ", sizeof line);
                           else
                                   strlcat(line, "=", sizeof line);
                   }
                   if (!AIT_ISEMPTY(&av->cfg_val) && AIT_TYPE(&av->cfg_val) == string)
                           strlcat(line, AIT_GET_STRZ(&av->cfg_val), sizeof line);
   skip_sec:
                   /* write */
                   if (!cfg_Write(f, "%s\n", line)) {
                           LOGERR;
                           CFG_RC_UNLOCK(cfg);
                           return -1;
                   }
           }
           CFG_RC_UNLOCK(cfg);
   
           return 0;
   }
 /*  /*
 * ConcatConfig() Concat two list in one * cfgConcatConfig() - Concat two configs into one
 * @cfg = Head list element of main list *
 * @add_cfg = Head list element of added list * @cfg = Config root
 * return: 0 ok; -1 error:: can`t concat lists * @add_cfg = Concated config will be destroy after merge
*/ * return: -1 error or 0 ok
int ConcatConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg) */
 int
 cfgConcatConfig(cfg_root_t * __restrict cfg, cfg_root_t * __restrict add_cfg)
 {  {
        struct tagPair *item;        struct tagCfg *item;
        int ret = 0; 
   
         if (!cfg || !add_cfg)          if (!cfg || !add_cfg)
                 return -1;                  return -1;
   
        for (item = cfg->slh_first; item->sle_next; item = item->sle_next);        CFG_RC_LOCK(add_cfg);
        item->sle_next = add_cfg->slh_first;        CFG_RC_LOCK(cfg);
   
        add_cfg->slh_first = NULL;        /* concat lists & red-black trees */
         TAILQ_FOREACH(item, add_cfg, cfg_next) {
                 TAILQ_INSERT_TAIL(cfg, item, cfg_next);
                 RB_INSERT(tagRC, cfg, item);
         }
   
        return ret;        CFG_RC_UNLOCK(cfg);
 
         TAILQ_INIT(add_cfg);
         RB_INIT(add_cfg);
         CFG_RC_UNLOCK(add_cfg);
         pthread_mutex_destroy(&add_cfg->rc_mtx);
         return 0;
 }  }
   
 /*  /*
 * MergeConfig() Marge two list in one cfg and destroy add_cfg * cfgMergeConfig() - 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!) * @cfg = Config root of main list
 * return: 0 ok; -1 error:: can`t merge lists * @add_cfg = Merged config will be destroy after merge
*/ * return: -1 error or 0 ok
int MergeConfig(sl_config * __restrict cfg, sl_config * __restrict add_cfg) */
 int
 cfgMergeConfig(cfg_root_t * __restrict cfg, cfg_root_t * __restrict add_cfg)
 {  {
        struct tagPair *item, *merge, *add_next, *next = NULL;        struct tagCfg *item, *merge, *add_next, *next;
         int flg;          int flg;
   
         if (!cfg || !add_cfg)          if (!cfg || !add_cfg)
                 return -1;                  return -1;
   
        item = add_cfg->slh_first;        CFG_RC_LOCK(add_cfg);
        while (item) {        CFG_RC_LOCK(cfg);
                add_next = item->sle_next; 
   
                for (flg = 0, merge = cfg->slh_first, next = merge->sle_next; next;         /* merge lists */
                                merge = merge->sle_next, next = merge->sle_next) {        TAILQ_FOREACH_SAFE(item, add_cfg, cfg_next, add_next) {
                        if (!merge->psSection && !item->psSection) {                flg = 0;
                 TAILQ_FOREACH_SAFE(merge, cfg, cfg_next, next) {
                         if (AIT_ISEMPTY(&merge->cfg_sec) && AIT_ISEMPTY(&item->cfg_sec)) {
                                 flg = 1;                                  flg = 1;
                                 merge->sle_next = item;  
                                 item->sle_next = next;  
                                 break;                                  break;
                         }                          }
                        if (merge->psSection && item->psSection &&                         if (!AIT_ISEMPTY(&merge->cfg_sec) && !AIT_ISEMPTY(&item->cfg_sec) && 
                                        !strcmp((char*) merge->psSection, (char*) item->psSection)) {                                        AIT_ADDR(&merge->cfg_sec) && AIT_ADDR(&item->cfg_sec) &&
                                         !strcmp(AIT_GET_STR(&merge->cfg_sec), AIT_GET_STR(&item->cfg_sec))) {
                                 flg = 1;                                  flg = 1;
                                 merge->sle_next = item;  
                                 item->sle_next = next;  
                                 break;                                  break;
                         }                          }
                 }                  }
   
                if (!flg) {                if (!flg)
                        if (!merge->sle_next) {                        TAILQ_INSERT_TAIL(cfg, item, cfg_next);
                                merge->sle_next = item;                else
                                item->sle_next = NULL;                        TAILQ_INSERT_AFTER(cfg, merge, item, cfg_next);
                        } else                RB_INSERT(tagRC, cfg, item);
                                return -1;        }
 
         CFG_RC_UNLOCK(cfg);
 
         TAILQ_INIT(add_cfg);
         RB_INIT(add_cfg);
         CFG_RC_UNLOCK(add_cfg);
         pthread_mutex_destroy(&add_cfg->rc_mtx);
         return 0;
 }
 
 /*
  * cfgReadLines() - Read custom lines and add new item at config root
  *
  * @f = File resource
  * @delim = Custom delimiter, if =NULL default is '='
  * @end = Custom user end of file, if =NULL default is EOF
  * @cfg = Config root
  * return: -1 error or 0 ok
  */
 int
 cfgReadLines(FILE *f, const char *delim, const char *end, cfg_root_t * __restrict cfg)
 {
         char line[BUFSIZ];
         struct tagCfg *d, *av = NULL;
         char *p, *psSec, *psAttr, *psVal;
 
         if (!cfg)
                 return -1;
         if (!delim)
                 delim = ATR_LINES_DELIM;
 
         while (!feof(f)) {
                 psSec = psAttr = psVal = NULL;
                 memset(line, 0, sizeof line);
                 fgets(line, sizeof line - 1, f);
                 /* check for user end-of-file */
                 if (strspn(line, end))
                         break;
 
                 if (!(psAttr = strpbrk(line, "\r\n"))) {
                         /* skip line, too long */
                         continue;
                 } else {
                         *psAttr = 0;
                         str_Trim(line);
                         if (!*line)
                                 continue;
                 }                  }
   
                item = add_next;                if (!av_MakeExt(line, delim, &p, &psVal))
        }                        continue;
                 else {
                         str_RTrim(p);
                         str_LTrim(psVal);
                 }
                 if (!av_MakeExt(p, SEC_LINES_DELIM, &psSec, &psAttr))
                         psAttr = p;
   
        add_cfg->slh_first = NULL;                /* *NEW PAIR* alloc new pair element */
                 av = e_malloc(sizeof(struct tagCfg));
                 if (!av) {
                         LOGERR;
                         return -1;
                 } else
                         memset(av, 0, sizeof(struct tagCfg));
   
                   if (psSec) {
                           AIT_SET_STR(&av->cfg_sec, psSec);
                           AIT_KEY(&av->cfg_sec) = crcFletcher16(AIT_GET_LIKE(&av->cfg_sec, u_short*), 
                                           E_ALIGN(AIT_LEN(&av->cfg_sec) - 1, 2) / 2);
                   }
                   if (psVal)
                           AIT_SET_STR(&av->cfg_val, psVal);
                   AIT_SET_STR(&av->cfg_attr, psAttr);
                   AIT_KEY(&av->cfg_attr) = crcFletcher16(AIT_GET_LIKE(&av->cfg_attr, u_short*), 
                                   E_ALIGN(AIT_LEN(&av->cfg_attr) - 1, 2) / 2);
   
                   CFG_RC_LOCK(cfg);
                   /* find & delete duplicates */
                   if ((d = RB_FIND(tagRC, cfg, av))) {
                           RB_REMOVE(tagRC, cfg, d);
                           TAILQ_REMOVE(cfg, d, cfg_next);
   
                           AIT_FREE_VAL(&d->cfg_val);
                           AIT_FREE_VAL(&d->cfg_attr);
                           AIT_FREE_VAL(&d->cfg_sec);
                           e_free(d);
                   }
   
                   TAILQ_INSERT_TAIL(cfg, av, cfg_next);
                   RB_INSERT(tagRC, cfg, av);
                   CFG_RC_UNLOCK(cfg);
           }
   
         return 0;          return 0;
 }  }
#endif
 /*
  * cfgWriteLines() - Write custom lines and export data to variable
  *
  * @f = File resource
  * @delim = Custom delimiter, if =NULL default is '='
  * @eol = End of line string, if =NULL default is "\n"
  * @section = Export only section, if =NULL default is all
  * @cfg = Config root
  * return: =NULL error or !=NULL exported data, must be free after use with ait_freeVar()
  */
 ait_val_t *
 cfgWriteLines(FILE *f, const char *delim, const char *eol, const char *section, cfg_root_t * __restrict cfg)
 {
         ait_val_t *v = NULL;
         struct tagCfg *av;
 
         if (!cfg)
                 return NULL;
         if (!delim)
                 delim = ATR_LINES_DELIM;
         if (!eol)
                 eol = EOL_LINES_DELIM;
         if (!(v = ait_allocVar())) {
                 cfg_SetErr(elwix_GetErrno(), "%s", elwix_GetError());
                 return NULL;
         } else
                 AIT_INIT_VAL2(v, string);
 
         TAILQ_FOREACH(av, cfg, cfg_next) {
                 if (section) {
                         if (!AIT_ISEMPTY(&av->cfg_sec) && *section)
                                 continue;
                         if (strcmp(section, AIT_GET_STRZ(&av->cfg_sec)))
                                 continue;
                 }
 
                 if (!AIT_ISEMPTY(&av->cfg_sec)) {
                         AIT_SET_STRCAT(v, AIT_GET_STR(&av->cfg_sec));
                         AIT_SET_STRCAT(v, SEC_LINES_DELIM);
                 }
                 if (!AIT_ISEMPTY(&av->cfg_attr)) {
                         AIT_SET_STRCAT(v, AIT_GET_STR(&av->cfg_attr));
                         AIT_SET_STRCAT(v, delim);
                 }
                 if (!AIT_ISEMPTY(&av->cfg_val))
                         AIT_SET_STRCAT(v, AIT_GET_STR(&av->cfg_val));
                 AIT_SET_STRCAT(v, eol);
         }
 
         if (f)
                 fputs(AIT_GET_STR(v), f);
         return v;
 }

Removed from v.1.6.4.2  
changed lines
  Added in v.1.18.4.1


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>