libconfig第一篇———使用指南

来源:互联网 发布:淘宝买高达模型推荐 编辑:程序博客网 时间:2024/05/02 01:02
 

libconfig第一篇———使用指南

http://blog.csdn.net/crazyhacking/article/details/9668981
官网:http://www.hyperrealm.com/libconfig/

1 libconfig是什么?

Libconfig是一个结构化的配置文件库,它可以定义一些配置文件,例如test.cfg . 它比xml可读性更好,而且更简洁。而且不像xml,它是 type-aware类型自我感知的,因此不需要做string parsing (分词?). 而ini太弱。


2 配置文件说明(摘自手册翻译)

libconfig支持结构化、层次化的配置。这些配置可以从文件中读取或写入文件,也可以在内存中操作。

一个配置由一组setting构成,setting由名字(name)关联,并有相应的值(value)。一个值(value)可以是以下任意一种类型:

标量值(scalarvalue):整型、64位整型、浮点数、布尔值或者字符串

数组(array):一组标量值的序列,所有的标量值必须为同一类型

群组(group):多个setting的集合

列表(list):一组值(value)的序列,各个值可(value)以分别为不同的类型,其他的列表也可以包含其中。


观察下面这一个层次化GUI应用程序的配置文件,它阐明了一个配置文件语法所有的元素。


#Exampleapplicationconfigurationfile

version="1.0";

application:

{

window:

{

title="MyApplication";

size={w=640;h=480;};

pos={x=350;y=250;};

};

list=(("abc",123,true),1.234,(/*anemptylist*/));

books=(

{

title="TreasureIsland";

author="RobertLouisStevenson";

price=29.95;

qty=5;

},

{

title="SnowCrash";

author="NealStephenson";

price=9.99;

qty=8;

}

);

misc:

{

pi=3.141592654;

bigint=9223372036854775807L;

columns=["LastName","FirstName","MI"];

bitmask=0x1FC3;

};

};



包含在配置中的某个setting可以用path来唯一定义,path用点号分隔连接多个名字(name),由最顶层的群组(group)开始,到setting自身结束。path中的每个名字都是一个setting的名字;如果这个setting没有名字,那是因为它是数组(array)或列表(list)中的一个元素。用方括号包含一个整型索引值可以用来表示它的名字。

举个例子,在上面这个多层的配置文件中,名为xsetting,指向它的path就是application.window.pos.x;名为versionsetting,指向它的path就是很简单的version;指向book列表中第2book,名为titlesetting,指向它的path就是application.books.[1].title

一个值(value)的数据类型由它本身的格式所决定。

如果一个值用双引号围住,那它被认为是一个字符串;

如果它看起来是一个整型或浮点数,那它就被认为是整型或浮点数;

如果它是TRUEFALSEtruefalse中的某个,那它就被认为是布尔值(TRUEFALSE大小写不敏感,比如tRuEfALse也被看作为TRUEFALSE);

如果在方括号中包含了多个逗号分隔的值,那它就被认为是数组;

如果在圆括号中包含了多个逗号分隔的值,那它就被认为是列表;

任何值如果不符合上述的标准,则会被认为是无效并且产生一个分析错误。

所有的名字(name)都是大小写敏感的,并且只能由数字字母、横杠(-),下横杠(_)和星号(*)组成,而且必须以字母或星号开头。其他字符都是非法的。

CC++中,整型、64位整型、浮点数和字符串分别被映射为intlonglongdoubleconstchar *。布尔型在C中被映射为int,在C++中被映射为bool


下面的章节会从更多的细节方面描述配置文件语法的各个元素。

  1. setting

一个setting的格式如下:

name= value;

或者

name: value;

结尾的分号是必须要有的,空白字符会被忽略;

value可以是标量值、数组、群组或者列表。


    1. 群组(group

一个群组的格式如下:

{setting1,setting2, …}

一个群组可以包含任意个setting,但是在群组中,每个setting的名字必须是唯一的。


    1. 数组(array

一个数组的格式如下:

[value,value, …]

一个数组可以有零个或者多个元素,但是每个元素都必须是相同类型的标量值。


    1. 列表(list

一个列表的格式如下:

(value,value, …)

一个列表可以有零个或者多个元素,而且每个元素可以分别是标量值、数组、群组或其他列表。


    1. 整型值

整型值(int)可以用两种方式表示:十进制数,由0-9组成,并且可以带+-;十六进制数,0x打头并且用十六进制数表示。


    1. 64位整型值

64位整型值(longlong)表示方法和整型值基本一致,但是需要在最后加上L来表明它是一个64位整型值。比如0L表示一个64位的0值。


    1. 浮点值

浮点值由一个十进制数,可以带正负符号,然后带上一个可选的指数。这个可选的指数又由字母E或者e加上一个可选的正负符号再加上具体的数字。


    1. 布尔值

布尔值的取值只能是truefalse,包括另外大小写混合的写法,比如tRueFaLSe


    1. 字符串

字符串是由双引号引起来的任意文本。字符串里的双引号由转义符\”替代,其他的转义符比如\\\f\r\n\t都可以被辨认,并且与通常的理解一致。

另外,转义符\x也被支持。它后面必须跟上刚好两个十六进制数,用来表示8位的ASCII值,比如\xFF表示值为0xFFASCII码。

其他的转义符都不被支持。

相邻的两个字符串会被自动连接,就像C的编码规则一样。在把一个很长得字符串格式化为很短的字符串的时候,就会很有用。比如,下面三种写法的字符串都是等价的。


"Thequickbrownfoxjumpedoverthelazydog."


"Thequickbrownfox"

"jumpedoverthelazydog."


"Thequick"/*注释*/"brownfox"//其他注释

"jumpedoverthelazydog."


    1. 注释

在配置文件中允许三种类型的注释

脚本风格的注释:从#开始到行尾的内容都为注释。

C风格的注释:/**/之间的内容,即使是跨行的,都被认为是注释。

C++风格的注释:从//开始到行尾的内容都被认为是注释。

如预料的一样,注释符在双引号字符串中出现,会被认为是字符串的文本而不是注释符。

在读取配置的时候,注释内容会被忽略,它们不会被认为是配置的一部分。因此,如果配置回写到文件中,原配置文件中的一些注释会丢失。


    1. 包含指令

一个配置文件可能包含了另外一个配置文件的内容,这时就要用到包含指令。这个指令产生的效果就是在包含点内联了那个文件的内容。

一个包含指令必须出现在它所在的那一行中,格式如下:

@include“filename”

文件名中反斜杠和双引号必须用转义符\\\”来替代。

举例说明,观察下面两个配置文件

#file:quote.cfg

quote="Criticismmaynotbeagreeable,butitisnecessary."

"Itfulfilsthesamefunctionaspaininthehuman"

"body.Itcallsattentiontoanunhealthystateof"

"things.\n"

"\t--WinstonChurchill";


#file:test.cfg

info:{

name="WinstonChurchill";

@include"quote.cfg"

country="UK";

};

包含文件最大只能嵌套10层,突破这个限制会产生一个分析错误。

与注释类似,包含指令也不是配置文件句法的一部分。包含指令在配置文件被分析之前就已经被处理了。因此,当配置回写回文件的时候,包含指令不会被保留。目前还不支持让程序把包含指令插入到配置文件中。


3C++版本的api说明

简单介绍几个重要的c++ 函数,完整版请参考官网。

说明参数为char *版本的对应也有 参数为string版本的

bool lookupValue (const char *path, int &value) 这个函数重载,参数2为各种类型的

These are convenience methods for looking up the value of a setting with the given path. If the setting is found and is of an appropriate type, the value is stored in value and the method returns true. Otherwise, value is left unmodified and the method returns false. These methods do not throw exceptions.

例子

int var1;          double var2;          const char *var3;                    if(config.lookupValue("values.var1", var1)             && config.lookupValue("values.var2", var2)             && config.lookupValue("values.var3", var3))          {            // use var1, var2, var3          }          else          {            // error handling here          }


— Method on Config: Setting & lookup (const std::string &path)
— Method on Config: Setting & lookup (const char * path)

These methods locate the setting specified by the path path. If the requested setting is not found, a SettingNotFoundException is thrown.

— Method on Config: bool exists (const std::string &path)
— Method on Config: bool exists (const char *path)

These methods test if a setting with the given path exists in the configuration. They return true if the setting exists, and false otherwise. These methods do not throw exceptions.

settings可以直接呗转化为各种类型(我们知道lookup返回的是路径)

The following examples demonstrate this usage:

          long width = config.lookup("application.window.size.w");                    bool splashScreen = config.lookup("application.splash_screen");                    std::string title = config.lookup("application.window.title");


— Method on Setting: bool lookupValue (const char *name, bool &value)
— Method on Setting: bool lookupValue (const std::string &name, bool &value)
— Method on Setting: bool lookupValue (const char *name, int &value)
— Method on Setting: bool lookupValue (const std::string &name, int &value)

These are convenience methods for looking up the value of a child setting with the given name. If the setting is found and is of an appropriate type, the value is stored in value and the method returns true. Otherwise, value is left unmodified and the method returns false. These methods do not throw exceptions.

    int var1;          double var2;          const char *var3;                    if(setting.lookupValue("var1", var1)             && setting.lookupValue("var2", var2)             && setting.lookupValue("var3", var3))          {            // use var1, var2, var3          }          else          {            // error handling here          }


— Method on Setting: Setting & add (const std::string &name, Setting::Type type)
— Method on Setting: Setting & add (const char *name, Setting::Type type)

These methods add a new child setting with the given name and type to the setting, which must be a group. They return a reference to the new setting. If the setting already has a child setting with the given name, or if the name is invalid, a SettingNameException is thrown. If the setting is not a group, aSettingTypeException is thrown.

Once a setting has been created, neither its name nor type can be changed.

— Method on Setting: Setting & add (Setting::Type type)

This method adds a new element to the setting, which must be of type TypeArray or TypeList. If the setting is an array which currently has zero elements, the type parameter (which must be TypeIntTypeInt64TypeFloatTypeBool, or TypeString) determines the type for the array; otherwise it must match the type of the existing elements in the array.

The method returns the new setting on success. If type is a scalar type, the new setting will have a default value of 0, 0.0, false, or NULL, as appropriate.

The method throws a SettingTypeException if the setting is not an array or list, or if type is invalid.

— Method on Setting: void remove (const std::string &name)
— Method on Setting: void remove (const char *name)

These methods remove the child setting with the given name from the setting, which must be a group. Any child settings of the removed setting are recursively destroyed as well.

If the setting is not a group, a SettingTypeException is thrown. If the setting does not have a child setting with the given name, aSettingNotFoundException is thrown.

— Method on Setting: void remove (unsigned int index)

This method removes the child setting at the given index index from the setting, which must be a group, list, or array. Any child settings of the removed setting are recursively destroyed as well.

If the setting is not a group, list, or array, a SettingTypeException is thrown. If index is out of range, a SettingNotFoundException is thrown.

— Method on Setting: const char * getName ()

This method returns the name of the setting, or NULL if the setting has no name. Storage for the returned string is managed by the library and released automatically when the setting is destroyed; the string must not be freed by the caller. For safety and convenience, consider assigning the return value to astd::string.

— Method on Setting: std::string getPath ()

This method returns the complete dot-separated path to the setting. Settings which do not have a name (list and array elements) are represented by their index in square brackets.

— Method on Setting: Setting & getParent ()

This method returns the parent setting of the setting. If the setting is the root setting, a SettingNotFoundException is thrown.

— Method on Setting: bool isRoot ()

This method returns true if the setting is the root setting, and false otherwise.

— Method on Setting: int getIndex ()

This method returns the index of the setting within its parent setting. When applied to the root setting, this method returns -1.

— Method on Setting: Setting::Type getType ()

This method returns the type of the setting. The Setting::Type enumeration consists of the following constants: TypeIntTypeInt64TypeFloat,TypeStringTypeBooleanTypeArrayTypeList, and TypeGroup.

— Method on Setting: Setting::Format getFormat ()
— Method on Setting: void setFormat (Setting::Format format)

These methods get and set the external format for the setting.

The Setting::Format enumeration consists of the following constants: FormatDefault and FormatHex. All settings support the FormatDefault format. The FormatHex format specifies hexadecimal formatting for integer values, and hence only applies to settings of type TypeInt and TypeInt64. If format is invalid for the given setting, it is ignored.

— Method on Setting: bool exists (const std::string &name)
— Method on Setting: bool exists (const char *name)

These methods test if the setting has a child setting with the given name. They return true if the setting exists, and false otherwise. These methods do not throw exceptions.

— Method on Setting: int getLength ()

This method returns the number of settings in a group, or the number of elements in a list or array. For other types of settings, it returns 0.

— Method on Setting: bool isGroup ()
— Method on Setting: bool isArray ()
— Method on Setting: bool isList ()

These convenience methods test if a setting is of a given type.

— Method on Setting: bool isAggregate ()
— Method on Setting: bool isScalar ()
— Method on Setting: bool isNumber ()

These convenience methods test if a setting is of an aggregate type (a group, array, or list), of a scalar type (integer, 64-bit integer, floating point, boolean, or string), and of a number (integer, 64-bit integer, or floating point), respectively.

— Method on Setting: const char * getSourceFile ()

This function returns the name of the file from which the setting was read, or NULL if the setting was not read from a file. This information is useful for reporting application-level errors. Storage for the returned string is managed by the library and released automatically when the configuration is destroyed; the string must not be freed by the caller.

— Method on Setting: unsigned int getSourceLine ()

This function returns the line number of the configuration file or stream at which the setting setting was read, or 0 if no line number is available. This information is useful for reporting application-level errors.


本文只看粗体即可,太多catch语句。两个例子均来自libconfig包的example文件夹下面,.

例子一:

#include <iostream>
#include <iomanip>
#include <cstdlib>
#include <libconfig.h++>
using namespace std;
using namespace libconfig;
// This example reads the configuration file 'example.cfg' and display some of its contents.

int main(int argc, char **argv)
{
  Config cfg;

  try
  {
    cfg.readFile("example.cfg"); //读配置文件
  }
  catch(const FileIOException &fioex)
  {
    std::cerr << "I/O error while reading file." << std::endl;
    return(EXIT_FAILURE);
  }
  catch(const ParseException &pex)
  {
    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
              << " - " << pex.getError() << std::endl;
    return(EXIT_FAILURE);
  }


  // Get the store name.
  try
  {
    string name = cfg.lookup("name"); // 查询某个路径“name”,得到setting,存储到name
    cout << "Store name: " << name << endl << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "No 'name' setting in configuration file." << endl;
  }

  const Setting& root = cfg.getRoot();//得到根setting
 // Output a list of all books in the inventory.
  try
  {
    const Setting &books = root["inventory"]["books"];
    int count = books.getLength();   //得到某个setting的长度,从而循环读取

       for(int i = 0; i < count; ++i)
    {
      const Setting &book = books[i];
      // Only output the record if all of the expected fields are present.
      string title, author;
      double price;
      int qty;
      if(!(book.lookupValue("title", title)  //查询名字为title的setting存储到title中
           && book.lookupValue("author", author)
           && book.lookupValue("price", price)
           && book.lookupValue("qty", qty)))
        continue;

      cout << setw(30) << left << title << "  "
           << setw(30) << left << author << "  "
           << '$' << setw(6) << right << price << "  "
           << qty
           << endl;
    }
    cout << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    // Ignore.
  }
  return(EXIT_SUCCESS);
}


// eof

例子二

头文件省略

// This example reads the configuration file 'example.cfg', adds a new
// movie record to the movies list, and writes the updated configuration to
// 'updated.cfg'.

int main(int argc, char **argv)
{
  static const char *output_file = "updated.cfg";

  Config cfg;
  // Read the file. If there is an error, report it and exit.
  try
  {
    cfg.readFile("example.cfg"); //读配置文件
  }
  catch(const FileIOException &fioex)
  {
    std::cerr << "I/O error while reading file." << std::endl;
    return(EXIT_FAILURE);
  }
  catch(const ParseException &pex)
  {
    std::cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
              << " - " << pex.getError() << std::endl;
    return(EXIT_FAILURE);
  }


// Get the store name.
  try
  {
    string name = cfg.lookup("name");    //通过"name"这个路径查找 到某个setting(名字为 name) 存储到string name 中
    cout << "Store name: " << name << endl << endl;
  }
  catch(const SettingNotFoundException &nfex)
  {
    cerr << "No 'name' setting in configuration file." << endl;
  }


  // Find the 'movies' setting. Add intermediate settings if they don't yet
  // exist.
  Setting &root = cfg.getRoot(); //返回root setting
  if(! root.exists("inventory"))
    root.add("inventory", Setting::TypeGroup);
  Setting &inventory = root["inventory"];
  if(! inventory.exists("movies"))
    inventory.add("movies", Setting::TypeList);
  Setting &movies = inventory["movies"];


  // Create the new movie entry.
  Setting &movie = movies.add(Setting::TypeGroup); //增加一个Setting::TypeGroup类型的子setting
  movie.add("title", Setting::TypeString) = "Buckaroo Banzai"; //增加一个子setting
  movie.add("media", Setting::TypeString) = "DVD";
  movie.add("price", Setting::TypeFloat) = 12.99;
  movie.add("qty", Setting::TypeInt) = 20;

  // Write out the updated configuration.
  try
  {
    cfg.writeFile(output_file); //把配置写到一个文件中
    cerr << "Updated configuration successfully written to: " << output_file
         << endl;
  }
  catch(const FileIOException &fioex)
  {
    cerr << "I/O error while writing file: " << output_file << endl;
    return(EXIT_FAILURE);
  }
  return(EXIT_SUCCESS);
}

// eof

配置文件:

example.cfg:

// An example configuration file that stores information about a store.

// Basic store information:
name = "Books, Movies & More";


// Store inventory:
inventory =
{
  books = ( { title  = "Treasure Island";
              author = "Robert Louis Stevenson";
              price  = 29.99;
              qty    = 5; },
            { title  = "Snow Crash";
              author = "Neal Stephenson";
              price  = 9.99;
              qty    = 8; }
          );


  movies = ( { title = "Brazil";
               media = "DVD";
               price = 19.99;
               qty = 11; },
             { title = "The City of Lost Children";
               media = "DVD";
               price = 18.99;
               qty = 5; },
             { title = "Memento";
               media = "Blu-Ray";
               price = 24.99;
               qty = 20;
             },
             { title = "Howard the Duck"; }
           );
};


// Store hours:
hours =
{
  mon = { open =  9; close = 18; };
  tue = { open =  9; close = 18; };
  wed = { open =  9; close = 18; };
  thu = { open =  9; close = 18; };
  fri = { open =  9; close = 20; };
  sat = { open =  9; close = 20; };
  sun = { open = 11; close = 16; };
};


0 0
原创粉丝点击