inih (INI Not Invented Here) — это простой анализатор файлов .INI, написанный на C. Это всего лишь пара страниц кода, и он был разработан как небольшой и простой , поэтому хорошо подходит для встроенных систем. Он также более или менее совместим со стилем Python ConfigParser файлов .INI, включая многострочный синтаксис в стиле RFC 822 и записи name: value
.
Чтобы использовать его, просто передайте ini_parse()
INI-файл, и он вызовет обратный вызов для каждой проанализированной пары name=value
, предоставив вам строки для раздела, имени и значения. Это сделано таким образом («стиль SAX»), потому что он хорошо работает на встроенных системах с малым объемом памяти, а также потому, что он подходит для реализации KISS.
Вы также можете вызвать ini_parse_file()
для анализа непосредственно из объекта FILE*
, ini_parse_string()
для анализа данных из строки или ini_parse_stream()
для анализа с использованием специальной функции чтения в стиле fgets для пользовательского ввода-вывода.
Загрузите выпуск, просмотрите исходный код или прочитайте о том, как использовать inih в стиле DRY с X-Macros.
Вы можете управлять различными аспектами 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 работает нормально, но он не является полноценным. В данный момент я не планирую больше работать над API C++, поэтому, если вам нужно немного больше возможностей (например, функции 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.version : '<version_as_int>',
после тега license
в функции project()
и version : meson.project_version(),
после тега soversion
в обеих функциях library()
. inih
можно легко использовать в проектах Tipi.build, просто добавив следующую запись в ваш .tipi/deps
(замените r56
тегом последней версии):
{
"benhoyt/inih" : { "@" : " r56 " }
}
Требуемый путь включения в ваш проект:
#include <ini.h>
Вы можете собрать и установить inih с помощью менеджера зависимостей vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install inih
Порт inih в vcpkg постоянно обновляется членами команды Microsoft и участниками сообщества. Если версия устарела, создайте проблему или запрос на извлечение в репозитории vcpkg.