Skip to content

ddn.config.ini

A robust, flexible, and fully-featured INI file parser and writer for the D programming language.

Overview

The ddn.config.ini module provides a comprehensive solution for handling configuration files in the INI format. It is designed to integrate seamlessly with the ddn.var dynamic type system, allowing for easy parsing into var objects and serializing var objects back to INI format.

The implementation focuses on robustness and flexibility, supporting standard INI features as well as common variations like inline comments, global properties, and escape sequences.

Features

Parsing

  • Standard Sections: Parses standard [section] headers into nested objects.
  • Global Properties: Supports properties defined before the first section (implicit globals) or within an explicit [global] section.
  • Flexible Comments: Supports both semicolon (;) and hash (#) as comment starters, including inline comments.
  • Quoted Values: Handles double-quoted values ("value") to preserve whitespace and special characters.
  • Escape Sequences: Decodes standard escape sequences (\n, \t, \", \\, etc.) within quoted strings.

Writing

  • Round-Trip Safety: The save and toIni functions automatically quote values containing special characters (comments, assignments, whitespace) and escape control characters.
  • Deterministic Output: Sections and keys are sorted lexicographically to ensure stable, reproducible output.
  • Direct File Writing: Supports writing directly to a file to avoid intermediate string allocations.

Robustness & Policy

  • Strict Mode: Optional strict mode (enabled by default) to validate input and catch malformed lines or unclosed quotes.
  • Global Merging: When enabled, properties in a [global] section are merged with implicit global properties (those at the top of the file).
  • Customizable Policy: IniPolicy allows configuring comment characters, strictness, and global property handling.

Usage

Basic Parsing

Parsing an INI string returns an Ini struct, which wraps a var object.

import ddn.config.ini;
import ddn.var;

string content = `
; Global settings
debug = true
timeout = 30

[database]
host = "localhost"
port = 5432
`;

Ini ini = parseIni(content);

// Access global properties
assert(ini["debug"].as!bool == true);

// Access section properties
assert(ini["database"]["host"].as!string == "localhost");

Accessing Sections

The Ini struct provides a convenience property sections to iterate over section names.

foreach (sectionName; ini.sections) {
    var section = ini[sectionName];
    // process section...
}

Writing to INI

You can save a var object (usually a Type.OBJECT) to an INI file or string.

var config = var.makeObject();
config["app_name"] = "My App"; // Global
config["server"] = var.makeObject();
config["server"]["port"] = 8080;

// Save to string
string iniString = toIni(config);

// Save directly to file
toIni(config, "config.ini");

Configuration Policy

Customize the parser behavior using IniPolicy.

IniPolicy policy;
policy.commentChars = ";";      // Only allow ; for comments
policy.strict = false;          // Ignore malformed lines instead of throwing
policy.allowGlobalProperties = true;

auto ini = parseIni(content, policy);

Advanced Features

Inline Comments & Escaping

The parser handles complex values correctly:

key1 = value ; This is an inline comment
key2 = "value with ; semicolon" ; Comment starts here
key3 = "Line 1\nLine 2" ; Multiline value using escape

Global Section Merging

If allowGlobalProperties is true, a [global] section is treated as the root scope.

implicit_key = 1

[global]
explicit_key = 2
implicit_key = "overwritten" ; Overwrites the earlier value

Result: - implicit_key: "overwritten" - explicit_key: 2