--- parser3/src/main/Attic/pa_hash.C 2001/03/24 10:54:46 1.29 +++ parser3/src/main/Attic/pa_hash.C 2002/10/25 08:02:09 1.52.4.1 @@ -1,11 +1,8 @@ /** @file Parser: hash class. - Copyright (c) 2001 ArtLebedev Group (http://www.artlebedev.com) - - Author: Alexander Petrosyan (http://design.ru/paf) - - $Id: pa_hash.C,v 1.29 2001/03/24 10:54:46 paf Exp $ + Copyright (c) 2001, 2002 ArtLebedev Group (http://www.artlebedev.com) + Author: Alexandr Petrosian (http://paf.design.ru) */ /* @@ -16,13 +13,12 @@ For more information about Zend please visit http://www.zend.com/ */ -#include "pa_config_includes.h" +static const char* IDENT_HASH_C="$Date: 2002/10/25 08:02:09 $"; #include "pa_hash.h" -#include "pa_threads.h" 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 */ @@ -35,15 +31,23 @@ int Hash::allocates_count= sizeof(allocates)/sizeof(uint); -void Hash::construct(Pool& apool, bool athread_safe) { - thread_safe=athread_safe; - +void Hash::construct_new() { allocated=allocates[allocates_index=0]; threshold=allocated*THRESHOLD_PERCENT/100; - used=0; + count=used=0; refs=static_cast(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(malloc(size, 7)); memcpy(refs, source.refs, size); +} + void Hash::expand() { int old_size=allocated; Pair **old_refs=refs; @@ -51,6 +55,7 @@ void Hash::expand() { // allocated bigger refs array allocates_index=allocates_index+1(calloc(sizeof(Pair *)*allocated)); // rehash @@ -82,7 +87,10 @@ uint Hash::generic_code(uint aresult, co return result; } -bool Hash::put(const Key& key, Val *value) { SYNCHRONIZED(thread_safe); +bool Hash::put(const Key& key, Val *value) { + if(!value) + return remove(key); + if(full()) expand(); @@ -100,10 +108,25 @@ bool Hash::put(const Key& key, Val *valu 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::Val *Hash::get(const Key& key) const { SYNCHRONIZED(thread_safe); +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%allocated; for(Pair *pair=refs[index]; pair; pair=pair->link) @@ -113,7 +136,7 @@ Hash::Val *Hash::get(const Key& key) con return 0; } -bool Hash::put_replace(const Key& key, Val *value) { SYNCHRONIZED(thread_safe); +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) @@ -127,7 +150,10 @@ bool Hash::put_replace(const Key& key, V return false; } -bool Hash::put_dont_replace(const Key& key, Val *value) { SYNCHRONIZED(thread_safe); +bool Hash::put_dont_replace(const Key& key, Val *value) { + if(!value) + return remove(key); + if(full()) expand(); @@ -141,28 +167,80 @@ bool Hash::put_dont_replace(const Key& k } // proper pair not found -- create&link_in new pair - *ref=NEW Pair(code, key, value, *ref); 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) { SYNCHRONIZED(thread_safe); +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) { +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) - if(pair->value) - (*func)(pair->key, pair->value, info); + (*func)(pair->key, pair->value, info); } -void Hash::clear() { SYNCHRONIZED(thread_safe); +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); - used=0; + count=used=0; +} + + +#ifndef DOXYGEN +struct Stringtolower_eq_string_info { + Pool *pool; + const String *looking_lower; +}; +#endif +void *stringtolower_eq_string(const Hash::Key& key, Hash::Val *value, void *info) { + Stringtolower_eq_string_info& i=*static_cast(info); + + return key.change_case(*i.pool, String::CC_LOWER) == *i.looking_lower?value:0; +} +Hash::Val *Hash::get_case_insensitive_internal(const Key& key_lower) const { + Stringtolower_eq_string_info info={&pool(), &key_lower}; + return first_that(stringtolower_eq_string, &info); +} +Hash::Val *Hash::get_case_insensitive(const Key& key) const { + return get_case_insensitive_internal(key.change_case(pool(), String::CC_LOWER)); +} + +bool put_case_insensitive(const Key& key, Val *value) { + const Key& key_lower=key.change_case(pool(), String::CC_LOWER); + if(get_case_insensitive_internal(key_lower)) + return true; +} + +// not as quick as it can be, but that's not needed [now] +bool Hash::put_dont_replace_case_insensitive(const Key& key, Val *value) { + const Key& key_lower=key.change_case(pool(), String::CC_LOWER); + if(get_case_insensitive_internal(key_lower)) + return true; + + put(key_lower, value); + return false; }