C++编程之配置文件解析:在实际项目中,经常会把软件的某些选项写入配置文件。 Windows 平台上的 INI 文件格式简单易用,设计了一个“类” ini_parser 来读写 INI 格式的配置文件。
struct ini_parser 可以解析 INI 格式的字符串、文件,也可以将内存中的符合 INI 格式的数据写入文件,能够支持 Windows 、Linux、Android等多平台。目前暂不支持选项分组功能。
功能相对简单,直接看源码吧。
下面是头文件:
structsingle_list;
structini_parser{
structsingle_list*keyvalues;
int(*parse_file)(structini_parser*,constchar*file);
int(*parse_string)(structini_parser*,constchar*text);
char*(*value)(structini_parser*,constchar*key);
void(*set_value)(structini_parser*,constchar*key,constchar*value);
void(*remove)(structini_parser*,constchar*key);
int(*save_to_file)(structini_parser*,constchar*file);
void(*deletor)(structini_parser*ini);
};
structini_parser*new_ini_parser(); struct init_parser 的声明符合我们在本系列文章中提到的面向对象框架,需要说明的是,一旦 deletor 方法被调用, ini_parser 的实例将不再允许访问。
下面是源文件:
#include"ini_parser.h"
#includ
e
#include
structtag_value_pair{
structslist_nodenode;
char*szTag;
char*szValue;
};
typedefstructtag_value_pairtag_value;
staticvoid_tag_value_free(structslist_node*node)
{
if(node)delete_tag_value_pair(node);
}
staticint_tag_value_hittest(structslist_node*node,void*key)
{
returnstrcmp((char*)tag,((structtag_value_pair*)node)->szTag);
}
staticstructsingle_list*new_tag_value_list()
{
returnnew_single_list(_tag_value_free,_tag_value_hittest);
}
staticstructtag_value_pair*new_tag_value_pair()
{
structtag_value_pair*pair=(structtag_value_pair*)malloc(sizeof(structtag_value_pair));
pair->node.next=0;
pair->szTag=0;
pair->szValue=0;
returnpair;
}
staticstructtag_value_pair*make_tag_value_pair(char*tag,char*value)
{
structtag_value_pair*pair=0;
if(!tag||!value)return0;
pair=(structtag_value_pair*)malloc(sizeof(structtag_value_pair));
pair->szTag=strdup(tag);
pair->szValue=strdup(value);
pair->node.next=0;
returnpair;
}
staticstructtag_value_pair*parse_line(char*line,intlen)
{
structtag_value_pair*pair=0;
intcount=0;
char*p=line;
char*end=0;m
char*start=line;
if(!p)return0;
while(*p=='')++p;
/*blankline*/
if(p-line==len||
*p=='\r'||
*p=='\n'||
*p=='\0')return0;
/*donotsupportgroup*/
if(*p=='[')return0;
/*comments*/
if(*p=='#')return0;
/*extractkey*/
start=p;
end=line+len;
while(*p!='='&&p!=end)++p;
if(p==end)
{
/*none'=',invalidline*/
return0;
}
end=p-1;
while(*end=='')--end;/*skipblankattheend*/
count=end-start+1;
pair=new_tag_value_pair();
pair->szTag=malloc(count+1);
strncpy(pair->szTag,start,count);
pair->szTag[count]=0;
/*extractvalue*/
++p;
end=line+len;/*nextposofthelastchar*/
while(*p==''&&p!=end)++p;
if(p==end)
{
delete_tag_value_pair(pair);
return0;
}
start=p;
--end;/*tothelastchar*/
if(*end=='\n'){*end=0;--end;}
if(*end=='\r'){*end=0;--end;}
count=end-start+1;
if(count>0)
{
pair->szValue=malloc(count+1);
strncpy(pair->szValue,start,count);
pair->szValue[count]=0;
}
/*releaseemptykey-valuepair*/
if(!pair->szValue)
{
delete_tag_value_pair(pair);
return0;
}
returnpair;
}
staticint_