Aquineo implementation of INI file format

Abstract

This document specifies a text-based file format for representing software configuration data in a format which is easily editable by humans and unambiguously readable by a simple automatic parser.

Introduction

The format described here is an implementation of the application initialization file format, further refered to as INI file format, written in C#. Since the original Microsoft specification (defined in the Microsoft Windows for Workgroups Resource Kit) is generic, and implementations vary widely, we document how the INI file and parser is implemented here.

Most current implementations are simple, e.g. don't prevail the sequence of sections or don't support comments. In particular, missing support for comments hinders one to process existing INI files. To overcome limitations we wrote our own INI file parser resulting in a complete implementation of INI file format.

INI file structure

An INI file is a text file divided into sections, each containing zero or more keys. Each key contains zero or more values separated by comma. Comment lines are supported before a section name line or a key name line, respectively. Inline comments are comments following a section's name or a key/value pair.

INI example

; Comment line (belongs to Section1)
[Section1] ; Inline comment of Section1
Key1=Value1
; Comment line (belongs to Key2)
Key2=Value1 , Value2,Value3 ; Inline comment of Key2
Key3= "Value1"

List of meta characters

[ hexadecimal code 5B
squared bracket open, marks the beginning of a section name
] hexadecimal code 5D
squared bracket close, marks the ending of a section name
; hexadecimal code 3B
semicolon, introduces a comment
= hexadecimal code 3D
equal sign, marks the ending of a key name
, hexadecimal code 2C
comma, separates values
\ hexadecimal code 5C
backslash, encodes a double quotation mark

Section names and key names

Section names are enclosed in square brackets, key names are followed by an equal sign. Both names are case-sensitive and both names are optionally surrounded by spacing characters, which are ignored.

Characters not allowed inside of section names are: square brackets, comma, semicolon, double quotation mark, and whitespace.

Characters not allowed inside of key names are: sign of equality, comma, semicolon, double quotation mark, and whitespace.

If the same section appears more than once in the same file, or if the same key appears more than once in the same section, then the last occurrence prevails.

When a parser encounters an unrecognized section name, the entire section (with all its keys) will be skipped. Within a known section, only unrecognized keys will be skipped.

Values

Values are always string values, no types or implicit type conversions are supported. Values may optionally be enclosed in double quotation marks. Values beginning or ending with whitespace characters, or containing commas or semicolons, must be enclosed in double quotation marks. Double quotation marks appearing inside of a value enclosed in double quotation marks must be encoded as an escape sequence, containing a backslash followed by a double quotation mark: \".

Escape sequences will under no circumstances be encoded or decoded automatically. The class CIni provides auxiliary methods for encoding or decoding string values.

Comments

Comments are introduced by a semicolon character. Comments terminate at the end of the line. The parser will treat an end of file like an end of line. To prevail the structure of a given INI file empty lines are read as comment lines assigned the value null.

Whitespace

Whitespace includes space (hexadecimal code 20), horizontal tab (9), line feed (A), carriage return (D), vertical tab (B), and form feed (C).

End of line

On Microsoft Windows operating systems both a line feed or a carriage return followed by a line feed terminate a line.

Encoding

Text may be encoded using any encoding of the .NET System.Text.Encoding class (ASCII, Unicode, UTF-7, UTF-8, "Latin1" etc.). Default encoding is UTF-8.

Summary of special features compared to other implementations of INI file format

Coding

The following example uses INI classes to create a new INI file.

using System.Collections;
using Planet.Utility.Ini; // Namespace of INI file format implementation
 
// Create a new INI file, set encoding to "Latin1".
CIni Ini = new CIni("Aquineo.ini",
  System.Text.Encoding.GetEncoding("Latin1"));
 
// Add a section with comment lines, inline comments,
// key/value pairs etc.
ArrayList CommentLines = new ArrayList();
CommentLines.Add("------------------------------------");
CommentLines.Add("Aquineo Software");
CommentLines.Add("Implementation of INI file format");
CommentLines.Add("------------------------------------");
Ini.AddSection("LibraryInfo", CommentLines);
Ini.GetSection("LibraryInfo").Comment = "General information on program";
 
// Add key and value for "Version".
Ini.GetSection("LibraryInfo").AddKey("Version", null);
Ini.GetSection("LibraryInfo").GetKey("Version").
  AddValue(new CIniValueItem("1.0.1"));
// Add key and value for "Licence" in one step.
Ini.SetValue("LibraryInfo", "Licence", "Open source", false);
// Add key and value for "Release" in one step.
Ini.SetValue("LibraryInfo", "Release", "2004-05-01", false);
// Add key for "Changes".
CommentLines = new ArrayList();
CommentLines.Add(null); // Empty line
CommentLines.Add("Changes (excluding bugfixes).");
Ini.GetSection("LibraryInfo").AddKey("Changes", CommentLines);
CIniKeyItem KeyChanges = Ini.GetSection("LibraryInfo").GetKey("Changes");
KeyChanges.AddValue(
  new CIniValueItem("2004-05-09: CIni.TextEncoding made read only."));
KeyChanges.AddValue(
  new CIniValueItem("2004-04-28: CIniValueItem.Value returns value " +
  "as is, not necessarily adding CIniValueItem.QUOTE_DELIMITER " +
  "char (\\\").", true));
 
// Finally save INI file.
Ini.Write();

This is what you should expect:

;------------------------------------
;Aquineo Software
;Implementation of INI file format
;------------------------------------
[LibraryInfo] ;General information on program
Version=1.0.1
Licence=Open source
Release=2004-05-01
 
;Changes (excluding bugfixes).
Changes=2004-05-09: CIni.TextEncoding made read only.,"2004-04-28: CIniValueItem.Value returns value as is, not necessarily adding CIniValueItem.QUOTE_DELIMITER char (\")."

This example loads the previously created INI file.

using Planet.Utility.Ini;
 
// Load an existing INI file, set encoding to "Latin1".
CIni Ini = new CIni("Aquineo.ini",
  System.Text.Encoding.GetEncoding("Latin1"));
 
// Read value.
string LibVersion = Ini.GetValue("LibraryInfo", "Version", 0, false);
 
// Pass list of changes.
for (int i = 0; i < Ini.CountValues("LibraryInfo", "Changes"); ++i)
{
  string Change = CIni.Unescape(
    Ini.GetValue("LibraryInfo", "Changes", i, false));
  // Do something with Change...
}

Changes

Licence

Aquineo disclaims all warranties with regard to this software, including all implied warranties of merchantability and fitness, in no event shall Aquineo be liable for any special, indirect or consequential damages or any damages whatsoever resulting from loss of use, data or profits, whether in an action of contract, negligence or other tortious action, arising out of or in connection with the use or performance of this software.

Permission to use, copy, modify, and distribute this software for any purpose and without fee is hereby granted, subject to the following restrictions:

  1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation and this permission notice is required:
    Copyright © 2004 Aquineo (www.aquineo.com)
  2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
  3. This notice may not be removed or altered from any source distribution.

Acknowledgment

We would like to thank Cloanto for making available their specification of INI file format:
http://www.cloanto.com/specs/ini.html.