Working with INI Configuration Files Cross-Platform (Win32/Un*x, MBCS/Unicode)

SimpleIni

Cross platform programming can be painful, especially when it comes to simple tasks that you don't want to think about because they aren't your main problem. Unfortunately, it sometimes takes longer than it should to solve these tasks. One of these problems is loading configuration files. Although cross-platform XML libraries are available, if the user of your software is going to directly modify the file, it can be painful. The old Windows INI configuration file is a lasting file format that is easy for the user to understand and hard to get wrong.

This component is a C++ class that provides the ability to load an INI-style configuration file on both Windows and Linux/Unix. It is fast, simple, and source code using this component will compile unchanged on either OS. It supports both MBCS and Unicode builds on Windows, and can load UTF-8 or MBCS files on all platforms.

Features

  • Public domain, free use in all software (including GPL and commercial)
  • Multi-platform (Windows 95/98/ME/NT/2K/XP/2003, Linux, Unix)
  • Loads and saves INI-style configuration files
  • Liberal acceptance of file format
    • Key/Values with no section
    • Removal of whitespace around sections, keys, and values
  • Optional case-insensitive sections and keys (for ASCII characters only)
  • Supports both char or wchar_t programming interfaces
  • Supports both MBCS (system locale) and UTF-8 file encodings
  • System locale does not need to be UTF-8 on Linux/Unix to load UTF-8 file
  • Support for non-ASCII characters in section, keys, values, and comments
  • Support for non-standard character types or file encodings via user-written converter classes
  • Support for adding/modifying values programmatically

Usage Summary

  1. Declare an instance of the appropriate class. Note that the following definitions are just shortcuts for commonly used types. Other types (for example, PRUnichar, unsigned short, unsigned char) are also possible.
  2. Interface Case-sensitive Typedef
    char No CSimpleIniA
    char Yes CSimpleIniCaseA
    wchar_t No CSimpleIniW
    wchar_t Yes CSimpleIniCaseW
  3. Call LoadFile() to load and parse the INI configuration file.
  4. Use the following functions to access the file's data:
  5. GetAllSections Return all section names
    GetAllKeys Return all key names for a section
    GetSection Return all key names and values in a section
    GetSectionSize Return the number of keys in a section
    GetValue Return a value for a section & key
    SetValue Add or update a value for a section & key
  6. Call SaveFile() to save the INI configuration file (if necessary)

Notes

  • The collation (sorting) order used for sections and keys returned from iterators is NOT DEFINED. If collation order of the text is important, you should do it yourself by either supplying a replacement SI_STRCMP class or by sorting the strings external to this library.
  • Linux/Unix systems must also compile and link ConvertUTF.c.
  • To load a UTF-8 file on Windows and expose it with SI_CHAR == char, you need to define SI_USING_WIN32_CHAR_FOR_UTF8.

Download

The current version of SimpleIni is 1.5. The home page is http://code.jellycan.com/SimpleIni/.

Example Program

This program loads an INI file and dumps out all of the data from it.

#include "SimpleIni.h"

int main(int argc, char * argv[])
{
   setlocale(LC_CTYPE, "");

   if (argc < 2) {
      printf(
         "Usage: %s iniFile [useMBCS]\n"
         "   Pass 1 for useMBCS to use system locale file
             encoding\n",
         argv[0]);
      return 1;
   }
   bool bIsUtf8 = (argc < 3) ? true : *argv[2] != '1';

   const char * pDebug;
   printf("Dumping file using char version:\n");
   CSimpleIniA ini;
   if (0 != ini.LoadFile(argv[1], bIsUtf8)) {
      printf("Failed to open: %s\n", argv[1]);
       exit(1);
   }
   CSimpleIniA::TNames sections;
   ini.GetAllSections(sections);
   CSimpleIniA::TNames::const_iterator j = sections.begin();
   for ( ; j != sections.end(); ++j ) {
      printf("\n");
      if (*j[0]) {
         printf("[%s]\n", pDebug = *j);
      }
      const CSimpleIniA::TKeyVal * pSection = ini.GetSection(*j);
      if (pSection) {
         CSimpleIniA::TKeyVal::const_iterator i =
            pSection->begin();
         for ( ;i != pSection->end(); ++i) {
            printf("%s=%s\n", pDebug = i->first, i->second);
         }
      }
   }

   printf("\nQuerying section: [standard]\n");
   CSimpleIniA::TNames keys;
   ini.GetAllKeys("standard", keys);
   CSimpleIniA::TNames::const_iterator k = keys.begin();
   for ( ; k != keys.end(); ++k ) {
      printf("Key: %s\n", pDebug = *k);
   }

   pDebug = ini.GetValue("standard", "foo", 0);
   printf("\nValue of standard::foo is '%s'\n", pDebug ?
           pDebug : "(null)");

   ini.SetValue("standard", "foo", "wibble");
   pDebug = ini.GetValue("standard", "foo", 0);
   printf("Value of standard::foo is now '%s'\n", pDebug ?
           pDebug : "(null)");

   FILE * fp = fopen("testsi-char.ini", "wb");
   if (fp) {
      ini.SaveFile( fp, "; testsi.cpp test output (char)" SI_NEWLINE );
      fclose(fp);
   }

   return 0;
}

Disclaimer

This code is released as public domain. You can do with it whatever you like: use it, modify it, distribute it, sell it, delete it, or send it to your mother-in-law. I make no promises or guarantees that this code will work correctly or at all. Use it completely at your own risk.



About the Author

Brodie Thiesfield

Programming to eat. Donations of canned food accepted.

Downloads

Comments

  • Looks pretty good but I don't know how to use the UTF-8

    Posted by mikoil on 04/27/2006 06:56am

    ... I'm planning to use this class inside a DLL so I can use it under VB. Tried to display the UTF-8 ini file but couldn't. Maybe You can post here the appropiate changes I should make? Anyway thanks a lot ! :)

    • VB Unicode

      Posted by brofield on 04/27/2006 10:31am

      VB is not good at displaying Unicode text, there are lots of caveats and problems when working with full Unicode (i.e. text outside of the system default legacy character encoding). It does work fine under C++ as long as you use the wchar_t version, CSimpleIniW. Without knowing more about your usage I can't give advice. Essentially, use the CSimpleIniW version, load the file passing "true" for bIsUtf8. Ensure that the file is actually saved in UTF-8 format, e.g. use Textpad, Visual Studio .NET (Advanced Save Options), or another UTF-8 enabled editor. You may have to convert the strings to BSTR when handing them over to VB. Have fun.

      Reply
    • And by the way how did this image came to my profile..

      Posted by mikoil on 04/27/2006 07:50am

      Looks very scary, who put that? Not me for sure hehe, if any admin see this, please remove my image :)

      Reply
    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date