Annotation of parser3/src/main/pa_hash.C, revision 1.48
1.25 paf 1: /** @file
1.26 paf 2: Parser: hash class.
3:
1.19 paf 4: Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com)
1.47 paf 5: Author: Alexander Petrosyan <paf@design.ru> (http://paf.design.ru)
1.26 paf 6:
1.48 ! paf 7: $Id: pa_hash.C,v 1.47 2001/11/05 11:46:28 paf Exp $
1.1 paf 8: */
9:
10: /*
11: The prime numbers used from zend_hash.c,
12: the part of Zend scripting engine library,
13: Copyrighted (C) 1999-2000 Zend Technologies Ltd.
14: http://www.zend.com/license/0_92.txt
15: For more information about Zend please visit http://www.zend.com/
16: */
1.23 paf 17:
1.11 paf 18: #include "pa_hash.h"
1.2 paf 19:
1.8 paf 20: void *Hash::Pair::operator new(size_t size, Pool& apool) {
1.43 paf 21: return apool.malloc(size, 6);
1.2 paf 22: }
23:
1.1 paf 24: /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */
1.18 paf 25: uint Hash::allocates[]={
1.1 paf 26: 5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963,
27: 16229, 32531, 65407, 130987, 262237, 524521, 1048793,
28: 2097397, 4194103, 8388857, 16777447, 33554201, 67108961,
29: 134217487, 268435697, 536870683, 1073741621, 2147483399};
1.18 paf 30: int Hash::allocates_count=
31: sizeof(allocates)/sizeof(uint);
1.1 paf 32:
33:
1.39 parser 34: void Hash::construct_new() {
1.18 paf 35: allocated=allocates[allocates_index=0];
36: threshold=allocated*THRESHOLD_PERCENT/100;
1.41 parser 37: count=used=0;
1.18 paf 38: refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated));
1.39 parser 39: }
40:
41: void Hash::construct_copy(const Hash& source) {
42: allocates_index=source.allocates_index;
43: allocated=source.allocated;
44: threshold=source.threshold;
45: used=source.used;
1.41 parser 46: count=source.count;
1.39 parser 47: size_t size=sizeof(Pair *)*allocated;
1.43 paf 48: refs=static_cast<Pair **>(malloc(size, 7)); memcpy(refs, source.refs, size);
1.1 paf 49: }
50:
51: void Hash::expand() {
1.18 paf 52: int old_size=allocated;
1.2 paf 53: Pair **old_refs=refs;
1.4 paf 54:
1.2 paf 55: // allocated bigger refs array
1.18 paf 56: allocates_index=allocates_index+1<allocates_count?allocates_index+1:allocates_count-1;
57: allocated=allocates[allocates_index];
1.33 paf 58: threshold=allocated*THRESHOLD_PERCENT/100;
1.18 paf 59: refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated));
1.1 paf 60:
61: // rehash
1.2 paf 62: Pair **old_ref=old_refs;
63: for(int old_index=0; old_index<old_size; old_index++)
64: for(Pair *pair=*old_ref++; pair; ) {
65: Pair *linked_pair=pair->link;
66:
1.18 paf 67: uint new_index=pair->code%allocated;
1.2 paf 68: Pair **new_ref=&refs[new_index];
69: pair->link=*new_ref;
70: *new_ref=pair;
1.1 paf 71:
1.2 paf 72: pair=linked_pair;
73: }
1.1 paf 74: }
75:
1.18 paf 76: uint Hash::generic_code(uint aresult, const char *start, uint allocated) {
1.1 paf 77: uint result=aresult, g;
1.18 paf 78: const char *end=start+allocated;
1.1 paf 79:
80: while (start<end) {
81: result=(result<<4)+*start++;
82: if ((g=(result&0xF0000000))) {
83: result=result^(g>>24);
84: result=result^g;
85: }
86: }
87: return result;
88: }
89:
1.31 paf 90: bool Hash::put(const Key& key, Val *value) {
1.48 ! paf 91: if(!value)
! 92: return remove(key);
! 93:
1.1 paf 94: if(full())
95: expand();
96:
1.2 paf 97: uint code=key.hash_code();
1.18 paf 98: uint index=code%allocated;
1.2 paf 99: Pair **ref=&refs[index];
100: for(Pair *pair=*ref; pair; pair=pair->link)
101: if(pair->code==code && pair->key==key) {
102: // found a pair with the same key
103: pair->value=value;
1.17 paf 104: return true;
1.1 paf 105: }
1.2 paf 106:
1.7 paf 107: // proper pair not found -- create&link_in new pair
1.17 paf 108: if(!*ref) // root cell were used?
109: used++; // not, we'll use it and record the fact
1.15 paf 110: *ref=NEW Pair(code, key, value, *ref);
1.41 parser 111: count++;
1.17 paf 112: return false;
1.1 paf 113: }
114:
1.48 ! paf 115: bool Hash::remove(const Key& key) {
1.44 paf 116: uint code=key.hash_code();
117: uint index=code%allocated;
118: for(Pair **ref=&refs[index]; *ref; ref=&(*ref)->link)
119: if((*ref)->code==code && (*ref)->key==key) {
120: // found a pair with the same key
121: *ref=(*ref)->link;
122: --count;
1.48 ! paf 123: return true;
1.44 paf 124: }
1.48 ! paf 125:
! 126: return false;
1.44 paf 127: }
128:
1.31 paf 129: Hash::Val *Hash::get(const Key& key) const {
1.2 paf 130: uint code=key.hash_code();
1.18 paf 131: uint index=code%allocated;
1.2 paf 132: for(Pair *pair=refs[index]; pair; pair=pair->link)
1.1 paf 133: if(pair->code==code && pair->key==key)
134: return pair->value;
135:
136: return 0;
137: }
1.16 paf 138:
1.31 paf 139: bool Hash::put_replace(const Key& key, Val *value) {
1.16 paf 140: uint code=key.hash_code();
1.18 paf 141: uint index=code%allocated;
1.16 paf 142: for(Pair *pair=refs[index]; pair; pair=pair->link)
143: if(pair->code==code && pair->key==key) {
144: // found a pair with the same key, replacing
145: pair->value=value;
146: return true;
147: }
148:
149: // proper pair not found
150: return false;
151: }
152:
1.31 paf 153: bool Hash::put_dont_replace(const Key& key, Val *value) {
1.48 ! paf 154: if(!value)
! 155: return remove(key);
! 156:
1.17 paf 157: if(full())
158: expand();
159:
160: uint code=key.hash_code();
1.18 paf 161: uint index=code%allocated;
1.17 paf 162: Pair **ref=&refs[index];
163: for(Pair *pair=*ref; pair; pair=pair->link)
164: if(pair->code==code && pair->key==key) {
165: // found a pair with the same key, NOT replacing
166: return true;
167: }
168:
169: // proper pair not found -- create&link_in new pair
170: if(!*ref) // root cell were used?
171: used++; // not, we'll use it and record the fact
1.41 parser 172: *ref=NEW Pair(code, key, value, *ref);
173: count++;
1.17 paf 174: return false;
175: }
176:
1.31 paf 177: void Hash::merge_dont_replace(const Hash& src) {
1.18 paf 178: for(int i=0; i<src.allocated; i++)
1.17 paf 179: for(Pair *pair=src.refs[i]; pair; pair=pair->link)
180: put_dont_replace(pair->key, pair->value);
1.18 paf 181: // MAY:optimize this.allocated==src.allocated case
1.21 paf 182: }
183:
1.32 paf 184: void Hash::for_each(For_each_func func, void *info) const {
1.42 paf 185: Pair **ref=refs;
186: for(int index=0; index<allocated; index++)
187: for(Pair *pair=*ref++; pair; pair=pair->link)
1.44 paf 188: (*func)(pair->key, pair->value, info);
1.42 paf 189: }
190:
191: void Hash::for_each(For_each_func_refed func, void *info) const {
1.21 paf 192: Pair **ref=refs;
193: for(int index=0; index<allocated; index++)
194: for(Pair *pair=*ref++; pair; pair=pair->link)
1.44 paf 195: (*func)(pair->key, pair->value, info);
1.34 paf 196: }
197:
1.38 parser 198: void* Hash::first_that(First_that_func func, void *info) const {
1.34 paf 199: Pair **ref=refs;
200: for(int index=0; index<allocated; index++)
201: for(Pair *pair=*ref++; pair; pair=pair->link)
1.44 paf 202: if(void *result=(*func)(pair->key, pair->value, info))
203: return result;
1.34 paf 204: return 0;
1.23 paf 205: }
206:
1.31 paf 207: void Hash::clear() {
1.23 paf 208: memset(refs, 0, sizeof(*refs)*allocated);
1.41 parser 209: count=used=0;
1.17 paf 210: }
E-mail: