Skip to content

Commit

Permalink
Add ini_putbool() (as a companion to ini_getbool()).
Browse files Browse the repository at this point in the history
Some reformatting and clean-up of the manual.
  • Loading branch information
compuphase committed Jan 6, 2024
1 parent 755f9a8 commit ede00e1
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 67 deletions.
96 changes: 48 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# minIni
minIni is a portable and configurable library for reading and writing ".INI" files. At roughly 950 lines of commented source
code, minIni truly is a "mini" INI file parser, especially considering its features.
minIni is a portable and configurable library for reading and writing ".INI" files. At less than a thousand lines of
commented source code, minIni truly is a "mini" INI file parser, especially considering its features.

The library does not require the file I/O functions from the standard C/C++ library, but instead lets you configure
the file I/O interface to use via macros. minIni uses limited stack space and does not use dynamic memory (malloc and
The library does not require the file I/O functions from the standard C/C++ library, but instead lets you configure
the file I/O interface to use via macros. minIni uses limited stack space and does not use dynamic memory (malloc and
friends) at all.

Some minor variations on standard INI files are supported too, notably minIni supports INI files that lack sections.
Expand All @@ -13,15 +13,15 @@ Some minor variations on standard INI files are supported too, notably minIni su

minIni is derived from an earlier INI file parser (which I wrote) for desktop systems.

In turn, that earlier parser was a re-write of the code from the article "Multiplatform .INI Files" by Joseph J. Graf
in the March 1994 issue of Dr. Dobb's Journal. In other words, minIni has its roots in the work of Joseph Graf (even
In turn, that earlier parser was a re-write of the code from the article "Multiplatform .INI Files" by Joseph J. Graf
in the March 1994 issue of Dr. Dobb's Journal. In other words, minIni has its roots in the work of Joseph Graf (even
though the code has been almost completely re-written).


# Features

minIni is a programmer's library to read and write "INI" files in embedded systems. minIni takes little resources,
can be configured for various kinds of file I/O libraries and provides functionality for reading, writing and
minIni is a programmer's library to read and write "INI" files in embedded systems. minIni takes little resources,
can be configured for various kinds of file I/O libraries and provides functionality for reading, writing and
deleting keys from an INI file.

Although the main feature of minIni is that it is small and minimal, it has a few other features:
Expand All @@ -34,32 +34,32 @@ Although the main feature of minIni is that it is small and minimal, it has a fe
* Section and key enumeration are supported.
* You can optionally set the line termination (for text files) that minIni will use. (This is a compile-time setting, not a run-time setting.)
* Since writing speed is much lower than reading speed in Flash memory (SD/MMC cards, USB memory sticks), minIni minimizes "file writes" at the expense of double "file reads".
* The memory footprint is deterministic. There is no dynamic memory allocation.
* The memory footprint is deterministic. There is no dynamic memory allocation.

## 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
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 in a row 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
The above procedure is quite inefficient, however, when you need to retrieve quite a few settings in a row 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
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.


# INI file syntax

INI files are best known from Microsoft Windows, but they are also used with applications that run on other
INI files are best known from Microsoft Windows, but they are also used with applications that run on other
platforms (although their file extension is sometimes ".cfg" instead of ".ini").

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
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.

```
Expand All @@ -69,30 +69,30 @@ 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
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
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, but it does not ignore spaces between the brackets in a
section name. In other words, it is best not to put spaces behind the opening bracket "[" or before the closing
minIni ignores spaces around the "=" or ":" delimiters, but it does not ignore spaces between the brackets in a
section name. In other words, it is best not to put spaces behind the opening bracket "[" or before the closing
bracket "]" of a section name.

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
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).

For more details on the format, please see http://en.wikipedia.org/wiki/INI_file.
For more details on the format, please see http://en.wikipedia.org/wiki/INI_file.


# 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
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:
Expand All @@ -101,36 +101,36 @@ To get you started, the minIni distribution comes with the following example glu
* a glue file for Microchip's "Memory Disk Drive File System Library" (see http://www.microchip.com/),
* a glue file for the FAT library provided with the CCS PIC compiler (see http://www.ccsinfo.com/)
* a glue file for the EFS Library (EFSL, http://www.efsl.be/),
* and a glue file for the FatFs and Petit-FatFs libraries (http://elm-chan.org/fsw/ff/00index_e.html).
* and a glue file for the FatFs and Petit-FatFs libraries (http://elm-chan.org/fsw/ff/00index_e.html).

The minIni library does not rely on the availability of a standard C library, because embedded operating systems
may have limited support for file I/O. Even on full operating systems, separating the file I/O from the INI format
The minIni library does not rely on the availability of a standard C library, because embedded operating systems
may have limited support for file I/O. Even on full operating systems, separating the file I/O from the INI format
parsing carries advantages, because it allows you to cache the INI file and thereby enhance performance.

The glue file must specify the type that identifies a file, whether it is a handle or a pointer. For the standard
The glue file must specify the type that identifies a file, whether it is a handle or a pointer. For the standard
C/C++ file I/O library, this would be:

```C
#define INI_FILETYPE FILE*
```

If you are not using the standard C/C++ file I/O library, chances are that you need a different handle or
"structure" to identify the storage than the ubiquitous "FILE*" type. For example, the glue file for the FatFs
If you are not using the standard C/C++ file I/O library, chances are that you need a different handle or
"structure" to identify the storage than the ubiquitous "FILE*" type. For example, the glue file for the FatFs
library uses the following declaration:

```C
#define INI_FILETYPE FIL
```

The minIni functions declare variables of this INI_FILETYPE type and pass these variables to sub-functions
The minIni functions declare variables of this INI_FILETYPE type and pass these variables to sub-functions
(including the glue interface functions) by reference.

For "write support", another type that must be defined is for variables that hold the "current position" in a
For "write support", another type that must be defined is for variables that hold the "current position" in a
file. For the standard C/C++ I/O library, this is "fpos_t".

Another item that needs to be configured is the buffer size. The functions in the minIni library allocate this
buffer on the stack, so the buffer size is directly related to the stack usage. In addition, the buffer size
determines the maximum line length that is supported in the INI file and the maximum path name length for the
Another item that needs to be configured is the buffer size. The functions in the minIni library allocate this
buffer on the stack, so the buffer size is directly related to the stack usage. In addition, the buffer size
determines the maximum line length that is supported in the INI file and the maximum path name length for the
temporary file. For example, minGlue.h could contain the definition:

```C
Expand All @@ -139,9 +139,9 @@ temporary file. For example, minGlue.h could contain the definition:

The above macro limits the line length of the INI files supported by minIni to 512 characters.

The temporary file is only used when writing to INI files. The minIni routines copy/change the INI file to a
temporary file and then rename that temporary file to the original file. This approach uses the least amount of
memory. The path name of the temporary file is the same as the input file, but with the last character set to a
The temporary file is only used when writing to INI files. The minIni routines copy/change the INI file to a
temporary file and then rename that temporary file to the original file. This approach uses the least amount of
memory. The path name of the temporary file is the same as the input file, but with the last character set to a
tilde ("~").

Below is an example of a glue file (this is the one that maps to the C/C++ "stdio" library).
Expand All @@ -165,5 +165,5 @@ Below is an example of a glue file (this is the one that maps to the C/C++ "stdi

As you can see, a glue file is mostly a set of macros that wraps one function definition around another.

The glue file may contain more settings, for support of rational numbers, to explicitly set the line termination
character(s), or to disable write support (for example). See the manual that comes with the archive for the details.
The glue file may contain more settings, for support of rational numbers, to explicitly set the line termination
character(s), or to disable write support (for example). See the manual that comes with the archive for the details.
16 changes: 15 additions & 1 deletion dev/minIni.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
* These routines are in part based on the article "Multiplatform .INI Files"
* by Joseph J. Graf in the March 1994 issue of Dr. Dobb's Journal.
*
* Copyright (c) CompuPhase, 2008-2021
* Copyright (c) CompuPhase, 2008-2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
Expand Down Expand Up @@ -949,4 +949,18 @@ int ini_putf(const TCHAR *Section, const TCHAR *Key, INI_REAL Value, const TCHAR
return ini_puts(Section, Key, LocalBuffer, Filename);
}
#endif /* INI_REAL */

/** ini_putbool()
* \param Section the name of the section to write the value in
* \param Key the name of the entry to write
* \param Value the value to write; it should be 0 or 1.
* \param Filename the name and full path of the .ini file to write to
*
* \return 1 if successful, otherwise 0
*/
int ini_putbool(const TCHAR *Section, const TCHAR *Key, int Value, const TCHAR *Filename)
{
return ini_puts(Section, Key, Value ? __T("true") : __T("false"), Filename);
}

#endif /* !INI_READONLY */
29 changes: 15 additions & 14 deletions dev/minIni.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* minIni - Multi-Platform INI file parser, suitable for embedded systems
*
* Copyright (c) CompuPhase, 2008-2021
* Copyright (c) CompuPhase, 2008-2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
Expand Down Expand Up @@ -37,24 +37,25 @@
extern "C" {
#endif

int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename);
long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename);
int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getbool(const mTCHAR *Section, const mTCHAR *Key, int DefValue, const mTCHAR *Filename);
long ini_getl(const mTCHAR *Section, const mTCHAR *Key, long DefValue, const mTCHAR *Filename);
int ini_gets(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *DefValue, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getsection(int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);
int ini_getkey(const mTCHAR *Section, int idx, mTCHAR *Buffer, int BufferSize, const mTCHAR *Filename);

int ini_hassection(const mTCHAR *Section, const mTCHAR *Filename);
int ini_haskey(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Filename);
int ini_hassection(const mTCHAR *Section, const mTCHAR *Filename);
int ini_haskey(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Filename);

#if defined INI_REAL
INI_REAL ini_getf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL DefValue, const mTCHAR *Filename);
#endif

#if !defined INI_READONLY
int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename);
int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename);
int ini_putbool(const TCHAR *Section, const TCHAR *Key, int Value, const TCHAR *Filename);
int ini_putl(const mTCHAR *Section, const mTCHAR *Key, long Value, const mTCHAR *Filename);
int ini_puts(const mTCHAR *Section, const mTCHAR *Key, const mTCHAR *Value, const mTCHAR *Filename);
#if defined INI_REAL
int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename);
int ini_putf(const mTCHAR *Section, const mTCHAR *Key, INI_REAL Value, const mTCHAR *Filename);
#endif
#endif /* INI_READONLY */

Expand Down Expand Up @@ -124,15 +125,15 @@ int ini_browse(INI_CALLBACK Callback, void *UserData, const mTCHAR *Filename);
#endif

#if ! defined INI_READONLY
bool put(const std::string& Section, const std::string& Key, bool Value)
{ return ini_putbool(Section.c_str(), Key.c_str(), (int)Value, iniFilename.c_str()) != 0; }

bool put(const std::string& Section, const std::string& Key, long Value)
{ return ini_putl(Section.c_str(), Key.c_str(), Value, iniFilename.c_str()) != 0; }

bool put(const std::string& Section, const std::string& Key, int Value)
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }

bool put(const std::string& Section, const std::string& Key, bool Value)
{ return ini_putl(Section.c_str(), Key.c_str(), (long)Value, iniFilename.c_str()) != 0; }

bool put(const std::string& Section, const std::string& Key, const std::string& Value)
{ return ini_puts(Section.c_str(), Key.c_str(), Value.c_str(), iniFilename.c_str()) != 0; }

Expand Down
8 changes: 4 additions & 4 deletions dev/wxMinIni.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* minIni - Multi-Platform INI file parser, wxWidgets interface
*
* Copyright (c) CompuPhase, 2008-2012
* Copyright (c) CompuPhase, 2008-2024
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
Expand Down Expand Up @@ -73,15 +73,15 @@ class minIni
#endif

#if ! defined INI_READONLY
bool put(const wxString& Section, const wxString& Key, bool Value) const
{ return ini_putbool(Section.utf8_str(), Key.utf8_str(), (int)Value, iniFilename.utf8_str()) != 0; }

bool put(const wxString& Section, const wxString& Key, long Value) const
{ return ini_putl(Section.utf8_str(), Key.utf8_str(), Value, iniFilename.utf8_str()) != 0; }

bool put(const wxString& Section, const wxString& Key, int Value) const
{ return ini_putl(Section.utf8_str(), Key.utf8_str(), (long)Value, iniFilename.utf8_str()) != 0; }

bool put(const wxString& Section, const wxString& Key, bool Value) const
{ return ini_putl(Section.utf8_str(), Key.utf8_str(), (long)Value, iniFilename.utf8_str()) != 0; }

bool put(const wxString& Section, const wxString& Key, const wxString& Value) const
{ return ini_puts(Section.utf8_str(), Key.utf8_str(), Value.utf8_str(), iniFilename.utf8_str()) != 0; }

Expand Down
Binary file modified doc/minIni.pdf
Binary file not shown.

0 comments on commit ede00e1

Please sign in to comment.