inih (INI no inventado aquí) es un analizador de archivos .INI simple escrito en C. Tiene solo un par de páginas de código y fue diseñado para ser pequeño y simple , por lo que es bueno para sistemas integrados. También es más o menos compatible con el estilo ConfigParser de Python de archivos .INI, incluida la sintaxis multilínea de estilo RFC 822 y las entradas name: value
.
Para usarlo, simplemente proporcione ini_parse()
un archivo INI y llamará una devolución de llamada para cada name=value
analizado, brindándole cadenas para la sección, nombre y valor. Se hace de esta manera ("estilo SAX") porque funciona bien en sistemas integrados con poca memoria, pero también porque permite una implementación de KISS.
También puede llamar ini_parse_file()
para analizar directamente desde un objeto FILE*
, ini_parse_string()
para analizar datos de una cadena, o ini_parse_stream()
para analizar utilizando una función lectora personalizada de estilo fgets para E/S personalizadas.
Descargue una versión, explore la fuente o lea sobre cómo usar inih en un estilo DRY con X-Macros.
Puede controlar varios aspectos de inih utilizando definiciones de preprocesador:
-DINI_ALLOW_MULTILINE=0
.-DINI_ALLOW_BOM=0
.;
personaje. Para deshabilitarlo, agregue -DINI_ALLOW_INLINE_COMMENTS=0
. También puede especificar qué caracteres inician un comentario en línea usando INI_INLINE_COMMENT_PREFIXES
.;
y #
para iniciar un comentario al principio de una línea. Puede anular esto cambiando INI_START_COMMENT_PREFIXES
.=
o :
en la línea) como un error. Para permitir nombres sin valores, agregue -DINI_ALLOW_NO_VALUE=1
e inih llamará a su función de controlador con el valor establecido en NULL.-DINI_STOP_ON_FIRST_ERROR=1
.ini_handler
no recibe el número de línea como parámetro. Si lo necesita, agregue -DINI_HANDLER_LINENO=1
.name=value
. Para detectar nuevas secciones (por ejemplo, el archivo INI tiene varias secciones con el mismo nombre), agregue -DINI_CALL_HANDLER_ON_NEW_SECTION=1
. Luego, se llamará a su función de controlador cada vez que se encuentre una nueva sección, con section
configurada con el nuevo nombre de la sección pero name
y value
establecidos en NULL.malloc
, especifique -DINI_USE_STACK=0
.-DINI_MAX_LINE=1000
. Tenga en cuenta que INI_MAX_LINE
debe ser 3 más que la línea más larga (debido a r
, n
y NUL).INI_INITIAL_ALLOC
especifica el tamaño de malloc inicial cuando se usa el montón. El valor predeterminado es 200 bytes.-DINI_USE_STACK=0
), inih asigna un búfer de tamaño fijo de INI_INITIAL_ALLOC
bytes. Para permitir que esto crezca a INI_MAX_LINE
bytes, duplicándolo si es necesario, configure -DINI_ALLOW_REALLOC=1
.malloc
, free
y realloc
de la biblioteca estándar; para utilizar un asignador personalizado, especifique -DINI_CUSTOM_ALLOCATOR=1
(y -DINI_USE_STACK=0
). Debe definir y vincular funciones denominadas ini_malloc
, ini_free
y (si INI_ALLOW_REALLOC
está configurada) ini_realloc
, que deben tener las mismas firmas que las funciones de asignación de memoria 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 ;
}
Si te gusta C++ y STL, también hay una clase INIReader fácil de usar que almacena valores en un map
y te permite Get()
ellos:
# 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 ;
}
Esta sencilla API de C++ funciona bien, pero no está completamente desarrollada. No planeo trabajar más en la API de C++ en este momento, así que si quieres un poco más de potencia (por ejemplo, las funciones GetSections()
y GetFields()
), mira estas bifurcaciones:
Algunas diferencias entre inih y el módulo de biblioteca estándar ConfigParser de Python:
_wfopen()
para abrir un archivo y luego ini_parse_file()
para analizarlo; inih no incluye el manejo wchar_t
o Unicode. meson.build
no es necesario para usar o compilar inih, su propósito principal es para distribuciones.-Ddefault_library=static
se construyen bibliotecas estáticas.-Ddistro_install=false
las bibliotecas, los encabezados y los archivos pkg-config no se instalarán.-Dwith_INIReader=false
puede desactivar la creación de la biblioteca C++.distro_install
está configurado en true
.inih
e INIReader
.inih_dep
e INIReader_dep
. Es posible que desee configurar default_library=static
y distro_install=false
para el subproyecto. Se proporciona un Wrap oficial en WrapDB.version : '<version_as_int>',
después de la etiqueta license
en la función project()
y version : meson.project_version(),
después de la etiqueta soversion
en ambas funciones library()
. inih
se puede usar fácilmente en proyectos tipi.build simplemente agregando la siguiente entrada a su .tipi/deps
(reemplace r56
con la etiqueta de la última versión):
{
"benhoyt/inih" : { "@" : " r56 " }
}
La ruta de inclusión requerida en su proyecto es:
#include <ini.h>
Puede compilar e instalar inih usando el administrador de dependencias vcpkg:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install inih
Los miembros del equipo de Microsoft y los contribuyentes de la comunidad mantienen actualizado el port inih en vcpkg. Si la versión no está actualizada, cree un problema o una solicitud de extracción en el repositorio de vcpkg.