minIni - a minimal INI file parser
minIni is a programmer's library to read and write "INI" files in embedded systems. minIni takes little resources, has a deterministic memory footprint and can be configured for various kinds of file I/O libraries. minIni provides functionality for reading, writing and deleting keys from an INI file, all in less than 1000 lines of (commented) C code (the code also compiles in C and comes with a wrapper class).
The principal purpose for minIni is to be used on embedded systems that run on an RTOS (or even without any operating system). minIni requires that such a system provides a kind of storage and file I/O system, but it does not require that this file I/O system is compatible with the standard C/C library —indeed, the standard library is often too big and resource-hungry for embedded systems.
If you wish to know more about minIni, please see the manual that is in the source code archive.
Downloads & license
- minIni 1.5 source archive (160 KiB, includes manual).
- Access to the most recent source code is available on GitHub
The minIni library is distributed under the Apache License, version 2.0, plus an exception clause to explicitly permit static linking of the library to commercial applications.
INI file syntax
INI files have a simple syntax with name/value pairs in a plain text
file. The name must be unique (per section) and the value must fit on a single line.
INI files are commonly separated into sections —in minIni, this is
optional. A section is a name between square brackets, like "[Network]
" in
the example below.
[Network] hostname=My Computer address=dhcp dns = 192.168.1.1
In the API and in this documentation, the "name" for a setting is denoted as the
key for the setting. The key and the value are separated by an equal
sign ("=
"). minIni supports the colon (":
") as an alternative to the
equal sign for the key/value delimiter.
Leading a trailing spaces around values or key names are removed. If you need
to include leading and/or trailing spaces in a value, put the value between
double quotes. The ini_gets()
function (from the minIni library, see
the minIni manual) strips off the double quotes from the returned value. Function
ini_puts()
adds double quotes if the value to write contains trailing
white space (or special characters).
minIni ignores spaces around the "=
" or ":
" delimiters,
as well as spaces following the opening bracket of a section name, or preceding
the closing bracket. Spaces in the names of sections or keys are not
ignored.
Comments in the INI must start with a semicolon (";") or a hash character ("#"), and run to the end of the line. A comment can be a line of its own, or it may follow a key/value pair (the "#" character and trailing comments are extensions of minIni).
INI file reading paradigms
There are two approaches to reading settings from an INI file. One way is to
call a function, such as GetProfileString()
for every section and
key that you need. This is especially convenient if there is a large INI file,
but you only need a few settings from that file at any time —especially
if the INI file can also change while your program runs. This is the approach
that the Microsoft Windows API uses.
The above procedure is quite inefficient, however, when you need to retrieve quite a few settings from the INI file —especially if the INI file is not cached in memory (which it isn't, in minIni). A different approach to getting settings from an INI file is to call a "parsing" function and let that function call the application back with the section and key names plus the associated data. XML parsing libraries often use this approach; see for example the Expat library.
minIni supports both approaches. For reading a single setting, use functions like
ini_gets()
. For the callback approach, implement a callback and call
ini_browse()
. See the minIni manual for details.
Adapting minIni to a file system
The minIni library must be configured for a platform with the help of a so-called
"glue file". This glue file contains macros (and possibly functions) that
map file reading and writing functions used by the minIni library to those
provided by the operating system. The glue file must be called
"minGlue.h
".
To get you started, the minIni distribution comes with the following example glue files:
-
a glue file that maps to the standard C/C library (specifically
the file I/O functions from the "
stdio
" package), - a glue file for Microchip's Memory Disk Drive File System Library,
- a glue file for the FAT library provided with the CCS PIC compiler,
- a glue file for the EFS Library (EFSL),
- and a glue file for the FatFs and Petit-FatFs libraries.
Multi-tasking
The minIni library does not have any global variables and it does not use any dynamically allocated memory. Yet, the library should not be considered "thread-safe" or re-entrant, because it implicitly uses a particular shared resource: the file system.
Multiple tasks reading from an INI file do not pose a problem. However, when one task is writing to an INI file, no other tasks should access this INI file —neither for reading, nor for writing. It might be easier, in the implementation, to serialize all accesses of the INI file.
The first advise in protecting resources from concurrent access in a multi-tasking environment is to avoid sharing resources between tasks. If only a single task uses a resource, no semaphore protection is necessary and no priority inversion or deadlock problems can occur. This advise also applies to the minIni library. If possible, make a single task the "owner" of the INI file and create a client/server architecture for other tasks to query and adjust settings.
If the INI file must be shared between tasks (and at least one of the tasks writes to the INI file), you need to write wrappers around the functions of the minIni library that block on a mutex or binary semaphore.
The minIni library comes with a glue file that uses BSD-style file locking to serialize access to an INI file. These file locking extensions are commonly available on Linux. For other multitasking environments, the glue file may serve as an example of how to implement file locking.
History
- Version 1.5, 6 January 2024
- New function
ini_putbool
.
Allow (and ignore) white space before and after a section name. - Version 1.4, 28 May 2021
- New functions
ini_haskey
andini_hassection
.
Bug fix in handling a zero byte in an INI file. - Version 1.3, 26 October 2020
- Avoid rewriting the INI file when attempting to delete a key that already
isn't present in the INI file.
When writing to an INI file, reopen the original file after opening the temporary file (because opening the temporary file may have been blocked on a file lock).
Added an example glue file for file locking in Linux.
Portability bug fixes (notably the use of strrchr() to get a pointer to the terminating zero was non-portable).
Updated documentation.
Some stylistic corrections by Martijn Vernooij and tbeu (typos, errors in comments). - Version 1.2.a, 14 May 2012
- Fixed an issue in Unicode/ANSI portability.
Changed example glue files to open INI files in binary mode; issue #20.
Corrected "portable strnicmp" for the case that TCHAR is a typedef; issue #21. - Version 1.2, 8 December 2011
- Correction in the FatFs and Petit-FatFs interface file, specifically the
ini_rename()
function, with thanks to Andrew Gubisch.
A second method for reading INI files is added:ini_browse()
invokes a callback function for every key/value pair that it reads from the INI file. This is much quicker if you have many settings to read. - Version 1.1, 20 June 2011
- Improvements in floating-point numbers support; other representations of
rational values are now supported too (e.g. fixed-point).
Improvements in writing an INI setting; the number of "writes" is minimized to increase performance (and minimize "wear") on Flash memory media.
A few more examples for "glue files" for file systems. - Version 1.0, 28 January 2011
- Support for floating point settings and boolean flags.
Minor corrections in the C interface. - Version 0.9, 6 July 2010
- Minor corrections, notably regarding the C interface (with thanks to Lieven de Cock)
and the FatFs / Petit-FatFs glue file (with thanks to Andreas Wetzel).
C methods to delete a section or key from an INI file, because "references" cannot be NULL.
The documentation is updated, especially regarding the C interface.
Nota Bene: some macros (for configuring the minIni library) were renamed; please see the updated manual for details. - Version 0.8, 27 October 2009
- Corrected updating of a key when the existing key has space characters around
the "="; issue #9.
Trailing comments (behind a section) are now allowed; issue #8.
When comment characters or trailing white space exists in a value, that value is now automatically put between quotes (when reading, the quotes are automatically removed). Double quotes in a string are now escaped (when writing) and restored when reading. - Version 0.7, 6 May 2009
- Added a C class (contributed by Steven Van Ingelgem; issue #2).
Added a read-only capability (contributed by Luca Bassanello).
Corrections, improved portability. - Version 0.6, 2 March 2009
- Reduce (redundant) writes (when writing unmodified settings back).
- Version 0.5, 30 September 2008
- Section and key enumeration.
- Version 0.4, 28 July 2008
- Support for values (in name/value pairs) that are between double quotes.
- Version 0.3, 19 May 2008
- Bug fix release.
- Version 0.2, 28 April 2008
- Example glue files for EFSL and FatFs; improved portability.
- Version 0.1, 25 April 2008
- Initial release
Acknowledgement
Back in 2003, I was maintaining an IDE (for the authoring language EGO). The IDE stores project information in INI files. Some projects grew large and crossed the 32 KiB limit that Microsoft Windows 95 and Windows 98 imposed on INI files (and back then, we were not prepared to drop support for Windows 98 yet). So I picked up the source code from the article "Multiplatform .INI Files" by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal.
The comment at the start of my implementation of the code from Joseph Graf's article contains the note "This release comes close to a complete re-write". There were quite a few issues with the original code. We also needed extensions such as deleting keys, and enumerating keys & sections, that the original code lacked.
In turn, minIni is complete re-write of my re-write of the Joseph Graf's code —this time to reduce the size and memory requirements of the library, plus changes to increase the portability and make it more suitable to embedded systems.
Despite the double re-write, I owe it to Joseph Graf's article to give me a jump-start.
Exception clause to the Apache License version 2.0
As a special exception to the Apache License 2.0 (and referring to the definitions in Section 1 of that license), you may link, statically or dynamically, the "Work" to other modules to produce an executable file containing portions of the "Work", and distribute that executable file in "Object" form under the terms of your choice, without any of the additional requirements listed in Section 4 of the Apache License 2.0. This exception applies only to redistributions in "Object" form (not "Source" form) and only if no modifications have been made to the "Work".
The "glue files" are provided as examples and distributed as "public domain" source code. The requirements of the Apache license do not apply to the glue files.