1 module mutils.container.hash_map_tow_way; 2 import mutils.container.hash_map; 3 4 struct HashMapTwoWay(KeyOnePar, KeyTwoPar) { 5 alias KeyOne = KeyOnePar; 6 alias KeyTwo = KeyTwoPar; 7 8 HashMap!(KeyOne, KeyTwo) keyOneToKeyTwo; 9 HashMap!(KeyTwo, KeyOne) keyTwoToKeyOne; 10 11 enum getIndexEmptyValue = keyOneToKeyTwo.getIndexEmptyValue; 12 13 invariant { 14 assert(keyOneToKeyTwo.length == keyTwoToKeyOne.length); 15 } 16 17 ~this() { 18 clear(); 19 } 20 21 void clear() { 22 keyOneToKeyTwo.clear(); 23 keyTwoToKeyOne.clear(); 24 } 25 26 void reset() { 27 keyOneToKeyTwo.reset(); 28 keyTwoToKeyOne.reset(); 29 } 30 31 size_t length() { 32 return keyOneToKeyTwo.length; 33 } 34 35 auto ref KeyTwo get()(auto ref KeyOne k, auto ref KeyTwo defaultValue) { 36 size_t index = keyOneToKeyTwo.getIndex(k); 37 if (index == getIndexEmptyValue) { 38 return defaultValue; 39 } else { 40 return keyOneToKeyTwo.elements[index].keyValue.value; 41 } 42 } 43 44 auto ref KeyOne get()(auto ref KeyTwo k, auto ref KeyOne defaultValue) { 45 size_t index = keyTwoToKeyOne.getIndex(k); 46 if (index == getIndexEmptyValue) { 47 return defaultValue; 48 } else { 49 return keyTwoToKeyOne.elements[index].keyValue.value; 50 } 51 } 52 53 void add()(auto ref KeyOne one, auto ref KeyTwo two) { 54 size_t indexOne = keyOneToKeyTwo.getIndex(one); 55 size_t indexTwo = keyTwoToKeyOne.getIndex(two); 56 if (indexOne != getIndexEmptyValue) { 57 KeyTwo value = keyOneToKeyTwo.elements[indexOne].keyValue.value; 58 if (value != two) { 59 keyTwoToKeyOne.remove(value); 60 keyOneToKeyTwo.elements[indexOne].keyValue.value = two; 61 } 62 } else { 63 keyOneToKeyTwo.add(one, two); 64 65 } 66 67 if (indexTwo != getIndexEmptyValue) { 68 KeyOne value = keyTwoToKeyOne.elements[indexTwo].keyValue.value; 69 if (value != one) { 70 keyOneToKeyTwo.remove(value); 71 keyTwoToKeyOne.elements[indexTwo].keyValue.value = one; 72 } 73 } else { 74 keyTwoToKeyOne.add(two, one); 75 } 76 77 } 78 79 void remove()(auto ref KeyOne one, auto ref KeyTwo two) { 80 size_t indexOne = keyOneToKeyTwo.getIndex(one); 81 size_t indexTwo = keyTwoToKeyOne.getIndex(two); 82 if (indexOne == getIndexEmptyValue || indexTwo == getIndexEmptyValue) { 83 assert(indexOne == indexTwo); 84 return; 85 } 86 assert(keyOneToKeyTwo.elements[indexOne].keyValue.value == two); 87 assert(keyTwoToKeyOne.elements[indexTwo].keyValue.value == one); 88 keyOneToKeyTwo.remove(one); 89 keyTwoToKeyOne.remove(two); 90 } 91 92 void remove()(auto ref KeyOne key) { 93 size_t index = keyOneToKeyTwo.getIndex(key); 94 if (index == getIndexEmptyValue) { 95 return; 96 } 97 KeyTwo value = keyOneToKeyTwo.elements[index].keyValue.value; 98 keyTwoToKeyOne.remove(value); 99 keyOneToKeyTwo.remove(key); 100 } 101 102 void remove()(auto ref KeyTwo key) { 103 size_t index = keyTwoToKeyOne.getIndex(key); 104 if (index == getIndexEmptyValue) { 105 return; 106 } 107 KeyOne value = keyTwoToKeyOne.elements[index].keyValue.value; 108 keyOneToKeyTwo.remove(value); 109 keyTwoToKeyOne.remove(key); 110 } 111 112 } 113 114 unittest { 115 HashMapTwoWay!(char, int) map; 116 117 map.add('a', 1); 118 assert(map.length == 1); 119 assert(map.get('a', 0) == 1); 120 assert(map.get(1, '\0') == 'a'); 121 122 map.add('a', 2); 123 assert(map.length == 1); 124 assert(map.get('a', 0) == 2); 125 assert(map.get(1, '\0') == '\0'); 126 assert(map.get(2, '\0') == 'a'); 127 128 map.add('b', 2); 129 assert(map.length == 1); 130 assert(map.get('a', 0) == 0); 131 assert(map.get('b', 0) == 2); 132 assert(map.get(1, '\0') == '\0'); 133 assert(map.get(2, '\0') == 'b'); 134 135 map.add('c', 3); 136 assert(map.length == 2); 137 138 map.remove('b'); 139 assert(map.length == 1); 140 141 map.remove(3); 142 assert(map.length == 0); 143 }