Skip to content

ddn.config.ini

Practical examples demonstrating everyday usage of the ddn.config.ini module.

Basic Parsing

Parse standard INI content with sections and key-value pairs.

/+ dub.sdl:
    name "ini-basic"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import ddn.var;
import std.stdio;

void main() {
    string content = `
[database]
host = localhost
port = 5432
enabled = true

[server]
name = "Primary Node"
timeout = 30
`;

    // Parse the INI string
    Ini config = parseIni(content);

    // Access values using standard var syntax
    string host = config["database"]["host"].as!string;
    int port = config["database"]["port"].as!int;
    bool enabled = config["database"]["enabled"].as!bool;

    writeln("DB Host: ", host);       // Output: DB Host: localhost
    writeln("DB Port: ", port);       // Output: DB Port: 5432
    writeln("DB Enabled: ", enabled); // Output: DB Enabled: true

    // Access another section
    writeln("Server Name: ", config["server"]["name"].as!string); // Output: Server Name: Primary Node
}

Global Properties

The parser supports properties defined outside of any section (global properties).

/+ dub.sdl:
    name "ini-globals"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import std.stdio;

void main() {
    string content = `
app_name = MyApp
version = 1.0.0

[logging]
level = info
`;

    // Global properties are enabled by default in IniPolicy
    auto config = parseIni(content);

    // Access global keys directly on the root object
    writeln("App: ", config["app_name"].as!string); // Output: App: MyApp
    writeln("Ver: ", config["version"].as!string);  // Output: Ver: 1.0.0

    // Access section keys
    writeln("Log Level: ", config["logging"]["level"].as!string); // Output: Log Level: info
}

Using Ini Wrapper

The Ini struct provides convenience methods like sections.

/+ dub.sdl:
    name "ini-wrapper"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import std.stdio;
import std.algorithm : sort;
import std.array : array;

void main() {
    string content = `
[users]
admin = true

[settings]
theme = dark
`;

    Ini config = parseIni(content);

    // Iterate over section names
    foreach (sectionName; config.sections) {
        writeln("Found section: ", sectionName);
    }
    // Output:
    // Found section: settings
    // Found section: users

    // Check for section existence
    if (config.contains("users")) {
        writeln("Users section exists");
    }
}

Advanced Parsing: Comments and Escaping

The parser supports inline comments (;, #) and standard escape sequences (\n, \t, \", etc.) when parsing values.

/+ dub.sdl:
    name "ini-advanced"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import std.stdio;

void main() {
    string content = `
[messages]
welcome = "Hello,\nWorld!"      ; Handles newline escape
path = "C:\\Windows\\System32"  # Handles backslash escape
quoted = "He said \"Yes\""      ; Handles quote escape

[comments]
inline = value ; This comment is stripped
hash_style = value # This is also a comment
quoted_comment = "value ; preserved" ; This is stripped
`;

    auto config = parseIni(content);

    writeln("Welcome: ", config["messages"]["welcome"].as!string);
    // Output:
    // Welcome: Hello,
    // World!

    writeln("Path: ", config["messages"]["path"].as!string);
    // Output: Path: C:\Windows\System32

    writeln("Inline: ", config["comments"]["inline"].as!string);
    // Output: Inline: value

    writeln("Quoted Comment: ", config["comments"]["quoted_comment"].as!string);
    // Output: Quoted Comment: value ; preserved
}

Writing INI Files

You can save a var structure back to an INI file or string. The writer handles quoting and escaping automatically.

/+ dub.sdl:
    name "ini-write"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import ddn.var;
import std.stdio;
import std.file : exists, remove;

void main() {
    // Construct data programmatically
    var data = var.makeObject();

    // Add global properties
    data["app_mode"] = "production";

    // Add sections
    data["network"] = var.makeObject();
    data["network"]["host"] = "127.0.0.1";
    data["network"]["port"] = 8080;

    data["desc"] = var.makeObject();
    data["desc"]["text"] = "Line 1\nLine 2"; // Will be escaped as "Line 1\nLine 2"
    data["desc"]["comment"] = "a;b";         // Will be quoted as "a;b"

    // 1. Generate string
    string iniString = toIni(data);
    writeln(iniString);

    // 2. Save directly to file
    string filename = "config.ini";
    toIni(data, filename);

    if (exists(filename)) {
        writeln("File saved successfully.");
        remove(filename); // Cleanup
    }
}

Configuring Policy

Customize parsing behavior using IniPolicy.

/+ dub.sdl:
    name "ini-policy"
    dependency "ddn" path="../.."
+/
import ddn.config.ini;
import std.stdio;

void main() {
    string content = `
key = value
[section]
broken_line_without_equals
`;

    // Default policy is strict (throws on malformed lines)
    try {
        parseIni(content);
    } catch (Exception e) {
        writeln("Strict parse failed: ", e.msg);
    }

    // Relaxed policy
    IniPolicy policy;
    policy.strict = false; // Ignore malformed lines

    auto config = parseIni(content, policy);
    writeln("Relaxed parse success. Key: ", config["key"].as!string);
}