Annotation of parser3/src/include/pa_inline_hash.h, revision 1.8

1.1       moko        1: /** @file
                      2:        Parser: inline-storage hash decls.
                      3: 
1.3       moko        4:        Copyright (c) 2001-2026 Art. Lebedev Studio (https://www.artlebedev.com)
1.1       moko        5:        Authors: Konstantin Morshnev <moko@design.ru>
                      6: */
                      7: 
                      8: #ifndef PA_INLINE_HASH_H
                      9: #define PA_INLINE_HASH_H
                     10: 
1.8     ! moko       11: #define IDENT_PA_INLINE_HASH_H "$Id: pa_inline_hash.h,v 1.7 2026/04/30 16:06:48 moko Exp $"
1.1       moko       12: 
                     13: #include "pa_hash.h"
                     14: 
1.6       moko       15: #define PA_INLINE_HASH_N 13  // Low overflow rate, high first-hit ratio
1.7       moko       16: #define PA_PROBE_LIMIT 8     // Prevents long probe chains from degrading the inline table
1.1       moko       17: 
1.4       moko       18: // Linear-probing inline hash with PA_INLINE_HASH_N slots before overflow to HashString<V>.
1.1       moko       19: 
1.2       moko       20: template<typename V> class InlineHashString: public PA_Object {
1.1       moko       21: public:
                     22: 
1.8     ! moko       23:        InlineHashString() : foverflow(0) {
        !            24:                memset(fkeys, 0, sizeof(fkeys));
1.4       moko       25:        }
1.1       moko       26: 
1.4       moko       27:        ~InlineHashString() {
1.2       moko       28: #ifdef USE_DESTRUCTORS
1.4       moko       29:                if(foverflow) delete foverflow;
1.2       moko       30: #endif
1.4       moko       31:        }
1.2       moko       32: 
1.1       moko       33:        V get(const String& name) const {
                     34:                const String::Body& nb = name;
1.4       moko       35:                const uint hash = nb.get_hash_code();
                     36:                int i = hash % PA_INLINE_HASH_N;
1.5       moko       37: 
                     38:                // Optimized first, >50% hits
                     39:                if(!fkeys[i]) return 0;  // NULL implies foverflow==NULL
                     40:                if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) return fvalues[i];
                     41:                // Сollision
1.6       moko       42:                for(int n = 0; n < PA_PROBE_LIMIT-1; n++) {
1.4       moko       43:                        if(++i >= PA_INLINE_HASH_N) i = 0;
1.5       moko       44:                        if(!fkeys[i]) return 0;
                     45:                        if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) return fvalues[i];
1.1       moko       46:                }
                     47:                return foverflow ? foverflow->get(name) : 0;
                     48:        }
                     49: 
                     50:        bool put(const String& name, V value) {
                     51:                const String::Body& nb = name;
1.4       moko       52:                const uint hash = nb.get_hash_code();
                     53:                int i = hash % PA_INLINE_HASH_N;
1.5       moko       54: 
                     55:                // Optimized first
                     56:                if(!fkeys[i]) { fkeys[i] = &nb; fvalues[i] = value; return false; }
                     57:                if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) { fvalues[i] = value; return true; }
                     58:                // Сollision
1.6       moko       59:                for(int n = 0; n < PA_PROBE_LIMIT-1; n++) {
1.4       moko       60:                        if(++i >= PA_INLINE_HASH_N) i = 0;
1.5       moko       61:                        if(!fkeys[i]) { fkeys[i] = &nb; fvalues[i] = value; return false; }
                     62:                        if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) { fvalues[i] = value; return true; }
1.1       moko       63:                }
                     64:                if(!foverflow)
                     65:                        foverflow = new HashString<V>();
                     66:                return foverflow->put(name, value);
                     67:        }
                     68: 
                     69:        bool put_replaced(const String& name, V value) {
                     70:                const String::Body& nb = name;
1.4       moko       71:                const uint hash = nb.get_hash_code();
                     72:                int i = hash % PA_INLINE_HASH_N;
1.5       moko       73: 
                     74:                // Optimized first
                     75:                if(!fkeys[i]) return false;
                     76:                if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) { fvalues[i] = value; return true; }
                     77:                // Сollision
1.6       moko       78:                for(int n = 0; n < PA_PROBE_LIMIT-1; n++) {
1.4       moko       79:                        if(++i >= PA_INLINE_HASH_N) i = 0;
1.5       moko       80:                        if(!fkeys[i]) return false;
                     81:                        if(fkeys[i]->get_hash_code() == hash && *fkeys[i] == nb) { fvalues[i] = value; return true; }
1.1       moko       82:                }
                     83:                return foverflow ? foverflow->put_replaced(name, value) : false;
                     84:        }
                     85: 
                     86:        template<typename I> void for_each(void callback(const String::Body&, V, I), I info) const {
1.4       moko       87:                for(int i = 0; i < PA_INLINE_HASH_N; i++) {
                     88:                        if(fkeys[i])
                     89:                                callback(*fkeys[i], fvalues[i], info);
                     90:                }
1.1       moko       91:                if(foverflow)
                     92:                        foverflow->for_each(callback, info);
                     93:        }
                     94: 
                     95: private:
                     96:        HashString<V>* foverflow;
1.4       moko       97:        const String::Body* fkeys[PA_INLINE_HASH_N];  // NULL=empty, initialized in constructor
                     98:        V fvalues[PA_INLINE_HASH_N];
                     99: 
1.1       moko      100: };
                    101: 
                    102: #endif // PA_INLINE_HASH_H

E-mail: