1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
29 // This package implements a vector of items.
31 #define Destroy(x) if (x) { (x)->destroy(); delete (x); (x) = NULL; }
32 #define VecSize(x) ((x) ? (x)->size() : 0)
34 void destroy (void *vec); // Free up the "two-dimension" Vectors
36 typedef int (*CompareFunc)(const void*, const void*);
37 typedef int (*ExtCompareFunc)(const void*, const void*, const void*);
38 typedef int (*SearchFunc)(char*, char*);
42 typedef int (*StdCompareFunc)(const void*, const void*);
75 template <class ITEM> void
76 qsort (ITEM *, size_t, ExtCompareFunc, void *);
78 template <typename ITEM> class Vector
98 void append (const ITEM item);
99 void addAll (Vector<ITEM> *vec);
100 Vector<ITEM> *copy (); // Return a copy of "this".
114 // Return the first index in "this" that equals "item".
115 // Return -1 if "item" is not found.
116 long find (const ITEM item);
117 long find_r (const ITEM item);
119 // Insert "item" into "index"'th slot of "this",
120 // moving everything over by 1.
121 void insert (long index, const ITEM item);
123 // Insert "item" after locating its appropriate index
124 void incorporate (const ITEM item, CompareFunc func);
126 // Remove and return the "index"'th item from "this",
127 // moving everything over by 1.
128 ITEM remove (long index);
130 // Swap two items in "this",
131 void swap (long index1, long index2);
139 // Store "item" into the "index"'th slot of "this".
140 void store (long index, const ITEM item);
143 put (long index, const ITEM item)
148 // Sort the vector according to compare
150 sort (CompareFunc compare, void *arg = NULL)
152 qsort (data, count, (ExtCompareFunc) compare, arg);
156 // Binary search, vector must be sorted
157 long bisearch (long start, long end, void *key, CompareFunc func);
158 void destroy (); // delete all vector elements (must be pointers!)
180 dump (const char * /* msg */)
187 void resize (long index);
189 ITEM *data; // Pointer to data vector
190 long count; // Number of items
191 long limit; // Vector length (power of 2)
195 template<> VecType Vector<int>::type ();
196 template<> VecType Vector<unsigned>::type ();
197 template<> VecType Vector<char>::type ();
198 template<> VecType Vector<bool>::type ();
199 template<> VecType Vector<double>::type ();
200 template<> VecType Vector<long long>::type ();
201 template<> VecType Vector<uint64_t>::type ();
202 template<> VecType Vector<void*>::type ();
203 template<> VecType Vector<char*>::type ();
204 template<> VecType Vector<Vector<int>*>::type ();
205 template<> VecType Vector<Vector<char*>*>::type ();
206 template<> VecType Vector<Vector<long long>*>::type ();
207 template<> void Vector<char *>::destroy ();
209 #define KILOCHUNK 1024
210 #define MEGACHUNK 1024*1024
211 #define GIGACHUNK 1024*1024*1024
213 // A standard looping construct:
214 #define Vec_loop(ITEM, vec, index, item) \
216 for (index = 0, item = ((vec)->size() > 0) ? (vec)->fetch(0) : (ITEM)0; \
217 index < (vec)->size(); \
218 item = (++index < (vec)->size()) ? (vec)->fetch(index) : (ITEM)0)
220 template <typename ITEM>
221 Vector<ITEM>::Vector (long sz)
224 limit = sz > 0 ? sz : KILOCHUNK; // was 0;
225 data = limit ? (ITEM *) malloc (sizeof (ITEM) * limit) : NULL;
229 template <typename ITEM> void
231 ::resize (long index)
237 while (index >= limit)
239 if (limit > GIGACHUNK)
240 limit += GIGACHUNK; // Deoptimization for large experiments
244 data = (ITEM *) realloc (data, limit * sizeof (ITEM));
247 template <typename ITEM> void
248 Vector<ITEM>::append (const ITEM item)
250 // This routine will append "item" to the end of "this".
253 data[count++] = item;
256 template <typename ITEM> void
257 Vector<ITEM>::addAll (Vector<ITEM> *vec)
260 for (int i = 0, sz = vec->size (); i < sz; i++)
261 append (vec->fetch (i));
264 template <typename ITEM> Vector<ITEM> *
265 Vector<ITEM>::copy ()
267 // This routine will return a copy of "this".
268 Vector<ITEM> *vector;
269 vector = new Vector<ITEM>;
270 vector->count = count;
271 vector->limit = limit;
272 vector->data = (ITEM *) malloc (sizeof (ITEM) * limit);
273 (void) memcpy ((char *) vector->data, (char *) data, sizeof (ITEM) * count);
277 template <typename ITEM> long
278 Vector<ITEM>::find (const ITEM match_item)
280 for (long i = 0; i < size (); i++)
281 if (match_item == get (i))
286 template <typename ITEM> long
287 Vector<ITEM>::find_r (const ITEM match_item)
289 for (long i = size () - 1; i >= 0; i--)
290 if (match_item == get (i))
295 template <typename ITEM> void
296 Vector<ITEM>::insert (long index, const ITEM item)
298 // This routine will insert "item" into the "index"'th slot of "this".
299 // An error occurs if "index" > size().
300 // "index" is allowed to be equal to "count" in the case that
301 // you are inserting past the last element of the vector.
302 // In that case, the bcopy below becomes a no-op.
304 assert (index <= count);
306 (void) memmove (((char *) (&data[index + 1])), (char *) (&data[index]),
307 (count - index - 1) * sizeof (ITEM));
311 template <typename ITEM> ITEM
312 Vector<ITEM>::remove (long index)
314 // This routine will remove the "index"'th item from "this" and
315 // return it. An error occurs if "index" >= size();.
317 assert (index < count);
318 ITEM item = data[index];
319 for (long i = index + 1; i < count; i++)
320 data[i - 1] = data[i];
322 // Bad code that works good when ITEM is a pointer type
327 template <typename ITEM> void
328 Vector<ITEM>::swap (long index1, long index2)
332 data[index1] = data[index2];
336 template <typename ITEM> void
337 Vector<ITEM>::store (long index, const ITEM item)
342 memset (&data[count], 0, (index - count) * sizeof (ITEM));
348 // This routine performs a binary search across
349 // the entire vector, with "start" being the low boundary.
350 // It is assumed that the vector is SORTED in
351 // ASCENDING ORDER by the same criteria as the
353 // If no match is found, -1 is returned.
354 template <typename ITEM> long
355 Vector<ITEM>::bisearch (long start, long end, void *key, CompareFunc compare)
361 return -1; // start exceeds limit
362 itemp = (ITEM *) bsearch ((char *) key, (char *) &data[start],
363 end - start, sizeof (ITEM), (StdCompareFunc) compare);
364 if (itemp == (ITEM *) 0)
365 return -1; // not found
366 return (long) (itemp - data);
369 template <typename ITEM> void
370 Vector<ITEM>::incorporate (const ITEM item, CompareFunc compare)
376 long md = (lt + rt) / 2;
377 if (compare (data[md], item) < 0)
390 template <typename ITEM> void
391 qsort (ITEM *base, size_t nelem, ExtCompareFunc qcmp, void *arg)
395 // For small arrays use insertion sort
396 if (nelem < QSTHRESH)
398 for (size_t i = 1; i < nelem; i++)
402 if (qcmp (q, p, arg) > 0)
406 while (q > base && qcmp (q - 1, &t, arg) > 0)
417 ITEM *last = base + nelem - 1;
418 ITEM *mid = base + nelem / 2;
419 // Sort the first, middle, and last elements
420 ITEM *a1 = base, *a2, *a3;
421 if (qcmp (base, mid, arg) > 0)
423 if (qcmp (mid, last, arg) > 0)
428 else if (qcmp (base, last, arg) > 0)
439 else if (qcmp (mid, last, arg) > 0)
443 if (qcmp (base, last, arg) > 0) // m-l-b
464 while (i < mid && qcmp (i, mid, arg) <= 0)
466 while (j > mid && qcmp (mid, j, arg) <= 0)
490 // Compare two partitions. Do the smaller one by recursion
491 // and loop over the larger one.
492 size_t nleft = mid - base;
493 size_t nright = nelem - nleft - 1;
496 qsort (base, nleft, qcmp, arg);
502 qsort (mid + 1, nright, qcmp, arg);
508 template<> inline void
509 Vector<char*>::destroy ()
511 for (long i = 0; i < count; i++)
516 template <typename ITEM> inline void
517 Vector<ITEM>::destroy ()
519 for (long i = 0; i < count; i++)