Diff for /parser3/src/include/pa_hash.h between versions 1.94 and 1.105

version 1.94, 2015/10/26 01:21:55 version 1.105, 2025/01/06 19:47:18
Line 1 Line 1
 /** @file  /** @file
         Parser: hash class decl.          Parser: hash class decl.
   
         Copyright (c) 2001-2015 Art. Lebedev Studio (http://www.artlebedev.com)          Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com)
   
         Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)          Authors: Konstantin Morshnev <moko@design.ru>, Alexandr Petrosian <paf@design.ru>
 */  
   
 /*  
         The prime numbers used from zend_hash.c,  
         the part of Zend scripting engine library,  
         Copyrighted (C) 1999-2000    Zend Technologies Ltd.  
         http://www.zend.com/license/0_92.txt  
         For more information about Zend please visit http://www.zend.com/  
 */  */
   
 #ifndef PA_HASH_H  #ifndef PA_HASH_H
Line 25 Line 17
   
 const int HASH_ALLOCATES_COUNT=29;  const int HASH_ALLOCATES_COUNT=29;
   
 /** Zend comment: Generated on an Octa-ALPHA 300MHz CPU & 2.5GB RAM monster   // nearest primes to 5 * 2^n
   
         paf: HPUX ld could not handle static member: unsatisfied symbols  
 */  
 static uint Hash_allocates[HASH_ALLOCATES_COUNT]={  static uint Hash_allocates[HASH_ALLOCATES_COUNT]={
         5, 11, 19, 53, 107, 223, 463, 983, 1979, 3907, 7963,           5, 11, 19, 41, 79, 163, 317, 641, 1279, 2557, 5119,
         16229, 32531, 65407, 130987, 262237, 524521, 1048793,           10243, 20479, 40961, 81919, 163841, 327673, 655357,
         2097397, 4194103, 8388857, 16777447, 33554201, 67108961,           1310719, 2621447, 5242883, 10485767, 20971529, 41943049,
         134217487, 268435697, 536870683, 1073741621, 2147483399};          83886091, 167772161, 335544323, 671088637, 1342177283};
   
 /// useful generic hash function  /// useful generic hash function
 inline void generic_hash_code(uint& result, char c) {  inline void generic_hash_code(uint& result, char c) {
Line 125  public: Line 114  public:
         HASH() {           HASH() { 
                 allocated=Hash_allocates[allocates_index=0];                  allocated=Hash_allocates[allocates_index=0];
                 fpairs_count=fused_refs=0;                  fpairs_count=fused_refs=0;
                 refs=new Pair*[allocated];                  refs=new(PointerGC) Pair*[allocated];
                 HASH_ORDER_CLEAR();                  HASH_ORDER_CLEAR();
         }          }
   
Line 134  public: Line 123  public:
                 allocated=source.allocated;                  allocated=source.allocated;
                 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(PointerGC) Pair*[allocated];
                 // clone & rehash                  // clone & rehash
 #ifdef HASH_ORDER  #ifdef HASH_ORDER
                 HASH_ORDER_CLEAR();                  HASH_ORDER_CLEAR();
Line 163  public: Line 152  public:
                                 delete pair;                                  delete pair;
                                 pair=next;                                  pair=next;
                         }                          }
                 delete[] refs;                  operator delete[](refs);
         }          }
 #endif  #endif
   
Line 210  public: Line 199  public:
                                 else                                  else
                                         last=pair->prev;                                          last=pair->prev;
 #endif  #endif
                                 delete pair;  
                                 *ref=next;                                  *ref=next;
                                 --fpairs_count;                                  --fpairs_count;
                                 return true;                                  return true;
Line 256  public: Line 244  public:
                 return (first) ? first->value : V(0);                  return (first) ? first->value : V(0);
         }          }
   
           inline Pair* last_pair() const {
                   return (fpairs_count) ? (Pair*)((char *)last - offsetof(Pair, next)) : NULL;
           }
   
         String::Body last_key() const {          String::Body last_key() const {
                 if (fpairs_count) {                  if(Pair* pair = last_pair()) {
                         Pair* pair = (Pair*)((char *)last - offsetof(Pair, next));  
 #ifdef HASH_CODE_CACHING  #ifdef HASH_CODE_CACHING
                         return String::Body(pair->key, pair->code);                          return String::Body(pair->key, pair->code);
 #else  #else
Line 270  public: Line 261  public:
         }          }
   
         V last_value() const {          V last_value() const {
                 return (fpairs_count) ? ((Pair *)((char *)last - offsetof(Pair, next)))->value : V(0);                  if(Pair* pair = last_pair())
                           return pair->value;
                   return NULL;
         }          }
   
         void order_clear() {          void order_clear() {
Line 283  public: Line 276  public:
                 *last=pair;                  *last=pair;
                 last=&(pair->next);                  last=&(pair->next);
         }          }
   
 #endif //HASH_ORDER  #endif //HASH_ORDER
   
         /// 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
Line 420  protected: Line 412  protected:
                 if (allocates_index<HASH_ALLOCATES_COUNT-1) allocates_index++;                  if (allocates_index<HASH_ALLOCATES_COUNT-1) allocates_index++;
                 // allocated bigger refs array                  // allocated bigger refs array
                 allocated=Hash_allocates[allocates_index];                  allocated=Hash_allocates[allocates_index];
                 refs=new Pair*[allocated];                  refs=new(PointerGC) Pair*[allocated];
   
                 // rehash                  // rehash
                 Pair **old_ref=old_refs;                  Pair **old_ref=old_refs;
Line 436  protected: Line 428  protected:
                                 pair=next;                                  pair=next;
                         }                          }
   
                 delete[] old_refs;                  operator delete[](old_refs);
         }          }
   
 private: //disabled  private: //disabled
Line 471  public: Line 463  public:
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
   
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 Pair **ref=&this->refs[index];                  Pair **ref=&this->refs[index];
                 for(Pair *pair=*ref; pair; pair=pair->link)                  for(Pair *pair=*ref; pair; pair=pair->link)
                         if(pair->code==code && CORD_cmp(pair->key,key)==0) {                          if(pair->code==code && CORD_cmp(pair->key,key)==0) {
Line 492  public: Line 484  public:
         bool remove(K str) {          bool remove(K str) {
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 for(Pair **ref=&this->refs[index]; *ref; ref=&(*ref)->link){                  for(Pair **ref=&this->refs[index]; *ref; ref=&(*ref)->link){
                         Pair *pair=*ref;                          Pair *pair=*ref;
                         if(pair->code==code && CORD_cmp(pair->key,key)==0) {                          if(pair->code==code && CORD_cmp(pair->key,key)==0) {
Line 505  public: Line 497  public:
                                 else                                  else
                                         this->last=pair->prev;                                          this->last=pair->prev;
 #endif  #endif
                                 delete pair;  
                                 *ref=next;                                  *ref=next;
                                 --this->fpairs_count;                                  --this->fpairs_count;
                                 return true;                                  return true;
Line 519  public: Line 510  public:
         bool contains(K str){          bool contains(K str){
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 for(Pair *pair=this->refs[index]; pair; pair=pair->link){                  for(Pair *pair=this->refs[index]; pair; pair=pair->link){
                         if(pair->code==code && CORD_cmp(pair->key,key)==0)                          if(pair->code==code && CORD_cmp(pair->key,key)==0)
                                 return true;                                  return true;
Line 532  public: Line 523  public:
         V get(K str) const {          V get(K str) const {
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 for(Pair *pair=this->refs[index]; pair; pair=pair->link)                  for(Pair *pair=this->refs[index]; pair; pair=pair->link)
                         if(pair->code==code && CORD_cmp(pair->key,key)==0)                          if(pair->code==code && CORD_cmp(pair->key,key)==0)
                                 return pair->value;                                  return pair->value;
Line 548  public: Line 539  public:
                 } else {                  } else {
                         key=0;                          key=0;
                 }                  }
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 for(Pair *pair=this->refs[index]; pair; pair=pair->link)                  for(Pair *pair=this->refs[index]; pair; pair=pair->link)
                         if(pair->code==code && CORD_cmp(pair->key,(CORD)key)==0)                          if(pair->code==code && CORD_cmp(pair->key,(CORD)key)==0)
                                 return pair->value;                                  return pair->value;
   
                 return V(0);                  return V((const char *)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
Line 565  public: Line 556  public:
   
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 for(Pair *pair=this->refs[index]; pair; pair=pair->link)                  for(Pair *pair=this->refs[index]; pair; pair=pair->link)
                         if(pair->code==code && CORD_cmp(pair->key,key)==0) {                          if(pair->code==code && CORD_cmp(pair->key,key)==0) {
                                 // found a pair with the same key, replacing                                  // found a pair with the same key, replacing
Line 588  public: Line 579  public:
   
                 CORD key=str.get_cord();                  CORD key=str.get_cord();
                 uint code=str.get_hash_code();                  uint code=str.get_hash_code();
                 uint index=code%this->allocated;                  uint index=code % this->allocated;
                 Pair **ref=&this->refs[index];                  Pair **ref=&this->refs[index];
                 for(Pair *pair=*ref; pair; pair=pair->link)                  for(Pair *pair=*ref; pair; pair=pair->link)
                         if(pair->code==code && CORD_cmp(pair->key,key)==0) {                          if(pair->code==code && CORD_cmp(pair->key,key)==0) {
Line 604  public: Line 595  public:
                 return false;                  return false;
         }          }
   
           /// rename $.from[] to $.to[]
           void rename(K from, K to) {
                   CORD key_from=from.get_cord();
                   uint code_from=from.get_hash_code();
                   uint index_from=code_from % this->allocated;
   
                   CORD key_to=to.get_cord();
                   uint code_to=to.get_hash_code();
                   uint index_to=code_to % this->allocated;
   
                   if(code_from == code_to && CORD_cmp(key_from, key_to)==0)
                           return;
   
                   for(Pair **ref=&this->refs[index_from]; *ref; ref=&(*ref)->link){
                           Pair *pair=*ref;
                           if(pair->code==code_from && CORD_cmp(pair->key,key_from)==0) {
                                   // found a pair with the required key
   
                                   // remove it from the from key first
                                   Pair *next=pair->link;
                                   *ref=next;
   
                                   // to simplify code
                                   remove(to);
   
                                   // change pair key
                                   pair->code=code_to;
                                   (CORD &)(pair->key)=key_to;
   
                                   // link to the to key, hash order left intact
                                   if(!(pair->link=this->refs[index_to])) // root was unused?
                                           this->fused_refs++; // we've used it and record the fact
                                   this->refs[index_to]=pair;
                                   return;
                           }
                   }
           }
   
         /// put all 'src' values if NO with same key existed          /// put all 'src' values if NO with same key existed
         void merge_dont_replace(const HASH_STRING& src) {          void merge_dont_replace(const HASH_STRING& src) {
 #ifdef HASH_ORDER  #ifdef HASH_ORDER
Line 677  public: Line 706  public:
 #endif  #endif
   
                 operator bool () {                  operator bool () {
                         return fcurrent != 0;                          return fcurrent != NULL;
                   }
   
                   String::Body key(){
   #ifdef HASH_CODE_CACHING
                           return String::Body(fcurrent->key, fcurrent->code);
   #else
                           return fcurrent->key;
   #endif
                   }
   
                   V value(){
                           return fcurrent->value;
                   }
   
                   Pair *pair(){
                           return fcurrent;
                   }
           };
   
   #ifdef HASH_ORDER
           /// simple reverse hash iterator
           class ReverseIterator {
                   const HASH_STRING<V>& fhash;
                   Pair *fcurrent;
           public:
                   ReverseIterator(const HASH_STRING<V>& ahash): fhash(ahash) {
                           fcurrent=fhash.last_pair();
                   }
   
                   void prev() {
                           fcurrent=(fcurrent->prev == &fhash.first) ? NULL : (Pair*)((char *)fcurrent->prev - offsetof(Pair, next));
                   }
   
                   operator bool () {
                           return fcurrent != NULL;
                 }                  }
   
                 String::Body key(){                  String::Body key(){
Line 696  public: Line 760  public:
                         return fcurrent;                          return fcurrent;
                 }                  }
         };          };
   #endif
   
 };  };
   

Removed from v.1.94  
changed lines
  Added in v.1.105


E-mail: