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 }