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 }