--- parser3/src/include/pa_hash.h 2020/10/11 22:58:37 1.100 +++ parser3/src/include/pa_hash.h 2025/05/26 00:52:15 1.107 @@ -1,23 +1,15 @@ /** @file Parser: hash class decl. - Copyright (c) 2001-2017 Art. Lebedev Studio (http://www.artlebedev.com) + Copyright (c) 2001-2024 Art. Lebedev Studio (http://www.artlebedev.com) - Author: Alexandr Petrosian (http://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/ + Authors: Konstantin Morshnev , Alexandr Petrosian */ #ifndef PA_HASH_H #define PA_HASH_H -#define IDENT_PA_HASH_H "$Id: pa_hash.h,v 1.100 2020/10/11 22:58:37 moko Exp $" +#define IDENT_PA_HASH_H "$Id: pa_hash.h,v 1.107 2025/05/26 00:52:15 moko Exp $" #include "pa_memory.h" #include "pa_types.h" @@ -25,15 +17,12 @@ 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 -*/ +// nearest primes to 5 * 2^n 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}; + 5, 11, 19, 41, 79, 163, 317, 641, 1279, 2557, 5119, + 10243, 20479, 40961, 81919, 163841, 327673, 655357, + 1310719, 2621447, 5242883, 10485767, 20971529, 41943049, + 83886091, 167772161, 335544323, 671088637, 1342177283}; /// useful generic hash function inline void generic_hash_code(uint& result, char c) { @@ -115,6 +104,9 @@ inline uint hash_code(int self) { #endif +#define HASH_PUT_CSTR(h, cstr, v) \ + { static const String::Body body_##__LINE__(cstr); (h).put(body_##__LINE__, (v)); } + template class HASH: public PA_Object { protected: class Pair; @@ -474,7 +466,7 @@ public: CORD key=str.get_cord(); uint code=str.get_hash_code(); - uint index=code%this->allocated; + uint index=code % this->allocated; Pair **ref=&this->refs[index]; for(Pair *pair=*ref; pair; pair=pair->link) if(pair->code==code && CORD_cmp(pair->key,key)==0) { @@ -491,11 +483,15 @@ public: return false; } + bool put(const char *str, V value) { + return put(String::Body(str), value); + } + /// remove the [key] @returns existed or not bool remove(K str) { CORD key=str.get_cord(); 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){ Pair *pair=*ref; if(pair->code==code && CORD_cmp(pair->key,key)==0) { @@ -521,7 +517,7 @@ public: bool contains(K str){ CORD key=str.get_cord(); 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){ if(pair->code==code && CORD_cmp(pair->key,key)==0) return true; @@ -534,7 +530,7 @@ public: V get(K str) const { CORD key=str.get_cord(); 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) if(pair->code==code && CORD_cmp(pair->key,key)==0) return pair->value; @@ -550,7 +546,7 @@ public: } else { key=0; } - uint index=code%this->allocated; + uint index=code % this->allocated; for(Pair *pair=this->refs[index]; pair; pair=pair->link) if(pair->code==code && CORD_cmp(pair->key,(CORD)key)==0) return pair->value; @@ -567,7 +563,7 @@ public: CORD key=str.get_cord(); 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) if(pair->code==code && CORD_cmp(pair->key,key)==0) { // found a pair with the same key, replacing @@ -590,7 +586,7 @@ public: CORD key=str.get_cord(); uint code=str.get_hash_code(); - uint index=code%this->allocated; + uint index=code % this->allocated; Pair **ref=&this->refs[index]; for(Pair *pair=*ref; pair; pair=pair->link) if(pair->code==code && CORD_cmp(pair->key,key)==0) { @@ -606,6 +602,44 @@ public: 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 void merge_dont_replace(const HASH_STRING& src) { #ifdef HASH_ORDER