xref: /netbsd-src/external/gpl3/binutils/dist/gprofng/src/IntervalMap.h (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
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