inih(INI Not Invented Here )是一個用 C 語言編寫的簡單的 .INI 檔案解析器。它也或多或少與 Python 的 ConfigParser 風格的 .INI 檔案相容,包括 RFC 822 風格的多行語法和name: value
條目。
要使用它,只需給ini_parse()
一個 INI 文件,它就會為解析的每個name=value
對調用回調,為您提供部分、名稱和值的字串。它以這種方式完成(“SAX 風格”),因為它在低內存嵌入式系統上運行良好,而且還因為它適合 KISS 實現。
您也可以呼叫ini_parse_file()
來直接從FILE*
物件進行解析, ini_parse_string()
來解析字串中的數據,或是呼叫ini_parse_stream()
來使用自訂I/O 的自訂fgets 樣式讀取器函數進行解析。
下載版本、瀏覽原始碼或閱讀有關如何透過 X-Macros 以 DRY 風格使用 inih 的資訊。
您可以使用預處理器定義來控制 inih 的各個方面:
-DINI_ALLOW_MULTILINE=0
。-DINI_ALLOW_BOM=0
。;
特點。若要停用,請新增-DINI_ALLOW_INLINE_COMMENTS=0
。您也可以使用INI_INLINE_COMMENT_PREFIXES
指定哪些字元開始內嵌註解。;
和#
在行首開始註解。您可以透過變更INI_START_COMMENT_PREFIXES
來覆寫此設定。=
:
:)視為錯誤。若要允許沒有值的名稱,請新增-DINI_ALLOW_NO_VALUE=1
,inih 將呼叫您的處理函數,並將值設為 NULL。-DINI_STOP_ON_FIRST_ERROR=1
。ini_handler
回呼不接收行號作為參數。如果需要,請新增-DINI_HANDLER_LINENO=1
。name=value
對上呼叫處理程序。若要偵測新部分(例如,INI 檔案具有多個同名部分),請新增-DINI_CALL_HANDLER_ON_NEW_SECTION=1
。然後,每次遇到新節時都會呼叫處理函數, section
設定為新節名稱,但name
和value
設定為 NULL。malloc
在堆上分配,請指定-DINI_USE_STACK=0
。-DINI_MAX_LINE=1000
內容。請注意, INI_MAX_LINE
必須比最長行多 3(由於r
、 n
和 NUL)。INI_INITIAL_ALLOC
指定使用堆時的初始malloc大小。預設為 200 位元組。-DINI_USE_STACK=0
) 時,inih 會指派INI_INITIAL_ALLOC
位元組的固定大小緩衝區。若要允許其成長到INI_MAX_LINE
位元組(如果需要則加倍),請設定-DINI_ALLOW_REALLOC=1
。malloc
、 free
和realloc
函數;若要使用自訂分配器,請指定-DINI_CUSTOM_ALLOCATOR=1
(和-DINI_USE_STACK=0
)。您必須定義並連結名為ini_malloc
、 ini_free
和(如果設定了INI_ALLOW_REALLOC
) ini_realloc
的函數,它們必須具有與stdlib.h
記憶體分配函數相同的簽章。 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "../ini.h"
typedef struct
{
int version ;
const char * name ;
const char * email ;
} configuration ;
static int handler ( void * user , const char * section , const char * name ,
const char * value )
{
configuration * pconfig = ( configuration * ) user ;
#define MATCH ( s , n ) strcmp(section, s) == 0 && strcmp(name, n) == 0
if ( MATCH ( "protocol" , "version" )) {
pconfig -> version = atoi ( value );
} else if ( MATCH ( "user" , "name" )) {
pconfig -> name = strdup ( value );
} else if ( MATCH ( "user" , "email" )) {
pconfig -> email = strdup ( value );
} else {
return 0 ; /* unknown section/name, error */
}
return 1 ;
}
int main ( int argc , char * argv [])
{
configuration config ;
if ( ini_parse ( "test.ini" , handler , & config ) < 0 ) {
printf ( "Can't load 'test.ini'n" );
return 1 ;
}
printf ( "Config loaded from 'test.ini': version=%d, name=%s, email=%sn" ,
config . version , config . name , config . email );
return 0 ;
}
如果您喜歡 C++ 和 STL,還有一個易於使用的 INIReader 類,它將值儲存在map
中並允許您Get()
它們:
# include < iostream >
# include " INIReader.h "
int main ()
{
INIReader reader ( " ../examples/test.ini " );
if (reader. ParseError () < 0 ) {
std::cout << " Can't load 'test.ini' n " ;
return 1 ;
}
std::cout << " Config loaded from 'test.ini': version= "
<< reader. GetInteger ( " protocol " , " version " , - 1 ) << " , name= "
<< reader. Get ( " user " , " name " , " UNKNOWN " ) << " , email= "
<< reader. Get ( " user " , " email " , " UNKNOWN " ) << " , pi= "
<< reader. GetReal ( " user " , " pi " , - 1 ) << " , active= "
<< reader. GetBoolean ( " user " , " active " , true ) << " n " ;
return 0 ;
}
這個簡單的 C++ API 運作得很好,但還不是很成熟。我目前不打算在 C++ API 上進行更多工作,因此如果您想要更多功能(例如GetSections()
和GetFields()
函數),請參閱這些分支:
inih 和 Python 的 ConfigParser 標準函式庫模組之間的一些差異:
_wfopen()
開啟文件,然後呼叫ini_parse_file()
解析它; inih 不包括wchar_t
或 Unicode 處理。 meson.build
檔案不需要使用或編譯 inih,它的主要目的是用於發行版。-Ddefault_library=static
建構靜態庫。-Ddistro_install=false
庫、標頭和 pkg-config 檔案將不會安裝。-Dwith_INIReader=false
可以停用建置 C++ 函式庫。distro_install
設定為true
,這些將不起作用。inih
和INIReader
。inih_dep
和INIReader_dep
依賴變數。您可能需要為子項目設定default_library=static
和distro_install=false
。 WrapDB 上提供了官方的 Wrap。version : '<version_as_int>',
位於project()
函數中的license
標記之後,以及version : meson.project_version(),
位於兩個library()
函數中的soversion
標記之後。 只需將以下條目新增至.tipi/deps
(將r56
替換為最新版本標記),即可在 tipi.build 專案中輕鬆使用inih
:
{
"benhoyt/inih" : { "@" : " r56 " }
}
專案中所需的包含路徑是:
#include <ini.h>
您可以使用 vcpkg 依賴管理器建置和安裝 inih:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install inih
vcpkg 中的 inih 連接埠由 Microsoft 團隊成員和社群貢獻者保持最新。如果版本已過時,請在 vcpkg 儲存庫上建立問題或拉取要求。