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.