Diff for /libaitcfg/src/parse.c between versions 1.6.4.1 and 1.10.2.4

version 1.6.4.1, 2012/04/02 14:39:02 version 1.10.2.4, 2012/09/17 14:17:12
Line 47  SUCH DAMAGE. Line 47  SUCH DAMAGE.
 #include "aitcfg.h"  #include "aitcfg.h"
   
   
#if 0static inline int
// cfgDbg() Debug/Log operationcfg_Write(FILE *f, char *fmt, ...)
static inline int cfgDbg(FILE *f, char *fmt, ...) 
 {  {
         int ret = 0;          int ret = 0;
         va_list lst;          va_list lst;
Line 61  static inline int cfgDbg(FILE *f, char *fmt, ...) Line 60  static inline int cfgDbg(FILE *f, char *fmt, ...)
         return ret;          return ret;
 }  }
   
/*static inline void
 * InvertQueue() InvertQueue order //{cfg} list of elements for revert_invertQueue(cfg_root_t * __restrict cfg)
 * @cfg = Head list element for revert  
*/ 
static inline void InvertQueue(sl_config * __restrict cfg) 
 {  {
        struct tagPair *item, *next, *prev = NULL;        struct tagCfg *item, *next, *prev = NULL;
   
        for (item = cfg->slh_first; item; item = next) {        SLIST_FOREACH_SAFE(item, cfg, cfg_next, next) {
                next = item->sle_next;                item->cfg_next.sle_next = prev;
                item->sle_next = prev; 
                 prev = item;                  prev = item;
         }          }
         cfg->slh_first = prev;          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;  
 }  
   
 // ---------------------------------------------------  
 #endif  
   
 /*  /*
  * cfgReadConfig() - Read file and add new item at config root   * cfgReadConfig() - Read file and add new item at config root
  *   *
Line 147  static inline int cfgWrite(FILE *f, sl_config * __rest Line 80  static inline int cfgWrite(FILE *f, sl_config * __rest
  * @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];
         struct tagCfg *av = NULL;          struct tagCfg *av = NULL;
Line 182  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 116  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));                                  io_UnquotStr((char*) 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 = io_malloc(sizeof(struct tagCfg));
                 if (!av) {                  if (!av) {
                         LOGERR;                          LOGERR;
                         return -1;                          return -1;
Line 200  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 134  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
                 }                  }
   
                 /* 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;
Line 238  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 172  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);                                        io_align(AIT_LEN(&av->cfg_sec) - 1, 2) / 2);
                 }                  }
   
                 io_RTrimStr(psAttr);                  io_RTrimStr(psAttr);
Line 248  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 182  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
                 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);                                io_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);
Line 258  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg Line 192  int cfgReadConfig(FILE *f, cfg_root_t * __restrict cfg
         return 0;          return 0;
 }  }
   
 #if 0  
 /*  /*
 * WriteConfig() Write to file from items in config list * cfgWriteConfig() - Write config from memory
 * @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
 cfgWriteConfig(FILE *f, cfg_root_t * __restrict cfg, int whitespace)
 {  {
        return cfgWrite(f, cfg, 1);        struct tagCfg *av;
}        time_t tim;
         char line[BUFSIZ] = { 0 }, szSection[STRSIZ] = { 0 };
   
/*        CFG_RC_LOCK(cfg);
 * cfg_WriteConfig() Write to file from items in config list without whitespaces!        _invertQueue(cfg);
 * @f = file resource        SLIST_FOREACH(av, cfg, cfg_next) {
 * @cfg = Head list element                /* add +1 line for section [] */
 * return: 0 ok; -1 error:: can`t write to file                if (!AIT_ISEMPTY(&av->cfg_sec) && AIT_ADDR(&av->cfg_sec) && 
*/                                strcmp(AIT_GET_STR(&av->cfg_sec), szSection)) {
int cfg_WriteConfig(FILE *f, sl_config * __restrict cfg)                        strlcpy(szSection, AIT_GET_STR(&av->cfg_sec), sizeof szSection);
{                        if (!cfg_Write(f, "\n[%s]\n", AIT_GET_STR(&av->cfg_sec))) {
        return cfgWrite(f, cfg, 0);                                LOGERR;
                                 CFG_RC_UNLOCK(cfg);
                                 return -1;
                         }
                 }
                 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);
 
                 /* write */
                 if (!cfg_Write(f, "%s\n", line)) {
                         LOGERR;
                         CFG_RC_UNLOCK(cfg);
                         return -1;
                 }
         }
         _invertQueue(cfg);
         CFG_RC_UNLOCK(cfg);
 
         if (whitespace) {
                 time(&tim);
                 memset(line, 0, sizeof line);
                 strftime(line, sizeof line, "(UTC) %Y-%m-%d %H:%M:%S", gmtime(&tim));
                 cfg_Write(f, "\n## Config was saved at :: %s ##\n", line);
         }
 
         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 */
         for (item = SLIST_FIRST(cfg); SLIST_NEXT(item, cfg_next); item = SLIST_NEXT(item, cfg_next));
         SLIST_NEXT(item, cfg_next) = SLIST_FIRST(add_cfg);
   
        return ret;        /* concat red-black trees */
         SLIST_FOREACH(item, add_cfg, cfg_next)
                 RB_INSERT(tagRC, cfg, item);
 
         CFG_RC_UNLOCK(cfg);
         CFG_RC_UNLOCK(add_cfg);
 
         add_cfg->slh_first = NULL;
         add_cfg->rbh_root = NULL;
         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) {        SLIST_FOREACH_SAFE(item, add_cfg, cfg_next, add_next) {
                        if (!merge->psSection && !item->psSection) {                flg = 0;
                 SLIST_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) {                        SLIST_INSERT_HEAD(cfg, item, cfg_next);
                                merge->sle_next = item;                else
                                item->sle_next = NULL;                        SLIST_INSERT_AFTER(merge, item, cfg_next);
                        } else                RB_INSERT(tagRC, cfg, item);
                                return -1; 
                } 
 
                item = add_next; 
         }          }
   
           CFG_RC_UNLOCK(cfg);
           CFG_RC_UNLOCK(add_cfg);
   
         add_cfg->slh_first = NULL;          add_cfg->slh_first = NULL;
           add_cfg->rbh_root = NULL;
           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;
                           io_TrimStr(line);
                           if (!*line)
                                   continue;
                   }
   
                   if (!io_MakeAV2(line, delim, &p, &psVal))
                           continue;
                   else {
                           io_RTrimStr(p);
                           io_LTrimStr(psVal);
                   }
                   if (!io_MakeAV2(p, SEC_LINES_DELIM, &psSec, &psAttr))
                           psAttr = p;
   
                   /* *NEW PAIR* alloc new pair element */
                   av = io_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*), 
                                           io_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*), 
                                   io_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);
                           SLIST_REMOVE(cfg, d, tagCfg, cfg_next);
   
                           AIT_FREE_VAL(&d->cfg_val);
                           AIT_FREE_VAL(&d->cfg_attr);
                           AIT_FREE_VAL(&d->cfg_sec);
                           io_free(d);
                   }
   
                   SLIST_INSERT_HEAD(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 io_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 = io_allocVar())) {
                 cfg_SetErr(io_GetErrno(), "%s", io_GetError());
                 return NULL;
         } else
                 AIT_INIT_VAL2(v, string);
 
         SLIST_FOREACH(av, cfg, cfg_next) {
                 if (AIT_ISEMPTY(&av->cfg_attr))
                         continue;
                 if (section) {
                         if (!AIT_ISEMPTY(&av->cfg_sec) && *section)
                                 continue;
                         if (strcmp(section, AIT_GET_STR(&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);
                 }
                 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.1  
changed lines
  Added in v.1.10.2.4


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