aboutsummaryrefslogtreecommitdiff
path: root/gprofng/src/vec.h
diff options
context:
space:
mode:
Diffstat (limited to 'gprofng/src/vec.h')
-rw-r--r--gprofng/src/vec.h524
1 files changed, 524 insertions, 0 deletions
diff --git a/gprofng/src/vec.h b/gprofng/src/vec.h
new file mode 100644
index 0000000..28b1800c
--- /dev/null
+++ b/gprofng/src/vec.h
@@ -0,0 +1,524 @@
+/* Copyright (C) 2021 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. */
+
+#ifndef _PERFAN_VEC_H
+#define _PERFAN_VEC_H
+
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+
+// This package implements a vector of items.
+
+#define Destroy(x) if (x) { (x)->destroy(); delete (x); (x) = NULL; }
+#define VecSize(x) ((x) ? (x)->size() : 0)
+
+void destroy (void *vec); // Free up the "two-dimension" Vectors
+
+typedef int (*CompareFunc)(const void*, const void*);
+typedef int (*ExtCompareFunc)(const void*, const void*, const void*);
+typedef int (*SearchFunc)(char*, char*);
+
+extern "C"
+{
+ typedef int (*StdCompareFunc)(const void*, const void*);
+}
+
+enum Search_type
+{
+ LINEAR,
+ BINARY,
+ HASH
+};
+
+enum Direction
+{
+ FORWARD,
+ REVERSE
+};
+
+enum VecType
+{
+ VEC_VOID = 0,
+ VEC_INTEGER,
+ VEC_CHAR,
+ VEC_BOOL,
+ VEC_DOUBLE,
+ VEC_LLONG,
+ VEC_VOIDARR,
+ VEC_STRING,
+ VEC_INTARR,
+ VEC_BOOLARR,
+ VEC_LLONGARR,
+ VEC_STRINGARR,
+ VEC_DOUBLEARR
+};
+
+template <class ITEM> void
+qsort (ITEM *, size_t, ExtCompareFunc, void *);
+
+template <typename ITEM> class Vector
+{
+public:
+
+ Vector ()
+ {
+ count = 0;
+ data = NULL;
+ limit = 0;
+ sorted = false;
+ };
+
+ Vector (long sz);
+
+ virtual
+ ~Vector ()
+ {
+ free (data);
+ }
+
+ void append (const ITEM item);
+ void addAll (Vector<ITEM> *vec);
+ Vector<ITEM> *copy (); // Return a copy of "this".
+
+ ITEM
+ fetch (long index)
+ {
+ return data[index];
+ }
+
+ ITEM
+ get (long index)
+ {
+ return data[index];
+ }
+
+ // Return the first index in "this" that equals "item".
+ // Return -1 if "item" is not found.
+ long find (const ITEM item);
+ long find_r (const ITEM item);
+
+ // Insert "item" into "index"'th slot of "this",
+ // moving everything over by 1.
+ void insert (long index, const ITEM item);
+
+ // Insert "item" after locating its appropriate index
+ void incorporate (const ITEM item, CompareFunc func);
+
+ // Remove and return the "index"'th item from "this",
+ // moving everything over by 1.
+ ITEM remove (long index);
+
+ // Swap two items in "this",
+ void swap (long index1, long index2);
+
+ long
+ size ()
+ {
+ return count;
+ }
+
+ // Store "item" into the "index"'th slot of "this".
+ void store (long index, const ITEM item);
+
+ void
+ put (long index, const ITEM item)
+ {
+ store (index, item);
+ }
+
+ // Sort the vector according to compare
+ void
+ sort (CompareFunc compare, void *arg = NULL)
+ {
+ qsort (data, count, (ExtCompareFunc) compare, arg);
+ sorted = true;
+ }
+
+ // Binary search, vector must be sorted
+ long bisearch (long start, long end, void *key, CompareFunc func);
+ void destroy (); // delete all vector elements (must be pointers!)
+
+ void
+ reset ()
+ {
+ count = 0;
+ sorted = false;
+ }
+
+ bool
+ is_sorted ()
+ {
+ return sorted;
+ }
+
+ virtual VecType
+ type ()
+ {
+ return VEC_VOID;
+ }
+
+ virtual void
+ dump (const char * /* msg */)
+ {
+ return;
+ }
+
+private:
+
+ void resize (long index);
+
+ ITEM *data; // Pointer to data vector
+ long count; // Number of items
+ long limit; // Vector length (power of 2)
+ bool sorted;
+};
+
+template<> VecType Vector<int>::type ();
+template<> VecType Vector<unsigned>::type ();
+template<> VecType Vector<char>::type ();
+template<> VecType Vector<bool>::type ();
+template<> VecType Vector<double>::type ();
+template<> VecType Vector<long long>::type ();
+template<> VecType Vector<uint64_t>::type ();
+template<> VecType Vector<void*>::type ();
+template<> VecType Vector<char*>::type ();
+template<> VecType Vector<Vector<int>*>::type ();
+template<> VecType Vector<Vector<char*>*>::type ();
+template<> VecType Vector<Vector<long long>*>::type ();
+template<> void Vector<char *>::destroy ();
+
+#define KILOCHUNK 1024
+#define MEGACHUNK 1024*1024
+#define GIGACHUNK 1024*1024*1024
+
+// A standard looping construct:
+#define Vec_loop(ITEM, vec, index, item) \
+if (vec != NULL) \
+ for (index = 0, item = ((vec)->size() > 0) ? (vec)->fetch(0) : (ITEM)0; \
+ index < (vec)->size(); \
+ item = (++index < (vec)->size()) ? (vec)->fetch(index) : (ITEM)0)
+
+template <typename ITEM>
+Vector<ITEM>::Vector (long sz)
+{
+ count = 0;
+ limit = sz > 0 ? sz : KILOCHUNK; // was 0;
+ data = limit ? (ITEM *) malloc (sizeof (ITEM) * limit) : NULL;
+ sorted = false;
+}
+
+template <typename ITEM> void
+Vector<ITEM>
+::resize (long index)
+{
+ if (index < limit)
+ return;
+ if (limit < 16)
+ limit = 16;
+ while (index >= limit)
+ {
+ if (limit > GIGACHUNK)
+ limit += GIGACHUNK; // Deoptimization for large experiments
+ else
+ limit = limit * 2;
+ }
+ data = (ITEM *) realloc (data, limit * sizeof (ITEM));
+}
+
+template <typename ITEM> void
+Vector<ITEM>::append (const ITEM item)
+{
+ // This routine will append "item" to the end of "this".
+ if (count >= limit)
+ resize (count);
+ data[count++] = item;
+}
+
+template <typename ITEM> void
+Vector<ITEM>::addAll (Vector<ITEM> *vec)
+{
+ if (vec)
+ for (int i = 0, sz = vec->size (); i < sz; i++)
+ append (vec->fetch (i));
+}
+
+template <typename ITEM> Vector<ITEM> *
+Vector<ITEM>::copy ()
+{
+ // This routine will return a copy of "this".
+ Vector<ITEM> *vector;
+ vector = new Vector<ITEM>;
+ vector->count = count;
+ vector->limit = limit;
+ vector->data = (ITEM *) malloc (sizeof (ITEM) * limit);
+ (void) memcpy ((char *) vector->data, (char *) data, sizeof (ITEM) * count);
+ return vector;
+}
+
+template <typename ITEM> long
+Vector<ITEM>::find (const ITEM match_item)
+{
+ for (long i = 0; i < size (); i++)
+ if (match_item == get (i))
+ return i;
+ return -1;
+}
+
+template <typename ITEM> long
+Vector<ITEM>::find_r (const ITEM match_item)
+{
+ for (long i = size () - 1; i >= 0; i--)
+ if (match_item == get (i))
+ return i;
+ return -1;
+}
+
+template <typename ITEM> void
+Vector<ITEM>::insert (long index, const ITEM item)
+{
+ // This routine will insert "item" into the "index"'th slot of "this".
+ // An error occurs if "index" > size().
+ // "index" is allowed to be equal to "count" in the case that
+ // you are inserting past the last element of the vector.
+ // In that case, the bcopy below becomes a no-op.
+ assert (index >= 0);
+ assert (index <= count);
+ append (item);
+ (void) memmove (((char *) (&data[index + 1])), (char *) (&data[index]),
+ (count - index - 1) * sizeof (ITEM));
+ data[index] = item;
+}
+
+template <typename ITEM> ITEM
+Vector<ITEM>::remove (long index)
+{
+ // This routine will remove the "index"'th item from "this" and
+ // return it. An error occurs if "index" >= size();.
+ assert (index >= 0);
+ assert (index < count);
+ ITEM item = data[index];
+ for (long i = index + 1; i < count; i++)
+ data[i - 1] = data[i];
+ count--;
+ // Bad code that works good when ITEM is a pointer type
+ data[count] = item;
+ return data[count];
+}
+
+template <typename ITEM> void
+Vector<ITEM>::swap (long index1, long index2)
+{
+ ITEM item;
+ item = data[index1];
+ data[index1] = data[index2];
+ data[index2] = item;
+}
+
+template <typename ITEM> void
+Vector<ITEM>::store (long index, const ITEM item)
+{
+ if (index >= count)
+ {
+ resize (index);
+ memset (&data[count], 0, (index - count) * sizeof (ITEM));
+ count = index + 1;
+ }
+ data[index] = item;
+}
+
+// This routine performs a binary search across
+// the entire vector, with "start" being the low boundary.
+// It is assumed that the vector is SORTED in
+// ASCENDING ORDER by the same criteria as the
+// compare function.
+// If no match is found, -1 is returned.
+template <typename ITEM> long
+Vector<ITEM>::bisearch (long start, long end, void *key, CompareFunc compare)
+{
+ ITEM *itemp;
+ if (end == -1)
+ end = count;
+ if (start >= end)
+ return -1; // start exceeds limit
+ itemp = (ITEM *) bsearch ((char *) key, (char *) &data[start],
+ end - start, sizeof (ITEM), (StdCompareFunc) compare);
+ if (itemp == (ITEM *) 0)
+ return -1; // not found
+ return (long) (itemp - data);
+}
+
+template <typename ITEM> void
+Vector<ITEM>::incorporate (const ITEM item, CompareFunc compare)
+{
+ long lt = 0;
+ long rt = count - 1;
+ while (lt <= rt)
+ {
+ long md = (lt + rt) / 2;
+ if (compare (data[md], item) < 0)
+ lt = md + 1;
+ else
+ rt = md - 1;
+ }
+ if (lt == count)
+ append (item);
+ else
+ insert (lt, item);
+}
+
+#define QSTHRESH 6
+
+template <typename ITEM> void
+qsort (ITEM *base, size_t nelem, ExtCompareFunc qcmp, void *arg)
+{
+ for (;;)
+ {
+ // For small arrays use insertion sort
+ if (nelem < QSTHRESH)
+ {
+ for (size_t i = 1; i < nelem; i++)
+ {
+ ITEM *p = base + i;
+ ITEM *q = p - 1;
+ if (qcmp (q, p, arg) > 0)
+ {
+ ITEM t = *p;
+ *p = *q;
+ while (q > base && qcmp (q - 1, &t, arg) > 0)
+ {
+ *q = *(q - 1);
+ --q;
+ }
+ *q = t;
+ }
+ }
+ return;
+ }
+
+ ITEM *last = base + nelem - 1;
+ ITEM *mid = base + nelem / 2;
+ // Sort the first, middle, and last elements
+ ITEM *a1 = base, *a2, *a3;
+ if (qcmp (base, mid, arg) > 0)
+ {
+ if (qcmp (mid, last, arg) > 0)
+ { // l-m-b
+ a2 = last;
+ a3 = last;
+ }
+ else if (qcmp (base, last, arg) > 0)
+ { // l-b-m
+ a2 = mid;
+ a3 = last;
+ }
+ else
+ { // m-b-l
+ a2 = mid;
+ a3 = mid;
+ }
+ }
+ else if (qcmp (mid, last, arg) > 0)
+ {
+ a1 = mid;
+ a3 = last;
+ if (qcmp (base, last, arg) > 0) // m-l-b
+ a2 = base;
+ else // b-l-m
+ a2 = a3;
+ }
+ else // b-m-l
+ a3 = a2 = a1;
+ if (a1 != a2)
+ {
+ ITEM t = *a1;
+ *a1 = *a2;
+ if (a2 != a3)
+ *a2 = *a3;
+ *a3 = t;
+ }
+
+ // Partition
+ ITEM *i = base + 1;
+ ITEM *j = last - 1;
+ for (;;)
+ {
+ while (i < mid && qcmp (i, mid, arg) <= 0)
+ i++;
+ while (j > mid && qcmp (mid, j, arg) <= 0)
+ j--;
+ if (i == j)
+ break;
+ ITEM t = *i;
+ *i = *j;
+ *j = t;
+ if (i == mid)
+ {
+ mid = j;
+ i++;
+ }
+ else if (j == mid)
+ {
+ mid = i;
+ j--;
+ }
+ else
+ {
+ i++;
+ j--;
+ }
+ }
+
+ // Compare two partitions. Do the smaller one by recursion
+ // and loop over the larger one.
+ size_t nleft = mid - base;
+ size_t nright = nelem - nleft - 1;
+ if (nleft <= nright)
+ {
+ qsort (base, nleft, qcmp, arg);
+ base = mid + 1;
+ nelem = nright;
+ }
+ else
+ {
+ qsort (mid + 1, nright, qcmp, arg);
+ nelem = nleft;
+ }
+ }
+}
+
+template<> inline void
+Vector<char*>::destroy ()
+{
+ for (long i = 0; i < count; i++)
+ free (data[i]);
+ count = 0;
+}
+
+template <typename ITEM> inline void
+Vector<ITEM>::destroy ()
+{
+ for (long i = 0; i < count; i++)
+ delete data[i];
+ count = 0;
+}
+
+#endif /* _VEC_H */