mirror of https://github.com/adamdruppe/arsd.git
Implement function `parseIniMergedAA`
This commit is contained in:
parent
c300956cf7
commit
c38b37cce9
116
ini.d
116
ini.d
|
@ -703,6 +703,7 @@ private enum OperatingMode operatingMode(string) = (is(string == char[]))
|
||||||
* [IniFilteredParser]
|
* [IniFilteredParser]
|
||||||
* [parseIniDocument]
|
* [parseIniDocument]
|
||||||
* [parseIniAA]
|
* [parseIniAA]
|
||||||
|
* [parseIniMergedAA]
|
||||||
)
|
)
|
||||||
+/
|
+/
|
||||||
struct IniParser(
|
struct IniParser(
|
||||||
|
@ -1366,6 +1367,7 @@ struct IniParser(
|
||||||
* [IniParser]
|
* [IniParser]
|
||||||
* [parseIniDocument]
|
* [parseIniDocument]
|
||||||
* [parseIniAA]
|
* [parseIniAA]
|
||||||
|
* [parseIniMergedAA]
|
||||||
)
|
)
|
||||||
+/
|
+/
|
||||||
struct IniFilteredParser(
|
struct IniFilteredParser(
|
||||||
|
@ -2203,7 +2205,10 @@ struct IniDocument(string) if (isCompatibleString!string) {
|
||||||
Parses an INI string into a document ("DOM").
|
Parses an INI string into a document ("DOM").
|
||||||
|
|
||||||
See_also:
|
See_also:
|
||||||
[parseIniAA]
|
$(LIST
|
||||||
|
* [parseIniAA]
|
||||||
|
* [parseIniMergedAA]
|
||||||
|
)
|
||||||
+/
|
+/
|
||||||
IniDocument!string parseIniDocument(IniDialect dialect = IniDialect.defaults, string)(string rawIni) @safe pure nothrow
|
IniDocument!string parseIniDocument(IniDialect dialect = IniDialect.defaults, string)(string rawIni) @safe pure nothrow
|
||||||
if (isCompatibleString!string) {
|
if (isCompatibleString!string) {
|
||||||
|
@ -2359,7 +2364,10 @@ company = "Digital Mars"
|
||||||
)
|
)
|
||||||
|
|
||||||
See_also:
|
See_also:
|
||||||
[parseIniDocument]
|
$(LIST
|
||||||
|
* [parseIniMergedAA]
|
||||||
|
* [parseIniDocument]
|
||||||
|
)
|
||||||
+/
|
+/
|
||||||
string[immutable(char)[]][immutable(char)[]] parseIniAA(
|
string[immutable(char)[]][immutable(char)[]] parseIniAA(
|
||||||
IniDialect dialect = IniDialect.defaults,
|
IniDialect dialect = IniDialect.defaults,
|
||||||
|
@ -2590,6 +2598,110 @@ key = merged and overwritten
|
||||||
assert(aa["2"]["key"] == "overwritten");
|
assert(aa["2"]["key"] == "overwritten");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/++
|
||||||
|
Parses an INI string into a section-less associate array.
|
||||||
|
All sections are merged.
|
||||||
|
|
||||||
|
$(LIST
|
||||||
|
* Section names are discarded.
|
||||||
|
* Duplicate keys cause values to get overwritten.
|
||||||
|
)
|
||||||
|
|
||||||
|
See_also:
|
||||||
|
$(LIST
|
||||||
|
* [parseIniAA]
|
||||||
|
* [parseIniDocument]
|
||||||
|
)
|
||||||
|
+/
|
||||||
|
string[immutable(char)[]] parseIniMergedAA(
|
||||||
|
IniDialect dialect = IniDialect.defaults,
|
||||||
|
string,
|
||||||
|
)(
|
||||||
|
string rawIni,
|
||||||
|
) @safe pure nothrow {
|
||||||
|
static if (is(string == immutable(char)[])) {
|
||||||
|
immutable(char)[] toString(string key) => key;
|
||||||
|
} else {
|
||||||
|
immutable(char)[] toString(string key) => key.idup;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parser = IniParser!(dialect, string)(rawIni);
|
||||||
|
|
||||||
|
string[immutable(char)[]] section;
|
||||||
|
|
||||||
|
string keyName = null;
|
||||||
|
string value = null;
|
||||||
|
|
||||||
|
void commitKeyValuePair(string nextKey) {
|
||||||
|
if (keyName !is null) {
|
||||||
|
section[toString(keyName)] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyName = nextKey;
|
||||||
|
value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValue(string nextValue) {
|
||||||
|
value = nextValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!parser.skipIrrelevant()) {
|
||||||
|
switch (parser.front.type) with (TokenType) {
|
||||||
|
|
||||||
|
case key:
|
||||||
|
commitKeyValuePair(parser.front.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case value:
|
||||||
|
setValue(parser.front.data);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case sectionHeader:
|
||||||
|
// nothing to do
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
assert(false, "Unexpected parsing error."); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.popFront();
|
||||||
|
}
|
||||||
|
|
||||||
|
commitKeyValuePair(null);
|
||||||
|
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest {
|
||||||
|
static immutable demoData = `
|
||||||
|
key0 = value0
|
||||||
|
|
||||||
|
[1]
|
||||||
|
key1 = value1
|
||||||
|
key2 = other value
|
||||||
|
|
||||||
|
[2]
|
||||||
|
key1 = value2
|
||||||
|
key3 = yet another value`;
|
||||||
|
|
||||||
|
// Parse INI file into an associative array with merged sections.
|
||||||
|
string[string] aa = parseIniMergedAA(demoData);
|
||||||
|
|
||||||
|
// As sections were merged, entries sharing the same key got overridden.
|
||||||
|
// Hence, there are only four entries left.
|
||||||
|
assert(aa.length == 4);
|
||||||
|
|
||||||
|
// The "key1" entry of the first section got overruled
|
||||||
|
// by the "key1" entry of the second section that came later.
|
||||||
|
assert(aa["key1"] == "value2");
|
||||||
|
|
||||||
|
// Entries with unique keys got through unaffected.
|
||||||
|
assert(aa["key0"] == "value0");
|
||||||
|
assert(aa["key2"] == "other value");
|
||||||
|
assert(aa["key3"] == "yet another value");
|
||||||
|
}
|
||||||
|
|
||||||
private void stringifyIniString(string, OutputRange)(string data, OutputRange output) {
|
private void stringifyIniString(string, OutputRange)(string data, OutputRange output) {
|
||||||
if (data is null) {
|
if (data is null) {
|
||||||
output.put("\"\"");
|
output.put("\"\"");
|
||||||
|
|
Loading…
Reference in New Issue