1 #include "Cello/Map.h"
2
3 #include "Cello/List.h"
4 #include "Cello/Bool.h"
5 #include "Cello/None.h"
6 #include "Cello/Exception.h"
7
8 #include <string.h>
9
10 struct MapNode {
11 var leaf_key;
12 var leaf_val;
13 struct MapNode* left;
14 struct MapNode* right;
15 };
16
17 data {
18 var type;
19 var keys;
20 struct MapNode* root;
21 } MapData;
22
23 var Map = type_data {
24 type_begin(Map),
25 type_entry(Map, New),
26 type_entry(Map, Assign),
27 type_entry(Map, Copy),
28 type_entry(Map, Eq),
29 type_entry(Map, Collection),
30 type_entry(Map, Dict),
31 type_entry(Map, Iter),
32 type_entry(Map, Show),
33 type_end(Map),
34 };
35
Map_New(var self,var_list vl)36 var Map_New(var self, var_list vl) {
37 MapData* md = cast(self, Map);
38 md->keys = new(List);
39 md->root = NULL;
40 return self;
41 }
42
Map_Delete(var self)43 var Map_Delete(var self) {
44 MapData* md = cast(self, Map);
45 clear(self);
46 delete(md->keys);
47 return self;
48 }
49
Map_Size(void)50 size_t Map_Size(void) {
51 return sizeof(MapData);
52 }
53
Map_Assign(var self,var obj)54 void Map_Assign(var self, var obj) {
55 MapData* other = cast(obj, Map);
56 clear(self);
57
58 foreach(key in other) {
59 var val = get(other, key);
60 put(self, key, val);
61 }
62 }
63
Map_Copy(var self)64 var Map_Copy(var self) {
65 var newmap = new(Map);
66 foreach(key in self) {
67 var val = get(self, key);
68 put(newmap, key, val);
69 }
70 return newmap;
71 }
72
Map_Eq(var self,var obj)73 var Map_Eq(var self, var obj) {
74 MapData* md = cast(self, Map);
75 if_neq(type_of(obj), Map) { return False; }
76
77 foreach(key in obj) {
78 if (not contains(self, key)) { return False; }
79 if_neq(get(obj, key), get(self, key)) { return False; }
80 }
81
82 foreach(key in self) {
83 if (not contains(obj, key)) { return False; }
84 if_neq(get(self, key), get(obj, key)) { return False; }
85 }
86
87 return True;
88 }
89
Map_Len(var self)90 int Map_Len(var self) {
91 MapData* md = cast(self, Map);
92 return len(md->keys);
93 }
94
Map_Clear(var self)95 void Map_Clear(var self) {
96 MapData* md = cast(self, Map);
97
98 while(not is_empty(self)) {
99 discard(self, at(md->keys,0));
100 }
101 }
102
Map_Contains(var self,var key)103 var Map_Contains(var self, var key) {
104 MapData* md = cast(self, Map);
105 return contains(md->keys, key);
106 }
107
108 local bool inorder_opt = true;
109
Map_Next_Inorder(struct MapNode * node)110 local var Map_Next_Inorder(struct MapNode* node) {
111
112 inorder_opt = not inorder_opt;
113
114 if (inorder_opt) {
115
116 struct MapNode* rnode = node->left;
117
118 while(1) {
119 if (rnode->right is NULL) return rnode->leaf_key;
120 else rnode = rnode->right;
121 }
122
123 } else {
124
125 struct MapNode* lnode = node->right;
126
127 while(1) {
128 if (lnode->left is NULL) return lnode->leaf_key;
129 else lnode = lnode->left;
130 }
131
132 }
133
134 }
135
Map_Discard(var self,var key)136 void Map_Discard(var self, var key) {
137 MapData* md = cast(self, Map);
138
139 struct MapNode** parent = &md->root;
140 struct MapNode* node = md->root;
141
142 while(node != NULL) {
143
144 if_eq(node->leaf_key, key) {
145
146 if ((node->left is NULL) and
147 (node->right is NULL)) {
148 *parent = NULL;
149 free(node);
150 discard(md->keys, key);
151 return;
152 }
153
154 if ((node->left is NULL) and
155 not (node->right is NULL)) {
156 *parent = node->right;
157 free(node);
158 discard(md->keys, key);
159 return;
160 }
161
162 if ((node->right is NULL) and
163 not (node->left is NULL)) {
164 *parent = node->left;
165 free(node);
166 discard(md->keys, key);
167 return;
168 }
169
170 if (not (node->right is NULL) and
171 not (node->left is NULL)) {
172 var inorder_key = Map_Next_Inorder(node);
173 var inorder_val = get(self, inorder_key);
174
175 discard(self, inorder_key);
176
177 node->leaf_key = inorder_key;
178 node->leaf_val = inorder_val;
179
180 discard(md->keys, key);
181 return;
182 }
183
184 }
185
186 if_lt(node->leaf_key, key) {
187 parent = &node->left;
188 node = node->left;
189 } else {
190 parent = &node->right;
191 node = node->right;
192 }
193
194 }
195
196 }
197
Map_Get(var self,var key)198 var Map_Get(var self, var key) {
199 MapData* md = cast(self, Map);
200
201 struct MapNode* node = md->root;
202
203 while(node != NULL) {
204 if_eq(node->leaf_key, key) return node->leaf_val;
205 if_lt(node->leaf_key, key) node = node->left;
206 else node = node->right;
207 }
208
209 return throw(KeyError, "Key '%$' not in Map!", key);
210 }
211
Map_Node_New(var key,var val)212 local struct MapNode* Map_Node_New(var key, var val) {
213 struct MapNode* node = malloc(sizeof(struct MapNode));
214
215 if (node == NULL) { throw(OutOfMemoryError, "Cannot create new Map Node. Out of memory!"); }
216
217 node->leaf_key = key;
218 node->leaf_val = val;
219 node->left = NULL;
220 node->right = NULL;
221 return node;
222 }
223
Map_Put(var self,var key,var val)224 void Map_Put(var self, var key, var val) {
225 MapData* md = cast(self, Map);
226
227 struct MapNode** parent = &md->root;
228 struct MapNode* node = md->root;
229
230 while (node != NULL) {
231
232 if_eq(node->leaf_key, key) {
233 node->leaf_val = val;
234 return;
235 }
236
237 if_lt(node->leaf_key, key) {
238 parent = &node->left;
239 node = node->left;
240 } else {
241 parent = &node->right;
242 node = node->right;
243 }
244
245 }
246
247 *parent = Map_Node_New(key, val);
248 push(md->keys, key);
249 return;
250
251 }
252
Map_Iter_Start(var self)253 var Map_Iter_Start(var self) {
254 MapData* md = cast(self, Map);
255 return iter_start(md->keys);
256 }
257
Map_Iter_End(var self)258 var Map_Iter_End(var self) {
259 MapData* md = cast(self, Map);
260 return iter_end(md->keys);
261 }
262
Map_Iter_Next(var self,var curr)263 var Map_Iter_Next(var self, var curr) {
264 MapData* md = cast(self, Map);
265 return iter_next(md->keys, curr);
266 }
267
Map_Show(var self,var output,int pos)268 int Map_Show(var self, var output, int pos) {
269 MapData* md = cast(self, Map);
270
271 pos = print_to(output, pos, "<'Map' At 0x%p {", self);
272
273 for(int i = 0; i < len(self); i++) {
274 var key = at(md->keys, i);
275 var val = get(self, key);
276 pos = print_to(output, pos, "%$:%$", key, get(self, key));
277 if (i < len(self)-1) { pos = print_to(output, pos, ", "); }
278 }
279
280 pos = print_to(output, pos, "}>");
281
282 return pos;
283 }
284
285