inih (INI Not Invented Here) est un simple analyseur de fichiers .INI écrit en C. Il ne contient que quelques pages de code et il a été conçu pour être petit et simple , il convient donc aux systèmes embarqués. Il est également plus ou moins compatible avec le style ConfigParser de fichiers .INI de Python, y compris la syntaxe multiligne de style RFC 822 et les entrées name: value .
Pour l'utiliser, donnez simplement ini_parse() un fichier INI, et il appellera un rappel pour chaque paire name=value analysée, vous donnant des chaînes pour la section, le nom et la valeur. C'est fait de cette façon ("style SAX") parce que cela fonctionne bien sur les systèmes embarqués à faible mémoire, mais aussi parce que cela permet une implémentation KISS.
Vous pouvez également appeler ini_parse_file() pour analyser directement à partir d'un objet FILE* , ini_parse_string() pour analyser les données d'une chaîne, ou ini_parse_stream() pour analyser à l'aide d'une fonction de lecteur personnalisée de style fgets pour des E/S personnalisées.
Téléchargez une version, parcourez la source ou découvrez comment utiliser inih dans un style DRY avec X-Macros.
Vous pouvez contrôler divers aspects d'inih à l'aide des définitions du préprocesseur :
-DINI_ALLOW_MULTILINE=0 .-DINI_ALLOW_BOM=0 .; personnage. Pour désactiver, ajoutez -DINI_ALLOW_INLINE_COMMENTS=0 . Vous pouvez également spécifier quel(s) caractère(s) démarrent un commentaire en ligne à l'aide de INI_INLINE_COMMENT_PREFIXES .; et # pour commencer un commentaire au début d'une ligne. Vous pouvez remplacer cela en modifiant INI_START_COMMENT_PREFIXES .= ou : sur la ligne) comme une erreur. Pour autoriser les noms sans valeur, ajoutez -DINI_ALLOW_NO_VALUE=1 , et inih appellera votre fonction de gestionnaire avec une valeur définie sur NULL.-DINI_STOP_ON_FIRST_ERROR=1 .ini_handler ne reçoit pas le numéro de ligne en tant que paramètre. Si vous en avez besoin, ajoutez -DINI_HANDLER_LINENO=1 .name=value . Pour détecter de nouvelles sections (par exemple, le fichier INI a plusieurs sections portant le même nom), ajoutez -DINI_CALL_HANDLER_ON_NEW_SECTION=1 . Votre fonction de gestionnaire sera alors appelée chaque fois qu'une nouvelle section est rencontrée, avec section définie sur le nouveau nom de section mais name et value définis sur NULL.malloc à la place, spécifiez -DINI_USE_STACK=0 .-DINI_MAX_LINE=1000 . Notez que INI_MAX_LINE doit être 3 de plus que la ligne la plus longue (en raison de r , n et de NUL).INI_INITIAL_ALLOC spécifie la taille initiale de malloc lors de l'utilisation du tas. La valeur par défaut est 200 octets.-DINI_USE_STACK=0 ), inih alloue un tampon de taille fixe d'octets INI_INITIAL_ALLOC . Pour permettre à ce nombre d'atteindre INI_MAX_LINE octets, en doublant si nécessaire, définissez -DINI_ALLOW_REALLOC=1 .malloc , free et realloc de la bibliothèque standard sont utilisées ; pour utiliser un allocateur personnalisé, spécifiez -DINI_CUSTOM_ALLOCATOR=1 (et -DINI_USE_STACK=0 ). Vous devez définir et lier des fonctions nommées ini_malloc , ini_free et (si INI_ALLOW_REALLOC est défini) ini_realloc , qui doivent avoir les mêmes signatures que les fonctions d'allocation de mémoire 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 vous aimez le C++ et le STL, il existe également une classe INIReader facile à utiliser qui stocke les valeurs dans une map et vous permet de les 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 ;
} Cette simple API C++ fonctionne bien, mais elle n’est pas très complète. Je n'ai pas l'intention de travailler davantage sur l'API C++ pour le moment, donc si vous voulez un peu plus de puissance (par exemple les fonctions GetSections() et GetFields() ), consultez ces forks :
Quelques différences entre inih et le module de bibliothèque standard ConfigParser de Python :
_wfopen() pour ouvrir un fichier, puis ini_parse_file() pour l'analyser ; inih n'inclut pas la gestion wchar_t ou Unicode. meson.build n'est pas nécessaire pour utiliser ou compiler inih, son objectif principal est les distributions.-Ddefault_library=static des bibliothèques statiques sont construites.-Ddistro_install=false les bibliothèques, les en-têtes et les fichiers pkg-config ne seront pas installés.-Dwith_INIReader=false vous pouvez désactiver la construction de la bibliothèque C++.distro_install est défini sur true .inih et INIReader .inih_dep et INIReader_dep . Vous souhaiterez peut-être définir default_library=static et distro_install=false pour le sous-projet. Un Wrap officiel est fourni sur WrapDB.version : '<version_as_int>', après la balise license dans la fonction project() et version : meson.project_version(), après la balise soversion dans les deux fonctions library() . inih peut être facilement utilisé dans les projets tipi.build en ajoutant simplement l'entrée suivante à votre .tipi/deps (remplacez r56 par la dernière balise de version) :
{
"benhoyt/inih" : { "@" : " r56 " }
}Le chemin d'inclusion requis dans votre projet est :
#include <ini.h> Vous pouvez créer et installer inih à l'aide du gestionnaire de dépendances vcpkg :
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install inih
Le port inih dans vcpkg est tenu à jour par les membres de l'équipe Microsoft et les contributeurs de la communauté. Si la version est obsolète, veuillez créer un problème ou une pull request sur le référentiel vcpkg.