|
|
1.1 ! root 1: #include "check.h" ! 2: ! 3: // This may look like C code, but it is really -*- C++ -*- ! 4: /* ! 5: Copyright (C) 1988 Free Software Foundation ! 6: written by Doug Lea ([email protected]) ! 7: ! 8: This file is part of GNU CC. ! 9: ! 10: GNU CC is distributed in the hope that it will be useful, ! 11: but WITHOUT ANY WARRANTY. No author or distributor ! 12: accepts responsibility to anyone for the consequences of using it ! 13: or for whether it serves any particular purpose or works at all, ! 14: unless he says so in writing. Refer to the GNU CC General Public ! 15: License for full details. ! 16: ! 17: Everyone is granted permission to copy, modify and redistribute ! 18: GNU CC, but only under the conditions described in the ! 19: GNU CC General Public License. A copy of this license is ! 20: supposed to have been given to you along with GNU CC so you ! 21: can know your rights and responsibilities. It should be in a ! 22: file named COPYING. Among other things, the copyright notice ! 23: and this notice must be preserved on all copies. ! 24: */ ! 25: ! 26: /* GNU hash tables converted to demonstrate PT */ ! 27: ! 28: template <class T, class U> class VHashAssocNode ! 29: { ! 30: public: ! 31: T key; ! 32: U cont; ! 33: char status; ! 34: }; ! 35: ! 36: ! 37: template <class T, class U> class VHashAssocTrav ; ! 38: ! 39: ! 40: template <class T, class U> class VHashAssoc ! 41: { ! 42: friend class VHashAssocTrav<T,U> ; ! 43: ! 44: VHashAssocNode<T,U> * tab; ! 45: int size; ! 46: int cnt; ! 47: ! 48: public: ! 49: static unsigned int (*key_hash_function)(T &); ! 50: int (* key_key_equality_function )(T&, T&); ! 51: ! 52: unsigned int key_hash(T& a); ! 53: int key_key_eq(T&a, T& b); ! 54: ! 55: VHashAssoc(int sz); ! 56: VHashAssoc(VHashAssoc& a); ! 57: ~VHashAssoc(); ! 58: ! 59: VHashAssoc& operator = (VHashAssoc& a); ! 60: ! 61: int count(); ! 62: int empty(); ! 63: int full(); ! 64: int capacity(); ! 65: ! 66: void clear(); ! 67: void resize(int newsize); ! 68: ! 69: U& operator [] (T& k); ! 70: int contains(T& key); ! 71: int del(T& key); ! 72: ! 73: ! 74: void apply(void f(U& v)); ! 75: void error(const char* msg); ! 76: }; ! 77: ! 78: template <class T, class U> class VHashAssocTrav ! 79: { ! 80: VHashAssoc<T,U>* h; ! 81: int pos; ! 82: ! 83: ! 84: public: ! 85: VHashAssocTrav(VHashAssoc<T,U>& l); ! 86: ~VHashAssocTrav(); ! 87: int null(); ! 88: int valid(); ! 89: operator void* (); ! 90: int operator ! (); ! 91: void advance(); ! 92: void reset(); ! 93: void reset(VHashAssoc<T,U>& l); ! 94: T& key(); ! 95: U& get(); ! 96: }; ! 97: ! 98: template <class T, class U> unsigned int VHashAssoc<T,U>::key_hash(T& a) ! 99: { ! 100: return (*VHashAssoc<T,U>::key_hash_function)(a); ! 101: } ! 102: ! 103: template <class T, class U> int VHashAssoc<T,U>::key_key_eq(T&a, T& b) ! 104: { ! 105: return (*VHashAssoc<T,U>::key_key_equality_function)(a, b); ! 106: } ! 107: ! 108: ! 109: template <class T, class U> VHashAssoc<T,U>::~VHashAssoc() ! 110: { ! 111: delete [size] tab; ! 112: } ! 113: ! 114: template <class T, class U> VHashAssoc<T,U>::count() ! 115: { ! 116: return cnt; ! 117: } ! 118: ! 119: template <class T, class U> VHashAssoc<T,U>::empty() ! 120: { ! 121: return cnt == 0; ! 122: } ! 123: ! 124: template <class T, class U> VHashAssoc<T,U>::full() ! 125: { ! 126: return cnt == size; ! 127: } ! 128: ! 129: template <class T, class U> VHashAssoc<T,U>::capacity() ! 130: { ! 131: return size; ! 132: } ! 133: ! 134: template <class T, class U> VHashAssocTrav<T,U>::VHashAssocTrav(VHashAssoc<T,U>& a) ! 135: { ! 136: h = &a; ! 137: reset(); ! 138: } ! 139: ! 140: template <class T, class U> void VHashAssocTrav<T,U>::reset(VHashAssoc<T,U>& a) ! 141: { ! 142: h = &a; ! 143: reset(); ! 144: } ! 145: ! 146: ! 147: template <class T, class U> VHashAssocTrav<T,U>::~VHashAssocTrav() {} ! 148: ! 149: template <class T, class U> VHashAssocTrav<T,U>::null() ! 150: { ! 151: return pos < 0; ! 152: } ! 153: ! 154: template <class T, class U> VHashAssocTrav<T,U>::valid() ! 155: { ! 156: return pos >= 0; ! 157: } ! 158: ! 159: template <class T, class U> VHashAssocTrav<T,U>::operator void* () ! 160: { ! 161: return (pos < 0)? 0 : this; ! 162: } ! 163: ! 164: template <class T, class U> VHashAssocTrav<T,U>::operator ! () ! 165: { ! 166: return (pos < 0); ! 167: } ! 168: ! 169: ! 170: template <class T, class U> T & VHashAssocTrav<T,U>::key() ! 171: { ! 172: if (pos < 0) ! 173: h->error("operation on null traverser"); ! 174: return h->tab[pos].key; ! 175: } ! 176: ! 177: template <class T, class U> U & VHashAssocTrav<T,U>::get() ! 178: { ! 179: if (pos < 0) ! 180: h->error("operation on null traverser"); ! 181: return h->tab[pos].cont; ! 182: } ! 183: ! 184: enum {EMPTYCELL, VALIDCELL, DELETEDCELL } ; ! 185: ! 186: ! 187: // error handling ! 188: ! 189: ! 190: ! 191: template <class T, class U>void VHashAssoc<T,U>::error(const char* msg) ! 192: { ! 193: // (*VHashAssoc_error_handler)(msg); ! 194: } ! 195: ! 196: template <class T, class U>VHashAssoc<T,U>::VHashAssoc(int sz) ! 197: { ! 198: tab = new VHashAssocNode<T,U>[size = sz]; ! 199: for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL; ! 200: cnt = 0; ! 201: } ! 202: ! 203: template <class T, class U>VHashAssoc<T,U>::VHashAssoc(VHashAssoc<T,U>& a) ! 204: { ! 205: tab = new VHashAssocNode<T,U>[size = a.size]; ! 206: for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL; ! 207: cnt = 0; ! 208: for (VHashAssocTrav<T,U> p(a); p; p.advance()) ! 209: (*this)[p.key()] = p.get(); ! 210: } ! 211: ! 212: template <class T, class U> VHashAssoc<T,U>& VHashAssoc<T,U>::operator = ! 213: (VHashAssoc<T,U>& a) ! 214: { ! 215: if (a.tab != tab) ! 216: { ! 217: clear(); ! 218: delete [size] tab; ! 219: tab = new VHashAssocNode<T,U>[size = a.size]; ! 220: for (int i = 0; i < size; ++i) tab[i].status = EMPTYCELL; ! 221: cnt = 0; ! 222: for (VHashAssocTrav<T,U> p(a); p; p.advance()) ! 223: (*this)[p.key()] = p.get(); ! 224: } ! 225: return *this; ! 226: } ! 227: ! 228: /* ! 229: * hashing method: double hash based on high bits of hash fct, ! 230: * followed by linear probe. Can't do too much better if Assoc ! 231: * sizes not constrained to be prime. ! 232: */ ! 233: ! 234: ! 235: static inline doublehashinc(unsigned int h, int s) ! 236: { ! 237: return ((h / s) % s) >> 1; ! 238: } ! 239: ! 240: ! 241: template <class T, class U>U& VHashAssoc<T,U>::operator [](T & key) ! 242: { ! 243: int bestspot = -1; ! 244: unsigned int hashval = key_hash(key); ! 245: int h = hashval % size; ! 246: for (int i = 0; i <= size; ++i) ! 247: { ! 248: if (tab[h].status == EMPTYCELL) ! 249: { ! 250: if (bestspot < 0) bestspot = h; ! 251: tab[bestspot].key = key; ! 252: tab[bestspot].status = VALIDCELL; ! 253: ++cnt; ! 254: return tab[bestspot].cont; ! 255: } ! 256: else if (tab[h].status == DELETEDCELL) ! 257: { ! 258: if (bestspot < 0) bestspot = h; ! 259: } ! 260: else if (key_key_eq(tab[h].key, key)) ! 261: return tab[h].cont; ! 262: if (i == 0) ! 263: h = (h + doublehashinc(hashval, size)) % size; ! 264: else if (++h >= size) ! 265: h -= size; ! 266: } ! 267: error("cannot add to full Assoc table"); ! 268: return tab[0].cont ; // suppress warning message ! 269: } ! 270: ! 271: ! 272: template <class T, class U>int VHashAssoc<T,U>::contains(T & key) ! 273: { ! 274: unsigned int hashval = key_hash(key); ! 275: int h = hashval % size; ! 276: for (int i = 0; i <= size; ++i) ! 277: { ! 278: if (tab[h].status == EMPTYCELL) ! 279: return 0; ! 280: else if (tab[h].status == VALIDCELL && key_key_eq(tab[h].key, key)) ! 281: return 1; ! 282: if (i == 0) ! 283: h = (h + doublehashinc(hashval, size)) % size; ! 284: else if (++h >= size) ! 285: h -= size; ! 286: } ! 287: return 0; ! 288: } ! 289: ! 290: template <class T, class U>int VHashAssoc<T,U>::del(T & key) ! 291: { ! 292: unsigned int hashval = key_hash(key); ! 293: int h = hashval % size; ! 294: for (int i = 0; i <= size; ++i) ! 295: { ! 296: if (tab[h].status == EMPTYCELL) ! 297: return 0; ! 298: else if (tab[h].status == VALIDCELL && key_key_eq(tab[h].key, key)) ! 299: { ! 300: tab[h].status = DELETEDCELL; ! 301: --cnt; ! 302: return 1; ! 303: } ! 304: if (i == 0) ! 305: h = (h + doublehashinc(hashval, size)) % size; ! 306: else if (++h >= size) ! 307: h -= size; ! 308: } ! 309: return 0; ! 310: } ! 311: ! 312: /* ! 313: template <class T, class U>void VHashAssoc<T,U>::apply(UProcedure f) ! 314: { ! 315: for (int i = 0; i < size; ++i) ! 316: if (tab[i].status == VALIDCELL) ! 317: (*f)(tab[i].cont); ! 318: } ! 319: */ ! 320: ! 321: template <class T, class U>void VHashAssoc<T,U>::clear() ! 322: { ! 323: for (int i = 0; i < size; ++i) ! 324: tab[i].status = EMPTYCELL; ! 325: cnt = 0; ! 326: } ! 327: ! 328: template <class T, class U>void VHashAssoc<T,U>::resize(int newsize) ! 329: { ! 330: if (newsize < cnt) ! 331: error("requested resize too small"); ! 332: VHashAssocNode<T,U>* oldtab = tab; ! 333: int oldsize = size; ! 334: tab = new VHashAssocNode<T,U>[size = newsize]; ! 335: for (int i = 0; i < size; ++i) ! 336: tab[i].status = EMPTYCELL; ! 337: cnt = 0; ! 338: for (i = 0; i < oldsize; ++i) ! 339: if (oldtab[i].status == VALIDCELL) ! 340: (*this)[oldtab[i].key] = oldtab[i].cont; ! 341: delete [oldsize] oldtab; ! 342: } ! 343: ! 344: template <class T, class U>void VHashAssocTrav<T,U>::reset() ! 345: { ! 346: for (pos = 0; pos < h->size; ++pos) ! 347: if (h->tab[pos].status == VALIDCELL) ! 348: return; ! 349: pos = -1; ! 350: } ! 351: ! 352: template <class T, class U>void VHashAssocTrav<T,U>::advance() ! 353: { ! 354: if (pos < 0) ! 355: return; ! 356: for (pos++; pos < h->size; ++pos) ! 357: if (h->tab[pos].status == VALIDCELL) ! 358: return; ! 359: pos = -1; ! 360: } ! 361: ! 362: ! 363: const int size = 100 ; ! 364: ! 365: ! 366: unsigned int f(int & i) { return i ; } ! 367: ! 368: unsigned int f1(char & i) { return (int)i ; } ! 369: ! 370: int g(int& k1, int& k2){ ! 371: return (k1 == k2) ; ! 372: } ! 373: ! 374: int g1(char & k1, char & k2){ ! 375: return (k1 == k2) ; ! 376: } ! 377: ! 378: ! 379: ! 380: ! 381: VHashAssoc<int, int> foo(2*size) ; ! 382: ! 383: ! 384: main () { ! 385: ! 386: ! 387: start_test(__FILE__) ; ! 388: ! 389: foo.key_hash_function = f ; ! 390: foo.key_key_equality_function= g ; ! 391: // populate the hash ! 392: for (int i = 0 ; ! foo.full() ; i++) ! 393: foo[i] = i ; ! 394: ! 395: for (i = 0 ; i < size ; i++) { ! 396: check(foo.contains(i)) ; ! 397: check(foo[i] == i) ; ! 398: } ! 399: ! 400: foo.resize(size * 4) ; ! 401: ! 402: // repeat the tests, resizing should not have impacted it any ! 403: for (i = 0 ; i < size ; i++) { ! 404: check(foo.contains(i)) ; ! 405: check(foo[i] == i) ; ! 406: check (foo.del(i)) ; ! 407: check(!foo.contains(i)) ; ! 408: } ! 409: { ! 410: // try another one ! 411: VHashAssoc<char, char *> foo(2*size) ; ! 412: foo.key_hash_function = f1 ; ! 413: foo.key_key_equality_function= g1 ; ! 414: // populate the hash ! 415: for (char i = 0 ; ! foo.full() ; i++) { ! 416: char *p = new char ; ! 417: *p = i ; ! 418: foo[i] = p ; ! 419: } ! 420: ! 421: for (i = 0 ; i < size ; i++) { ! 422: check(foo.contains(i)) ; ! 423: check(*(foo[i]) == i) ; ! 424: } ! 425: ! 426: foo.resize(size * 4) ; ! 427: ! 428: // repeat the tests, resizing should not have impacted it any ! 429: for (i = 0 ; i < size ; i++) { ! 430: check(foo.contains(i)) ; ! 431: check(*(foo[i]) == i) ; ! 432: check (foo.del(i)) ; ! 433: check(!foo.contains(i)) ; ! 434: } ! 435: } ! 436: ! 437: end_test() ; ! 438: ! 439: } ! 440:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.