@@ -129,23 +129,30 @@ public:
129129// if you don't want that (keys are shared), just use GHashSet<const char*> instead
130130template <class Hash =GHashKey_xxHash<const char *>, class Eq =GHashKey_Eq<const char *>, typename khInt_t=uint64_t >
131131 class GStrSet : public GHashSet <const char *, Hash, Eq, khInt_t> {
132+ protected:
133+ const char * lastKey=NULL ;
132134 public:
133135 inline int Add (const char * ky) { // return -1 if the key already exists
134136 int absent=-1 ;
135137 khInt_t i=this ->put (ky, &absent);
136138 if (absent==1 ) {// key was actually added
137139 const char * s=Gstrdup (ky);
138140 this ->key (i)=s; // store a copy of the key string
141+ lastKey=s;
139142 return i;
140143 }
141144 // key was already there
142145 return -1 ;
143146 }
144147
148+ inline const char * getLastKey () { return lastKey; }
149+
145150 int Remove (const char * ky) { // return index being removed, or -1 if no such key exists
146151 khInt_t i=this ->get (ky);
147152 if (i!=this ->end ()) {
148- GFREE (this ->key (i)); // free string copy
153+ const char * s=this ->key (i);
154+ if (s==lastKey) lastKey=NULL ;
155+ GFREE (s); // free string copy
149156 this ->del (i);
150157 return i;
151158 }
@@ -159,6 +166,7 @@ template <class Hash=GHashKey_xxHash<const char*>, class Eq=GHashKey_Eq<const ch
159166 // deallocate string copy
160167 GFREE (this ->key (i));
161168 }
169+ lastKey=NULL ;
162170 this ->clear (); // does not shrink !
163171 }
164172
@@ -175,6 +183,7 @@ template <class Hash=GHashKey_xxHash<const char*>, class Eq=GHashKey_Eq<const ch
175183};
176184
177185// generic hash map where keys and values can be of any type
186+ // Warning: keys are always copied (shared), including const char* keys -- no deep copy!
178187template <class K , class V , class Hash =GHashKey_xxHash<K>, class Eq =GHashKey_Eq<K>, typename khInt_t=uint64_t >
179188 class GHashMap :public std ::conditional< is_char_ptr<K>::value,
180189 klib::KHashMapCached< K, V, Hash, Eq, khInt_t>,
@@ -370,7 +379,7 @@ public:
370379template <class V , class Hash =GHashKey_xxHash<const char *>, class Eq =GHashKey_Eq<const char *>, typename khInt_t=uint64_t >
371380 class GHash :public GHashMap <const char *, V, Hash, Eq, khInt_t> {
372381protected:
373-
382+ const char * lastKey= NULL ;
374383public:
375384 GHash (bool doFree=true ) {
376385 this ->freeItems =doFree;
@@ -383,17 +392,23 @@ public:
383392 if (absent==1 ) { // key was actually added
384393 const char * s=Gstrdup (ky);
385394 this ->key (i)=s; // store a copy of the key string
395+ lastKey=s;
386396 this ->value (i)=val; // value is always copied
387397 return i;
388398 }
389399 return -1 ;
390400 }
401+
402+ inline const char * getLastKey () { return lastKey; }
403+
391404 template <typename T=V> inline
392405 typename std::enable_if< std::is_pointer<T>::value, int >::type
393406 Remove (const char * ky) { // return index being removed
394407 khInt_t i=this ->get (ky);
395408 if (i!=this ->end ()) {
396- GFREE (this ->key (i)); // free string copy
409+ const char * s=this ->key (i);
410+ if (s==lastKey) lastKey=NULL ;
411+ GFREE (s); // free string copy
397412 if (this ->freeItems ) delete this ->value (i);
398413 this ->del (i);
399414 return i;
@@ -406,7 +421,9 @@ public:
406421 Remove (const char * ky) { // return index being removed
407422 khInt_t i=this ->get (ky);
408423 if (i!=this ->end ()) {
409- GFREE (this ->key (i)); // free string copy
424+ const char * s=this ->key (i);
425+ if (s==lastKey) lastKey=NULL ;
426+ GFREE (s); // free string copy
410427 this ->del (i);
411428 return i;
412429 }
@@ -422,6 +439,7 @@ public:
422439 if (this ->freeItems ) delete this ->value (i);
423440 GFREE (this ->key (i));
424441 }
442+ lastKey=NULL ;
425443 this ->clear ();
426444 }
427445
@@ -433,6 +451,7 @@ public:
433451 if (!this ->__kh_used (this ->used , i)) continue ;
434452 GFREE (this ->key (i));
435453 }
454+ lastKey=NULL ;
436455 this ->clear ();
437456 }
438457
0 commit comments