parseIni function
Parses input as INI text into section → key → value. Entries before the
first [section] land under iniGlobalSection (''). A declared but empty
[section] still appears as an empty map. The separator is the first = on
the line (so url=http://x keeps the colon in the value). Blank lines and
full-line # / ; comments are skipped; any other line lacking = throws a
FormatException naming the offending line — strict by design so a typo in
config surfaces instead of being silently dropped.
Set allowExport to strip a leading export from keys (shell-style files).
Example:
parseIni('[db]\nhost = localhost\nport = 5432');
// {db: {host: localhost, port: 5432}}
Audited: 2026-06-12 11:26 EDT
Implementation
Map<String, Map<String, String>> parseIni(String input, {bool allowExport = false}) {
final Map<String, Map<String, String>> out = <String, Map<String, String>>{};
String section = iniGlobalSection;
for (final String raw in input.split('\n')) {
final String line = raw.trim();
if (line.isEmpty || _isComment(line)) {
continue;
}
// A `[name]` header opens (or re-opens) a section; create it eagerly so an
// empty section is still observable, then move on to the next line.
final String? header = _sectionName(line);
if (header != null) {
section = header;
out.putIfAbsent(section, () => <String, String>{});
continue;
}
final MapEntry<String, String> entry = _entry(raw, line, allowExport: allowExport);
out.putIfAbsent(section, () => <String, String>{})[entry.key] = entry.value;
}
return out;
}