UtilBox(ub)基础组件 -- ConfigureLoader文件配置读取模块
来源:互联网 发布:求主析取范式算法 编辑:程序博客网 时间:2024/04/30 17:36
好久没更新博客了哈,今天抽空把之前写了一部分的东西拿出来继续分享。
linux的getopt()和getopt_long()大家都用过,读取命令行参数,比如./test -h 127.0.0.1 -c 100 --port 8080类似这样的。好多脚本语言python,shell这样获取比较简单直接sh就可以了(比如echo "./server --start --port 8080" >> ./start.sh)。有些软件为了方便,都有一个configure文件,通过对configure文件的修改来实现软件的配置控制,熟悉Java开发的对此应该很有感触,Tomcat/Apache的webserver,配置文件一大堆,基本不太可能通过启动时候传入,很多Linux软件都是通过configure文件来设置。
通过configure文件的方式,既方便了传入配置的启动,还可以在文件中针对某一个配置进行注释性的说明,而且也方便查阅。
OK,下面就来说一下这个ConfigureLoader(一下简称cfgloader),它主要实现了对文件中文本的行解析,配置都是通过KeyValue对来编写,可以添加自己的注释(以#开头) :
#server端口号port : 9999#这是关于线程数的#设置threads : 10#最大连接数max_conns : 1024
KeyValue通过":"冒号来分割,并忽略其中的空格。下面来说一下接口,首先一个conf_load(const char*)来获取用户的数据,为什么不用FILE*或者filedescriptor,因为这样限制比较大,这些配置也接受来自getopt哈。然后就是相应的获取KV的接口,conf_get(const char* key),通过传入key获取value,这里可以得到的数据类型是整数或者字符串。如果查询不到或者转换失败会返回NULL或者0。这里有一个小问题待考究,就是conf_get_integer返回long,而long是atol()函数获得的,所以即使用户写的不是数字,也会转化成0,这个可以通过自己写转换,或者传入一个int* error,或者返回INT_MIN来设置成功失败。
接口:
#ifdef __cplusplusextern "C" {#endiftypedef struct kv_t { char* k; char* v;}kv_t;typedef struct config_t{ kv_t* kv_list; size_t count; size_t used;}config_t;/** *@brief : load configure string from char* , * and parse. string MUST like "key:value" * *@param : [in] configure string * *@return : configure structure */config_t* ub_config_load(const char*);/** *@brief : get number from spicified key * *@param : [in] configure structrue to be released * [out] is error */long ub_config_get_integer(config_t* cfg, const char* key);** *@brief : get CONST char string from spicified key * *@param : configure structrue to be released */const char* ub_config_get_string(config_t* cfg, const char* key);/** *@brief : load configure string from char* , * and parse. * *@param : configure structrue to be released */void ub_config_release(config_t*);size_t ub_config_used(config_t*);void ub_config_print(config_t*);#ifdef __cplusplus}#endif
实现的话其实比较简单 , 晒出parse整个字串的代码把 ,其他的先不care :
const char* line = cfg; const char* cur = cfg; // iterator char string while((line-cfg)!=len+1) { // still in same line if (*(line)!='\n' && (*line)!='\0') { line++; continue; } else { // first check the cacpacity if (config->used >= config->count) { // extends space config->kv_list = (kv_t*)realloc(config->kv_list,sizeof(kv_t)*config->count*2); if (NULL == config->kv_list) goto cleanup; else { config->count *= 2; } } kv_t* kv_pair = &config->kv_list[config->used]; /** * For Key */ // skip blank sapce while(*cur==' ') cur++; // ignore the comment (start with "#") if (*cur == '#' || *cur == '\n' || *cur == '\r') goto keepgo; const char* key = cur; while(*key!=' '&&*key!=':'&&key!=line) key++; // alloc len(key) + '\0' space char* tmp_key = (char*)calloc(1,key-cur+1); memcpy(tmp_key,cur,key-cur); int breakout = 0; while(*cur++!=':') { if (cur==line) { free(tmp_key); breakout = 1; } } // don't find value if (breakout) goto keepgo; /** * For Value */ // skip blank space after ": " while(*cur==' ') cur++; // oops , bad string if (cur>=line) { free(tmp_key); goto keepgo; } const char* value = cur; while(value<=line) { if (*(value+1)==' ' || value+1==line) break; else value++; } char* tmp_value = (char*)calloc(1,value-cur+2); // don't copy "\n" memcpy(tmp_value,cur,value-cur+1); // kv ok config->used++; kv_pair->k = tmp_key; kv_pair->v = tmp_value;keepgo: line++; cur = line; } } return config;cleanup : free(config);check_exception : return NULL;}
这个些地方又可以优化的部分,大家可以自己考虑一下,比如放入kv_list数组时候可以有序,这样检索时候可以做二分。或者用Hash,但在小数据量下,Hash的效果并不一定比二分优,反而可能更低。字符切割是自己写的。双指针移动,这里可以考虑省去小部分代码。。。
- UtilBox(ub)基础组件 -- ConfigureLoader文件配置读取模块
- UtilBox(ub)基础组件 -- Log日志(1)
- UtilBox(ub)基础组件 -- Log日志(2)
- UtilBox(ub)基础组件 -- epoll_server网络事件模型
- UtilBox(ub)基础组件 -- EasyCurl 发送http请求(1)
- UtilBox(ub)基础组件 -- EasyCurl 发送http请求(2)
- UtilBox(ub)基础组件 -- 并发任务队列Taskqueue/TaskDispatcher (一)
- UtilBox基础组件
- Java学习基础组件---Properties文件的读取
- 基础调试命令 - u/ub/uf
- 模块配置组件 Example 程序
- 模块配置组件 Example 程序
- golang基础-beego读取配置_输出log日志、tailf组件读取log、配置zookeeper_kafka、发送log至kafka
- python linecache 模块读取文件
- 文件读取 基础问题
- ini文件配置模块
- Ubuntu如何安装和配置Conky_我的Ub…
- HTML5文件读取FileReader及文件读取模块的封装
- rcp(插件开发)深入理解菜单(Menu)功能及其扩展点
- 如何在Android中启动JAVA程序
- GDB的使用方法(推荐)
- 企业的任何方法均可融入敏捷技术
- CScrollView中画图问题
- UtilBox(ub)基础组件 -- ConfigureLoader文件配置读取模块
- MFC对话框最小化到托盘编程实现步骤
- read by other session等待事件
- android4.0 编译报错的解决方法
- amcharts使用总结
- Ubuntu:MySQL数据库和相关工具的下载
- Could not instantiate class named NSLayoutConstraint
- Android命令am简介
- php和java两者的对比与取舍