/***************************** writed by zhangliang email: liangzhws@foxmail.com date:2016/6/19 *****************************/ /************************* data model CFG---------- ----------- | cg_count | CFGNODE----->| cn_count | | next |--- | node_name | | | | key | | | | | | value | | | key | | | | | | value | | . / . / . _ / CFGNODE----->| cn_count |< | next |----> NULL | node_name | | | . . . *************************/ #ifndef _CFG_H_ #define _CFG_H_ 1 typedef struct ConfigNode { int cn_count; struct ConfigNode * next; char cn_buf[]; }ConfigNode_t,* CFGNODE; typedef struct Config { int cg_count; char cg_buf[]; }Config_t, * CFG; /** @name: readConfig @function: init CFGfrom config file @param1: #const char * fileptr# file path @return: #CFG# return null is failure ,other is success */ CFG readConfig(const char * fileptr); /** @name: closeConfig @function: destory CFG @param1: #CFG cgptr# CFGobject @return: #void# */ void closeConfig(CFG cgptr); /** @name: getConfigNode @function: get the node from config_t object @param1: #const CFG* cgptr# CFGobject; @param2: #char * nameptr# node's name @return: #CFGNODE*# return null is the node not exist in config, other return the config_node object */ CFGNODE getConfigNode(const CFG cgptr, const char * nameptr); /** @name: getConfigField @function: get the value of key from config_node object @param1: #CFGNODE cnptr# config_node object @param2: #const char * keyptr# key's name */ char * getConfigField(CFGNODE cnptr, const char * keyptr); /** @name: getConfigNodeField @function: get the value of key from config object @param1: #CFG cgptr# CFGobject @param2: #const char * nodeptr# node's name @param3: #const char * keyptr# key's name @return: #char * # return NULL is means the node not exist or the value is empty, other is value */ char * getConfigNodeField(const CFG cgptr, const char * nodeptr, const char * keyptr); /** */ #endif
#include"cfg.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAXLINE 1024 #define CONFIGNODE 0 #define CONFIGFIELD 1 #define CONFIGNONE 2 static char * trim(char * sptr) { char * pend = sptr + strlen(sptr)-1; char * pstart = sptr; int n = 0; for (;pstart <= pend && *pstart == ' '; ++pstart); for (;pend > pstart && *pend == ' '; --pend); *++pend = ''; n = pend - pstart + 1; memmove(sptr, pstart, n); return sptr; } static int parseConfig(char * lineptr,int * type, char * nodeptr, char * keyptr, char * valueptr) { int n = 0; int flag = 0; char * pnode = nodeptr; char * pkey = keyptr; char * pval = valueptr; char * line = strdup(lineptr); char * p = trim(line); if ('[' == *p) { ++p; while (*p != ']') { if (*p != ' ' && *p != 't') { if (nodeptr != NULL) *pnode++ = *p; ++n; } if (*++p == '') { n = 0; if (type != NULL) *type = CONFIGNONE; if (nodeptr != NULL) *nodeptr = ''; break; } } n += 1; if (type != NULL) *type = CONFIGNODE; if (nodeptr != NULL) *pnode = ''; } else if ('#' == *p || '=' == *p) { n = 0; if (type != NULL) *type = CONFIGNONE; } else { while (*p != '#' && *p != '' && *p != 'n') { if ('=' == *p) { flag = 1; } else if (*p != ' ') { if (0 == flag && keyptr != NULL) { *pkey++ = *p; } else if(1 == flag && valueptr != NULL){ *pval++ = *p; } ++n; } ++p; } n = n + (n != 0 && 0 == flag ? 1 : 0); if (0 == n) { if (type != NULL) *type = CONFIGNONE; } else { n += 2; if (type != NULL) *type = CONFIGFIELD; if (0 == flag && valueptr != NULL) { *pval++ = '1'; } if (keyptr != NULL) { *pkey = ''; } if (valueptr != NULL) { *pval = ''; } } } free(line); return n; } CFGNODE getConfigNode(const CFG cgptr, const char * nameptr) { int i = 0; ConfigNode_t * cnptr; char * nptr; cnptr = (ConfigNode_t *)cgptr->cg_buf; for (i = 0; i < cgptr->cg_count; ++i) { nptr = (char *)cnptr + sizeof(ConfigNode_t); if (strcmp(nameptr, nptr) == 0) { return cnptr; } cnptr = cnptr->next; } return NULL; } char * getConfigField(CFGNODE cnptr, const char * keyptr) { int i = 0; char * nptr; char * kptr; char * vptr; nptr = (char *)cnptr + sizeof(ConfigNode_t); kptr = nptr + strlen(nptr) + 1; for (i = 0; i < cnptr->cn_count; ++i) { vptr = kptr + strlen(kptr) + 1; if (strcmp(kptr, keyptr) == 0) { return vptr; } kptr = vptr + strlen(vptr) + 1; } return NULL; } char * getConfigNodeField(const CFG cgptr, const char * nameptr, const char * keyptr) { ConfigNode_t * cnptr; if (NULL == (cnptr = getConfigNode(cgptr, nameptr))){ return NULL; } return getConfigField(cnptr, keyptr); } CFG readConfig(const char * fileptr) { char line[MAXLINE] =""; char node[MAXLINE] =""; char key[MAXLINE] =""; char value[MAXLINE] =""; int type; int nodecount = 0; Config_t * cgptr = NULL; ConfigNode_t * cnptr = NULL; ConfigNode_t * cnprevptr = NULL; char * punUsed = NULL; int n = 0; FILE * fp; fp = fopen(fileptr,"r"); if (NULL == fp) { return NULL; } while (fgets(line, sizeof(line), fp)) { n += parseConfig(line, &type, NULL, NULL, NULL); if (CONFIGNODE == type) ++nodecount; } n = n + sizeof(Config_t) + nodecount * sizeof(ConfigNode_t); cgptr = (Config_t *)malloc(n); cgptr->cg_count = nodecount; punUsed = cgptr->cg_buf; fseek(fp, 0, SEEK_SET); while (fgets(line, sizeof(line), fp)) { parseConfig(line, &type, node, key, value); switch (type) { case CONFIGNODE: cnptr = (ConfigNode_t *) punUsed; cnptr->cn_count = 0; cnptr->next = NULL; punUsed += sizeof(ConfigNode_t); strcpy(punUsed, node); punUsed += strlen(punUsed) + 1; if (cnprevptr != NULL) { cnprevptr->next = cnptr; } cnprevptr = cnptr; break; case CONFIGFIELD: ++cnptr->cn_count; strcpy(punUsed, key); punUsed += strlen(punUsed) + 1; strcpy(punUsed, value); punUsed += strlen(punUsed) + 1; break; } } fclose(fp); return (CFG)cgptr; } void closeConfig(CFG cgptr) { free((char *) cgptr); }