--- parser3/src/include/pa_hash.h 2010/08/04 15:08:44 1.82 +++ parser3/src/include/pa_hash.h 2015/09/24 21:28:19 1.89 @@ -1,7 +1,7 @@ /** @file Parser: hash class decl. - Copyright (c) 2001-2009 ArtLebedev Group (http://www.artlebedev.com) + Copyright (c) 2001-2012 Art. Lebedev Studio (http://www.artlebedev.com) Author: Alexandr Petrosian (http://paf.design.ru) */ @@ -17,7 +17,7 @@ #ifndef PA_HASH_H #define PA_HASH_H -static const char * const IDENT_HASH_H="$Date: 2010/08/04 15:08:44 $"; +#define IDENT_PA_HASH_H "$Id: pa_hash.h,v 1.89 2015/09/24 21:28:19 moko Exp $" #include "pa_memory.h" #include "pa_types.h" @@ -90,11 +90,13 @@ inline uint hash_code(int self) { #undef HASH #undef HASH_STRING #undef HASH_NEW_PAIR +#undef HASH_ORDER_CLEAR #undef HASH_FOR_EACH #define HASH OrderedHash #define HASH_STRING OrderedHashString #define HASH_NEW_PAIR(code, key, value) *ref=new Pair(code, key, value, *ref, this->last); this->last=&((*ref)->next) +#define HASH_ORDER_CLEAR() first=0; last=&first #define HASH_FOR_EACH \ for(Pair *pair=this->first; pair; pair=pair->next) @@ -104,6 +106,7 @@ inline uint hash_code(int self) { #define HASH Hash #define HASH_STRING HashString #define HASH_NEW_PAIR(code, key, value) *ref=new Pair(code, key, value, *ref) +#define HASH_ORDER_CLEAR() #define HASH_FOR_EACH \ Pair **ref=this->refs; \ @@ -117,29 +120,24 @@ public: typedef K key_type; typedef V value_type; + class Pair; HASH() { allocated=Hash_allocates[allocates_index=0]; - threshold=allocated*THRESHOLD_PERCENT/100; fpairs_count=fused_refs=0; - refs=new(UseGC) Pair*[allocated]; -#ifdef HASH_ORDER - first=0; - last=&first; -#endif + refs=new Pair*[allocated]; + HASH_ORDER_CLEAR(); } HASH(const HASH& source) { allocates_index=source.allocates_index; allocated=source.allocated; - threshold=source.threshold; fused_refs=source.fused_refs; fpairs_count=source.fpairs_count; - refs=new(UseGC) Pair*[allocated]; + refs=new Pair*[allocated]; // clone & rehash #ifdef HASH_ORDER - first=0; - last=&first; + HASH_ORDER_CLEAR(); for(Pair *pair=source.first; pair; pair=pair->next) { uint index=pair->code%allocated; @@ -246,13 +244,38 @@ public: } #ifdef HASH_ORDER + String::Body first_key() const { + return (first) ? String::Body(first->key, first->code) : String::Body(); + } + V first_value() const { return (first) ? first->value : V(0); } + String::Body last_key() const { + if (fpairs_count) { + Pair* pair = (Pair*)((char *)last - offsetof(Pair, next)); + return String::Body(pair->key, pair->code); + } else { + return String::Body(); + } + } + V last_value() const { return (fpairs_count) ? ((Pair *)((char *)last - offsetof(Pair, next)))->value : V(0); } + + void order_clear() { + HASH_ORDER_CLEAR(); + } + + void order_next(Pair* pair) { + pair->prev=last; + pair->next=0; + *last=pair; + last=&(pair->next); + } + #endif /// put a [value] under the [key] if that [key] existed @returns existed or not @@ -337,29 +360,18 @@ public: /// remove all elements void clear() { memset(refs, 0, sizeof(*refs)*allocated); - fpairs_count=fused_refs=0; -#ifdef HASH_ORDER - first=0; - last=&first; -#endif + fpairs_count=fused_refs=0; + HASH_ORDER_CLEAR(); } protected: - /// expand when these %% of allocated exausted - enum { - THRESHOLD_PERCENT=75 - }; - /// the index of [allocated] in [Hash_allocates] int allocates_index; /// number of allocated pairs int allocated; - /// helper: expanding when fused_refs == threshold - int threshold; - /// used pairs int fused_refs; @@ -389,19 +401,18 @@ protected: Pair **last; #endif - /// filled to threshold: needs expanding - bool is_full() { return fused_refs==threshold; } + /// filled to threshold (THRESHOLD_PERCENT=75), needs expanding + bool is_full() { return fused_refs + allocated/4 >= allocated; } /// allocate larger buffer & rehash void expand() { int old_allocated=allocated; Pair **old_refs=refs; - allocates_index=allocates_index+1& fhash; Pair *fcurrent; + int i; public: Iterator(const HASH_STRING& ahash): fhash(ahash) { +#ifdef HASH_ORDER fcurrent=fhash.first; +#else + fcurrent=0; + for(i=0; inext; +#else + if(fcurrent=fcurrent->link) + return; + for(i++; ivalue; } + + Pair *pair(){ + return fcurrent; + } }; }; #else //HASH_CODE_CACHING @@ -634,20 +665,21 @@ template class HASH_STRING: #ifndef HASH_ORDER /// Auto-object used to temporarily substituting/removing string hash values -template +template class Temp_hash_value { - HashString &fhash; - K fname; + H *fhash; + String::Body fname; V saved_value; public: - Temp_hash_value(HashString& ahash, K aname, V avalue) : - fhash(ahash), - fname(aname), - saved_value(ahash.get(aname)) { - fhash.put(aname, avalue); + Temp_hash_value(H *ahash, String::Body aname, V avalue) : fhash(ahash), fname(aname) { + if(fhash){ + saved_value=fhash->get(aname); + fhash->put(aname, avalue); + } } - ~Temp_hash_value() { - fhash.put(fname, saved_value); + ~Temp_hash_value() { + if(fhash) + fhash->put(fname, saved_value); } }; #endif