Annotation of parser3/src/main/pa_hash.C, revision 1.49

1.25      paf         1: /** @file
1.26      paf         2:        Parser: hash class.
                      3: 
1.49    ! paf         4:        Copyright (c) 2001, 2002 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.49    ! paf         7:        $Id: pa_hash.C,v 1.48 2001/11/12 10:00:32 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: