|
|
| version 1.21, 2001/03/18 11:37:52 | version 1.52, 2002/08/01 11:41:19 |
|---|---|
| Line 1 | Line 1 |
| /* | /** @file |
| Parser | Parser: hash class. |
| Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) | |
| Author: Alexander Petrosyan <paf@design.ru> (http://design.ru/paf) | |
| $Id$ | Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) |
| Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru) | |
| */ | */ |
| /* | /* |
| Line 14 | Line 13 |
| For more information about Zend please visit http://www.zend.com/ | For more information about Zend please visit http://www.zend.com/ |
| */ | */ |
| static const char* IDENT_HASH_C="$Date$"; | |
| #include "pa_hash.h" | #include "pa_hash.h" |
| #include "pa_threads.h" | |
| void *Hash::Pair::operator new(size_t size, Pool& apool) { | void *Hash::Pair::operator new(size_t size, Pool& apool) { |
| return apool.malloc(size); | return apool.malloc(size, 6); |
| } | } |
| /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */ | /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */ |
| Line 31 int Hash::allocates_count= | Line 31 int Hash::allocates_count= |
| sizeof(allocates)/sizeof(uint); | sizeof(allocates)/sizeof(uint); |
| void Hash::construct(Pool& apool, bool athread_safe) { | void Hash::construct_new() { |
| thread_safe=athread_safe; | |
| allocated=allocates[allocates_index=0]; | allocated=allocates[allocates_index=0]; |
| threshold=allocated*THRESHOLD_PERCENT/100; | threshold=allocated*THRESHOLD_PERCENT/100; |
| used=0; | count=used=0; |
| refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated)); | refs=static_cast<Pair **>(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<Pair **>(malloc(size, 7)); memcpy(refs, source.refs, size); | |
| } | |
| void Hash::expand() { | void Hash::expand() { |
| int old_size=allocated; | int old_size=allocated; |
| Pair **old_refs=refs; | Pair **old_refs=refs; |
| Line 47 void Hash::expand() { | Line 55 void Hash::expand() { |
| // allocated bigger refs array | // allocated bigger refs array |
| allocates_index=allocates_index+1<allocates_count?allocates_index+1:allocates_count-1; | allocates_index=allocates_index+1<allocates_count?allocates_index+1:allocates_count-1; |
| allocated=allocates[allocates_index]; | allocated=allocates[allocates_index]; |
| threshold=allocated*THRESHOLD_PERCENT/100; | |
| refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated)); | refs=static_cast<Pair **>(calloc(sizeof(Pair *)*allocated)); |
| // rehash | // rehash |
| Line 78 uint Hash::generic_code(uint aresult, co | Line 87 uint Hash::generic_code(uint aresult, co |
| return result; | return result; |
| } | } |
| bool Hash::put(const Key& key, Value *value) { SYNCHRONIZED(thread_safe); | bool Hash::put(const Key& key, Val *value) { |
| if(!value) | |
| return remove(key); | |
| if(full()) | if(full()) |
| expand(); | expand(); |
| Line 96 bool Hash::put(const Key& key, Value *va | Line 108 bool Hash::put(const Key& key, Value *va |
| if(!*ref) // root cell were used? | if(!*ref) // root cell were used? |
| used++; // not, we'll use it and record the fact | used++; // not, we'll use it and record the fact |
| *ref=NEW Pair(code, key, value, *ref); | *ref=NEW Pair(code, key, value, *ref); |
| count++; | |
| return false; | |
| } | |
| 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; | return false; |
| } | } |
| Hash::Value *Hash::get(const Key& key) const { SYNCHRONIZED(thread_safe); | Hash::Val *Hash::get(const Key& key) const { |
| uint code=key.hash_code(); | uint code=key.hash_code(); |
| uint index=code%allocated; | uint index=code%allocated; |
| for(Pair *pair=refs[index]; pair; pair=pair->link) | for(Pair *pair=refs[index]; pair; pair=pair->link) |
| Line 109 Hash::Value *Hash::get(const Key& key) c | Line 136 Hash::Value *Hash::get(const Key& key) c |
| return 0; | return 0; |
| } | } |
| bool Hash::put_replace(const Key& key, Value *value) { SYNCHRONIZED(thread_safe); | bool Hash::put_replace(const Key& key, Val *value) { |
| uint code=key.hash_code(); | uint code=key.hash_code(); |
| uint index=code%allocated; | uint index=code%allocated; |
| for(Pair *pair=refs[index]; pair; pair=pair->link) | for(Pair *pair=refs[index]; pair; pair=pair->link) |
| Line 123 bool Hash::put_replace(const Key& key, V | Line 150 bool Hash::put_replace(const Key& key, V |
| return false; | return false; |
| } | } |
| bool Hash::put_dont_replace(const Key& key, Value *value) { SYNCHRONIZED(thread_safe); | bool Hash::put_dont_replace(const Key& key, Val *value) { |
| if(!value) | |
| return remove(key); | |
| if(full()) | if(full()) |
| expand(); | expand(); |
| Line 137 bool Hash::put_dont_replace(const Key& k | Line 167 bool Hash::put_dont_replace(const Key& k |
| } | } |
| // proper pair not found -- create&link_in new pair | // proper pair not found -- create&link_in new pair |
| *ref=NEW Pair(code, key, value, *ref); | |
| if(!*ref) // root cell were used? | if(!*ref) // root cell were used? |
| used++; // not, we'll use it and record the fact | used++; // not, we'll use it and record the fact |
| *ref=NEW Pair(code, key, value, *ref); | |
| count++; | |
| return false; | return false; |
| } | } |
| void Hash::merge_dont_replace(const Hash& src) { SYNCHRONIZED(thread_safe); | void Hash::merge_dont_replace(const Hash& src) { |
| for(int i=0; i<src.allocated; i++) | for(int i=0; i<src.allocated; i++) |
| for(Pair *pair=src.refs[i]; pair; pair=pair->link) | for(Pair *pair=src.refs[i]; pair; pair=pair->link) |
| put_dont_replace(pair->key, pair->value); | put_dont_replace(pair->key, pair->value); |
| // MAY:optimize this.allocated==src.allocated case | // MAY:optimize this.allocated==src.allocated case |
| } | } |
| void Hash::foreach(Foreach_func func, void *info) { | void Hash::for_each(For_each_func func, void *info) const { |
| Pair **ref=refs; | |
| for(int index=0; index<allocated; index++) | |
| for(Pair *pair=*ref++; pair; pair=pair->link) | |
| (*func)(pair->key, pair->value, info); | |
| } | |
| void Hash::for_each(For_each_func_refed func, void *info) const { | |
| Pair **ref=refs; | Pair **ref=refs; |
| for(int index=0; index<allocated; index++) | for(int index=0; index<allocated; index++) |
| for(Pair *pair=*ref++; pair; pair=pair->link) | for(Pair *pair=*ref++; pair; pair=pair->link) |
| (*func)(info, pair->key, pair->value); | (*func)(pair->key, pair->value, info); |
| } | |
| void* Hash::first_that(First_that_func func, void *info) const { | |
| Pair **ref=refs; | |
| for(int index=0; index<allocated; index++) | |
| for(Pair *pair=*ref++; pair; pair=pair->link) | |
| 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; | |
| } | } |