/* Copyright (C) 2021-2024 Free Software Foundation, Inc. Contributed by Oracle. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* * String Map implementation. */ #ifndef _DBE_STRINGMAP_H #define _DBE_STRINGMAP_H #include #include #include #include template class StringMap : public Map { public: StringMap (int htable_size = 1024, int chunk_size = 16384); ~StringMap (); void clear (); void put (const char *key, Value_t val); Value_t get (const char *key); Value_t get (const char *key, typename Map::Relation rel); Value_t remove (const char*); Vector *keySet (); Vector *values (); private: static unsigned hash (const char *key) { return (unsigned) crc64 (key, strlen (key)); } struct Entry { char *key; Value_t val; }; int CHUNK_SIZE, HTABLE_SIZE; int entries; int nchunks; Entry **chunks; Vector *index; Entry **hashTable; }; template StringMap::StringMap (int htable_size, int chunk_size) { HTABLE_SIZE = htable_size; CHUNK_SIZE = chunk_size; entries = 0; nchunks = 0; chunks = NULL; index = new Vector; hashTable = new Entry*[HTABLE_SIZE]; for (int i = 0; i < HTABLE_SIZE; i++) hashTable[i] = NULL; } template StringMap::~StringMap () { for (int i = 0; i < entries; ++i) { Entry *entry = index->fetch (i); free (entry->key); } for (int i = 0; i < nchunks; i++) delete[] chunks[i]; delete[] chunks; delete index; delete[] hashTable; } template void StringMap::clear () { for (int i = 0; i < entries; ++i) { Entry *entry = index->fetch (i); free (entry->key); } entries = 0; index->reset (); for (int i = 0; i < HTABLE_SIZE; i++) hashTable[i] = NULL; } template void StringMap::put (const char *key, Value_t val) { unsigned idx = hash (key) % HTABLE_SIZE; Entry *entry = hashTable[idx]; if (entry && strcmp (entry->key, key) == 0) { entry->val = val; return; } int lo = 0; int hi = entries - 1; while (lo <= hi) { int md = (lo + hi) / 2; entry = index->fetch (md); int cmp = strcmp (entry->key, key); if (cmp < 0) lo = md + 1; else if (cmp > 0) hi = md - 1; else { entry->val = val; return; } } if (entries >= nchunks * CHUNK_SIZE) { nchunks++; // Reallocate Entry chunk array Entry **new_chunks = new Entry*[nchunks]; for (int i = 0; i < nchunks - 1; i++) new_chunks[i] = chunks[i]; delete[] chunks; chunks = new_chunks; // Allocate new chunk for entries. chunks[nchunks - 1] = new Entry[CHUNK_SIZE]; } entry = &chunks[entries / CHUNK_SIZE][entries % CHUNK_SIZE]; entry->key = strdup (key); entry->val = val; index->insert (lo, entry); hashTable[idx] = entry; entries++; } template Value_t StringMap::get (const char *key) { unsigned idx = hash (key) % HTABLE_SIZE; Entry *entry = hashTable[idx]; if (entry && strcmp (entry->key, key) == 0) return entry->val; int lo = 0; int hi = entries - 1; while (lo <= hi) { int md = (lo + hi) / 2; entry = index->fetch (md); int cmp = strcmp (entry->key, key); if (cmp < 0) lo = md + 1; else if (cmp > 0) hi = md - 1; else { hashTable[idx] = entry; return entry->val; } } return (Value_t) 0; } template Value_t StringMap::get (const char *key, typename Map::Relation rel) { if (rel != Map::REL_EQ) return (Value_t) 0; return get (key); } template Value_t StringMap::remove (const char*) { // Not implemented if (1) assert (0); return (Value_t) 0; } template Vector * StringMap::values () { Vector *vals = new Vector(entries); for (int i = 0; i < entries; ++i) { Entry *entry = index->fetch (i); vals->append (entry->val); } return vals; } template Vector * StringMap::keySet () { Vector *keys = new Vector(entries); for (int i = 0; i < entries; ++i) { Entry *entry = index->fetch (i); keys->append (entry->key); } return keys; } #endif