77beed787a1e7cafc4aaaa02f4dd9eceabef518e
[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 void WorkList::reset() {
83   head=tail;
84   headoffset=0;
85   tailoffset=0;
86 }
87
88 int WorkList::hasMoreElements() {
89   //  return (ptr != 0);
90   return ((head!=tail)||(headoffset!=tailoffset));
91 }
92
93 int WorkList::getid() {
94   return tail->data[tailoffset];
95 }
96
97 int WorkList::gettype() {
98   return tail->data[tailoffset+1];
99 }
100
101 int WorkList::getlvalue() {
102   return tail->data[tailoffset+2];
103 }
104
105 int WorkList::getrvalue() {
106   return tail->data[tailoffset+3];
107 }
108
109 WorkList::~WorkList() {
110   struct ListNode *ptr=tail;
111   while(ptr) {
112     struct ListNode *oldptr=ptr;
113     ptr=ptr->next;
114     free(oldptr);
115   }
116 }
117
118 void WorkList::pop() {
119   int newoffset=tailoffset+4;
120   struct ListNode *ptr=tail;
121   if (newoffset>=WLISTSIZE) {
122     newoffset-=WLISTSIZE;
123     struct ListNode *oldptr=ptr;
124     ptr=ptr->next;
125     free(oldptr);
126   }
127   tail=ptr;
128   tailoffset=newoffset;
129 }
130
131 void WorkList::add(int id,int type, int lvalue, int rvalue) {
132   if (headoffset==WLISTSIZE) {
133     if (head->next==0) {
134       head->next=(struct ListNode *)malloc(sizeof(struct ListNode));
135       head->next=0;
136     }
137     headoffset=0;
138     head=head->next;
139   }
140   head->data[headoffset++]=id;
141   head->data[headoffset++]=type;
142   head->data[headoffset++]=lvalue;
143   head->data[headoffset++]=rvalue;
144 }
145
146 /* SIMPLE HASH ********************************************************/
147 SimpleIterator* SimpleHash::iterator() {
148   return new SimpleIterator(listhead,listtail,tailindex/*,this*/);
149 }
150
151 void SimpleHash::iterator(SimpleIterator & it) {
152   //  it.table=this;
153   it.cur=listhead;
154   it.index=0;
155   it.tailindex=tailindex;
156   it.tail=listtail;
157 }
158
159 SimpleHash::SimpleHash(int size) {
160     if (size <= 0) {
161         throw SimpleHashException();
162     }
163     this->size = size;
164     this->bucket = (struct SimpleNode **) calloc(sizeof(struct SimpleNode *)*size,1);
165     /* Set allocation blocks*/
166     this->listhead=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
167     this->listtail=this->listhead;
168     this->tailindex=0;
169     /*Set data counts*/
170     this->numparents = 0;
171     this->numchildren = 0;
172     this->numelements = 0;
173 }
174
175 SimpleHash::~SimpleHash() {
176   free(bucket);
177   struct ArraySimple *ptr=listhead;
178   while(ptr) {
179       struct ArraySimple *next=ptr->nextarray;
180       free(ptr);
181       ptr=next;
182   }
183 }
184
185 int SimpleHash::firstkey() {
186   struct ArraySimple *ptr=listhead;
187   int index=0;
188   while((index==ARRAYSIZE)||!ptr->nodes[index].inuse) {
189     if (index==ARRAYSIZE) {
190       index=0;
191       ptr=ptr->nextarray;
192     } else
193       index++;
194   }
195   return ptr->nodes[index].key;
196 }
197
198 void SimpleHash::addParent(SimpleHash* parent) {
199     parents[numparents++] = parent;
200     parent->addChild(this);
201 }
202
203 void SimpleHash::addChild(SimpleHash *child) {
204   children[numchildren++]=child;
205 }
206
207 int SimpleHash::remove(int key, int data) {
208     unsigned int hashkey = (unsigned int)key % size;
209     
210     struct SimpleNode **ptr = &bucket[hashkey];
211
212     for (int i = 0; i < numchildren; i++) {
213       children[i]->remove(key, data);
214     }
215
216     while (*ptr) {
217         if ((*ptr)->key == key && (*ptr)->data == data) {
218           struct SimpleNode *toremove=*ptr;
219           *ptr=(*ptr)->next;
220
221           toremove->inuse=0; /* Marked as unused */
222
223           numelements--;
224           return 1;
225         }
226         ptr = &((*ptr)->next);
227     }
228
229     return 0;
230 }
231
232
233
234 int SimpleHash::add(int key, int data) {
235   /* Rehash code */
236   if (numelements>=size) {
237     int newsize=2*size+1;
238     struct SimpleNode ** newbucket = (struct SimpleNode **) calloc(sizeof(struct SimpleNode *)*newsize,1);
239     for(int i=size-1;i>=0;i--) {
240       for(struct SimpleNode *ptr=bucket[i];ptr!=NULL;) {
241         struct SimpleNode * nextptr=ptr->next;
242         unsigned int newhashkey=(unsigned int)ptr->key % newsize;
243         ptr->next=newbucket[newhashkey];
244         newbucket[newhashkey]=ptr;
245         ptr=nextptr;
246       }
247     }
248     size=newsize;
249     free(bucket);
250     bucket=newbucket;
251   }
252
253   unsigned int hashkey = (unsigned int)key % size;
254   struct SimpleNode **ptr = &bucket[hashkey];
255   
256   /* check that this key/object pair isn't already here */
257   /* TBD can be optimized for set v. relation */
258
259   while (*ptr) {
260     if ((*ptr)->key == key && (*ptr)->data == data) {
261       return 0;
262     }
263     ptr = &((*ptr)->next);
264   }
265   if (tailindex==ARRAYSIZE) {
266     listtail->nextarray=(struct ArraySimple *) calloc(sizeof(struct ArraySimple),1);
267     tailindex=0;
268     listtail=listtail->nextarray;
269   }
270   
271   *ptr = &listtail->nodes[tailindex++];
272   (*ptr)->key=key;
273   (*ptr)->data=data;
274   (*ptr)->inuse=1;
275   
276   numelements++;
277   
278   for (int i = 0; i < numparents; i++) {
279     parents[i]->add(key, data);
280   }
281   return 1;
282 }
283
284 bool SimpleHash::contains(int key) {
285     unsigned int hashkey = (unsigned int)key % size;
286     
287     struct SimpleNode *ptr = bucket[hashkey];
288     while (ptr) {
289         if (ptr->key == key) {
290             // we already have this object 
291             // stored in the hash so just return
292             return true;
293         }
294         ptr = ptr->next;
295     }
296     return false;
297 }
298
299 bool SimpleHash::contains(int key, int data) {
300     unsigned int hashkey = (unsigned int)key % size;
301     
302     struct SimpleNode *ptr = bucket[hashkey];
303     while (ptr) {
304         if (ptr->key == key && ptr->data == data) {
305             // we already have this object 
306             // stored in the hash so just return
307             return true;
308         }
309         ptr = ptr->next;
310     }
311     return false;
312 }
313
314 int SimpleHash::count(int key) {
315     unsigned int hashkey = (unsigned int)key % size;
316     int count = 0;
317
318     struct SimpleNode *ptr = bucket[hashkey];
319     while (ptr) {
320         if (ptr->key == key) {
321             count++;
322         }
323         ptr = ptr->next;
324     }
325     return count;
326 }
327
328 int SimpleHash::get(int key, int&data) {
329     unsigned int hashkey = (unsigned int)key % size;
330     
331     struct SimpleNode *ptr = bucket[hashkey];
332     while (ptr) {
333         if (ptr->key == key) {
334             data = ptr->data;
335             return 1; // success
336         }
337         ptr = ptr->next;
338     }
339         
340     return 0; // failure
341 }
342
343 int SimpleHash::countdata(int data) {
344     int count = 0;
345     struct ArraySimple *ptr = listhead;
346     while(ptr) {
347       if (ptr->nextarray) {
348         for(int i=0;i<ARRAYSIZE;i++)
349           if (ptr->nodes[i].data == data
350               &&ptr->nodes[i].inuse) {
351             count++;
352           }
353       } else {
354         for(int i=0;i<tailindex;i++)
355           if (ptr->nodes[i].data == data
356               &&ptr->nodes[i].inuse) {
357             count++;
358           }
359       }
360       ptr = ptr->nextarray;
361     }
362     return count;
363 }
364
365 SimpleHashException::SimpleHashException() {}
366 // ************************************************************
367
368
369 RepairHashNode::RepairHashNode(int setrelation, int rule, int lvalue, int rvalue, int data, int data2, int ismodify){
370     this->setrelation = setrelation;
371     this->lvalue=lvalue;
372     this->rvalue=rvalue;
373     this->data = data;
374     this->data2 = data2;
375     this->next = 0;
376     this->lnext=0;
377     this->rule=rule;
378     this->ismodify=ismodify;
379 }
380
381 // ************************************************************
382
383 RepairHash::RepairHash(int size) {
384     if (size <= 0) {
385         throw SimpleHashException();
386     }
387     this->size = size;
388     this->bucket = new RepairHashNode* [size];
389     for (int i=0;i<size;i++)
390       bucket[i]=0;
391     this->nodelist=0;
392     this->numelements = 0;
393 }
394
395 #define REPAIRSIZE 100
396 RepairHash::RepairHash() {
397     this->size = REPAIRSIZE;
398     this->bucket = new RepairHashNode* [REPAIRSIZE];
399     for (int i=0;i<REPAIRSIZE;i++)
400       bucket[i]=0;
401     this->nodelist=0;
402     this->numelements = 0;
403 }
404
405 RepairHash::~RepairHash() {
406   delete [] this->bucket;
407   RepairHashNode *ptr=nodelist;
408   while(ptr) {
409       RepairHashNode *next=ptr->lnext;
410       delete ptr;
411       ptr=next;
412   }
413 }
414
415 #define SETFLAG (1<<31)
416
417 int RepairHash::addset(int setv, int rule, int value, int data) {
418   return addrelation(setv||SETFLAG, rule, value,0,data);
419 }
420
421 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data) {
422     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
423     
424     RepairHashNode **ptr = &bucket[hashkey];
425
426     /* check that this key/object pair isn't already here */
427     // TBD can be optimized for set v. relation */
428     while (*ptr) {
429         if ((*ptr)->setrelation == relation && 
430             (*ptr)->rule==rule &&
431             (*ptr)->lvalue==lvalue &&
432             (*ptr)->rvalue==rvalue &&
433             (*ptr)->data == data&&
434             (*ptr)->data2 == 0) {
435             return 0;
436         }
437         ptr = &((*ptr)->next);
438     }
439     
440     *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,0,0);
441     (*ptr)->lnext=nodelist;
442     nodelist=*ptr;
443     numelements++;
444     return 1;
445 }
446
447 int RepairHash::addrelation(int relation, int rule, int lvalue, int rvalue, int data, int data2) {
448     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
449     
450     RepairHashNode **ptr = &bucket[hashkey];
451
452     /* check that this key/object pair isn't already here */
453     // TBD can be optimized for set v. relation */
454     while (*ptr) {
455         if ((*ptr)->setrelation == relation && 
456             (*ptr)->rule==rule &&
457             (*ptr)->lvalue==lvalue &&
458             (*ptr)->rvalue==rvalue &&
459             (*ptr)->data == data &&
460             (*ptr)->data2 == data2) {
461             return 0;
462         }
463         ptr = &((*ptr)->next);
464     }
465     
466     *ptr = new RepairHashNode(relation,rule,lvalue,rvalue, data,data2,1);
467     (*ptr)->lnext=nodelist;
468     nodelist=*ptr;
469     numelements++;
470     return 1;
471 }
472
473 bool RepairHash::containsset(int setv, int rule, int value) {
474   return containsrelation(setv||SETFLAG, rule, value,0);
475 }
476
477 bool RepairHash::containsrelation(int relation, int rule, int lvalue, int rvalue) {
478     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
479     
480     RepairHashNode **ptr = &bucket[hashkey];
481
482     /* check that this key/object pair isn't already here */
483     // TBD can be optimized for set v. relation */
484     while (*ptr) {
485         if ((*ptr)->setrelation == relation && 
486             (*ptr)->rule==rule &&
487             (*ptr)->lvalue==lvalue &&
488             (*ptr)->rvalue==rvalue) {
489             return true;
490         }
491         ptr = &((*ptr)->next);
492     }
493     return false;
494 }
495
496 int RepairHash::getset(int setv, int rule, int value) {
497   return getrelation(setv||SETFLAG, rule, value,0);
498 }
499
500 int RepairHash::ismodify(int relation, int rule, int lvalue,int rvalue) {
501     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
502     
503     RepairHashNode **ptr = &bucket[hashkey];
504
505     /* check that this key/object pair isn't already here */
506     // TBD can be optimized for set v. relation */
507     while (*ptr) {
508         if ((*ptr)->setrelation == relation && 
509             (*ptr)->rule==rule &&
510             (*ptr)->lvalue==lvalue &&
511             (*ptr)->rvalue==rvalue) {
512           return (*ptr)->ismodify;
513         }
514         ptr = &((*ptr)->next);
515     }
516     return 0;
517 }
518
519 int RepairHash::getrelation2(int relation, int rule, int lvalue,int rvalue) {
520     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
521     
522     RepairHashNode **ptr = &bucket[hashkey];
523
524     /* check that this key/object pair isn't already here */
525     // TBD can be optimized for set v. relation */
526     while (*ptr) {
527         if ((*ptr)->setrelation == relation && 
528             (*ptr)->rule==rule &&
529             (*ptr)->lvalue==lvalue &&
530             (*ptr)->rvalue==rvalue) {
531           return (*ptr)->data2;
532         }
533         ptr = &((*ptr)->next);
534     }
535     return 0;
536 }
537
538 int RepairHash::getrelation(int relation, int rule, int lvalue,int rvalue) {
539     unsigned int hashkey = ((unsigned int)(relation ^ rule ^ lvalue ^ rvalue)) % size;
540     
541     RepairHashNode **ptr = &bucket[hashkey];
542
543     /* check that this key/object pair isn't already here */
544     // TBD can be optimized for set v. relation */
545     while (*ptr) {
546         if ((*ptr)->setrelation == relation && 
547             (*ptr)->rule==rule &&
548             (*ptr)->lvalue==lvalue &&
549             (*ptr)->rvalue==rvalue) {
550           return (*ptr)->data;
551         }
552         ptr = &((*ptr)->next);
553     }
554     return 0;
555 }