--- parser3/src/main/Attic/pa_hash.C 2001/01/29 11:53:42 1.4 +++ parser3/src/main/Attic/pa_hash.C 2003/01/22 15:39:08 1.53.2.1 @@ -1,5 +1,8 @@ -/* - $Id: pa_hash.C,v 1.4 2001/01/29 11:53:42 paf Exp $ +/** @file + Parser: hash class. + + Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ /* @@ -10,43 +13,50 @@ For more information about Zend please visit http://www.zend.com/ */ -#include "pa_pool.h" -#include "pa_threads.h" +static const char* IDENT_HASH_C="$Date: 2003/01/22 15:39:08 $"; + +#include "pa_hash.h" -void *Hash::Pair::operator new(size_t size, Pool *apool) { - return apool->malloc(size); +void *Hash::Pair::operator new(size_t size) { + return pa_malloc(size); } /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */ -uint Hash::sizes[]={ +uint Hash::allocates[]={ 5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987, 262237, 524521, 1048793, 2097397, 4194103, 8388857, 16777447, 33554201, 67108961, 134217487, 268435697, 536870683, 1073741621, 2147483399}; -int Hash::sizes_count= - sizeof(sizes)/sizeof(uint); +int Hash::allocates_count= + sizeof(allocates)/sizeof(uint); -void *Hash::operator new(size_t size, Pool *apool) { - return apool->malloc(size); -} -Hash::Hash(Pool *apool) { - pool=apool; - - size=sizes[size_index=0]; - threshold=size*THRESHOLD_PERCENT/100; - used=0; - refs=static_cast(pool->calloc(sizeof(Pair *)*size)); +void Hash::construct_new() { + allocated=allocates[allocates_index=0]; + threshold=allocated*THRESHOLD_PERCENT/100; + count=used=0; + refs=static_cast(pa_calloc(sizeof(Pair *)*allocated)); +} + +void Hash::construct_copy(const Hash& source) { + allocates_index=source.allocates_index; + allocated=source.allocated; + threshold=source.threshold; + used=source.used; + count=source.count; + size_t size=sizeof(Pair *)*allocated; + refs=static_cast(pa_malloc(size)); memcpy(refs, source.refs, size); } void Hash::expand() { - int old_size=size; + int old_size=allocated; Pair **old_refs=refs; // allocated bigger refs array - size_index=size_index+1(pool->calloc(sizeof(Pair *)*size)); + allocates_index=allocates_index+1(pa_calloc(sizeof(Pair *)*allocated)); // rehash Pair **old_ref=old_refs; @@ -54,7 +64,7 @@ void Hash::expand() { for(Pair *pair=*old_ref++; pair; ) { Pair *linked_pair=pair->link; - uint new_index=pair->code%size; + uint new_index=pair->code%allocated; Pair **new_ref=&refs[new_index]; pair->link=*new_ref; *new_ref=pair; @@ -63,9 +73,9 @@ void Hash::expand() { } } -uint Hash::generic_code(uint aresult, char *start, uint size) { +uint Hash::generic_code(uint aresult, const char *start, uint allocated) { uint result=aresult, g; - char *end=start+size; + const char *end=start+allocated; while (startlink) if(pair->code==code && pair->key==key) { // found a pair with the same key pair->value=value; - return; + return true; } - // not found proper pair -- create&link_in new pair - *ref=new(pool) Pair(code, key, value, *ref); + // proper pair not found -- create&link_in new pair + if(!*ref) // root cell were used? + used++; // not, we'll use it and record the fact + *ref=new Pair(code, key, value, *ref); + count++; + return false; } -Hash::Value* Hash::get(Key& key) { - SYNCHRONIZED; +bool Hash::remove(const Key& key) { + uint code=key.hash_code(); + uint index=code%allocated; + for(Pair **ref=&refs[index]; *ref; ref=&(*ref)->link) + if((*ref)->code==code && (*ref)->key==key) { + // found a pair with the same key + *ref=(*ref)->link; + --count; + return true; + } + return false; +} + +Hash::Val *Hash::get(const Key& key) const { uint code=key.hash_code(); - uint index=code%size; + uint index=code%allocated; for(Pair *pair=refs[index]; pair; pair=pair->link) if(pair->code==code && pair->key==key) return pair->value; return 0; } + +bool Hash::put_replace(const Key& key, Val *value) { + uint code=key.hash_code(); + uint index=code%allocated; + for(Pair *pair=refs[index]; pair; pair=pair->link) + if(pair->code==code && pair->key==key) { + // found a pair with the same key, replacing + pair->value=value; + return true; + } + + // proper pair not found + return false; +} + +bool Hash::put_dont_replace(const Key& key, Val *value) { + if(!value) + return remove(key); + + if(full()) + expand(); + + uint code=key.hash_code(); + uint index=code%allocated; + Pair **ref=&refs[index]; + for(Pair *pair=*ref; pair; pair=pair->link) + if(pair->code==code && pair->key==key) { + // found a pair with the same key, NOT replacing + return true; + } + + // proper pair not found -- create&link_in new pair + if(!*ref) // root cell were used? + used++; // not, we'll use it and record the fact + *ref=new Pair(code, key, value, *ref); + count++; + return false; +} + +void Hash::merge_dont_replace(const Hash& src) { + for(int i=0; ilink) + put_dont_replace(pair->key, pair->value); + // MAY:optimize this.allocated==src.allocated case +} + +void Hash::for_each(For_each_func func, void *info) const { + Pair **ref=refs; + for(int index=0; indexlink) + (*func)(pair->key, pair->value, info); +} + +void Hash::for_each(For_each_func_refed func, void *info) const { + Pair **ref=refs; + for(int index=0; indexlink) + (*func)(pair->key, pair->value, info); +} + +void* Hash::first_that(First_that_func func, void *info) const { + Pair **ref=refs; + for(int index=0; indexlink) + if(void *result=(*func)(pair->key, pair->value, info)) + return result; + return 0; +} + +void Hash::clear() { + memset(refs, 0, sizeof(*refs)*allocated); + count=used=0; +}