1 /**
2 * Data Store
3 * 
4 * Copyright:
5 * (C) 1999-2007 Jack Lloyd
6 * (C) 2014-2015 Etienne Cimon
7 *
8 * License:
9 * Botan is released under the Simplified BSD License (see LICENSE.md)
10 */
11 module botan.utils.datastor.datastor;
12 import botan.constants;
13 public import botan.utils.exceptn;
14 import botan.utils.parsing;
15 import botan.codec.hex;
16 import memutils.dictionarylist;
17 import memutils.vector;
18 import botan.utils.types;
19 import memutils.hashmap;
20 import std.traits : isNumeric;
21 import std.conv : to;
22 
23 /**
24 * Data Store
25 */
26 struct DataStore
27 {
28 public:
29     /*
30     * DataStore Equality Comparison
31     */
32     bool opEquals(in DataStore other) const
33     {
34         return (m_contents == other.m_contents);
35     }
36 
37     /*
38     * Search based on an arbitrary predicate
39     */
40     DictionaryListRef!(string, string) searchFor(bool delegate(string, string) predicate) const
41     {
42         DictionaryListRef!(string, string) output;
43 
44         foreach (const ref string key, const ref string val; m_contents)
45             if (predicate(key, val))
46                 output.insert(key, val);
47         
48         return output;
49     }
50 
51     /*
52     * Search based on key equality
53     */
54     Vector!string get(in string looking_for) const
55     {
56         Vector!string output;
57         foreach (const ref string k, const ref string v; m_contents) {
58             if (looking_for == k)
59                 output.pushBack(v);
60         }
61         return output.move;
62     }
63 
64 
65     /*
66     * Get a single atom
67     */
68     string get1(in string key) const
69     {
70         Vector!string vals = get(key);
71         
72         if (vals.empty)
73             throw new InvalidState("get1: No values set for " ~ key);
74         if (vals.length > 1)
75             throw new InvalidState("get1: More than one value for " ~ key);
76         
77         return vals[0];
78     }
79 
80     string get1(in string key,
81                 in string default_value) const
82     {
83         Vector!string vals = get(key);
84         
85         if (vals.length > 1)
86             throw new InvalidState("get1: More than one value for " ~ key);
87         
88         if (vals.empty)
89             return default_value;
90         
91         return vals[0];
92     }
93 
94     /*
95     * Get a single std::vector atom
96     */
97     Vector!ubyte
98         get1Memvec(in string key) const
99     {
100         Vector!string vals = get(key);
101         
102         if (vals.empty)
103             return Vector!ubyte();
104         
105         if (vals.length > 1)
106             throw new InvalidState("get1_memvec: Multiple values for " ~  key);
107         
108         return hexDecode(vals[0]);
109     }
110 
111     /*
112     * Get a single uint atom
113     */
114     uint get1Uint(in string key, uint default_val = 0) const
115     {
116         Vector!string vals = get(key);
117         
118         if (vals.empty)
119             return default_val;
120         else if (vals.length > 1)
121             throw new InvalidState("get1_uint: Multiple values for " ~ key);
122         return to!uint(vals[0]);
123     }
124 
125     /*
126     * Check if this key has at least one value
127     */
128     bool hasValue(in string key) const
129     {
130         return (m_contents.get(key, string.init) != string.init);
131     }
132     
133     /*
134     * Insert a single key and value
135     */
136     void add(in string key, in string val)
137     {
138         m_contents.insert(key.idup, val.idup);
139     }
140     
141     /*
142     * Insert a single key and value
143     */
144     void add(T)(in string key, in T val)
145         if (isNumeric!T)
146     {
147         add(key.idup, to!string(cast(long)val));
148     }
149     
150     /*
151     * Insert a single key and value
152     */
153     void add(ALLOC)(in string key, auto const ref Vector!(ubyte, ALLOC) val)
154     {
155         add(key.idup, hexEncode(val.ptr, val.length));
156     }
157     
158     void add(ALLOC)(in string key, auto const ref RefCounted!(Vector!(ubyte, ALLOC), ALLOC) val)
159     {
160         add(key.idup, hexEncode(val.ptr, val.length));
161     }
162     
163     /*
164     * Insert a mapping of key/value pairs
165     */
166     void add(in DictionaryListRef!(string, string) input)
167     {
168         foreach (const ref string k, const ref string v; input)
169             m_contents.insert(k.idup, v.idup);
170     }
171 
172     string toString() const {
173         Vector!char buffer;
174         foreach (const ref string k, const ref string v; m_contents) {
175             buffer ~= "Key: ";
176             buffer ~= k;
177             buffer ~= ", Value: ";
178             buffer ~= v;
179             buffer ~= "\n";
180         }
181         return buffer[].idup;
182     }
183 
184 private:
185     DictionaryListRef!(string, string) m_contents;
186 }