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
saveandtoInifunctions 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:
IniPolicyallows 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.
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