更新解析

master
brisk 2014-10-12 01:44:40 +08:00
parent ff93b3a80c
commit 047ea038d5
1 changed files with 369 additions and 164 deletions

View File

@ -1,17 +1,71 @@
#include "hash/hash.h"
#include "stack/stack.h"
#include <ctype.h>
//解析过程的各状态
enum conf_stat
{
conf_stat_start,
conf_stat_normal,
conf_stat_note,
conf_stat_key,
conf_stat_more_key,
conf_stat_quote,
conf_stat_done
};
#define POP (*data)
#define ADVANCE (++data)
#define BACK (--data)
#define LEN (data-str)
#define CONF_GET_VALUE(value,stack) \
{\
if(conf_stack_get_data(stack) == NULL)\
{\
retcode=CONF_KEY_ERR;\
printf("行:%d ",line);\
goto end;\
}\
value=realloc(value,sizeof(char*)*(value_len+2));\
if(value == NULL)\
{\
retcode=CONF_NO_MEM;\
goto end;\
}\
value[value_len]=strdup(conf_stack_get_data(stack));\
if(value[value_len] == NULL)\
{\
retcode=CONF_NO_MEM;\
free(value);\
goto end;\
}\
value[value_len+1]=NULL;\
++value_len;\
}
int line=1; //行
//解析对参数
//data为配置文件内容
//正确时返回0并置res为参数列表conf->len为参数个数
//错误时返回错误代码
int parse_value(CONF *conf,char *data,CONF_VALUE **res);
//int parse_value(CONF *conf,char *data,CONF_VALUE **res);
int parse_value(CONF *conf,char *data);
//得到一行的偏移量
int next_line(char *data);
//释放内存
void free_data(CONF_ARG *data);
//得到键
void get_key(char **key,int *index,CONF_ARG *arg);
//读取键值
int _conf_read_key(char *data,int len,STACK *stack);
//获取值状态
enum conf_stat _conf_value_status(char c);
//读取值
int _conf_read_value(char *data,int len,STACK *stack);
//读取带有引号的值
int _conf_read_value_with_quote(char *data,int len,STACK *stack,char quote);
//打开配置文件并初始化值
//path为配置文件路径
@ -36,6 +90,7 @@ CONF *conf_open(const char *path)
//初始化键值对
conf->len=0;
conf->size=HASH_DEFAULT;
conf->hash_data=NULL;
return conf;
@ -46,11 +101,9 @@ CONF *conf_open(const char *path)
//解析成功返回错误代码
int conf_parse(CONF *conf)
{
CONF_VALUE *value=NULL; //参数对列表
char *data; //配置文件内容
long file_len; //配置文件长度
int retcode;
int i;
//加载配置文件内容到内存
if(fseek(conf->fp,0L,SEEK_END) != 0)
@ -66,36 +119,15 @@ int conf_parse(CONF *conf)
//关闭文件
fclose(conf->fp);
//解析
retcode=parse_value(conf,data,&value);
//开辟内存空间
conf->hash_data=malloc(sizeof(CONF_ARG)*conf->len);
//开辟内存空间出错
if(conf->hash_data == NULL)
{
//如果已经解析了则进行释放
if(value)
free(value);
//返回错误
retcode=CONF_NO_MEM;
}
//初始化数组
for(i=0;i != conf->len;++i)
{
conf->hash_data[i].len=0;
conf->hash_data[i].next=NULL;
conf->hash_data[i].value=NULL;
}
//插入数据
for(i=0;i != conf->len;++i)
conf_value_insert(conf->hash_data,&value[i],conf->len);
//创建表
conf->hash_data=malloc(sizeof(CONF_ARG)*conf->size);
if(conf->hash_data == NULL) return CONF_NO_MEM;
//初始化键值对
conf_hash_zero(conf->hash_data,conf->size);
//解析
retcode=parse_value(conf,data);
free(data);
//free(value);
return retcode;
}
@ -173,7 +205,6 @@ int conf_insert(CONF_CREATER *creater,char *key,char *value,char *note)
int conf_save(CONF_CREATER *creater)
{
CONF_CREATER *head=creater;
// int i;
if(creater->len == 0)
return CONF_NO_DATA;
@ -186,14 +217,6 @@ int conf_save(CONF_CREATER *creater)
if(creater->key != NULL && creater->value != NULL)
fprintf(head->fp,"%s = %s\n",creater->key,creater->value);
creater=creater->next;
//如果该键有多个参数则用,分开
/*if(creater->value->value[1] != NULL)
{
for(i=1;creater->value->value[i] != NULL;++i)
fprintf(creater->fp,",%s",creater->value->value[i]);
}
fwrite("\n",1,1,creater->fp);*/
}
fclose(head->fp);
@ -207,7 +230,7 @@ void conf_free(CONF *conf)
int i;
int j;
for(i=0;i != conf->len;++i)
for(i=0;i != conf->size;++i)
{
if(conf->hash_data[i].len != 0)
free_data(&conf->hash_data[i]);
@ -255,157 +278,230 @@ void conf_error(int errcode)
case CONF_VALUE_ERR:
printf("错误:错误的值!\n");
break;
case STACK_MAX:
printf("参数字符过多!\n");
break;
default:
printf("未知错误!\n");
}
}
//解析参数
int parse_value(CONF *conf,char *data,CONF_VALUE **res)
int parse_value(CONF *conf,char *data)
{
int i=0; //字符偏移量
int flags=0; //'与"的标记
int key=0; //键标记
int arg=0; //,标记
int len=0; //键值对个数
int count=0; //参数个数
CONF_VALUE *value=NULL; //存放键值参数
STACK stack; //存放参数的栈
//保存解析字符串的首地址
char *str=data;
//状态
int status;
int save_status;
int end_status;
//引号
char quote;
//存储字符串的栈
STACK stack;
CONF_VALUE *value=NULL;
int retcode=CONF_OK;
//多参数个数
int value_len=0;
//初始化栈和状态
conf_stack_init(&stack);
status=conf_stat_start;
save_status=conf_stat_normal;
end_status=conf_stat_done;
while(data[i])
redo:
while(POP)
{
switch(data[i])
switch(POP)
{
case '=': //读取键,如果第一次读到=则表示键已读完
if(!key)
//注释
case '#':
if(save_status == conf_stat_normal)
status=conf_stat_note;
else if(save_status == conf_stat_key)
{
value=realloc(value,sizeof(CONF_VALUE)*(len+1));
if(value == NULL)
return CONF_NO_MEM;
value[len].key=malloc(sizeof(char)*conf_stack_length(&stack)+1);
if(value[len].key == NULL)
return CONF_NO_MEM;
snprintf(value[len].key,sizeof(char)*conf_stack_length(&stack)+1,"%s",stack.data);
key=1;
value[len].value=NULL;
conf_stack_cleanup(&stack);
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
conf_free(conf);
goto end;
}
break;
//读取值
case '=':
if(save_status == conf_stat_key)
status=conf_stat_key;
else
{
if(conf_stack_push(&stack,data[i]) != 0) //否则则是值压入栈
return STACK_MAX;
}
break;
/* 如果第一次读到"则设置"标记
* "则如果flags为1则表示读取完成
* 2'"压入栈中
*/
case '"':
if(!flags)
flags=1;
else if(flags == 1)
flags=0;
else if(flags == 2)
{
if(conf_stack_push(&stack,data[i]) != 0)
return STACK_MAX;
}
break;
case '\'': //上同
if(!flags)
flags=2;
else if(flags == 2)
flags=0;
else if(flags == 1)
{
if(conf_stack_push(&stack,data[i]) != 0)
return STACK_MAX;
}
break;
/* 多参数标记
* '/"标记则直接压入
* '/"标记且arg未设置则设置arg
* arg0
*/
case ',':
if(flags)
conf_stack_push(&stack,data[i]);
if(!flags && !arg)
arg=1;
if(arg) //存入多参数
{
value[len].value=realloc(value[len].value,sizeof(char *)*(count+1));
if(value[len].value == NULL)
return CONF_NO_MEM;
value[len].value[count]=malloc(sizeof(char)*conf_stack_length(&stack)+1);
if(value[len].value[count] == NULL)
return CONF_NO_MEM;
snprintf(value[len].value[count],sizeof(char)*conf_stack_length(&stack)+1,"%s",stack.data);
++count;
conf_stack_cleanup(&stack);
arg=0;
}
break;
case '#': //如果没有设置flags则是注释直接跳到下一行
if(!flags)
i+=next_line(data+i);
else
{
if(conf_stack_push(&stack,data[i]) != 0)
return STACK_MAX;
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
if(value)
{
if(value->key)
free(value->key);
free(value);
}
conf_free(conf);
goto end;
}
break;
//过滤空白符
case ' ':
case '\t':
if(flags)
if(end_status == conf_stat_done)
while(isspace(POP))
ADVANCE;
goto redo;
case '\n':
if(save_status == conf_stat_normal)
ADVANCE;
else
{
if(conf_stack_push(&stack,data[i]) != 0)
return STACK_MAX;
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
conf_free(conf);
goto end;
}
++line;
goto redo;
case '\0':
if(status == conf_stat_normal)
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
conf_free(conf);
goto end;
}
status=conf_stat_done;
break;
case '\n': //一行数据读完
if(conf_stack_empty(&stack))
break;
value[len].value=realloc(value[len].value,sizeof(char *)*(count+2));
if(value[len].value == NULL)
return CONF_NO_MEM;
value[len].value[count]=malloc(sizeof(char)*conf_stack_length(&stack)+1);
if(value[len].value[count] == NULL)
return CONF_NO_MEM;
snprintf(value[len].value[count],sizeof(char)*conf_stack_length(&stack)+1,"%s",stack.data);
value[len].value[count+1]=NULL;
count=0;
++len;
key=0;
conf_stack_cleanup(&stack);
break;
default: //插入字符
if(conf_stack_push(&stack,data[i]) != 0)
return STACK_MAX;
default:
if(save_status == conf_stat_key)
{
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
conf_free(conf);
goto end;
}
save_status=conf_stat_normal;
status=conf_stat_start;
}
++i;
switch(status)
{
//过滤注释
case conf_stat_note:
data+=next_line(data);
status=conf_stat_start;
save_status=conf_stat_normal;
++line;
goto redo;
//读取键
case conf_stat_start:
data+=_conf_read_key(data,LEN,&stack);
value=malloc(sizeof(CONF_VALUE));
if(value == NULL)
{
retcode=CONF_NO_MEM;
conf_free(conf);
goto end;
}
if(conf_stack_get_data(&stack) == NULL)
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
free(value);
conf_free(conf);
goto end;
}
value->key=strdup(conf_stack_get_data(&stack));
if(value->key == NULL)
{
retcode=CONF_NO_MEM;
free(value);
conf_free(conf);
goto end;
}
conf_stack_cleanup(&stack);
save_status=conf_stat_key;
end_status=conf_stat_done;
value->value=NULL;
goto redo;
//设置值状态
case conf_stat_key:
ADVANCE;
while((POP == ' ') || (POP == '\t'))
ADVANCE;
save_status=conf_stat_key;
end_status=_conf_value_status(POP);
break;
case conf_stat_done:
retcode=CONF_OK;
goto end;
}
value_redo:
switch(end_status)
{
//读取完成,保存数据到表中
case conf_stat_done:
if((save_status != conf_stat_key) ||
(status == conf_stat_key))
{
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
conf_free(conf);
goto end;
}
//重置状态
status=conf_stat_start;
save_status=conf_stat_normal;
value_len=0;
if(conf->len/conf->size >= HASH_SP)
conf_hash_update(conf);
if(conf_value_insert(conf->hash_data,value,conf->size))
++conf->len;
BACK;
value=NULL;
conf_stack_cleanup(&stack);
break;
//读取值
case conf_stat_normal:
data+=_conf_read_value(data,LEN,&stack);
CONF_GET_VALUE(value->value,&stack);
while(isspace(POP) && (POP != '\n'))
ADVANCE;
end_status=_conf_value_status(POP);
status=conf_stat_start;
goto value_redo;
//读取带有引号的值
case conf_stat_quote:
quote=POP;
ADVANCE;
data+=_conf_read_value_with_quote(data,LEN,&stack,quote);
CONF_GET_VALUE(value->value,&stack);
ADVANCE;
end_status=_conf_value_status(POP);
goto value_redo;
//多参数值读取
case conf_stat_more_key:
conf_stack_cleanup(&stack);
ADVANCE;
end_status=_conf_value_status(POP);
goto value_redo;
}
ADVANCE;
}
*res=value;
conf->len=len;
return 0;
end:
conf_stack_destroy(&stack);
return retcode;
}
int next_line(char *data)
{
int i=0;
while(data[i] != '\n')
while((data[i] != '\n') && (data[i] != '\0'))
++i;
return i-1;
return i+1;
}
void free_data(CONF_ARG *data)
@ -438,7 +534,7 @@ char **conf_key_list(CONF *conf)
key[conf->len]=NULL;
//读取出所有键
for(i=0;i < conf->len;++i)
for(i=0;i < conf->size;++i)
if(conf->hash_data[i].len > 0)
get_key(key,&index,&conf->hash_data[i]);
@ -464,12 +560,12 @@ CONF_VALUE *conf_value_get(CONF *conf,const char *key)
/* 首先使用第一个哈希函数计算出哈希值如果找到匹配的key则返回
* 使key
* NULL */
hash=conf_hash_func1(key)%conf->len;
hash=conf_hash_func1(key)%conf->size;
if(conf_hash_search(&conf->hash_data[hash],key,&value))
return value;
else
{
hash=conf_hash_func2(key)%conf->len;
hash=conf_hash_func2(key)%conf->size;
if(conf_hash_search(&conf->hash_data[hash],key,&value))
return value;
}
@ -488,7 +584,7 @@ CONF_VALUE **conf_value_get_all(CONF *conf)
return NULL;
//第一次扫描数组中所有存在数据的地方并计算长度
for(i=0;i != conf->len;++i)
for(i=0;i != conf->size;++i)
if(conf->hash_data[i].len > 0)
++len;
@ -498,7 +594,7 @@ CONF_VALUE **conf_value_get_all(CONF *conf)
return NULL;
value[len]=NULL;
//第二次扫描,返回数组中所有有数据的值
for(i=0;i != conf->len;++i)
for(i=0;i != conf->size;++i)
{
if(conf->hash_data[i].len > 0)
{
@ -509,3 +605,112 @@ CONF_VALUE **conf_value_get_all(CONF *conf)
return value;
}
int _conf_read_key(char *data,int len,STACK *stack)
{
int i=0;
char c;
while(isspace(POP) && (POP != '\n'))
{
ADVANCE;
++i;
}
if(POP == '\n')
{
printf("行:%d 列:%d 解析出错\n",line,i-len);
return 0;
}
do
{
c=POP;
if(isspace(c) || c == '=' || c == '#')
break;
conf_stack_push(stack,c);
++i;
ADVANCE;
}while(c);
return i;
}
enum conf_stat _conf_value_status(char c)
{
switch(c)
{
case ',':
return conf_stat_more_key;
case '\'':
case '"':
return conf_stat_quote;
case '#':
case '\n':
return conf_stat_done;
default:
return conf_stat_normal;
}
}
int _conf_read_value(char *data,int len,STACK *stack)
{
char c;
int i=0;
while(isspace(POP) && (POP != '\n'))
{
ADVANCE;
++i;
}
if(POP == '\n')
{
printf("行:%d 列:%d 解析出错!\n",line,i-len);
return 0;
}
do
{
c=POP;
if(isspace(c) || c == ',' || c == '#')
break;
conf_stack_push(stack,c);
++i;
ADVANCE;
}while(c);
return i;
}
int _conf_read_value_with_quote(char *data,int len,STACK *stack,char quote)
{
char c;
int i=0;
while(isspace(POP) && (POP != '\n'))
{
ADVANCE;
++i;
}
if(POP == '\n')
{
printf("行:%d 列:%d 解析出错!\n",line,i-len);
return 0;
}
do
{
c=POP;
if(c == quote)
break;
conf_stack_push(stack,c);
++i;
ADVANCE;
}while(c);
if(c == '\0')
return 0;
return i;
}