Diff for /parser3/src/include/pa_hash.h between versions 1.58.2.18.2.5 and 1.71

version 1.58.2.18.2.5, 2003/03/21 16:16:43 version 1.71, 2009/04/17 13:13:09
Line 1 Line 1
 /** @file  /** @file
         Parser: hash class decl.          Parser: hash class decl.
   
         Copyright (c) 2001-2003 ArtLebedev Group (http://www.artlebedev.com)          Copyright (c) 2001-2005 ArtLebedev Group (http://www.artlebedev.com)
   
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
 */  */
Line 17 Line 17
 #ifndef PA_HASH_H  #ifndef PA_HASH_H
 #define PA_HASH_H  #define PA_HASH_H
   
 static const char* IDENT_HASH_H="$Date$";  static const char * const IDENT_HASH_H="$Date$";
   
 #include "pa_memory.h"  #include "pa_memory.h"
 #include "pa_types.h"  #include "pa_types.h"
   
   const int HASH_ALLOCATES_COUNT=29;
   
   /** Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster 
   
           paf: HPUX ld could not handle static member: unsatisfied symbols
   */
   static uint Hash_allocates[HASH_ALLOCATES_COUNT]={
           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};
   
   /// useful generic hash function
   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
   inline void generic_hash_code(uint& result, const char* buf, size_t size) {
           const char* end=buf+size;
           while(buf<end) {
                   result=(result<<4)+*buf++;
                   if(uint g=(result&0xF0000000)) {
                           result=result^(g>>24);
                           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;
   }
   
 /**   /** 
         Simple hash.          Simple hash.
   
Line 37  public: Line 87  public:
         typedef V value_type;          typedef V value_type;
   
         Hash() {           Hash() { 
                 allocated=allocates[allocates_index=0];                  allocated=Hash_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=new(0) Pair*[allocated];                  refs=new(UseGC) Pair*[allocated];
         }          }
   
         Hash(const Hash& source) {          Hash(const Hash& source) {
Line 49  public: Line 99  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(0) Pair*[allocated];                  refs=new(UseGC) Pair*[allocated];
   
                 // clone & rehash                  // clone & rehash
                 Pair **old_ref=source.refs;                  Pair **old_ref=source.refs;
Line 64  public: Line 114  public:
                         }                          }
         }          }
   
           ~Hash() {
                   delete[] refs;
           }
   
         /// 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) {                  if(!value) {
Line 91  public: Line 145  public:
                 return false;                  return false;
         }          }
   
           /// put a [value] under the [key] @returns existed or not
           template<typename R, typename F, typename I> R replace_maybe_append(K key, V value, F prevent, I info) {
                   if(!value) {
                           // they can come here from somewhere (true with maybe_replace_maybe_append, keeping parallel)
                           remove(key);
                           // this has nothing to do with properties, doing no special property handling here
                           return 0; 
                   }
   
                   if(is_full()) 
                           expand();
   
                   uint code=hash_code(key);
                   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
                                   pair->value=value;
                                   return reinterpret_cast<R>(1);
                           }
                   
                   // proper pair not found 
                   // prevent-function intercepted append?
                   if(R result=prevent(value, info))
                           return result;
                   
                   //create&link_in new pair
                   if(!*ref) // root cell were fused_refs?
                           fused_refs++; // not, we'll use it and record the fact
                   *ref=new Pair(code, key, value, *ref);
                   fpairs_count++;
                   return 0;
           }
   
           /// put a [value] under the [key] @returns existed or not
           template<typename R, typename F1, typename F2, typename I> 
                   R maybe_replace_maybe_append(K key, V value, F1 prevent_replace, F2 prevent_append, I info) 
           {
                   if(!value) {
                           // they can come here from Temp_value_element::dctor to restore some empty value
                           remove(key);
                           // this has nothing to do with properties, doing no special property handling here
                           return 0; 
                   }
   
                   if(is_full()) 
                           expand();
   
                   uint code=hash_code(key);
                   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
   
                                   // prevent-function intercepted replace?
                                   if(R result=prevent_replace(pair->value, info))
                                           return result;
                                   
                                   pair->value=value;
                                   return reinterpret_cast<R>(1);
                           }
                   
                   // proper pair not found 
                   // prevent-function intercepted append?
                   if(R result=prevent_append(value, info))
                           return result;
                   
                   //create&link_in new pair
                   if(!*ref) // root cell were fused_refs?
                           fused_refs++; // not, we'll use it and record the fact
                   *ref=new Pair(code, key, value, *ref);
                   fpairs_count++;
                   return 0;
           }
   
           /// put a [value] under the [key] @returns existed or not
           template<typename R, typename F1, typename I> 
                   R maybe_replace_never_append(K key, V value, F1 prevent_replace, I info) 
           {
                   if(!value) {
                           // they can come here from somewhere (true with maybe_replace_maybe_append, keeping parallel)
                           remove(key);
                           // this has nothing to do with properties, doing no special property handling here
                           return 0; 
                   }
   
                   if(is_full()) 
                           expand();
   
                   uint code=hash_code(key);
                   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
   
                                   // prevent-function intercepted replace?
                                   if(R result=prevent_replace(pair->value, info))
                                           return result;
                                   
                                   pair->value=value;
                                   return reinterpret_cast<R>(1);
                           }
                   
                   return 0;
           }
   
         /// remove the [key] @returns existed or not          /// remove the [key] @returns existed or not
         bool remove(K key) {          bool remove(K key) {
                 uint code=hash_code(key);                  uint code=hash_code(key);
Line 108  public: Line 271  public:
                 return false;                  return false;
         }          }
   
           /// return true if key exists
           bool contains(K key){
                   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 true;
                   }
   
                   return false;
           }
   
         /// get associated [value] by the [key]          /// get associated [value] by the [key]
         V get(K key) const {          V get(K key) const {
                 uint code=hash_code(key);                  uint code=hash_code(key);
Line 119  public: Line 294  public:
                 return V(0);                  return V(0);
         }          }
   
           /// get associated [value] by the [key] + [code] (faster)
           V get_by_hash_code(uint code, K key) const {
                   uint index=code%allocated;
                   for(Pair *pair=refs[index]; pair; pair=pair->link)
                           if(pair->code==code && pair->key==key)
                                   return pair->value;
                   
                   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_replaced(K key, V value) {
                 if(!value) {                  if(!value) {
                         remove(key);                          remove(key);
                         return false;                          return false;
Line 138  public: Line 323  public:
                 return false;                  return false;
         }          }
   
           /// put a [value] under the [key] if that [key] existed @returns existed or not
           template<typename R, typename F> R maybe_put_replaced(K key, V value, F prevent) {
                   if(!value) {
                           // they can come here from Temp_value_element::dctor to restore some empty value
                           remove(key);
                           // this has nothing to do with properties, doing no special property handling here
                           return 0; 
                   }
   
                   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) {
                                   // found a pair with the same key, replacing
                                   // prevent-function intercepted put?
                                   if(R result=prevent(pair->value))
                                           return result;
                                   
                                   pair->value=value;
                                   return reinterpret_cast<R>(1);
                           }
   
                   // proper pair not found 
                   return 0;
           }
   
         /// 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) {                  if(!value) {
Line 184  public: Line 395  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;
Line 208  private: Line 427  private:
                 THRESHOLD_PERCENT=75                  THRESHOLD_PERCENT=75
         };          };
   
         /// the index of [allocated] in [allocates]          /// the index of [allocated] in [Hash_allocates]
         int allocates_index;          int allocates_index;
   
         /// possible [allocates]. prime numbers  
         static uint allocates[];  
           
         static int allocates_count;  
   
         /// number of allocated pairs          /// number of allocated pairs
         int allocated;          int allocated;
   
Line 251  private: Line 465  private:
                 int old_allocated=allocated;                  int old_allocated=allocated;
                 Pair **old_refs=refs;                  Pair **old_refs=refs;
   
                 allocates_index=allocates_index+1<allocates_count?allocates_index+1:allocates_count-1;                  allocates_index=allocates_index+1<HASH_ALLOCATES_COUNT?allocates_index+1:HASH_ALLOCATES_COUNT-1;
                 // allocated bigger refs array                  // allocated bigger refs array
                 allocated=allocates[allocates_index];                  allocated=Hash_allocates[allocates_index];
                 threshold=allocated*THRESHOLD_PERCENT/100;                  threshold=allocated*THRESHOLD_PERCENT/100;
                 refs=new(UseGC) Pair*[allocated];                  refs=new(UseGC) Pair*[allocated];
   
Line 279  private: //disabled Line 493  private: //disabled
         Hash& operator = (const Hash&) { return *this; }          Hash& operator = (const Hash&) { return *this; }
 };  };
   
 /* Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster */  
 template<typename K, typename V>  
 uint Hash<K, V>::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};  
   
 template<typename K, typename V>  
 int Hash<K, V>::allocates_count=sizeof(allocates)/sizeof(uint);  
   
 /// 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  
 inline void generic_hash_code(uint& result, const char* buf, size_t size) {  
         const char* end=buf+size;  
         while(buf<end) {  
                 result=(result<<4)+*buf++;  
                 if(uint g=(result&0xF0000000)) {  
                         result=result^(g>>24);  
                         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;  
 }  
   
 ///     Auto-object used to temporarily substituting/removing hash values  ///     Auto-object used to temporarily substituting/removing hash values
 template <typename K, typename V>  template <typename K, typename V>
 class Temp_hash_value {  class Temp_hash_value {

Removed from v.1.58.2.18.2.5  
changed lines
  Added in v.1.71


E-mail: