ini文件读取

来源:互联网 发布:伊巴卡生涯数据 编辑:程序博客网 时间:2024/06/05 15:14
#ifndef INI_FILES_H_#define INI_FILES_H_#ifdef __cplusplusextern "C" {#endif#define max_sec_len 20#define max_key_len 20#define max_val_len 64#define max_section_counts 100struct ini_file;typedef struct ini_file* ini_file_handle;/** *  函数:   load_ini_file*创建一个ini文件句柄 *  参数:  *          const char * const f_name ini文件全名,包括文件路径  *  返回值: *          NULL 创建ini文件句柄失败 *非NULL 创建ini文件句柄成功 *  版本号:1.0 */ini_file_handle load_ini_file(const char*const f_name);/** *  函数:   get_value           *获取对应的section,key值 *  参数:  *          ini_file_handle h             ini文件句柄 *          const char * const s_name     section名称 *          const char * const k_name     key名称 *  *  返回值: *NULL  没有找到对应的section,key值 *非NULL 指向对应的section,key值 *  版本号:1.0 */const char*const get_value(ini_file_handle h, const char*const s_name,const char*const k_name);/** *  函数:   get_section           *根据key,以及key对应的值返回包含第一个这个值得section名称 *  参数:  *          ini_file_handle h           ini文件句柄 *          const char * const k_name   key名称 *          const char * const k_val    key对应的值 *  *  返回值: *          NULL    没有找到包含key=value的section *非NULL  指向第一个包含key=value的section名称 *  版本号:1.0 * */const char*const get_section(ini_file_handle h,const char*const  k_name,const char*const k_val);/** *  函数:   find_section           *查找该ini文件中是否包含一个特定的section *  参数:  *          ini_file_handle h          ini文件句柄 *          const char * const s_name  section名称  *  返回值: *          NULL   在该ini文件中没有找到指定的section *非NULL 指向ini文件中的section名称 *  版本号:1.0 * */const char*const find_section(ini_file_handle h,const char*const s_name);/** *  函数:   unload_ini_file           * *  参数:  *          ini_file_handle h  *  返回值: *          void *  版本号:1.0 * */void unload_ini_file(ini_file_handle h);#ifdef __cplusplus}#endif#endif /* INI_FILES_H_ */
#include <ini_files.h>#include <string.h>#include <errno.h>#include <stdlib.h>#include <stdio.h>#ifndef _countof#define _countof(x) sizeof(x)/sizeof(x[0])#endif#define hints printf#define max_line_count ((max_key_len + max_val_len) * 2)#define common_checked(exp,ret) do{\if(exp)\{\hints("%s(%d)"#exp":error = %s(%d)\n",__FUNCTION__,__LINE__,strerror(errno),errno);\ret;\}\}while(0)struct key_values{char k_name[max_key_len];char v_valu[max_val_len];};struct section{struct key_values kv_sets[max_section_counts];int key_counts;char s_name[max_sec_len];};struct ini_file {struct section sections[max_section_counts];int sec_counts;};static int parse_ini_section(const char*const line,struct section*const sec){int ret = sscanf(line,"[%[^]]",sec->s_name);if(1 != ret){hints("parse section name failed = %s\n",line);return 0;}sec->key_counts = -1;return 1;}static int parse_ini_keyval(const char*const line,struct section*const sec){int j = ++(sec->key_counts);char*const k_name = sec->kv_sets[j].k_name;char*const k_valu = sec->kv_sets[j].v_valu;int ret = sscanf(line,"%[^=]=%s",k_name,k_valu);if (2 != ret){hints("parse key=value pare failed %s\n",line);return 0;}return 1;}static const char*const filter_ini_line(char*const line){char* commnet_pos = NULL;if (NULL == line){return line;}commnet_pos = strchr(line,';');if(NULL == commnet_pos){return line;}*commnet_pos = '\0';return (0 == strlen(line)) ? NULL : line;}static int parse_ini_context(FILE* f,struct section f_context[max_section_counts]){int i = 0;for (i = -1; !feof(f) && i < max_section_counts -1;) {char buffer[max_line_count] = {0};char*const line = fgets(buffer,sizeof(buffer),f);if (NULL == filter_ini_line(line)){continue;}if(NULL != strchr(line,'[') && NULL != strchr(line,']')){if(!parse_ini_section(line,&f_context[++i])){break;}continue;}if(NULL != strchr(line,'=')){if(!parse_ini_keyval(line,&f_context[i])){break;}continue;}hints("read error line %s\n",line);}return i;}static int load_ini_context(const char*const file_name, struct ini_file*const f_context) {FILE* file_handle = fopen(file_name, "r");common_checked(NULL == file_handle,return -1);memset(f_context,0,sizeof(struct ini_file));f_context->sec_counts = parse_ini_context(file_handle,f_context->sections);fclose(file_handle);return f_context->sec_counts;}ini_file_handle load_ini_file(const char*const f_name) {struct ini_file* ret = NULL;common_checked(NULL == f_name,return NULL);ret = (struct ini_file*)malloc(sizeof(struct ini_file));common_checked(NULL == ret , return NULL);if (load_ini_context(f_name,ret) <= 0){free(ret);return NULL;}return ret;}const char*const get_value(ini_file_handle h, const char*const s_name,const char*const k_name){int i = 0, j = 0;common_checked(NULL == s_name || NULL == k_name,return NULL);for (i = 0; i <= h->sec_counts; ++i) {if(0 == strcmp(s_name,h->sections[i].s_name)){break;}}if(i > h->sec_counts){hints("get section [%s] failed\n",s_name);return NULL;}for (j = 0; j <= h->sections[i].key_counts; ++j) {const struct key_values*const kv = &h->sections[i].kv_sets[j];if(0 == strcmp(k_name,kv->k_name)){return kv->v_valu;}}hints("get [%s] %s value failed\n",s_name,k_name);return NULL;}const char*const get_section(ini_file_handle h,const char*const k_name,const char*const k_val){int i = 0, j = 0;common_checked(NULL == k_name || NULL == k_val,return NULL);for (i = 0; i <= h->sec_counts; ++i) {for (j = 0; j <= h->sections[i].key_counts; ++j) {const char*const name = h->sections[i].kv_sets[j].k_name;const char*const valu = h->sections[i].kv_sets[j].v_valu;if( 0 == strcmp(k_name,name) && 0 == strcmp(k_val,valu)){return h->sections[i].s_name;}}}hints("get section failed by %s=%s\n",k_name,k_val);return NULL;}const char*const find_section(ini_file_handle h,const char*const s_name){int i = 0;common_checked(NULL == s_name,return NULL);for (i = 0; i <= h->sec_counts; ++i) {if(strcmp(h->sections[i].s_name,s_name) == 0){return h->sections[i].s_name;}}hints("find section failed %s\n",s_name);return NULL;}void unload_ini_file(ini_file_handle h){free(h);}#ifdef ini_file_test#include <assert.h>static void show_context(ini_file_handle h){int i= 0, j = 0;common_checked(NULL == h,return);for (i = 0; i <= h->sec_counts; ++i) {hints("[%s]\n",h->sections[i].s_name);for (j = 0; j <= h->sections[i].key_counts; ++j) {const struct key_values*const kv = &h->sections[i].kv_sets[j];hints("%s=%s\n",kv->k_name,kv->v_valu);}}}static void check_context(ini_file_handle h){int i = 0, j = 0;for (i = 0; i <= h->sec_counts; ++i){assert(NULL != find_section(h,h->sections[i].s_name));for (j = 0; j <= h->sections[i].key_counts;++j){assert(NULL != get_value(h,h->sections[i].s_name,h->sections[i].kv_sets[j].k_name));assert(NULL != get_section(h,h->sections[i].kv_sets[j].k_name,h->sections[i].kv_sets[j].v_valu));}}assert(NULL == get_section(h,"aa","bb"));assert(NULL == get_value(h,"aabb","bbaa"));assert(NULL == find_section(h,"acd"));}int main(int argc,char* argv[]){if(2 == argc){ini_file_handle fh = load_ini_file(argv[1]);common_checked(NULL == fh , return -1);show_context(fh);check_context(fh);unload_ini_file(fh);return 0;}printf("usage : %s file_name\n",argv[0]);return -1;}#endif