1*cb63e24eSchristos /* Copyright (C) 2021-2024 Free Software Foundation, Inc.
24f645668Schristos Contributed by Oracle.
34f645668Schristos
44f645668Schristos This file is part of GNU Binutils.
54f645668Schristos
64f645668Schristos This program is free software; you can redistribute it and/or modify
74f645668Schristos it under the terms of the GNU General Public License as published by
84f645668Schristos the Free Software Foundation; either version 3, or (at your option)
94f645668Schristos any later version.
104f645668Schristos
114f645668Schristos This program is distributed in the hope that it will be useful,
124f645668Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
134f645668Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144f645668Schristos GNU General Public License for more details.
154f645668Schristos
164f645668Schristos You should have received a copy of the GNU General Public License
174f645668Schristos along with this program; if not, write to the Free Software
184f645668Schristos Foundation, 51 Franklin Street - Fifth Floor, Boston,
194f645668Schristos MA 02110-1301, USA. */
204f645668Schristos
214f645668Schristos /*
224f645668Schristos * Interval Map implementation.
234f645668Schristos *
244f645668Schristos * Interval Map makes the following assumptions:
254f645668Schristos * - if duplicate keys, the last one will be stored
264f645668Schristos * - <TBC>
274f645668Schristos */
284f645668Schristos #ifndef _DBE_INTERVALMAP_H
294f645668Schristos #define _DBE_INTERVALMAP_H
304f645668Schristos
314f645668Schristos #include <assert.h>
324f645668Schristos #include <vec.h>
334f645668Schristos #include <Map.h>
344f645668Schristos
354f645668Schristos template <typename Key_t, typename Value_t>
364f645668Schristos class IntervalMap : public Map<Key_t, Value_t>
374f645668Schristos {
384f645668Schristos public:
394f645668Schristos
404f645668Schristos IntervalMap ();
414f645668Schristos ~IntervalMap ();
424f645668Schristos void put (Key_t key, Value_t val);
434f645668Schristos Value_t get (Key_t key);
444f645668Schristos Value_t get (Key_t key, typename Map<Key_t, Value_t>::Relation rel);
454f645668Schristos Value_t remove (Key_t key);
464f645668Schristos
474f645668Schristos private:
484f645668Schristos
494f645668Schristos struct Entry
504f645668Schristos {
514f645668Schristos Key_t key;
524f645668Schristos Value_t val;
534f645668Schristos };
544f645668Schristos
554f645668Schristos static const int CHUNK_SIZE;
564f645668Schristos
574f645668Schristos int entries;
584f645668Schristos int nchunks;
594f645668Schristos Entry **chunks;
604f645668Schristos Vector<Entry*> *index;
614f645668Schristos };
624f645668Schristos
634f645668Schristos template <typename Key_t, typename Value_t>
644f645668Schristos const int IntervalMap<Key_t, Value_t>::CHUNK_SIZE = 16384;
654f645668Schristos
664f645668Schristos template <typename Key_t, typename Value_t>
IntervalMap()674f645668Schristos IntervalMap<Key_t, Value_t>::IntervalMap ()
684f645668Schristos {
694f645668Schristos entries = 0;
704f645668Schristos nchunks = 0;
714f645668Schristos chunks = NULL;
724f645668Schristos index = new Vector<Entry*>;
734f645668Schristos }
744f645668Schristos
754f645668Schristos template <typename Key_t, typename Value_t>
~IntervalMap()764f645668Schristos IntervalMap<Key_t, Value_t>::~IntervalMap ()
774f645668Schristos {
784f645668Schristos for (int i = 0; i < nchunks; i++)
794f645668Schristos delete[] chunks[i];
804f645668Schristos delete[] chunks;
814f645668Schristos delete index;
824f645668Schristos }
834f645668Schristos
844f645668Schristos template <typename Key_t, typename Value_t>
854f645668Schristos void
put(Key_t key,Value_t val)864f645668Schristos IntervalMap<Key_t, Value_t>::put (Key_t key, Value_t val)
874f645668Schristos {
884f645668Schristos int lo = 0;
894f645668Schristos int hi = entries - 1;
904f645668Schristos while (lo <= hi)
914f645668Schristos {
924f645668Schristos int md = (lo + hi) / 2;
934f645668Schristos Entry *entry = index->fetch (md);
944f645668Schristos int cmp = entry->key < key ? -1 : entry->key > key ? 1 : 0;
954f645668Schristos if (cmp < 0)
964f645668Schristos lo = md + 1;
974f645668Schristos else if (cmp > 0)
984f645668Schristos hi = md - 1;
994f645668Schristos else
1004f645668Schristos {
1014f645668Schristos entry->val = val;
1024f645668Schristos return;
1034f645668Schristos }
1044f645668Schristos }
1054f645668Schristos
1064f645668Schristos if (entries >= nchunks * CHUNK_SIZE)
1074f645668Schristos {
1084f645668Schristos nchunks++;
1094f645668Schristos // Reallocate Entry chunk array
1104f645668Schristos Entry **new_chunks = new Entry*[nchunks];
1114f645668Schristos for (int i = 0; i < nchunks - 1; i++)
1124f645668Schristos new_chunks[i] = chunks[i];
1134f645668Schristos delete chunks;
1144f645668Schristos chunks = new_chunks;
1154f645668Schristos
1164f645668Schristos // Allocate new chunk for entries.
1174f645668Schristos chunks[nchunks - 1] = new Entry[CHUNK_SIZE];
1184f645668Schristos }
1194f645668Schristos Entry *entry = &chunks[entries / CHUNK_SIZE][entries % CHUNK_SIZE];
1204f645668Schristos entry->key = key;
1214f645668Schristos entry->val = val;
1224f645668Schristos index->insert (lo, entry);
1234f645668Schristos entries++;
1244f645668Schristos }
1254f645668Schristos
1264f645668Schristos template <typename Key_t, typename Value_t>
1274f645668Schristos Value_t
get(Key_t key)1284f645668Schristos IntervalMap<Key_t, Value_t>::get (Key_t key)
1294f645668Schristos {
1304f645668Schristos return get (key, Map<Key_t, Value_t>::REL_EQ);
1314f645668Schristos }
1324f645668Schristos
1334f645668Schristos template <typename Key_t, typename Value_t>
1344f645668Schristos Value_t
get(Key_t key,typename Map<Key_t,Value_t>::Relation rel)1354f645668Schristos IntervalMap<Key_t, Value_t>::get (Key_t key, typename Map<Key_t, Value_t>::Relation rel)
1364f645668Schristos {
1374f645668Schristos int lo = 0;
1384f645668Schristos int hi = entries - 1;
1394f645668Schristos while (lo <= hi)
1404f645668Schristos {
1414f645668Schristos int md = (lo + hi) / 2;
1424f645668Schristos Entry *entry = index->fetch (md);
1434f645668Schristos int cmp = entry->key < key ? -1 : entry->key > key ? 1 : 0;
1444f645668Schristos switch (rel)
1454f645668Schristos {
1464f645668Schristos case Map<Key_t, Value_t>::REL_LT:
1474f645668Schristos if (cmp < 0)
1484f645668Schristos lo = md + 1;
1494f645668Schristos else
1504f645668Schristos hi = md - 1;
1514f645668Schristos break;
1524f645668Schristos case Map<Key_t, Value_t>::REL_GT:
1534f645668Schristos if (cmp <= 0)
1544f645668Schristos lo = md + 1;
1554f645668Schristos else
1564f645668Schristos hi = md - 1;
1574f645668Schristos break;
1584f645668Schristos case Map<Key_t, Value_t>::REL_LE:
1594f645668Schristos case Map<Key_t, Value_t>::REL_GE:
1604f645668Schristos case Map<Key_t, Value_t>::REL_EQ:
1614f645668Schristos if (cmp < 0)
1624f645668Schristos lo = md + 1;
1634f645668Schristos else if (cmp > 0)
1644f645668Schristos hi = md - 1;
1654f645668Schristos else
1664f645668Schristos return entry->val;
1674f645668Schristos break;
1684f645668Schristos }
1694f645668Schristos }
1704f645668Schristos switch (rel)
1714f645668Schristos {
1724f645668Schristos case Map<Key_t, Value_t>::REL_LT:
1734f645668Schristos case Map<Key_t, Value_t>::REL_LE:
1744f645668Schristos return hi >= 0 ? index->fetch (hi)->val : (Value_t) 0;
1754f645668Schristos case Map<Key_t, Value_t>::REL_GT:
1764f645668Schristos case Map<Key_t, Value_t>::REL_GE:
1774f645668Schristos return lo < entries ? index->fetch (lo)->val : (Value_t) 0;
1784f645668Schristos case Map<Key_t, Value_t>::REL_EQ:
1794f645668Schristos break;
1804f645668Schristos }
1814f645668Schristos return (Value_t) 0;
1824f645668Schristos }
1834f645668Schristos
1844f645668Schristos template <typename Key_t, typename Value_t>
1854f645668Schristos Value_t
remove(Key_t)1864f645668Schristos IntervalMap<Key_t, Value_t>::remove (Key_t)
1874f645668Schristos {
1884f645668Schristos // Not implemented
1894f645668Schristos if (1)
1904f645668Schristos assert (0);
1914f645668Schristos return (Value_t) 0;
1924f645668Schristos }
1934f645668Schristos
1944f645668Schristos #endif
195