1 /** 2 License: public domain 3 Authors: Simon Bürger 4 */ 5 module jive.map; 6 7 private import std.range; 8 private import std.algorithm; 9 private import jive.set; 10 11 /** 12 * An (unordered map), based on jive.set. 13 * Similar to builtin 'V[Key]', but with value-semantics. 14 */ 15 struct Map(Key, V) 16 { 17 private Set!Entry entries; 18 19 private static struct Entry 20 { 21 Key key; 22 V value; 23 24 size_t toHash() const @safe /*pure*/ nothrow 25 { 26 return typeid(Key).getHash(&key); 27 } 28 29 bool opEquals(const(Entry) b) const @safe pure nothrow 30 { 31 return key == b.key; 32 } 33 34 bool opEquals(ref const(Entry) b) const @safe pure nothrow 35 { 36 return key == b.key; 37 } 38 39 bool opEquals(const(Key) b) const @safe pure nothrow 40 { 41 return key == b; 42 } 43 44 bool opEquals(ref const(Key) b) const @safe pure nothrow 45 { 46 return key == b; 47 } 48 } 49 50 /** returns: true if set is empty */ 51 bool empty() const pure nothrow @safe 52 { 53 return entries.empty; 54 } 55 56 /** returns: number of elements in the set */ 57 size_t length() const pure nothrow @safe 58 { 59 return entries.length; 60 } 61 62 /** returns: true if key is found in the map */ 63 bool opIn_r(T)(auto ref const(T) key) const 64 if(is(typeof(T.init == Key.init))) 65 { 66 return entries.opIn_r(key); 67 } 68 69 /** 70 * Lookup a key and return the stored value. 71 * If the key does not currently exist, it is created and its 72 * value set to V.init. 73 */ 74 ref V opIndex(T)(auto ref const(T) key) 75 if(is(typeof(T.init < Key.init))) 76 { 77 auto r = entries.find(key); 78 79 if(r is null) 80 { 81 entries.add(Entry(key, V.init)); 82 r = entries.find(key); 83 } 84 85 assert(r !is null); 86 return r.value; 87 } 88 89 /** 90 * Remove a key and associated value from the map. 91 * returns: true if removed, false if not found 92 */ 93 bool remove(T)(auto ref const(T) k) 94 if(is(typeof(T.init < Key.init))) 95 { 96 return entries.remove(k); 97 } 98 99 /** 100 * Traverse all entries using foreach. 101 * TODO: turn this into ranges 102 */ 103 int opApply(int delegate(ref Key) dg) 104 { 105 int r = 0; 106 foreach(ref e; entries[]) 107 if((r = dg(e.key)) != 0) 108 break; 109 return r; 110 } 111 112 /** 113 * ditto 114 */ 115 int opApply(int delegate(ref Key, ref V) dg) 116 { 117 int r = 0; 118 foreach(ref e; entries[]) 119 if((r = dg(e.key, e.value)) != 0) 120 break; 121 return r; 122 } 123 } 124 125 unittest 126 { 127 Map!(int,int) a; 128 a[1] = 1; 129 a[2] = 2; 130 a[1] = 3; 131 a.remove(2); 132 133 assert(1 in a); 134 assert(2 !in a); 135 assert(a.length == 1); 136 assert(a[1] == 3); 137 }