構成ファイル。 Libconfigライブラリ

はじめに



どういうわけか、設定iniファイルまたはjsonをサーバーに固定し、オプションでソートする方法を探していますが、何らかの理由で不快または単純すぎる、または自転車でした。 また、XMLの構成は大好きですが、時には非常に大きなファイルであり、少数の設定で大量のテキストを書くのは不便です。 友人にこのトピックに関する質問をしたら、彼は私に図書館を投げました。 彼女は、jsonにyamlを混ぜたものを思い出させます。







ライブラリには、機能とオブジェクトの2つのインターフェイスがあります。 オブジェクトは機能的な実装を内部で使用するため、これらは非常に似ていますが、この投稿で説明したいくつかの違いがあります。





セットアップと接続

構成ファイル

Cで使用

C ++での使用



セットアップと接続



ライブラリは多くのリポジトリにあるため、インストールは簡単です。

$ sudo aptitude install libconfig8 libconfig8-dev libconfig++ libconfig++-dev
      
      







ソースコードでは、C ++は1つのインクルードのみで接続されています。

 #include <libconfig.h++>
      
      





または

 #include <libconfig.hh>
      
      





またはC

 #include <libconfig.h>
      
      







構成ファイル



構成ファイルは、次のタイプの構造です。

 # Example application configuration file version = "1.0"; application: { window: { title = "My Application"; size = { w = 640; h = 480; }; pos = { x = 350; y = 250; }; }; list = ( ( "abc", 123, true ), 1.234, ( /* an empty list */) ); books = ( { title = "Treasure Island"; author = "Robert Louis Stevenson"; price = 29.95; qty = 5; }, { title = "Snow Crash"; author = "Neal Stephenson"; price = 9.99; qty = 8; } ); misc: { pi = 3.141592654; bigint = 9223372036854775807L; columns = [ "Last Name", "First Name", "MI" ]; bitmask = 0x1FC3; }; };
      
      







構成のエントリの主なタイプは次のタイプです。

要素(設定)
これは、構成構造の最小の重要な部分であり、Key-Valueの形式をとります。

 name = value;
      
      





または

 name : value
      
      





グループ


グループには任意の数の要素を含めることができますが、各要素にはグループ内の一意のキーを含める必要があります。 中括弧で書かれています:

 { settings... }
      
      





配列(配列)


ゼロでも任意の数の要素が含まれますが、すべての要素は値のみで構成され、配列内で同じスカラー型でなければなりません。 角括弧内に書き込みます。

 [ value, value ... ]
      
      





リスト


リストには、ゼロ個以上のスカラー要素、配列、グループ、またはリストが含まれます。 それは括弧で書かれています:

 ( value, value ... )
      
      





整数値(整数)


それらは通常の10進法(±0-9)または16進法(0xA-f)で記述されます。 ただし、整数値は-2147483648..2147483647(32ビット)の範囲によって制限されますが、大きな範囲が必要な場合は、末尾に「L」が追加されます。

 3578934 897893450934L
      
      





小数の浮動小数点数(float)


また、通常の方法で記録されます。

 3.1415
      
      





指数表記は「e」の標準です。

ブール値(ブール)


値は「true」または「false」として記述され、大文字と小文字を区別しません(もちろん引用符なし)。

ひも


二重引用符で書かれています
 "     "
      
      





次のオプションは、同じ文字列値になります。

 "  " "  "
      
      





 "  " /*  */ "  " //  " "
      
      





コメント


構成には、C ++でよく知られている3つのタイプがあります。



外部接続(含まれる)


これは、一般的に、最もおいしいおいしいです。

 # file: quote.cfg quote = "Criticism may not be agreeable, but it is necessary." " It fulfils the same function as pain in the human" " body. It calls attention to an unhealthy state of" " things.\n" "\t--Winston Churchill";
      
      





 # file: test.cfg info: { name = "Winston Churchill"; @include "quote.cfg" country = "UK"; };
      
      







APIを使用



このパートでは、すべての機能について説明するのではなく、主に機能のみを説明します。これらは一般的に類似しているため、主なニュアンスです。



以下で使用される機能の説明



 #include <stdio.h> #include <stdlib.h> #include <libconfig.h> /*      'example.cfg'     */ int main(int argc, char **argv) { /*   . */ config_t cfg; config_setting_t *setting; const char *str; config_init(&cfg); /*   */ /*  .  ,    */ if(! config_read_file(&cfg, "example.cfg")) { fprintf(stderr, "%s:%d - %s\n", config_error_file(&cfg), config_error_line(&cfg), config_error_text(&cfg)); config_destroy(&cfg); return(EXIT_FAILURE); } /*    "name". */ if(config_lookup_string(&cfg, "name", &str)) printf("Store name: %s\n\n", str); else fprintf(stderr, "No 'name' setting in configuration file.\n"); /*     . */ setting = config_lookup(&cfg, "inventory.books"); if(setting != NULL) { int count = config_setting_length(setting); int i; printf("%-30s %-30s %-6s %s\n", "TITLE", "AUTHOR", "PRICE", "QTY"); for(i = 0; i < count; ++i) { config_setting_t *book = config_setting_get_elem(setting, i); /*    ,      . */ const char *title, *author; double price; int qty; if(!(config_setting_lookup_string(book, "title", &title) && config_setting_lookup_string(book, "author", &author) && config_setting_lookup_float(book, "price", &price) && config_setting_lookup_int(book, "qty", &qty))) continue; printf("%-30s %-30s $%6.2f %3d\n", title, author, price, qty); } putchar('\n'); } /*     . */ setting = config_lookup(&cfg, "inventory.movies"); if(setting != NULL) { unsigned int count = config_setting_length(setting); unsigned int i; printf("%-30s %-10s %-6s %s\n", "TITLE", "MEDIA", "PRICE", "QTY"); for(i = 0; i < count; ++i) { config_setting_t *movie = config_setting_get_elem(setting, i); /*    ,     . */ const char *title, *media; double price; int qty; if(!(config_setting_lookup_string(movie, "title", &title) && config_setting_lookup_string(movie, "media", &media) && config_setting_lookup_float(movie, "price", &price) && config_setting_lookup_int(movie, "qty", &qty))) continue; printf("%-30s %-10s $%6.2f %3d\n", title, media, price, qty); } putchar('\n'); } config_destroy(&cfg); /*   ,      */ return(EXIT_SUCCESS); }
      
      







機能の簡単な説明


ドキュメントの完全な説明。



config_t-構成ファイルのタイプ(これはエントリではありません)。 大まかに言えば、メインコンテナーです。

config_setting_t-構成アイテムのオブジェクト。 この例では、コンテナから返される検索対象のアイテムへのポインタを使用しています。

int config_read_file (config_t * config、const char * filename)-関数は構成ファイルfilenameをメモリに読み込み、タイプconfig_tのオブジェクトに入力します。 ファイルから読み込むことはできませんが、すぐに行をconfig_read_string()に「フィード」するか、ファイル記述子をconfig_read()に渡します

int config_lookup_string (const config_t * config、const char * path、const char ** value)-config config内の指定されたパスパスで、文字列へのポインターの形式で値を検索して返します。

config_setting_t * config_lookup (const config_t * config、const char * path)-指定された内部パスで構成内のレコードを検索し、それを返します。

config_setting_t * config_setting_get_elem (const config_setting_t * setting、unsigned int index)-配列に使用され、そのような番号とそのような番号を持つ要素を順番に返すリスト

int config_setting_lookup_string (const config_setting_t * setting、const char * name、const char ** value)-

指定された設定エントリに関連するname要素の子の値を返します

特定のレコードの値を取得する必要がある場合、次のように機能します

int config_setting_get_int (const config_setting_t *設定)



C ++ API



同じ例ですが、C ++です。 サイト上の完全なドキュメント



 #include <iostream> #include <iomanip> #include <cstdlib> #include <libconfig.h++> using namespace std; using namespace libconfig; // ,    'example.cfg'     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); } //   . try { string name = cfg.lookup("name"); cout << "Store name: " << name << endl << endl; } catch(const SettingNotFoundException &nfex) { cerr << "No 'name' setting in configuration file." << endl; } const Setting& root = cfg.getRoot(); //     . try { const Setting &books = root["inventory"]["books"]; int count = books.getLength(); cout << setw(30) << left << "TITLE" << " " << setw(30) << left << "AUTHOR" << " " << setw(6) << left << "PRICE" << " " << "QTY" << endl; for(int i = 0; i < count; ++i) { const Setting &book = books[i]; //    ,     . string title, author; double price; int qty; if(!(book.lookupValue("title", 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. } //     . try { const Setting &movies = root["inventory"]["movies"]; int count = movies.getLength(); cout << setw(30) << left << "TITLE" << " " << setw(10) << left << "MEDIA" << " " << setw(6) << left << "PRICE" << " " << "QTY" << endl; for(int i = 0; i < count; ++i) { const Setting &movie = movies[i]; //   ,    . string title, media; double price; int qty; if(!(movie.lookupValue("title", title) && movie.lookupValue("media", media) && movie.lookupValue("price", price) && movie.lookupValue("qty", qty))) continue; cout << setw(30) << left << title << " " << setw(10) << left << media << " " << '$' << setw(6) << right << price << " " << qty << endl; } cout << endl; } catch(const SettingNotFoundException &nfex) { // Ignore. } return(EXIT_SUCCESS); }
      
      





ここでは、機能スタイルと同じ原則で、設定からデータを受信する前にのみ、ルート要素cfg.getRoot()を取得する必要があります。 そしてその後、彼から残りの要素に目を向ける。 また、ほとんどすべてのエラーで例外がスローされることに注意する必要があります



おわりに



便利な構成の読み取りに加えて、APIは構成要素を作成し、メディアに書き込む機能も提供します。



すべては、ライブラリWebサイトのドキュメント[en]にあります。



例にはソースが付属しています。 これらは、コンソールで次のコマンドを使用してダウンロードできます。

 $ apt-get source libconfig++
      
      





または直接リンクのソースから。



ドキュメントはHTMLおよびPDF形式で提供されます。

GNU LGPLライセンス。



All Articles