diff --git a/src/ini_file_reader.c b/src/ini_file_reader.c index a55e0f2..9df28b3 100644 --- a/src/ini_file_reader.c +++ b/src/ini_file_reader.c @@ -22,11 +22,44 @@ #define _LINE_BUFFER_SIZE 512 #define _INIT_ALLOC_ITEM_COUNT 32 +static AnnotationMap *g_annotataionMap; + +static int remallocSection(IniSection *pSection, IniItem **pItem); static int iniDoLoadFromFile(const char *szFilename, \ IniContext *pContext); static int iniDoLoadItemsFromBuffer(char *content, \ IniContext *pContext); +void iniSetAnnotationCallBack(AnnotationMap *map, int count) +{ + int bytes; + AnnotationMap *p; + + if (count <= 0) { + logWarning("file: "__FILE__", line: %d, " \ + "iniSetAnnotationCallBack fail count(%d) is incorrectly.", \ + __LINE__, count); + return; + } + + bytes = sizeof(AnnotationMap) * (count + 1); + g_annotataionMap = (AnnotationMap *) malloc(bytes); + if (g_annotataionMap == NULL) { + logError("file: "__FILE__", line: %d, " \ + "malloc fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return; + } + + memcpy(g_annotataionMap, map, bytes); + + p = g_annotataionMap + count; + p->func_name = NULL; + p->func_init = NULL; + p->func_destroy = NULL; + p->func_get = NULL; +} + static int iniCompareByItemName(const void *p1, const void *p2) { return strcmp(((IniItem *)p1)->name, ((IniItem *)p2)->name); @@ -241,19 +274,30 @@ int iniLoadFromBuffer(char *content, IniContext *pContext) static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) { + AnnotationMap *pAnnoMap; IniSection *pSection; IniItem *pItem; char *pLine; char *pLastEnd; char *pEqualChar; + char *pFunc_name; + char *pItemName; + char *pAnnoItemLine; char *pIncludeFilename; + char *pItemValue[100]; char full_filename[MAX_PATH_SIZE]; + int i; int nLineLen; int nNameLen; + int nItemCnt; int nValueLen; int result; + int isAnnotation; result = 0; + nItemCnt = -1; + pAnnoItemLine = NULL; + isAnnotation = 0; pLastEnd = content - 1; pSection = pContext->current_section; pItem = pSection->items + pSection->count; @@ -328,6 +372,136 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) free(pIncludeFilename); continue; } + else if (isAnnotation || (*pLine == '#' && \ + strncasecmp(pLine+1, "@function", 9) == 0 && \ + (*(pLine+10) == ' ' || *(pLine+10) == '\t'))) + { + if (isAnnotation == 0) { + pFunc_name = strdup(pLine + 11); + if (pFunc_name == NULL) { + logError("file: "__FILE__", line: %d, " \ + "strdup %d bytes fail", __LINE__, \ + (int)strlen(pLine + 11) + 1); + result = errno != 0 ? errno : ENOMEM; + break; + } + + trim(pFunc_name); + isAnnotation = 1; + pAnnoItemLine = pLastEnd + 1; + continue; + } + + isAnnotation = 0; + + if (pLine != pAnnoItemLine) { + logError("file: "__FILE__", line: %d, " \ + "the @function and annotation item " \ + "must be next to each other", __LINE__); + result = EINVAL; + free(pFunc_name); + break; + } + + trim(pLine); + if (*pLine == '#' || *pLine == '\0') { + logError("file: "__FILE__", line: %d, " \ + "the @function and annotation item " \ + "must be next to each other", __LINE__); + result = EINVAL; + free(pFunc_name); + break; + } + + pEqualChar = strchr(pLine, '='); + if (pEqualChar == NULL) { + logError("file: "__FILE__", line: %d, " \ + "the @function and annotation item " \ + "must be next to each other", __LINE__); + result = EINVAL; + free(pFunc_name); + break; + } + + nNameLen = pEqualChar - pLine; + nValueLen = strlen(pLine) - (nNameLen + 1); + if (nNameLen > FAST_INI_ITEM_NAME_LEN) { + nNameLen = FAST_INI_ITEM_NAME_LEN; + } + + if (pSection->count >= pSection->alloc_count) { + result = remallocSection(pSection, &pItem); + if (result) { + free(pFunc_name); + break; + } + } + + memcpy(pItem->name, pLine, nNameLen); + memcpy(pItem->value, pEqualChar + 1, nValueLen); + + trim(pItem->name); + trim(pItem->value); + + if (g_annotataionMap == NULL) { + logWarning("file: "__FILE__", line: %d, " \ + "not set annotataionMap and (%s) will use " \ + "the item value (%s)", __LINE__, pItem->name, + pItem->value); + pSection->count++; + pItem++; + free(pFunc_name); + continue; + } + + pAnnoMap = g_annotataionMap; + while (pAnnoMap->func_name) { + if (strlen(pAnnoMap->func_name) == strlen(pFunc_name) + && strcasecmp(pFunc_name, pAnnoMap->func_name) == 0) + { + pAnnoMap->func_init(); + nItemCnt = pAnnoMap->func_get(pItem->value, pItemValue, 100); + break; + } + pAnnoMap++; + } + + if (nItemCnt == -1) { + logWarning("file: "__FILE__", line: %d, " \ + "not found corresponding annotation func (%s)" \ + " and (%s) will use the item value (%s).", __LINE__, + pItem->name, pFunc_name, pItem->value); + pSection->count++; + pItem++; + free(pFunc_name); + continue; + } else if (nItemCnt == 0) { + logWarning("file: "__FILE__", line: %d, " \ + "annotation func(%s) execute failed and" + "(%s) will use the item value (%s)", __LINE__, + pItem->name, pFunc_name, pItem->value); + pSection->count++; + pItem++; + free(pFunc_name); + continue; + } + + pItemName = pItem->name; + for (i = 0; i < nItemCnt; i++) { + memcpy(pItem->name, pItemName, strlen(pItemName) + 1); + memcpy(pItem->value, pItemValue[i], strlen(pItemValue[i]) + 1); + pSection->count++; + pItem++; + if (pSection->count >= pSection->alloc_count) { + result = remallocSection(pSection, &pItem); + if (result) { + break; + } + } + } + free(pFunc_name); + continue; + } trim(pLine); if (*pLine == '#' || *pLine == '\0') @@ -368,7 +542,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) __LINE__, \ (int)sizeof(IniSection), \ result, STRERROR(result)); - + break; } @@ -395,66 +569,38 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) pItem = pSection->items + pSection->count; continue; } - + pEqualChar = strchr(pLine, '='); if (pEqualChar == NULL) { continue; } - + nNameLen = pEqualChar - pLine; nValueLen = strlen(pLine) - (nNameLen + 1); if (nNameLen > FAST_INI_ITEM_NAME_LEN) { nNameLen = FAST_INI_ITEM_NAME_LEN; } - + if (nValueLen > FAST_INI_ITEM_VALUE_LEN) { nValueLen = FAST_INI_ITEM_VALUE_LEN; } - - if (pSection->count >= pSection->alloc_count) - { - int bytes; - IniItem *pNew; - if (pSection->alloc_count == 0) - { - pSection->alloc_count = _INIT_ALLOC_ITEM_COUNT; - } - else - { - pSection->alloc_count *= 2; - } - bytes = sizeof(IniItem) * pSection->alloc_count; - pNew = (IniItem *)malloc(bytes); - if (pNew == NULL) - { - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail", __LINE__, bytes); - result = errno != 0 ? errno : ENOMEM; - break; - } - if (pSection->count > 0) - { - memcpy(pNew, pSection->items, - sizeof(IniItem) * pSection->count); - free(pSection->items); + if (pSection->count >= pSection->alloc_count) { + result = remallocSection(pSection, &pItem); + if (result) { + break; } - - pSection->items = pNew; - pItem = pSection->items + pSection->count; - memset(pItem, 0, sizeof(IniItem) * \ - (pSection->alloc_count - pSection->count)); } memcpy(pItem->name, pLine, nNameLen); memcpy(pItem->value, pEqualChar + 1, nValueLen); - + trim(pItem->name); trim(pItem->value); - + pSection->count++; pItem++; } @@ -462,6 +608,44 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext) return result; } +static int remallocSection(IniSection *pSection, IniItem **pItem) +{ + int bytes, result; + IniItem *pNew; + + if (pSection->alloc_count == 0) + { + pSection->alloc_count = _INIT_ALLOC_ITEM_COUNT; + } + else + { + pSection->alloc_count *= 2; + } + bytes = sizeof(IniItem) * pSection->alloc_count; + pNew = (IniItem *)malloc(bytes); + if (pNew == NULL) + { + logError("file: "__FILE__", line: %d, " \ + "malloc %d bytes fail", __LINE__, bytes); + result = errno != 0 ? errno : ENOMEM; + return result; + } + + if (pSection->count > 0) + { + memcpy(pNew, pSection->items, + sizeof(IniItem) * pSection->count); + free(pSection->items); + } + + pSection->items = pNew; + *pItem = pSection->items + pSection->count; + memset(*pItem, 0, sizeof(IniItem) * \ + (pSection->alloc_count - pSection->count)); + + return 0; +} + static int iniFreeHashData(const int index, const HashData *data, void *args) { IniSection *pSection; @@ -485,6 +669,8 @@ static int iniFreeHashData(const int index, const HashData *data, void *args) void iniFreeContext(IniContext *pContext) { + AnnotationMap *pAnnoMap; + if (pContext == NULL) { return; @@ -498,6 +684,13 @@ void iniFreeContext(IniContext *pContext) hash_walk(&pContext->sections, iniFreeHashData, NULL); hash_destroy(&pContext->sections); + + pAnnoMap = g_annotataionMap; + while (pAnnoMap->func_name) + { + pAnnoMap->func_destroy(); + pAnnoMap++; + } } @@ -551,7 +744,7 @@ int64_t iniGetInt64Value(const char *szSectionName, const char *szItemName, \ IniContext *pContext, const int64_t nDefaultValue) { char *pValue; - + pValue = iniGetStrValue(szSectionName, szItemName, pContext); if (pValue == NULL) { @@ -567,7 +760,7 @@ int iniGetIntValue(const char *szSectionName, const char *szItemName, \ IniContext *pContext, const int nDefaultValue) { char *pValue; - + pValue = iniGetStrValue(szSectionName, szItemName, pContext); if (pValue == NULL) { @@ -583,7 +776,7 @@ double iniGetDoubleValue(const char *szSectionName, const char *szItemName, \ IniContext *pContext, const double dbDefaultValue) { char *pValue; - + pValue = iniGetStrValue(szSectionName, szItemName, pContext); if (pValue == NULL) { @@ -599,7 +792,7 @@ bool iniGetBoolValue(const char *szSectionName, const char *szItemName, \ IniContext *pContext, const bool bDefaultValue) { char *pValue; - + pValue = iniGetStrValue(szSectionName, szItemName, pContext); if (pValue == NULL) { @@ -628,7 +821,7 @@ int iniGetValues(const char *szSectionName, const char *szItemName, \ { return 0; } - + INI_FIND_ITEM(szSectionName, szItemName, pContext, pSection, \ targetItem, pFound, 0) if (pFound == NULL) @@ -677,7 +870,7 @@ IniItem *iniGetValuesEx(const char *szSectionName, const char *szItemName, \ IniItem *pItem; IniItem *pItemEnd; IniItem *pItemStart; - + *nTargetCount = 0; INI_FIND_ITEM(szSectionName, szItemName, pContext, pSection, \ targetItem, pFound, NULL) diff --git a/src/ini_file_reader.h b/src/ini_file_reader.h index b3ba6b7..8ed4bbf 100644 --- a/src/ini_file_reader.h +++ b/src/ini_file_reader.h @@ -19,6 +19,13 @@ #define FAST_INI_ITEM_NAME_LEN 64 #define FAST_INI_ITEM_VALUE_LEN 256 +typedef struct { + char *func_name; + int (*func_init) (); + void (*func_destroy) (); + int (*func_get) (char *key, char **pOutValue, int max_values); +} AnnotationMap; + typedef struct { char name[FAST_INI_ITEM_NAME_LEN + 1]; @@ -44,6 +51,8 @@ typedef struct extern "C" { #endif +void iniSetAnnotationCallBack(AnnotationMap *map, int count); + /** load ini items from file * parameters: * szFilename: the filename, can be an URL