Compare commits

...

7 Commits
v1.1 ... master

Author SHA1 Message Date
= f5e412a47b test1 2022-05-29 14:53:03 +08:00
= 1d07c8bf44 尝试使用cmake 2022-05-29 14:49:03 +08:00
brisk b2a60737a1 fix bugs 2017-12-28 15:47:14 +08:00
brisk abf645c4c5 添加conf_pos_msg_err接口 2014-10-12 18:28:10 +08:00
brisk 6c166e1b54 更新错误提示与BUG修复 2014-10-12 18:27:52 +08:00
brisk 4da5e92ef6 更新日志 2014-10-12 18:27:31 +08:00
brisk 74bf1f92e1 删除不必要的文件 2014-10-12 01:56:24 +08:00
8 changed files with 287 additions and 186 deletions

26
CMakeLists.txt Normal file
View File

@ -0,0 +1,26 @@
cmake_minimum_required(VERSION 3.0)
project(conf-c)
set(CMAKE_BUILD_TYPE Release)
#set(CMAKE_C_FLAGS_RELEASE "$ENV${CFLAGS} -O3 -Wall")
include_directories(src)
add_subdirectory(src)
add_subdirectory(example)
# uninstall target
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE @ONLY)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
endif()
include (CTest)
add_test(example example/example)

View File

@ -7,13 +7,13 @@ libconf.a:conf.o stack.o hash.o
cp libconf.a lib/
conf.o:src/conf.h src/conf.c
gcc -c src/conf.c
gcc -c src/conf.c -O2 -Wall
stack.o:src/stack/stack.h src/stack/stack.c
gcc -c src/stack/stack.c
gcc -c src/stack/stack.c -O2 -Wall
hash.o:src/hash/hash.h src/hash/hash.c
gcc -c src/hash/hash.c
gcc -c src/hash/hash.c -O2 -Wall
clean:
rm -rfv include lib *.o *.a

View File

@ -1,14 +0,0 @@
#这是一个测试文件
#单个参数
arg1 = abc
#多个参数
arg2 = abc,def
#空白符
arg3 = 'abc def'
#特殊符号
arg4 = "abc ' def"
#多参数,特殊符号
arg5 = "abc,def","#this is value",hello
#文件结束

View File

@ -1,114 +0,0 @@
/* conf-c一个基于c语言的轻量级读取/创建配置文件的库函数。
* 使MIT使/
*
*/
#ifndef _CONF_H
#define _CONF_H
/*配置文件中健/值以hash的方式存储在内存中*/
//#include "hash/hash.h"
//#include "stack/stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
//定义错误代码
#define CONF_OK 0 //操作成功
#define CONF_NO_DATA -1 //没有数据
#define CONF_NO_INIT -2 //未初始化
#define CONF_NO_MEM -3 //申请内存出错
#define CONF_KEY_ERR -4 //键错误
#define CONF_VALUE_ERR -5 //值错误
/*值数据结构*/
typedef struct conf_value
{
char *key;
char **value;
}CONF_VALUE;
/* 键/值对数据结构
* len
* next
*/
typedef struct arg
{
int len;
CONF_VALUE *value;
struct arg *next;
}CONF_ARG;
/* conf-c的数据结构
* fpFILE
* len/
* hash_data/
*/
typedef struct
{
FILE *fp;
int len;
CONF_ARG *hash_data;
}CONF;
//保存配置文件数据结构
//len为当前参数个数
//key为键
//value值
//note为注释
typedef struct creater
{
FILE *fp;
int len;
char *key;
char *value;
char *note;
struct creater *next;
}CONF_CREATER;
//打开并初始化path为配置文件的路经返回CONF数据
CONF *conf_open(const char *path);
//解析配置文件解析正确返回0出错返回小于0的错误代码
int conf_parse(CONF *conf);
//获取当前配置文件中键值对个数
int conf_count(CONF *conf);
//得到所有键
char **conf_key_list(CONF *conf);
//创建一个配置文件path为配置文件的路经
CONF_CREATER *conf_creater_new(const char *path);
/* 添加一个配置键/值对
* value
* note
* #
* :
* 0
* 0
*/
int conf_insert(CONF_CREATER *creater,char *key,char *value,char *note);
//保存配置文件,正确时返回0错误时返回小于0的错误代码
int conf_save(CONF_CREATER *creater);
//释放内存
void conf_free(CONF *conf);
//释放CONF_CREATER内存
void conf_creater_free(CONF_CREATER *creater);
//打印错误信息函数,errcode为错误代码
void conf_error(int errcode);
//根据一个键查找数据
CONF_VALUE *conf_value_get(CONF *conf,const char *key);
//得到所有键值对
CONF_VALUE **conf_value_get_all(CONF *conf);
#endif

11
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,11 @@
cmake_minimum_required(VERSION 3.0)
project(conf-c)
# file(GLOB sources .)
aux_source_directory(src sources)
message(STATUS, "lib src is ${sources}")
add_library(${PROJECT_NAME} SHARED ${sources})
add_library(confc::library ALIAS ${PROJECT_NAME})
set_target_properties(${PROJECT_NAME} PROPERTIES VERSION 0.4 SOVERSION 1)
target_include_directories(${PROJECT_NAME}
PUBLIC ${PROJECT_SOURCE_DIR}/src
)

View File

@ -2,6 +2,10 @@
#include "stack/stack.h"
#include <ctype.h>
extern unsigned int conf_hash_func1(const char *key);
extern unsigned int conf_hash_func2(const char *key);
extern int conf_hash_search(CONF_ARG *arg,char *key,CONF_VALUE **value);
//解析过程的各状态
enum conf_stat
{
@ -15,16 +19,16 @@ enum conf_stat
};
#define POP (*data)
#define ADVANCE (++data)
#define BACK (--data)
#define LEN (data-str)
#define ADVANCE (++data,++offset)
#define BACK (--data,--offset)
#define CONF_GET_VALUE(value,stack) \
{\
if(conf_stack_get_data(stack) == NULL)\
{\
retcode=CONF_KEY_ERR;\
printf("行:%d ",line);\
if(conferr)\
printf("行:%d 列:%d %c",line,offset,POP);\
goto end;\
}\
value=realloc(value,sizeof(char*)*(value_len+2));\
@ -45,6 +49,8 @@ enum conf_stat
}
int line=1; //行
int offset=1; //列
int conferr=0;
//解析对参数
//data为配置文件内容
@ -59,13 +65,15 @@ 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);
int _conf_read_key(char *data,STACK *stack);
//获取值状态
enum conf_stat _conf_value_status(char c);
//读取值
int _conf_read_value(char *data,int len,STACK *stack);
int _conf_read_value(char *data,STACK *stack);
//读取带有引号的值
int _conf_read_value_with_quote(char *data,int len,STACK *stack,char quote);
int _conf_read_value_with_quote(char *data,STACK *stack,char quote);
//读取带有引号的键
int _conf_read_key_with_quote(char *data,STACK *stack,char quote);
//打开配置文件并初始化值
//path为配置文件路径
@ -77,14 +85,16 @@ CONF *conf_open(const char *path)
conf=malloc(sizeof(CONF));
if(conf == NULL)
{
printf("申请内存空间出错!\n");
if(conferr)
printf("申请内存空间出错!\n");
return NULL;
}
//打开配置文件返回FILE指针
if((conf->fp=fopen(path,"rb")) == NULL)
{
printf("打开%s出错!\n",path);
if(conferr)
printf("打开%s出错!\n",path);
return NULL;
}
@ -149,13 +159,15 @@ CONF_CREATER *conf_creater_new(const char *path)
creater=malloc(sizeof(CONF_CREATER));
if(creater == NULL)
{
printf("申请内存空间出错!\n");
if(conferr)
printf("申请内存空间出错!\n");
return NULL;
}
if((creater->fp=fopen(path,"wb")) == NULL)
{
printf("创建配置文件出错!\n");
if(conferr)
printf("创建配置文件出错!\n");
return NULL;
}
@ -164,6 +176,8 @@ CONF_CREATER *conf_creater_new(const char *path)
creater->value=NULL;
creater->note=NULL;
creater->next=NULL;
return creater;
}
//插入一个参数到内存
@ -228,7 +242,7 @@ int conf_save(CONF_CREATER *creater)
void conf_free(CONF *conf)
{
int i;
int j;
//int j;
for(i=0;i != conf->size;++i)
{
@ -278,6 +292,12 @@ void conf_error(int errcode)
case CONF_VALUE_ERR:
printf("错误:错误的值!\n");
break;
case CONF_NO_KEY:
printf("错误:没有键名!\n");
break;
case CONF_NO_VALUE:
printf("错误:没有值!\n");
break;
default:
printf("未知错误!\n");
}
@ -286,8 +306,8 @@ void conf_error(int errcode)
//解析参数
int parse_value(CONF *conf,char *data)
{
//保存解析字符串的首地址
char *str=data;
/* //保存解析字符串的首地址
char *str=data;*/
//状态
int status;
int save_status;
@ -300,6 +320,7 @@ int parse_value(CONF *conf,char *data)
int retcode=CONF_OK;
//多参数个数
int value_len=0;
int index;
//初始化栈和状态
conf_stack_init(&stack);
@ -318,8 +339,11 @@ redo:
status=conf_stat_note;
else if(save_status == conf_stat_key)
{
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
retcode=CONF_NO_VALUE;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
free(value->key);
free(value);
conf_free(conf);
goto end;
}
@ -330,8 +354,9 @@ redo:
status=conf_stat_key;
else
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
retcode=CONF_NO_KEY;
if(conferr)
printf("行:%d 列:%d =",line,offset);
if(value)
{
if(value->key)
@ -354,28 +379,63 @@ redo:
ADVANCE;
else
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
retcode=CONF_NO_VALUE;
if(conferr)
printf("行:%d 列:%d %s",line,offset,value->key);
free(value->key);
free(value);
conf_free(conf);
goto end;
}
++line;
offset=1;
goto redo;
case '\0':
if(status == conf_stat_normal)
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
retcode=CONF_NO_VALUE;
if(conferr)
printf("行:%d 列:%d %s",line,offset,value->key);
free(value->key);
free(value);
conf_free(conf);
goto end;
}
status=conf_stat_done;
break;
case '\'':
case '"':
if(status == conf_stat_start && save_status != conf_stat_key)
status=conf_stat_quote;
else
{
retcode=CONF_KEY_ERR;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
goto end;
}
break;
case ',':
if(save_status == conf_stat_key || status != conf_stat_quote)
{
retcode=CONF_KEY_ERR;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
if(save_status == conf_stat_key)
{
free(value->key);
free(value);
}
goto end;
}
default:
if(save_status == conf_stat_key)
{
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
retcode=CONF_NO_VALUE;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
free(value->key);
free(value);
conf_free(conf);
goto end;
}
@ -391,10 +451,17 @@ redo:
status=conf_stat_start;
save_status=conf_stat_normal;
++line;
offset=1;
goto redo;
//读取键
case conf_stat_start:
data+=_conf_read_key(data,LEN,&stack);
index=_conf_read_key(data,&stack);
if(index == -1)
{
retcode=CONF_KEY_ERR;
goto end;
}
data+=index;
value=malloc(sizeof(CONF_VALUE));
if(value == NULL)
{
@ -404,8 +471,9 @@ redo:
}
if(conf_stack_get_data(&stack) == NULL)
{
retcode=CONF_KEY_ERR;
printf("行:%d ",line);
retcode=CONF_NO_KEY;
if(conferr)
printf("行:%d 列:%d",line,offset);
free(value);
conf_free(conf);
goto end;
@ -431,6 +499,48 @@ redo:
save_status=conf_stat_key;
end_status=_conf_value_status(POP);
break;
case conf_stat_quote:
quote=POP;
ADVANCE;
index=_conf_read_key_with_quote(data,&stack,quote);
if(index == -1)
{
retcode=CONF_KEY_ERR;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
goto end;
}
data+=index;
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_NO_KEY;
if(conferr)
printf("行:%d 列:%d",line,offset);
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;
ADVANCE;
goto redo;
case conf_stat_done:
retcode=CONF_OK;
goto end;
@ -444,8 +554,11 @@ value_redo:
if((save_status != conf_stat_key) ||
(status == conf_stat_key))
{
retcode=CONF_VALUE_ERR;
printf("行:%d ",line);
retcode=CONF_NO_VALUE;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
free(value->key);
free(value);
conf_free(conf);
goto end;
}
@ -463,21 +576,50 @@ value_redo:
break;
//读取值
case conf_stat_normal:
data+=_conf_read_value(data,LEN,&stack);
index=_conf_read_value(data,&stack);
if(index == -1)
{
retcode=CONF_VALUE_ERR;
goto end;
}
data+=index;
CONF_GET_VALUE(value->value,&stack);
while(isspace(POP) && (POP != '\n'))
ADVANCE;
end_status=_conf_value_status(POP);
if(end_status == conf_stat_normal || end_status == conf_stat_quote)
{
retcode=CONF_VALUE_ERR;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
goto end;
}
status=conf_stat_start;
goto value_redo;
//读取带有引号的值
case conf_stat_quote:
quote=POP;
ADVANCE;
data+=_conf_read_value_with_quote(data,LEN,&stack,quote);
index=_conf_read_value_with_quote(data,&stack,quote);
if(index == -1)
{
retcode=CONF_VALUE_ERR;
goto end;
}
data+=index;
CONF_GET_VALUE(value->value,&stack);
ADVANCE;
while(isspace(POP) && (POP != '\n'))
ADVANCE;
end_status=_conf_value_status(POP);
status=conf_stat_start;
if(end_status == conf_stat_normal)
{
retcode=CONF_VALUE_ERR;
if(conferr)
printf("行:%d 列:%d %c",line,offset,POP);
goto end;
}
goto value_redo;
//多参数值读取
case conf_stat_more_key:
@ -561,12 +703,12 @@ CONF_VALUE *conf_value_get(CONF *conf,const char *key)
* 使key
* NULL */
hash=conf_hash_func1(key)%conf->size;
if(conf_hash_search(&conf->hash_data[hash],key,&value))
if(conf_hash_search(&conf->hash_data[hash],(char *)key,&value))
return value;
else
{
hash=conf_hash_func2(key)%conf->size;
if(conf_hash_search(&conf->hash_data[hash],key,&value))
if(conf_hash_search(&conf->hash_data[hash],(char *)key,&value))
return value;
}
@ -606,7 +748,12 @@ CONF_VALUE **conf_value_get_all(CONF *conf)
return value;
}
int _conf_read_key(char *data,int len,STACK *stack)
void conf_pos_msg_err(int on)
{
conferr=on;
}
int _conf_read_key(char *data,STACK *stack)
{
int i=0;
char c;
@ -618,14 +765,15 @@ int _conf_read_key(char *data,int len,STACK *stack)
}
if(POP == '\n')
{
printf("行:%d 列:%d 解析出错\n",line,i-len);
return 0;
if(conferr)
printf("行:%d 列:%d 解析出错!",line,offset);
return -1;
}
do
{
c=POP;
if(isspace(c) || c == '=' || c == '#')
if(isspace(c) || c == '=' || c == '#' || c == ',' || c == '\'' || c == '"')
break;
conf_stack_push(stack,c);
++i;
@ -652,7 +800,7 @@ enum conf_stat _conf_value_status(char c)
}
}
int _conf_read_value(char *data,int len,STACK *stack)
int _conf_read_value(char *data,STACK *stack)
{
char c;
int i=0;
@ -664,14 +812,15 @@ int _conf_read_value(char *data,int len,STACK *stack)
}
if(POP == '\n')
{
printf("行:%d 列:%d 解析出错!\n",line,i-len);
return 0;
if(conferr)
printf("行:%d 列:%d 解析出错!",line,offset);
return -1;
}
do
{
c=POP;
if(isspace(c) || c == ',' || c == '#')
if(isspace(c) || c == ',' || c == '#' || c == '\'' || c == '"')
break;
conf_stack_push(stack,c);
@ -682,26 +831,22 @@ int _conf_read_value(char *data,int len,STACK *stack)
return i;
}
int _conf_read_value_with_quote(char *data,int len,STACK *stack,char quote)
int _conf_read_value_with_quote(char *data,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;
if(conferr)
printf("行:%d 列:%d 解析出错!",line,offset);
return -1;
}
do
{
c=POP;
if(c == quote)
if(c == quote || c == '\n')
break;
conf_stack_push(stack,c);
@ -709,8 +854,37 @@ int _conf_read_value_with_quote(char *data,int len,STACK *stack,char quote)
ADVANCE;
}while(c);
if(c == '\0')
return 0;
if(c == '\0'|| c == '\n')
return -1;
return i;
}
int _conf_read_key_with_quote(char *data,STACK *stack,char quote)
{
char c;
int i=0;
if(POP == '\n')
{
if(conferr)
printf("行:%d 列:%d 解析出错!",line,offset);
return -1;
}
do
{
c=POP;
if(c == quote || c == '\n')
break;
conf_stack_push(stack,c);
++i;
ADVANCE;
}while(c);
if(c == '\n' || c == '\0')
return -1;
return i;
}

View File

@ -1,5 +1,7 @@
/* VERSION : 1.1
* Date :2014-10-12
/* VERSION : 1.2
* Date : 2014-10-12
* : (Brisk)
* &BUG : briskgreen@163.com
* conf-cc/
* 使MIT使/
*
@ -13,6 +15,7 @@
//#include "stack/stack.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
//定义错误代码
@ -22,6 +25,8 @@
#define CONF_NO_MEM -3 //申请内存出错
#define CONF_KEY_ERR -4 //键错误
#define CONF_VALUE_ERR -5 //值错误
#define CONF_NO_KEY -6 //没有键名
#define CONF_NO_VALUE -7 //没有值
#define HASH_DEFAULT 100 //默认哈希表大小
#define HASH_SP 0.7 //当前哈希表中数据个数大于等于70%时表大小动态增长70%
@ -118,4 +123,7 @@ CONF_VALUE *conf_value_get(CONF *conf,const char *key);
//得到所有键值对
CONF_VALUE **conf_value_get_all(CONF *conf);
//是否打印错误信息位置
void conf_pos_msg_err(int on);
#endif

View File

@ -1,7 +1,17 @@
#V1.1
V1.1 at 2014-10-12
1、使用动态散列表存储存数
2、去除单个字符串长度512字节限制
3、CONF数据结构添加size成员标示散列表大小
4、更新解析
5、更新一些BUG
V1.2 at 2014-10-12
1、更新错误提示添加位置提示
2、添加conf_pos_msg_err接口控制是否在错误时打印信息
3、键名添加引号支持特殊键名
4、修复一些BUG
V1.3 at 2017-12-28
1、修复一些bug