From: Julian Seward Date: Sun, 25 Feb 2007 11:51:13 +0000 (+0000) Subject: Expandable arrays of arbitrary element type T are a simple, useful X-Git-Tag: svn/VALGRIND_3_3_0~352 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=804c7868a1cc5c142cecf529638b2b094bbdc21c;p=thirdparty%2Fvalgrind.git Expandable arrays of arbitrary element type T are a simple, useful 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 --- diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am index 42f6c05dcd..578e77db54 100644 --- a/coregrind/Makefile.am +++ b/coregrind/Makefile.am @@ -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 \ diff --git a/coregrind/m_debuginfo/readxcoff.c b/coregrind/m_debuginfo/readxcoff.c index be1451a253..19943d1a3c 100644 --- a/coregrind/m_debuginfo/readxcoff.c +++ b/coregrind/m_debuginfo/readxcoff.c @@ -108,252 +108,6 @@ /*--- 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 index 0000000000..b8e11d3295 --- /dev/null +++ b/coregrind/m_xarray.c @@ -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 index 0000000000..86e1d9a7fb --- /dev/null +++ b/coregrind/pub_core_xarray.h @@ -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 ---*/ +/*--------------------------------------------------------------------*/