|
|
| version 1.58.2.11, 2003/02/03 13:01:06 | version 1.59, 2003/07/24 11:31:21 |
|---|---|
| Line 19 | Line 19 |
| static const char* IDENT_HASH_H="$Date$"; | static const char* IDENT_HASH_H="$Date$"; |
| #include "pa_pool.h" | #include "pa_memory.h" |
| #include "pa_types.h" | #include "pa_types.h" |
| const int HASH_ALLOCATES_COUNT=29; | |
| /** | /** |
| Simple hash. | Simple hash. |
| Line 40 public: | Line 42 public: |
| allocated=allocates[allocates_index=0]; | allocated=allocates[allocates_index=0]; |
| threshold=allocated*THRESHOLD_PERCENT/100; | threshold=allocated*THRESHOLD_PERCENT/100; |
| fpairs_count=fused_refs=0; | fpairs_count=fused_refs=0; |
| refs=static_cast<Pair **>(pa_calloc(sizeof(Pair *)*allocated)); | refs=new(UseGC) Pair*[allocated]; |
| } | } |
| Hash(const Hash& source) { | Hash(const Hash& source) { |
| Line 49 public: | Line 51 public: |
| threshold=source.threshold; | threshold=source.threshold; |
| fused_refs=source.fused_refs; | fused_refs=source.fused_refs; |
| fpairs_count=source.fpairs_count; | fpairs_count=source.fpairs_count; |
| refs=new Pair*[allocated]; | refs=new(UseGC) Pair*[allocated]; |
| memcpy(refs, source.refs, sizeof(Pair *)*allocated); | |
| } | // clone & rehash |
| ~Hash() { | Pair **old_ref=source.refs; |
| destroy_pairs(); | for(int index=0; index<allocated; index++) |
| delete refs; | for(Pair *pair=*old_ref++; pair; ) { |
| Pair *next=pair->link; | |
| Pair **new_ref=&refs[index]; | |
| *new_ref=new Pair(pair->code, pair->key, pair->value, *new_ref); | |
| pair=next; | |
| } | |
| } | } |
| /// put a [value] under the [key] @returns existed or not | /// put a [value] under the [key] @returns existed or not |
| bool put(K key, V value) { | bool put(K key, V value) { |
| if(!value) { | |
| remove(key); | |
| return false; | |
| } | |
| if(is_full()) | if(is_full()) |
| expand(); | expand(); |
| Line 105 public: | Line 118 public: |
| if(pair->code==code && pair->key==key) | if(pair->code==code && pair->key==key) |
| return pair->value; | return pair->value; |
| return 0; | return V(0); |
| } | } |
| /// put a [value] under the [key] if that [key] existed @returns existed or not | /// put a [value] under the [key] if that [key] existed @returns existed or not |
| bool put_replace(K key, V value) { | bool put_replace(K key, V value) { |
| if(!value) { | |
| remove(key); | |
| return false; | |
| } | |
| uint code=hash_code(key); | uint code=hash_code(key); |
| 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 125 public: | Line 142 public: |
| /// put a [value] under the [key] if that [key] NOT existed @returns existed or not | /// put a [value] under the [key] if that [key] NOT existed @returns existed or not |
| bool put_dont_replace(K key, V value) { | bool put_dont_replace(K key, V value) { |
| if(!value) { | |
| remove(key); | |
| return false; | |
| } | |
| if(is_full()) | if(is_full()) |
| expand(); | expand(); |
| Line 145 public: | Line 166 public: |
| return false; | 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) { | void 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 | |
| } | } |
| /// number of elements in hash | /// number of elements in hash |
| Line 164 public: | Line 186 public: |
| callback(pair->key, pair->value, info); | callback(pair->key, pair->value, info); |
| } | } |
| /// iterate over all pairs | |
| template<typename I> void for_each_ref(void callback(K, V&, I), I info) const { | |
| Pair **ref=refs; | |
| for(int index=0; index<allocated; index++) | |
| for(Pair *pair=*ref++; pair; pair=pair->link) | |
| callback(pair->key, pair->value, info); | |
| } | |
| /// iterate over all pairs until condition becomes true, return that element | /// iterate over all pairs until condition becomes true, return that element |
| template<typename I> V first_that(bool callback(K, V, I), I info) const { | template<typename I> V first_that(bool callback(K, V, I), I 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) |
| if(callback(pair->key, pair->value, info)) | if(callback(pair->key, pair->value, info)) |
| return &pair->value; | return pair->value; |
| return 0;//V(0) | return V(0); |
| } | } |
| /// remove all elements | /// remove all elements |
| void clear() { | void clear() { |
| destroy_pairs(); memset(refs, 0, sizeof(*refs)*allocated); | memset(refs, 0, sizeof(*refs)*allocated); |
| fpairs_count=fused_refs=0; | fpairs_count=fused_refs=0; |
| } | } |
| Line 194 private: | Line 224 private: |
| /// possible [allocates]. prime numbers | /// possible [allocates]. prime numbers |
| static uint allocates[]; | static uint allocates[]; |
| static int allocates_count; | |
| /// number of allocated pairs | /// number of allocated pairs |
| int allocated; | int allocated; |
| Line 231 private: | Line 259 private: |
| int old_allocated=allocated; | int old_allocated=allocated; |
| Pair **old_refs=refs; | Pair **old_refs=refs; |
| allocates_index=allocates_index+1<HASH_ALLOCATES_COUNT?allocates_index+1:HASH_ALLOCATES_COUNT-1; | |
| // allocated bigger refs array | // allocated bigger refs array |
| 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; | threshold=allocated*THRESHOLD_PERCENT/100; |
| refs=static_cast<Pair **>(pa_calloc(sizeof(Pair *)*allocated)); | refs=new(UseGC) Pair*[allocated]; |
| // rehash | // rehash |
| Pair **old_ref=old_refs; | Pair **old_ref=old_refs; |
| Line 251 private: | Line 279 private: |
| pair=next; | pair=next; |
| } | } |
| delete old_refs; | delete[] old_refs; |
| } | |
| void destroy_pairs() { | |
| Pair **ref=refs; | |
| for(int index=0; index<allocated; index++) { | |
| Pair *pair=*ref++; | |
| while(pair) { | |
| Pair *next=pair->link; | |
| delete pair; | |
| pair=next; | |
| } | |
| } | |
| } | } |
| private: //disabled | private: //disabled |
| Line 273 private: //disabled | Line 289 private: //disabled |
| /* 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 */ |
| template<typename K, typename V> | template<typename K, typename V> |
| uint Hash<K, V>::allocates[]={ | uint Hash<K, V>::allocates[HASH_ALLOCATES_COUNT]={ |
| 5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, | 5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963, |
| 16229, 32531, 65407, 130987, 262237, 524521, 1048793, | 16229, 32531, 65407, 130987, 262237, 524521, 1048793, |
| 2097397, 4194103, 8388857, 16777447, 33554201, 67108961, | 2097397, 4194103, 8388857, 16777447, 33554201, 67108961, |
| 134217487, 268435697, 536870683, 1073741621, 2147483399}; | 134217487, 268435697, 536870683, 1073741621, 2147483399}; |
| template<typename K, typename V> | /// useful generic hash function |
| int Hash<K, V>::allocates_count=sizeof(allocates)/sizeof(uint); | inline void generic_hash_code(uint& result, char c) { |
| result=(result<<4)+c; | |
| if(uint g=(result&0xF0000000)) { | |
| result=result^(g>>24); | |
| result=result^g; | |
| } | |
| } | |
| /// useful generic hash function | |
| inline void generic_hash_code(uint& result, const char* s) { | |
| while(char c=*s++) { | |
| result=(result<<4)+c; | |
| if(uint g=(result&0xF0000000)) { | |
| result=result^(g>>24); | |
| result=result^g; | |
| } | |
| } | |
| } | |
| /// useful generic hash function | /// useful generic hash function |
| inline uint generic_hash_code(uint aresult, const char* start, uint allocated) { | inline void generic_hash_code(uint& result, const char* buf, size_t size) { |
| uint result=aresult, g; | const char* end=buf+size; |
| const char* end=start+allocated; | while(buf<end) { |
| result=(result<<4)+*buf++; | |
| while (start<end) { | if(uint g=(result&0xF0000000)) { |
| result=(result<<4)+*start++; | |
| if ((g=(result&0xF0000000))) { | |
| result=result^(g>>24); | result=result^(g>>24); |
| result=result^g; | result=result^g; |
| } | } |
| } | } |
| } | |
| /// simple hash code of int. used by EXIF mapping | |
| inline uint hash_code(int self) { | |
| uint result=0; | |
| generic_hash_code(result, (const char*)&self, sizeof(self)); | |
| return result; | return result; |
| } | } |