今日需要在C++中解析ini格式的配置文件,搜索了一下,在github上找到了一个stars较多的开源实现 https://github.com/brofield/simpleini/tree/master。
网络上有一些介绍该开源实现的各API功能的文章,本文仅作为一个补充。
集成
这个开源实现的集成方法很简单,只需要包含一个头文件即可。
语言标准
该开源实现的头文件采用了c++11的语法,看了下,也只是一个std::next方法,如果自己的代码用的C++标准版本低于11,也只需要patch一下std::next方法即可。
实现简介
该实现初始会要求加载ini文件(或者内存数据),加载时会先find每一个section,每找到一个section后,都会在该section后查找所有的key以及对应的value。
内存中,整个配置文件被解析后,是按照如下架构组织的:
/** map keys to values */
typedef std::multimap<Entry,const SI_CHAR *,typename Entry::KeyOrder> TKeyVal;
/** map sections to key/value map */
typedef std::map<Entry,TKeyVal,typename Entry::KeyOrder> TSection;
/** set of dependent string pointers. Note that these
pointers are dependent on memory owned by CSimpleIni.
*/
typedef std::list<Entry> TNamesDepend;
可以看到,这里最中的类是Entry这个类,每个section、key以及value的具体信息都存储在一个个entry对象中,包括内容、注释等等信息。
在该实现中,所有的value都是以字符串解释及存储的,当调用GetBoolValue时,该API会将字符串转为bool值;调用GetLongValue时,会将字符串转为long类型。
在初始加载并解析ini配置内容时,最重要的函数有两个:FindEntry和AddEntry,FindEntry函数会从内存中顺序读取字节并解析为Section/Key/Value,AddEntry会将FindEntry得到的结果赋值给Entry对象。
在读取配置时,最重要的就是GetValue这个API,该API要求传入Section和Key的名称,然后通过两次map的find找到对应的value值;另外由于传入的是字符串,而map的key都是Entry类型的对象,所以还会有两次Entry对象的构造。当有很多的section、key时,可以考虑添加直接以section的Entry对象、key的Entry对象为入参的API,可以节省一些查找的时间。
内存使用
注意,在加载ini文件时,会先new一个buffer1用于存储读取到的文件内容,之后再new一个buffer2用于存储格式转换后的内容;在构造map时,通常用的是浅拷贝,map中存放的只是指针,具体的内容在buffer2中。之后buffer2会驻留在内存中,buffer1在load结束后会释放。