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