Changed iterator behavior...It only iterates over the items in the set
[repair.git] / Repair / RepairCompiler / MCC / Runtime / SimpleHash.cc
1 #include "SimpleHash.h"
2 #include <stdarg.h>
3 #include <stdlib.h>
4
5 /* LINKED HASH NODE ****************************************************/
6
7 LinkedHashNode::LinkedHashNode(int key, int data, LinkedHashNode *next) {
8     this->key = key;
9     this->data = data;
10     this->next = next;
11     this->lnext=0;
12     this->lprev=0;
13 }
14
15 LinkedHashNode::LinkedHashNode() {
16     this->key = -1;
17     this->data = -1;
18     this->next = 0;
19     this->lnext=0;
20     this->lprev=0;
21 }
22
23 /* SIMPLE LIST ****************************************************/
24
25 SimpleList::SimpleList() {
26     ptr = 0;
27     head.next = 0;
28 }
29
30 void SimpleList::reset() {
31   // ptr = head.next;
32   ptr = &head;
33 }
34
35 int SimpleList::hasMoreElements() {
36   //  return (ptr != 0);
37   return (ptr->next != 0);
38 }
39
40 int SimpleList::nextElement() {
41   ptr = ptr->next;
42   return ptr->data;
43
44   //int data = ptr->data;
45   //ptr = ptr->next;
46   //return data;
47 }
48
49 void SimpleList::add(int data) {
50     LinkedHashNode *cur = &head;
51     while (cur->next) {
52         cur = cur->next;
53         if (cur->data == data) {
54             return; // no duplicates
55         }
56     }
57     cur->next = new LinkedHashNode(0, data, 0);
58     return;
59 }
60
61 int SimpleList::contains(int data) {
62     LinkedHashNode *cur = &head;
63     while (cur->next) {
64         cur = cur->next;
65         if (cur->data == data) {
66             return 1; // found!
67         }
68     }
69     return 0;    
70 }
71
72 /* WORK LIST ****************************************************/
73
74 WorkList::WorkList() {
75   head=(struct ListNode *) malloc(sizeof(struct ListNode));
76   tail=head;
77   head->next=0;
78   headoffset=0;
79   tailoffset=0;
80 }
81
82 int WorkList::hasMoreElements() {
83   //  return (ptr != 0);
84   return ((head!=tail)||(headoffset!=tailoffset));
85 }
86
87 int WorkList::getid() {
88   return tail->data[tailoffset];
89 }
90
91 int WorkList::gettype() {
92   return tail->data[tailoffset+1];
93 }
94
95 int WorkList::getlvalue() {
96   return tail->data[tailoffset+2];
97 }
98
99 int WorkList::getrvalue() {
100   return tail->data[tailoffset+3];
101 }
102
103 WorkList::~WorkList() {
104   struct ListNode *ptr=tail;
105   while(ptr) {
106     struct ListNode *oldptr=ptr;
107     ptr=ptr->next;
108     free(oldptr);
109   }
110 }
111
112 void WorkList::pop() {
113   int newoffset=tailoffset+4;
114   struct ListNode *ptr=tail;
115   if (newoffset>=WLISTSIZE) {
116     newoffset-=WLISTSIZE;
117     struct ListNode *oldptr=ptr;
118     ptr=ptr->next;
119     free(oldptr);
120   }
121   tail=ptr;
122   tailoffset=newoffset;
123 }
124
125 void WorkList::add(int id,int type, int lvalue, int rvalue) {
126   if (headoffset==WLISTSIZE) {
127     head->next=(struct ListNode *)malloc(sizeof(struct ListNode));
128     headoffset=0;
129     head=head->next;
130     head->next=0;
131   }
132   head->data[headoffset++]=id;
133   head->data[headoffset++]=type;
134   head->data[headoffset++]=lvalue;
135   head->data[headoffset++]=rvalue;
136 }
137
138 /* SIMPLE HASH ********************************************************/
139 SimpleIterator* SimpleHash::iterator() {
140   return new SimpleIterator(listhead,listtail,tailindex/*,this*/);
141 }
142
143 void SimpleHash::iterator(SimpleIterator & it) {
144   //  it.table=this;
145   it.cur=listhead;
146   it.index=0;
147   it.tailindex=tailindex;
148   it.tail=listtail;
149 }
150
151 SimpleHash::SimpleHash(int size) {
152     if (size <= 0) {
153         throw SimpleHashException();
154     }
155     this->size = size;
156     this->bucket = (struct SimpleNode **) calloc(sizeof(struct SimpleNode *)*size,1);
157     /* Set allocation blocks*/
158     this->listhead=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
159     this->listtail=this->listhead;
160     this->tailindex=0;
161     /*Set data counts*/
162     this->numparents = 0;
163     this->numchildren = 0;
164     this->numelements = 0;
165 }
166
167 SimpleHash::~SimpleHash() {
168   free(bucket);
169   struct ArraySimple *ptr=listhead;
170   while(ptr) {
171       struct ArraySimple *next=ptr->nextarray;
172       free(ptr);
173       ptr=next;
174   }
175 }
176
177 void SimpleHash::addParent(SimpleHash* parent) {
178     parents[numparents++] = parent;
179     parent->addChild(this);
180 }
181
182 void SimpleHash::addChild(SimpleHash *child) {
183   children[numchildren++]=child;
184 }
185
186 int SimpleHash::remove(int key, int data) {
187     unsigned int hashkey = (unsigned int)key % size;
188     
189     struct SimpleNode **ptr = &bucket[hashkey];
190
191     for (int i = 0; i < numchildren; i++) {
192       children[i]->remove(key, data);
193     }
194
195     while (*ptr) {
196         if ((*ptr)->key == key && (*ptr)->data == data) {
197           struct SimpleNode *toremove=*ptr;
198           *ptr=(*ptr)->next;
199
200           toremove->inuse=0; /* Marked as unused */
201
202           numelements--;
203           return 1;
204         }
205         ptr = &((*ptr)->next);
206     }
207
208     return 0;
209 }
210
211
212
213 int SimpleHash::add(int key, int data) {
214     unsigned int hashkey = (unsigned int)key % size;
215     
216     struct SimpleNode **ptr = &bucket[hashkey];
217
218     /* check that this key/object pair isn't already here */
219     // TBD can be optimized for set v. relation */
220     while (*ptr) {
221         if ((*ptr)->key == key && (*ptr)->data == data) {
222             return 0;
223         }
224         ptr = &((*ptr)->next);
225     }
226     if (tailindex==ARRAYSIZE) {
227       listtail->nextarray=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
228       tailindex=0;
229       listtail=listtail->nextarray;
230     }
231     
232     *ptr = &listtail->nodes[tailindex++];
233     (*ptr)->key=key;
234     (*ptr)->data=data;
235     (*ptr)->inuse=1;
236
237     numelements++;
238     
239     for (int i = 0; i < numparents; i++) {
240         parents[i]->add(key, data);
241     }
242
243     return 1;
244 }
245
246 bool SimpleHash::contains(int key) {
247     unsigned int hashkey = (unsigned int)key % size;
248     
249     struct SimpleNode *ptr = bucket[hashkey];
250     while (ptr) {
251         if (ptr->key == key) {
252             // we already have this object 
253             // stored in the hash so just return
254             return true;
255         }
256         ptr = ptr->next;
257     }
258     return false;
259 }
260
261 bool SimpleHash::contains(int key, int data) {
262     unsigned int hashkey = (unsigned int)key % size;
263     
264     struct SimpleNode *ptr = bucket[hashkey];
265     while (ptr) {
266         if (ptr->key == key && ptr->data == data) {
267             // we already have this object 
268             // stored in the hash so just return
269             return true;
270         }
271         ptr = ptr->next;
272     }
273     return false;
274 }
275
276 int SimpleHash::count(int key) {
277     unsigned int hashkey = (unsigned int)key % size;
278     int count = 0;
279
280     struct SimpleNode *ptr = bucket[hashkey];
281     while (ptr) {
282         if (ptr->key == key) {
283             count++;
284         }
285         ptr = ptr->next;
286     }
287     return count;
288 }
289
290 int SimpleHash::get(int key, int&data) {
291     unsigned int hashkey = (unsigned int)key % size;
292     
293     struct SimpleNode *ptr = bucket[hashkey];
294     while (ptr) {
295         if (ptr->key == key) {
296             data = ptr->data;
297             return 1; // success
298         }
299         ptr = ptr->next;
300     }
301         
302     return 0; // failure
303 }
304
305 int SimpleHash::countdata(int data) {
306     int count = 0;
307     struct ArraySimple *ptr = listhead;
308     while(ptr) {
309       if (ptr->nextarray) {
310         for(int i=0;i<ARRAYSIZE;i++)
311           if (ptr->nodes[i].data == data
312               &&ptr->nodes[i].inuse) {
313             count++;
314           }
315       } else {
316         for(int i=0;i<tailindex;i++)
317           if (ptr->nodes[i].data == data
318               &&ptr->nodes[i].inuse) {
319             count++;
320           }
321       }
322       ptr = ptr->nextarray;
323     }
324     return count;
325 }
326
327 SimpleHashException::SimpleHashException() {}
328 // ************************************************************
329
330
331 RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data){
332     this->setrelation = setrelation;
333     this->lvalue=lvalue;
334     this->rvalue=rvalue;
335     this->data = data;
336     this->next = 0;
337     this->lnext=0;
338     this->rule=rule;
339 }
340
341 // ************************************************************
342
343 RepairHash::RepairHash(int size) {
344     if (size <= 0) {
345         throw SimpleHashException();
346     }
347     this->size = size;
348     this->bucket = new RepairHashNode* [size];
349     for (int i=0;i<size;i++)
350       bucket[i]=0;
351     this->nodelist=0;
352     this->numelements = 0;
353 }
354
355 RepairHash::RepairHash() {
356   RepairHash(100);
357 }
358
359 RepairHash::~RepairHash() {
360   delete [] this->bucket;
361   RepairHashNode *ptr=nodelist;
362   while(ptr) {
363       RepairHashNode *next=ptr->lnext;
364       delete ptr;
365       ptr=next;
366   }
367 }
368
369 #define SETFLAG (1<<31)
370
371 int RepairHash::addset(int setv, int rule, int value, int data) {
372   return addrelation(setv||SETFLAG, rule, value,0,data);
373 }
374
375 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data) {
376     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
377     
378     RepairHashNode **ptr = &bucket[hashkey];
379
380     /* check that this key/object pair isn't already here */
381     // TBD can be optimized for set v. relation */
382     while (*ptr) {
383         if ((*ptr)->setrelation == relation && 
384             (*ptr)->rule==rule &&
385             (*ptr)->lvalue==lvalue &&
386             (*ptr)->rvalue==rvalue &&
387             (*ptr)->data == data) {
388             return 0;
389         }
390         ptr = &((*ptr)->next);
391     }
392     
393     *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data);
394     (*ptr)->lnext=nodelist;
395     nodelist=*ptr;
396     numelements++;
397     return 1;
398 }
399
400 bool RepairHash::containsset(int setv, int rule, int value) {
401   return containsrelation(setv||SETFLAG, rule, value,0);
402 }
403
404 bool RepairHash::containsrelation(int relation, int rule, int lvalue, int rvalue) {
405     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
406     
407     RepairHashNode **ptr = &bucket[hashkey];
408
409     /* check that this key/object pair isn't already here */
410     // TBD can be optimized for set v. relation */
411     while (*ptr) {
412         if ((*ptr)->setrelation == relation && 
413             (*ptr)->rule==rule &&
414             (*ptr)->lvalue==lvalue &&
415             (*ptr)->rvalue==rvalue) {
416             return true;
417         }
418         ptr = &((*ptr)->next);
419     }
420     return false;
421 }
422
423 int RepairHash::getset(int setv, int rule, int value) {
424   return getrelation(setv||SETFLAG, rule, value,0);
425 }
426
427 int RepairHash::getrelation(int relation, int rule, int lvalue,int rvalue) {
428     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
429     
430     RepairHashNode **ptr = &bucket[hashkey];
431
432     /* check that this key/object pair isn't already here */
433     // TBD can be optimized for set v. relation */
434     while (*ptr) {
435         if ((*ptr)->setrelation == relation && 
436             (*ptr)->rule==rule &&
437             (*ptr)->lvalue==lvalue &&
438             (*ptr)->rvalue==rvalue) {
439           return (*ptr)->data;
440         }
441         ptr = &((*ptr)->next);
442     }
443     return 0;
444 }