]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Expandable arrays of arbitrary element type T are a simple, useful
authorJulian Seward <jseward@acm.org>
Sun, 25 Feb 2007 11:51:13 +0000 (11:51 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 25 Feb 2007 11:51:13 +0000 (11:51 +0000)
abstraction implemented independently in several places in the code
base (bad!).  This commit moves into public view a generic
implementation of it which has been lurking in readxcoff.c for some
time.  Currently nothing uses it.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@6614

coregrind/Makefile.am
coregrind/m_debuginfo/readxcoff.c
coregrind/m_xarray.c [new file with mode: 0644]
coregrind/pub_core_xarray.h [new file with mode: 0644]

index 42f6c05dcdba9d569562f2b79539ce28a675ee5f..578e77db5432355219d6f7c5ef85ed39e6494bcf 100644 (file)
@@ -130,6 +130,7 @@ noinst_HEADERS = \
        pub_core_ume.h          \
        pub_core_vki.h          \
        pub_core_vkiscnums.h    \
+       pub_core_xarray.h       \
        m_coredump/priv_elf.h   \
        m_debuginfo/priv_storage.h      \
        m_debuginfo/priv_readstabs.h    \
@@ -188,6 +189,7 @@ COREGRIND_SOURCES_COMMON = \
        m_ume.c \
        m_vki.c \
        m_vkiscnums.c \
+       m_xarray.c \
        m_aspacemgr/aspacemgr-common.c \
        m_debuginfo/storage.c \
        m_debuginfo/debuginfo.c \
index be1451a253dfb3da58622f6f5f55d8fad79982fa..19943d1a3c16d776fae997103aacc9ed72b93bd0 100644 (file)
 /*--- Read XCOFF format debug info.                        ---*/
 /*------------------------------------------------------------*/
 
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
-
-// priv
-struct _XArray {
-   void* (*alloc) ( SizeT );
-   void (*free) ( void* );
-   Word (*cmpFn) ( void*, void* );
-   Word elemSzB;
-   void* arr;
-   Word usedsize;
-   Word totsize;
-   Bool sorted;
-};
-
-// public
-typedef  void  XArray;
-
-/* Create new XArray, using given allocation and free function, and
-   for elements of the specified size.  Alloc fn must not fail. */
-extern 
-XArray* newXA ( void*(*alloc_fn)(SizeT), 
-                void(*free_fn)(void*),
-                Word elemSzB );
-
-/* Free all memory associated with an XArray. */
-void deleteXA ( XArray* );
-
-/* Set the comparison function for this XArray. */
-void setCmpFnXA ( XArray*, Word (*compar)(void*,void*) );
-
-/* Add an element to an XArray.  Element is copied into the XArray. */
-void addToXA ( XArray*, void* elem );
-
-/* Sort an XArray using its comparison function, if set; else bomb. */
-void sortXA ( XArray* );
-
-/* Lookup (by binary search) 'key' in the array.  Set *first to be the
-   index of the first, and *last to be the index of the last matching
-   value found.  If any values are found, return True, else return
-   False, and don't change *first or *last.  Bomb if the array is not
-   sorted. */
-Bool lookupXA ( XArray*, void* key, Word* first, Word* last );
-
-/* How big is the XArray now? */
-Word sizeXA ( XArray* );
-
-/* Index into the XArray. */
-void* indexXA ( XArray*, Word );
-
-/* Drop the last n elements of an XArray. */
-void dropTailXA ( XArray*, Word );
-
-///////////////////////
-
-XArray* newXA ( void*(*alloc_fn)(SizeT), 
-                void(*free_fn)(void*),
-                Word elemSzB )
-{
-   struct _XArray* xa;
-   vg_assert(alloc_fn);
-   vg_assert(free_fn);
-   vg_assert(elemSzB > 0);
-   xa = alloc_fn( sizeof(struct _XArray) );
-   vg_assert(xa);
-   xa->alloc    = alloc_fn;
-   xa->free     = free_fn;
-   xa->cmpFn    = NULL;
-   xa->elemSzB  = elemSzB;
-   xa->usedsize = 0;
-   xa->totsize  = 0;
-   xa->sorted   = False;
-   xa->arr      = NULL;
-   return xa;
-}
-
-void deleteXA ( XArray* xao )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(xa->free);
-   if (xa->arr);
-      xa->free(xa->arr);
-   xa->free(xa);
-}
-
-void setCmpFnXA ( XArray* xao, Word (*compar)(void*,void*) )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(compar);
-   xa->cmpFn  = compar;
-   xa->sorted = False;
-}
-
-void addToXA ( XArray* xao, void* elem )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(elem);
-   vg_assert(xa->totsize >= 0);
-   vg_assert(xa->usedsize >= 0 && xa->usedsize <= xa->totsize);
-   if (xa->usedsize == xa->totsize) {
-      void* tmp;
-      Word  newsz;
-      if (xa->totsize == 0)
-         vg_assert(!xa->arr);
-      if (xa->totsize > 0)
-         vg_assert(xa->arr);
-      newsz = xa->totsize==0 ? 2 : 2 * xa->totsize;
-      if (0) 
-         VG_(printf)("addToXA: increasing from %ld to %ld\n", 
-                     xa->totsize, newsz);
-      tmp = xa->alloc(newsz * xa->elemSzB);
-      vg_assert(tmp);
-      if (xa->usedsize > 0) 
-         VG_(memcpy)(tmp, xa->arr, xa->usedsize * xa->elemSzB);
-      if (xa->arr)
-         xa->free(xa->arr);
-      xa->arr = tmp;
-      xa->totsize = newsz;
-   }
-   vg_assert(xa->usedsize < xa->totsize);
-   vg_assert(xa->arr);
-   VG_(memcpy)( ((UChar*)xa->arr) + xa->usedsize * xa->elemSzB,
-                elem, xa->elemSzB );
-   xa->usedsize++;
-   xa->sorted = False;
-}
-
-// Generic shell sort.  Like stdlib.h's qsort().
-static void ssort( void* base, Word nmemb, Word size,
-                   Word (*compar)(void*, void*) )
-{
-   Int   incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
-                      9841, 29524, 88573, 265720,
-                      797161, 2391484 };
-   Int   lo = 0;
-   Int   hi = nmemb-1;
-   Int   i, j, h, bigN, hp;
-
-   bigN = hi - lo + 1; if (bigN < 2) return;
-   hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
-
-   #define SORT \
-   for ( ; hp >= 0; hp--) { \
-      h = incs[hp]; \
-      for (i = lo + h; i <= hi; i++) { \
-         ASSIGN(v,0, a,i); \
-         j = i; \
-         while (COMPAR(a,(j-h), v,0) > 0) { \
-            ASSIGN(a,j, a,(j-h)); \
-            j = j - h; \
-            if (j <= (lo + h - 1)) break; \
-         } \
-         ASSIGN(a,j, v,0); \
-      } \
-   }
-
-   // General case
-   {
-      char* a = base;
-      char  v[size];      // will be at least 'size' bytes
-
-      #define ASSIGN(dst, dsti, src, srci) \
-      VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
-
-      #define COMPAR(dst, dsti, src, srci) \
-      compar( &dst[size*(dsti)], &src[size*(srci)] )
-
-      SORT;
-
-      #undef ASSIGN
-      #undef COMPAR
-   }
-   #undef SORT
-}
-
-void sortXA ( XArray* xao )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(xa->cmpFn);
-   ssort( xa->arr, xa->usedsize, xa->elemSzB, xa->cmpFn );
-   xa->sorted = True;
-}
-
-Bool lookupXA ( XArray* xao, void* key, Word* first, Word* last )
-{
-   Word  lo, mid, hi, cres;
-   void* midv;
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(xa->cmpFn);
-   vg_assert(xa->sorted);
-   lo = 0;
-   hi = xa->usedsize-1;
-   while (True) {
-      /* current unsearched space is from lo to hi, inclusive. */
-      if (lo > hi) return False; /* not found */
-      mid  = (lo + hi) / 2;
-      midv = indexXA( xa, mid );
-      cres = xa->cmpFn( key, midv );
-      if (cres < 0)  { hi = mid-1; continue; }
-      if (cres > 0)  { lo = mid+1; continue; }
-      /* Found it, at mid.  See how far we can expand this. */
-      vg_assert(xa->cmpFn( key, indexXA(xa, lo) ) >= 0);
-      vg_assert(xa->cmpFn( key, indexXA(xa, hi) ) <= 0);
-      *first = *last = mid;
-      while (*first > 0 
-             && 0 == xa->cmpFn( key, indexXA(xa, (*first)-1)))
-         (*first)--;
-      while (*last < xa->usedsize-1
-             && 0 == xa->cmpFn( key, indexXA(xa, (*last)+1)))
-         (*last)++;
-      return True;
-   }
-}
-
-Word sizeXA ( XArray* xao )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   return xa->usedsize;
-}
-
-void* indexXA ( XArray* xao, Word n )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(n >= 0);
-   vg_assert(n < xa->usedsize);
-   return ((char*)xa->arr) + n * xa->elemSzB;
-}
-
-void dropTailXA ( XArray* xao, Word n )
-{
-   struct _XArray* xa = (struct _XArray*)xao;
-   vg_assert(xa);
-   vg_assert(n >= 0);
-   vg_assert(n <= xa->usedsize);
-   xa->usedsize -= n;
-}
-
-/////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////
 
 /* COFF uses a strange way to represent symbol names.  A symbol is an
    eight-byte field.
diff --git a/coregrind/m_xarray.c b/coregrind/m_xarray.c
new file mode 100644 (file)
index 0000000..b8e11d3
--- /dev/null
@@ -0,0 +1,252 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An expandable array implementation.               m_xarray.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2007-2007 OpenWorks LLP
+      info@open-works.co.uk
+
+   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 2 of the
+   License, 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, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_xarray.h"    /* self */
+
+
+/* See pub_core_xarray.h for details of what this is all about. */
+
+struct _XArray {
+   void* (*alloc) ( SizeT );        /* alloc fn (nofail) */
+   void  (*free) ( void* );         /* free fn */
+   Word  (*cmpFn) ( void*, void* ); /* cmp fn (may be NULL) */
+   Word  elemSzB;   /* element size in bytes */
+   void* arr;       /* pointer to elements */
+   Word  usedsizeE; /* # used elements in arr */
+   Word  totsizeE;  /* max size of arr, in elements */
+   Bool  sorted;    /* is it sorted? */
+};
+
+
+XArray* VG_(newXA) ( void*(*alloc_fn)(SizeT), 
+                     void(*free_fn)(void*),
+                     Word elemSzB )
+{
+   struct _XArray* xa;
+   /* Implementation relies on Word being signed and (possibly)
+      on SizeT being unsigned. */
+   vg_assert( sizeof(Word) == sizeof(void*) );
+   vg_assert( ((Word)(-1)) < ((Word)(0)) );
+   vg_assert( ((SizeT)(-1)) > ((SizeT)(0)) );
+   /* check user-supplied info .. */
+   vg_assert(alloc_fn);
+   vg_assert(free_fn);
+   vg_assert(elemSzB > 0);
+   xa = alloc_fn( sizeof(struct _XArray) );
+   vg_assert(xa);
+   xa->alloc     = alloc_fn;
+   xa->free      = free_fn;
+   xa->cmpFn     = NULL;
+   xa->elemSzB   = elemSzB;
+   xa->usedsizeE = 0;
+   xa->totsizeE  = 0;
+   xa->sorted    = False;
+   xa->arr       = NULL;
+   return xa;
+}
+
+void VG_(deleteXA) ( XArray* xao )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(xa->free);
+   if (xa->arr);
+      xa->free(xa->arr);
+   xa->free(xa);
+}
+
+void VG_(setCmpFnXA) ( XArray* xao, Word (*compar)(void*,void*) )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(compar);
+   xa->cmpFn  = compar;
+   xa->sorted = False;
+}
+
+inline void* VG_(indexXA) ( XArray* xao, Word n )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(n >= 0);
+   vg_assert(n < xa->usedsizeE);
+   return ((char*)xa->arr) + n * xa->elemSzB;
+}
+
+void VG_(addToXA) ( XArray* xao, void* elem )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(elem);
+   vg_assert(xa->totsizeE >= 0);
+   vg_assert(xa->usedsizeE >= 0 && xa->usedsizeE <= xa->totsizeE);
+   if (xa->usedsizeE == xa->totsizeE) {
+      void* tmp;
+      Word  newsz;
+      if (xa->totsizeE == 0)
+         vg_assert(!xa->arr);
+      if (xa->totsizeE > 0)
+         vg_assert(xa->arr);
+      newsz = xa->totsizeE==0 ? 2 : 2 * xa->totsizeE;
+      if (0) 
+         VG_(printf)("addToXA: increasing from %ld to %ld\n", 
+                     xa->totsizeE, newsz);
+      tmp = xa->alloc(newsz * xa->elemSzB);
+      vg_assert(tmp);
+      if (xa->usedsizeE > 0) 
+         VG_(memcpy)(tmp, xa->arr, xa->usedsizeE * xa->elemSzB);
+      if (xa->arr)
+         xa->free(xa->arr);
+      xa->arr = tmp;
+      xa->totsizeE = newsz;
+   }
+   vg_assert(xa->usedsizeE < xa->totsizeE);
+   vg_assert(xa->arr);
+   VG_(memcpy)( ((UChar*)xa->arr) + xa->usedsizeE * xa->elemSzB,
+                elem, xa->elemSzB );
+   xa->usedsizeE++;
+   xa->sorted = False;
+}
+
+// Generic shell sort.  Like stdlib.h's qsort().
+static void ssort( void* base, Word nmemb, Word size,
+                   Word (*compar)(void*, void*) )
+{
+   Int   incs[14] = { 1, 4, 13, 40, 121, 364, 1093, 3280,
+                      9841, 29524, 88573, 265720,
+                      797161, 2391484 };
+   Int   lo = 0;
+   Int   hi = nmemb-1;
+   Int   i, j, h, bigN, hp;
+
+   bigN = hi - lo + 1; if (bigN < 2) return;
+   hp = 0; while (hp < 14 && incs[hp] < bigN) hp++; hp--;
+
+   #define SORT \
+   for ( ; hp >= 0; hp--) { \
+      h = incs[hp]; \
+      for (i = lo + h; i <= hi; i++) { \
+         ASSIGN(v,0, a,i); \
+         j = i; \
+         while (COMPAR(a,(j-h), v,0) > 0) { \
+            ASSIGN(a,j, a,(j-h)); \
+            j = j - h; \
+            if (j <= (lo + h - 1)) break; \
+         } \
+         ASSIGN(a,j, v,0); \
+      } \
+   }
+
+   // General case
+   {
+      char* a = base;
+      char  v[size];      // will be at least 'size' bytes
+
+      #define ASSIGN(dst, dsti, src, srci) \
+      VG_(memcpy)( &dst[size*(dsti)], &src[size*(srci)], size );
+
+      #define COMPAR(dst, dsti, src, srci) \
+      compar( &dst[size*(dsti)], &src[size*(srci)] )
+
+      SORT;
+
+      #undef ASSIGN
+      #undef COMPAR
+   }
+   #undef SORT
+}
+
+void VG_(sortXA) ( XArray* xao )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(xa->cmpFn);
+   ssort( xa->arr, xa->usedsizeE, xa->elemSzB, xa->cmpFn );
+   xa->sorted = True;
+}
+
+Bool VG_(lookupXA) ( XArray* xao, void* key, Word* first, Word* last )
+{
+   Word  lo, mid, hi, cres;
+   void* midv;
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(xa->cmpFn);
+   vg_assert(xa->sorted);
+   vg_assert(first);
+   vg_assert(last);
+   lo = 0;
+   hi = xa->usedsizeE-1;
+   while (True) {
+      /* current unsearched space is from lo to hi, inclusive. */
+      if (lo > hi) return False; /* not found */
+      mid  = (lo + hi) / 2;
+      midv = VG_(indexXA)( xa, mid );
+      cres = xa->cmpFn( key, midv );
+      if (cres < 0)  { hi = mid-1; continue; }
+      if (cres > 0)  { lo = mid+1; continue; }
+      /* Found it, at mid.  See how far we can expand this. */
+      vg_assert(xa->cmpFn( key, VG_(indexXA)(xa, lo) ) >= 0);
+      vg_assert(xa->cmpFn( key, VG_(indexXA)(xa, hi) ) <= 0);
+      *first = *last = mid;
+      while (*first > 0 
+             && 0 == xa->cmpFn( key, VG_(indexXA)(xa, (*first)-1)))
+         (*first)--;
+      while (*last < xa->usedsizeE-1
+             && 0 == xa->cmpFn( key, VG_(indexXA)(xa, (*last)+1)))
+         (*last)++;
+      return True;
+   }
+}
+
+Word VG_(sizeXA) ( XArray* xao )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   return xa->usedsizeE;
+}
+
+void VG_(dropTailXA) ( XArray* xao, Word n )
+{
+   struct _XArray* xa = (struct _XArray*)xao;
+   vg_assert(xa);
+   vg_assert(n >= 0);
+   vg_assert(n <= xa->usedsizeE);
+   xa->usedsizeE -= n;
+}
+
+
+/*--------------------------------------------------------------------*/
+/*--- end                                               m_xarray.c ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/pub_core_xarray.h b/coregrind/pub_core_xarray.h
new file mode 100644 (file)
index 0000000..86e1d9a
--- /dev/null
@@ -0,0 +1,95 @@
+
+/*--------------------------------------------------------------------*/
+/*--- An expandable array implementation.        pub_core_xarray.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2007-2007 OpenWorks LLP
+      info@open-works.co.uk
+
+   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 2 of the
+   License, 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, Inc., 59 Temple Place, Suite 330, Boston, MA
+   02111-1307, USA.
+
+   The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_XARRAY_H
+#define __PUB_CORE_XARRAY_H
+
+//--------------------------------------------------------------------
+// PURPOSE: Provides a simple but useful structure, which is an array
+// in which elements can be added at the end.  The array is expanded
+// as needed by multiplying its size by a constant factor (usually 2).
+// This gives amortised O(1) insertion cost, and, following sorting,
+// the usual O(N log N) binary search cost.  Arbitrary element sizes
+// are allowed; the comparison function for sort/lookup can be changed
+// at any time, and duplicates (modulo the comparison function) are
+// allowed.
+//--------------------------------------------------------------------
+
+
+/* It's an abstract type.  Bwaha. */
+typedef  void  XArray;
+
+/* Create new XArray, using given allocation and free function, and
+   for elements of the specified size.  Alloc fn must not fail (that
+   is, if it returns it must have succeeded.) */
+extern XArray* VG_(newXA) ( void*(*alloc_fn)(SizeT), 
+                            void(*free_fn)(void*),
+                            Word elemSzB );
+
+/* Free all memory associated with an XArray. */
+extern void VG_(deleteXA) ( XArray* );
+
+/* Set the comparison function for this XArray.  This clears an
+   internal 'array is sorted' flag, which means you must call sortXA
+   before making further queries with lookupXA. */
+extern void VG_(setCmpFnXA) ( XArray*, Word (*compar)(void*,void*) );
+
+/* Add an element to an XArray.  Element is copied into the XArray. */
+extern void VG_(addToXA) ( XArray*, void* elem );
+
+/* Sort an XArray using its comparison function, if set; else bomb.
+   Probably not a stable sort w.r.t. equal elements module cmpFn. */
+extern void VG_(sortXA) ( XArray* );
+
+/* Lookup (by binary search) 'key' in the array.  Set *first to be the
+   index of the first, and *last to be the index of the last matching
+   value found.  If any values are found, return True, else return
+   False, and don't change *first or *last.  Bomb if the array is not
+   sorted. */
+extern Bool VG_(lookupXA) ( XArray*, void* key, 
+                            /*OUT*/Word* first, /*OUT*/Word* last );
+
+/* How elements are there in this XArray now? */
+extern Word VG_(sizeXA) ( XArray* );
+
+/* Index into the XArray.  Checks bounds and bombs if the index is
+   invalid. */
+extern void* VG_(indexXA) ( XArray*, Word );
+
+/* Drop the last n elements of an XArray.  Bombs if there are less
+   than n elements in the array. */
+extern void VG_(dropTailXA) ( XArray*, Word );
+
+
+#endif   // __PUB_CORE_XARRAY_H
+
+/*--------------------------------------------------------------------*/
+/*--- end                                        pub_core_xarray.h ---*/
+/*--------------------------------------------------------------------*/