A small C99 library for reading .ini config files.
For more information on .ini files, jump to The INI format section.
- A C99 compiler
- GNU Make
You can simply install this library by running the following command (if needed, run it as root):
make installThis should install the library in the /usr/lib folder.
Alternatively, you could just drop the files ini.c and ini.h to a folder of your preference in your project, and build them along with the other source files in your project.
You can also uninstall the library by running: (as root, if needed):
make uninstall
To clean the unnecessary stuff after the compilation, run:
make clean
Here you'll find a basic introduction with an example on how to use this library. For further information, please read the reference section.
Let's say I have the following main.ini file:
; Here we have information about a person (in this case, John Doe).
[person]
name = John Doe
age = 43
[info]
; More information about John Doe
height = 1.80
mother = "Mary D. Jane"First of all, we need to load the ini file. An ini file can be loaded into memory by using the ini_load() function.
NULL is returned if the file cannot be loaded. The variable needs to be free'd after use.
#include <ini.h>
int main(void) {
ini_t *config = ini_load("main.ini");
// Treat the failure case accordingly
if (!config) {
return 1;
}
ini_free(config);
return 0;
}Now let's say we want to know the name of John Doe's mother.
The library provides the function ini_getstring() for retriving the value from a key-value pair as a string. If accepts an ini_file, a section name and the key name as parameters, in this order. Before using the value, we also need to check if it's .ok, that is, if it exists and its type is valid. After that, let's specify we want to get the value as a string.
ini_value mother = ini_getstring(config, "info", "mother");
if (mother.ok) {
printf("Name of John Doe's mother: %s\n", mother.value.String);
}What if we want to know John Doe's height?
It's simple, let's use the ini_getdecimal() function.
ini_value height = ini_getdecimal(config, "info", "height");
if (height.ok) {
printf("John Doe's height: %f\n", height.value.Decimal);
}Finally, let's check how old John Doe is:
ini_value age = ini_getint(config, "person", "age");
if (age.ok) {
printf("John Doe's age: %d\n", age.value.Integer);
}The final program should look something like this:
#include <ini.h>
#include <stdio.h>
int main(void) {
ini_file *config = ini_load("main.ini");
if (!config) {
return 1;
}
ini_value mother = ini_getstring(config, "info", "mother");
if (mother.ok) {
printf("Name of John Doe's mother: %s\n", mother.value.String);
}
ini_value height = ini_getdecimal(config, "info", "height");
if (height.ok) {
printf("John Doe's height: %f\n", height.value.Decimal);
}
ini_value age = ini_getint(config, "person", "age");
if (age.ok) {
printf("John Doe's age: %d\n", age.value.Integer);
}
ini_free(config);
return 0;
}You should now be able save the file (as main.c, for example) and compile this program with GCC by running:
gcc -lini main.c -o main
That's it. Happy hacking!
If you want to have a look at a pratical example on how to use this library, please check out the usage section.
Below there is a quick reference over the functions and types.
struct ini_file; // Represents the .ini file.
struct ini_value; // Represents a possible value from the .ini file.
// Note that if this value is valid it must have one of the following types:
// String (const char *)
// Boolean (bool)
// Integer (i64)
// Decimal (f64)// Loads a file and process it as an ini_file. The variable must be free'd after use.
ini_file *ini_load(const char *filename);
// Frees a variable of ini_file type.
void ini_free(ini_file *ini);
// Searchs for a value according to the table name and key. Returns a ini_value of type i64.
ini_value ini_getint(ini_file *ini, const char *tablename, const char *key);
// Searchs for a value according to the table name and key. Returns a ini_value of type bool.
ini_value ini_getbool(ini_file *ini, const char *tablename, const char *key);
// Searchs for a value according to the table name and key. Returns a ini_value of type const char *.
ini_value ini_getstring(ini_file *ini, const char *tablename, const char *key);
// Searchs for a value according to the table name and key. Returns a ini_value of type f64.
ini_value ini_getdouble(ini_file *ini, const char *tablename, const char *key);The .ini file format is mainly used as a configuration file that consists of sections containing key-value pairs. As there isn't really a standard for this format, in this section I'll be clarifing what I adopted as a standard for this library.
I'll organize this in three subsections, focusing on the three components that a .ini is made of: Section, Key-value pair, and Comments.
A section in .ini should be organized like this:
[this is a section] ; Spaces in a section title is valid.
[ThisIsAnotherSection] ; No spaces is of course valid.
[
this is not a section ; a section is meant to be defined in just one line, so this isn't valid
]
A key-value pair goes inside sections and can be defined just as you would declare a variable in a language like Ruby or Python:
[mySection]
the_key = the_value
A value can have one of the following types:
- i64
- bool
- string
- f64
Examples will be shown below.
[my section]
mynum = 11
myothernum = 100000000000
[my section]
mybool = true
myotherbool = false
Quoted string values (with escapes) are valid. Unquoted values and keys are trimmed of whitespace when loaded.
[my section]
mystr = "A valid string"
myotherstr = I'm also a valid string.
yetanotherstr = \"I'm a real string with quotes\"
[my section]
myfloat = 1.2
myotherfloat = 3.1444444
The ; character detones a comment. If it's inside a section definition, the rest of the line won't be treated as a comment.
; this is a valid comment
[proje;ct] ; this line is perfectly valid, and the name of this section is <proje;ct>
mynum ;= 11 the comment started right before the = sign. Here, no valid key-value pair is defined.
This library is a refactoring and ressurection of ini.