1 module keyvalues.keyvalue;
2 
3 import std.algorithm;
4 import std.array;
5 import std.string;
6 import std.traits;
7 
8 /++
9     In-memory representation of a KeyValues object.
10 +/
11 struct KeyValue
12 {
13     string key; ///The key of this KeyValue.
14     bool hasSubkeys; ///Whether this KeyValue has subkeys.
15     
16     union
17     {
18         string value; ///The value of this KeyValue, if hasSubkeys is false.
19         KeyValue[] subkeys; ///The subkeys of this KeyValue, if hasSubkeys is true.
20     }
21     
22     /++
23         Returns all subkeys whose key equal name.
24     +/
25     KeyValue[] opIndex(string name)
26     in { assert(hasSubkeys); }
27     body
28     {
29         return subkeys
30             .filter!(subkey => subkey.key == name)
31             .array
32         ;
33     }
34     
35     /++
36         Returns a pretty printed string representation of this KeyValue.
37     +/
38     string toString()
39     {
40         string valueRepr;
41         
42         if(hasSubkeys)
43             valueRepr = subkeys
44                 .map!(sk => sk.toString)
45                 .join(",\n")
46                 .replace("\n", "\n    ")
47                 .Identity!(str => "[\n    %s\n]".format(str))
48             ;
49         else
50             valueRepr = value
51                 .formatEscapes
52                 .Identity!(str => `"%s"`.format(str))
53             ;
54         
55         return "KeyValue(\n    \"%s\",\n    %s\n)".format(
56             key.formatEscapes,
57             valueRepr.replace("\n", "\n    "),
58         );
59     }
60     
61     //TODO: method to serialize to KeyValues text
62 }
63 
64 private string formatEscapes(string str)
65 {
66     return str
67         .replace("\\", `\\`)
68         .replace("\"", `\"`)
69         .replace("\n", `\n`)
70         .replace("\t", `\t`)
71     ;
72 }