add annotation mechanism for ini parse

dev
liuwei 2015-08-17 16:05:32 +08:00
parent f71c846a24
commit ad51130d2d
2 changed files with 246 additions and 44 deletions

View File

@ -22,11 +22,44 @@
#define _LINE_BUFFER_SIZE 512 #define _LINE_BUFFER_SIZE 512
#define _INIT_ALLOC_ITEM_COUNT 32 #define _INIT_ALLOC_ITEM_COUNT 32
static AnnotationMap *g_annotataionMap;
static int remallocSection(IniSection *pSection, IniItem **pItem);
static int iniDoLoadFromFile(const char *szFilename, \ static int iniDoLoadFromFile(const char *szFilename, \
IniContext *pContext); IniContext *pContext);
static int iniDoLoadItemsFromBuffer(char *content, \ static int iniDoLoadItemsFromBuffer(char *content, \
IniContext *pContext); 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) static int iniCompareByItemName(const void *p1, const void *p2)
{ {
return strcmp(((IniItem *)p1)->name, ((IniItem *)p2)->name); 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) static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
{ {
AnnotationMap *pAnnoMap;
IniSection *pSection; IniSection *pSection;
IniItem *pItem; IniItem *pItem;
char *pLine; char *pLine;
char *pLastEnd; char *pLastEnd;
char *pEqualChar; char *pEqualChar;
char *pFunc_name;
char *pItemName;
char *pAnnoItemLine;
char *pIncludeFilename; char *pIncludeFilename;
char *pItemValue[100];
char full_filename[MAX_PATH_SIZE]; char full_filename[MAX_PATH_SIZE];
int i;
int nLineLen; int nLineLen;
int nNameLen; int nNameLen;
int nItemCnt;
int nValueLen; int nValueLen;
int result; int result;
int isAnnotation;
result = 0; result = 0;
nItemCnt = -1;
pAnnoItemLine = NULL;
isAnnotation = 0;
pLastEnd = content - 1; pLastEnd = content - 1;
pSection = pContext->current_section; pSection = pContext->current_section;
pItem = pSection->items + pSection->count; pItem = pSection->items + pSection->count;
@ -328,6 +372,136 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
free(pIncludeFilename); free(pIncludeFilename);
continue; 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); trim(pLine);
if (*pLine == '#' || *pLine == '\0') if (*pLine == '#' || *pLine == '\0')
@ -414,10 +588,31 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
nValueLen = FAST_INI_ITEM_VALUE_LEN; nValueLen = FAST_INI_ITEM_VALUE_LEN;
} }
if (pSection->count >= pSection->alloc_count) if (pSection->count >= pSection->alloc_count) {
{ result = remallocSection(pSection, &pItem);
int bytes; if (result) {
break;
}
}
memcpy(pItem->name, pLine, nNameLen);
memcpy(pItem->value, pEqualChar + 1, nValueLen);
trim(pItem->name);
trim(pItem->value);
pSection->count++;
pItem++;
}
return result;
}
static int remallocSection(IniSection *pSection, IniItem **pItem)
{
int bytes, result;
IniItem *pNew; IniItem *pNew;
if (pSection->alloc_count == 0) if (pSection->alloc_count == 0)
{ {
pSection->alloc_count = _INIT_ALLOC_ITEM_COUNT; pSection->alloc_count = _INIT_ALLOC_ITEM_COUNT;
@ -433,7 +628,7 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
logError("file: "__FILE__", line: %d, " \ logError("file: "__FILE__", line: %d, " \
"malloc %d bytes fail", __LINE__, bytes); "malloc %d bytes fail", __LINE__, bytes);
result = errno != 0 ? errno : ENOMEM; result = errno != 0 ? errno : ENOMEM;
break; return result;
} }
if (pSection->count > 0) if (pSection->count > 0)
@ -444,22 +639,11 @@ static int iniDoLoadItemsFromBuffer(char *content, IniContext *pContext)
} }
pSection->items = pNew; pSection->items = pNew;
pItem = pSection->items + pSection->count; *pItem = pSection->items + pSection->count;
memset(pItem, 0, sizeof(IniItem) * \ memset(*pItem, 0, sizeof(IniItem) * \
(pSection->alloc_count - pSection->count)); (pSection->alloc_count - pSection->count));
}
memcpy(pItem->name, pLine, nNameLen); return 0;
memcpy(pItem->value, pEqualChar + 1, nValueLen);
trim(pItem->name);
trim(pItem->value);
pSection->count++;
pItem++;
}
return result;
} }
static int iniFreeHashData(const int index, const HashData *data, void *args) static int iniFreeHashData(const int index, const HashData *data, void *args)
@ -485,6 +669,8 @@ static int iniFreeHashData(const int index, const HashData *data, void *args)
void iniFreeContext(IniContext *pContext) void iniFreeContext(IniContext *pContext)
{ {
AnnotationMap *pAnnoMap;
if (pContext == NULL) if (pContext == NULL)
{ {
return; return;
@ -498,6 +684,13 @@ void iniFreeContext(IniContext *pContext)
hash_walk(&pContext->sections, iniFreeHashData, NULL); hash_walk(&pContext->sections, iniFreeHashData, NULL);
hash_destroy(&pContext->sections); hash_destroy(&pContext->sections);
pAnnoMap = g_annotataionMap;
while (pAnnoMap->func_name)
{
pAnnoMap->func_destroy();
pAnnoMap++;
}
} }

View File

@ -19,6 +19,13 @@
#define FAST_INI_ITEM_NAME_LEN 64 #define FAST_INI_ITEM_NAME_LEN 64
#define FAST_INI_ITEM_VALUE_LEN 256 #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 typedef struct
{ {
char name[FAST_INI_ITEM_NAME_LEN + 1]; char name[FAST_INI_ITEM_NAME_LEN + 1];
@ -44,6 +51,8 @@ typedef struct
extern "C" { extern "C" {
#endif #endif
void iniSetAnnotationCallBack(AnnotationMap *map, int count);
/** load ini items from file /** load ini items from file
* parameters: * parameters:
* szFilename: the filename, can be an URL * szFilename: the filename, can be an URL