|
|
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.3 ! moko 11: #define IDENT_PA_INLINE_HASH_H "$Id: pa_inline_hash.h,v 1.2 2026/04/25 02:28:31 moko Exp $"
1.1 moko 12:
13: #include "pa_hash.h"
14:
15: #define PA_HASH_INLINE_SIZE 4
16:
17: /// Inline-storage "hash" stores up to PA_HASH_INLINE_SIZE entries without heap allocation.
18: /// Fallbacks to HashString for overflow.
19:
1.2 moko 20: template<typename V> class InlineHashString: public PA_Object {
1.1 moko 21: public:
22:
23: struct Pair {
24: String::Body key;
25: V value;
26: };
27:
28: InlineHashString() : fcount(0), foverflow(0) {}
29:
1.2 moko 30: #ifdef USE_DESTRUCTORS
31: ~InlineHashString() { if(foverflow) delete foverflow; }
32: #endif
33:
1.1 moko 34: V get(const String& name) const {
35: const String::Body& nb = name;
36: const uint code = nb.get_hash_code();
37: for(int i = 0; i < fcount; i++) {
38: const String::Body& key = fpairs[i].key;
39: if(key.get_hash_code() == code && key == nb)
40: return fpairs[i].value;
41: }
42: return foverflow ? foverflow->get(name) : 0;
43: }
44:
45: bool put(const String& name, V value) {
46: const String::Body& nb = name;
47: const uint code = nb.get_hash_code();
48: for(int i = 0; i < fcount; i++) {
49: const String::Body& key = fpairs[i].key;
50: if(key.get_hash_code() == code && key == nb) {
51: fpairs[i].value = value;
52: return true;
53: }
54: }
55: if(fcount < PA_HASH_INLINE_SIZE) {
56: fpairs[fcount].key = name;
57: fpairs[fcount].value = value;
58: fcount++;
59: return false;
60: }
61: if(!foverflow)
62: foverflow = new HashString<V>();
63: return foverflow->put(name, value);
64: }
65:
66: bool put_replaced(const String& name, V value) {
67: const String::Body& nb = name;
68: const uint code = nb.get_hash_code();
69: for(int i = 0; i < fcount; i++) {
70: const String::Body& key = fpairs[i].key;
71: if(key.get_hash_code() == code && key == nb) {
72: fpairs[i].value = value;
73: return true;
74: }
75: }
76: return foverflow ? foverflow->put_replaced(name, value) : false;
77: }
78:
79: int count() const {
80: return fcount + (foverflow ? foverflow->count() : 0);
81: }
82:
83: template<typename I> void for_each(void callback(const String::Body&, V, I), I info) const {
84: for(int i = 0; i < fcount; i++)
85: callback(fpairs[i].key, fpairs[i].value, info);
86: if(foverflow)
87: foverflow->for_each(callback, info);
88: }
89:
90: private:
91: int fcount;
92: Pair fpairs[PA_HASH_INLINE_SIZE];
93: HashString<V>* foverflow;
94: };
95:
96: #endif // PA_INLINE_HASH_H