--- parser3/src/include/pa_hash.h 2003/01/24 14:36:10 1.58.2.6 +++ parser3/src/include/pa_hash.h 2003/03/18 11:54:55 1.58.2.18 @@ -1,7 +1,7 @@ /** @file Parser: hash class decl. - Copyright (c) 2001, 2003 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ @@ -17,7 +17,7 @@ #ifndef PA_HASH_H #define PA_HASH_H -static const char* IDENT_HASH_H="$Date: 2003/01/24 14:36:10 $"; +static const char* IDENT_HASH_H="$Date: 2003/03/18 11:54:55 $"; #include "pa_pool.h" #include "pa_types.h" @@ -40,7 +40,7 @@ public: allocated=allocates[allocates_index=0]; threshold=allocated*THRESHOLD_PERCENT/100; fpairs_count=fused_refs=0; - refs=static_cast(pa_calloc(sizeof(Pair *)*allocated)); + refs=new(0) Pair*[allocated]; } Hash(const Hash& source) { @@ -49,8 +49,19 @@ public: threshold=source.threshold; fused_refs=source.fused_refs; fpairs_count=source.fpairs_count; - refs=new Pair*[allocated]; - memcpy(refs, source.refs, sizeof(Pair *)*allocated); + refs=new(0) Pair*[allocated]; + + // clone & rehash + Pair **old_ref=source.refs; + for(int index=0; indexlink; + + Pair **new_ref=&refs[index]; + *new_ref=new Pair(pair->code, pair->key, pair->value, *new_ref); + + pair=next; + } } ~Hash() { destroy_pairs(); @@ -58,11 +69,15 @@ public: } /// put a [value] under the [key] @returns existed or not - bool put(const K key, V value) { + bool put(K key, V value) { + if(!value) { + remove(key); + return false; + } if(is_full()) expand(); - uint code=key.hash_code(); + uint code=hash_code(key); uint index=code%allocated; Pair **ref=&refs[index]; for(Pair *pair=*ref; pair; pair=pair->link) @@ -81,8 +96,8 @@ public: } /// remove the [key] @returns existed or not - bool remove(const K key) { - uint code=key.hash_code(); + bool remove(K key) { + uint code=hash_code(key); uint index=code%allocated; for(Pair **ref=&refs[index]; *ref; ref=&(*ref)->link) if((*ref)->code==code && (*ref)->key==key) { @@ -98,19 +113,23 @@ public: } /// get associated [value] by the [key] - V get(const K key) const { - uint code=key.hash_code(); + V get(K key) const { + uint code=hash_code(key); 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; + return V(0); } /// put a [value] under the [key] if that [key] existed @returns existed or not - bool put_replace(const K key, V value) { - uint code=key.hash_code(); + bool put_replace(K key, V value) { + if(!value) { + remove(key); + return false; + } + uint code=hash_code(key); uint index=code%allocated; for(Pair *pair=refs[index]; pair; pair=pair->link) if(pair->code==code && pair->key==key) { @@ -124,11 +143,15 @@ public: } /// put a [value] under the [key] if that [key] NOT existed @returns existed or not - bool put_dont_replace(const K key, V value) { + bool put_dont_replace(K key, V value) { + if(!value) { + remove(key); + return false; + } if(is_full()) expand(); - uint code=key.hash_code(); + uint code=hash_code(key); uint index=code%allocated; Pair **ref=&refs[index]; for(Pair *pair=*ref; pair; pair=pair->link) @@ -145,12 +168,13 @@ public: return false; } - /// put all 'src' values if NO with same key existed + /** put all 'src' values if NO with same key existed + @todo optimize this.allocated==src.allocated case + */ void 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 } /// number of elements in hash @@ -164,23 +188,15 @@ public: callback(pair->key, pair->value, info); } - /// iterate over all pairs, passing references - template void for_each(void callback(K, V&, I), I info) const { - Pair **ref=refs; - for(int index=0; indexlink) - callback(pair->key, pair->value, info); - } - /// iterate over all pairs until condition becomes true, return that element - template V *first_that(bool callback(K, V, I), I info) const { + template V first_that(bool callback(K, V, I), I info) const { Pair **ref=refs; for(int index=0; indexlink) if(callback(pair->key, pair->value, info)) - return &pair->value; + return pair->value; - return 0; + return V(0); } /// remove all elements @@ -220,11 +236,11 @@ private: class Pair: public PA_Allocated { public: uint code; - const K key; + K key; V value; Pair *link; - Pair(uint acode, const K akey, V avalue, Pair *alink) : + Pair(uint acode, K akey, V avalue, Pair *alink) : code(acode), key(akey), value(avalue), @@ -239,11 +255,11 @@ private: int old_allocated=allocated; Pair **old_refs=refs; - // allocated bigger refs array allocates_index=allocates_index+1(pa_calloc(sizeof(Pair *)*allocated)); + refs=new(0) Pair*[allocated]; // rehash Pair **old_ref=old_refs; @@ -291,9 +307,9 @@ template int Hash::allocates_count=sizeof(allocates)/sizeof(uint); /// useful generic hash function -inline uint generic_hash_code(uint aresult, const char *start, uint allocated) { +inline uint generic_hash_code(uint aresult, const char* start, size_t allocated) { uint result=aresult, g; - const char *end=start+allocated; + const char* end=start+allocated; while (start class Temp_hash_value { - Hash& fhash; - const K fname; + Hash& fhash; + K fname; V saved_value; public: - Temp_hash_value(Hash& ahash, const K aname, V avalue) : + Temp_hash_value(Hash& ahash, K aname, V avalue) : fhash(ahash), fname(aname), saved_value(ahash.get(aname)) {