2 /*--------------------------------------------------------------------*/
3 /*--- An expandable array implementation. m_xarray.h ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2007-2010 OpenWorks LLP
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_libcbase.h"
33 #include "pub_core_libcassert.h"
34 #include "pub_core_libcprint.h"
35 #include "pub_core_xarray.h" /* self */
38 /* See pub_tool_xarray.h for details of what this is all about. */
41 void* (*alloc) ( HChar*, SizeT ); /* alloc fn (nofail) */
42 HChar* cc; /* cost centre for alloc */
43 void (*free) ( void* ); /* free fn */
44 Int (*cmpFn) ( void*, void* ); /* cmp fn (may be NULL) */
45 Word elemSzB; /* element size in bytes */
46 void* arr; /* pointer to elements */
47 Word usedsizeE; /* # used elements in arr */
48 Word totsizeE; /* max size of arr, in elements */
49 Bool sorted; /* is it sorted? */
53 XArray* VG_(newXA) ( void*(*alloc_fn)(HChar*,SizeT),
55 void(*free_fn)(void*),
59 /* Implementation relies on Word being signed and (possibly)
60 on SizeT being unsigned. */
61 vg_assert( sizeof(Word) == sizeof(void*) );
62 vg_assert( ((Word)(-1)) < ((Word)(0)) );
63 vg_assert( ((SizeT)(-1)) > ((SizeT)(0)) );
64 /* check user-supplied info .. */
67 vg_assert(elemSzB > 0);
68 xa = alloc_fn( cc, sizeof(struct _XArray) );
74 xa->elemSzB = elemSzB;
82 XArray* VG_(cloneXA)( HChar* cc, XArray* xao )
84 struct _XArray* xa = (struct _XArray*)xao;
90 vg_assert(xa->elemSzB >= 1);
91 nyu_cc = cc ? cc : xa->cc;
92 nyu = xa->alloc( nyu_cc, sizeof(struct _XArray) );
95 /* Copy everything verbatim ... */
98 /* ... except we have to clone the contents-array */
100 /* Restrict the total size of the new array to its current
101 actual size. That means we don't waste space copying the
102 unused tail of the original. The tradeoff is that it
103 guarantees we will have to resize the child if even one more
104 element is later added to it, unfortunately. */
105 nyu->totsizeE = nyu->usedsizeE;
106 /* and allocate .. */
107 nyu->arr = nyu->alloc( nyu->cc, nyu->totsizeE * nyu->elemSzB );
112 VG_(memcpy)( nyu->arr, xa->arr, nyu->totsizeE * nyu->elemSzB );
118 void VG_(deleteXA) ( XArray* xao )
120 struct _XArray* xa = (struct _XArray*)xao;
128 void VG_(setCmpFnXA) ( XArray* xao, Int (*compar)(void*,void*) )
130 struct _XArray* xa = (struct _XArray*)xao;
137 inline void* VG_(indexXA) ( XArray* xao, Word n )
139 struct _XArray* xa = (struct _XArray*)xao;
142 vg_assert(n < xa->usedsizeE);
143 return ((char*)xa->arr) + n * xa->elemSzB;
146 static inline void ensureSpaceXA ( struct _XArray* xa )
148 if (xa->usedsizeE == xa->totsizeE) {
151 if (xa->totsizeE == 0)
153 if (xa->totsizeE > 0)
155 if (xa->totsizeE == 0) {
156 /* No point in having tiny (eg) 2-byte allocations for the
157 element array, since all allocs are rounded up to 8 anyway.
158 Hence increase the initial array size for tiny elements in
159 an attempt to avoid reallocations of size 2, 4, 8 if the
160 array does start to fill up. */
161 if (xa->elemSzB == 1) newsz = 8;
162 else if (xa->elemSzB == 2) newsz = 4;
165 newsz = 2 + (3 * xa->totsizeE) / 2; /* 2 * xa->totsizeE; */
167 if (0 && xa->totsizeE >= 10000)
168 VG_(printf)("addToXA: increasing from %ld to %ld\n",
169 xa->totsizeE, newsz);
170 tmp = xa->alloc(xa->cc, newsz * xa->elemSzB);
172 if (xa->usedsizeE > 0)
173 VG_(memcpy)(tmp, xa->arr, xa->usedsizeE * xa->elemSzB);
177 xa->totsizeE = newsz;
181 Word VG_(addToXA) ( XArray* xao, void* elem )
183 struct _XArray* xa = (struct _XArray*)xao;
186 vg_assert(xa->totsizeE >= 0);
187 vg_assert(xa->usedsizeE >= 0 && xa->usedsizeE <= xa->totsizeE);
189 vg_assert(xa->usedsizeE < xa->totsizeE);
191 VG_(memcpy)( ((UChar*)xa->arr) + xa->usedsizeE * xa->elemSzB,
195 return xa->usedsizeE-1;
198 Word VG_(addBytesToXA) ( XArray* xao, void* bytesV, Word nbytes )
201 struct _XArray* xa = (struct _XArray*)xao;
203 vg_assert(xa->elemSzB == 1);
204 vg_assert(nbytes >= 0);
205 vg_assert(xa->totsizeE >= 0);
206 vg_assert(xa->usedsizeE >= 0 && xa->usedsizeE <= xa->totsizeE);
208 for (i = 0; i < nbytes; i++) {
210 vg_assert(xa->usedsizeE < xa->totsizeE);
212 * (((UChar*)xa->arr) + xa->usedsizeE) = ((UChar*)bytesV)[i];
219 void VG_(sortXA) ( XArray* xao )
221 struct _XArray* xa = (struct _XArray*)xao;
223 vg_assert(xa->cmpFn);
224 VG_(ssort)( xa->arr, xa->usedsizeE, xa->elemSzB, xa->cmpFn );
228 Bool VG_(lookupXA_UNSAFE) ( XArray* xao, void* key,
229 /*OUT*/Word* first, /*OUT*/Word* last,
230 Int(*cmpFn)(void*,void*) )
232 Word lo, mid, hi, cres;
234 struct _XArray* xa = (struct _XArray*)xao;
239 hi = xa->usedsizeE-1;
241 /* current unsearched space is from lo to hi, inclusive. */
242 if (lo > hi) return False; /* not found */
244 midv = VG_(indexXA)( xa, mid );
245 cres = cmpFn( key, midv );
246 if (cres < 0) { hi = mid-1; continue; }
247 if (cres > 0) { lo = mid+1; continue; }
248 /* Found it, at mid. See how far we can expand this. */
249 vg_assert(cmpFn( key, VG_(indexXA)(xa, lo) ) >= 0);
250 vg_assert(cmpFn( key, VG_(indexXA)(xa, hi) ) <= 0);
251 *first = *last = mid;
253 && 0 == cmpFn( key, VG_(indexXA)(xa, (*first)-1)))
255 while (*last < xa->usedsizeE-1
256 && 0 == cmpFn( key, VG_(indexXA)(xa, (*last)+1)))
262 Bool VG_(lookupXA) ( XArray* xao, void* key,
263 /*OUT*/Word* first, /*OUT*/Word* last )
265 struct _XArray* xa = (struct _XArray*)xao;
267 vg_assert(xa->cmpFn);
268 vg_assert(xa->sorted);
269 return VG_(lookupXA_UNSAFE)(xao, key, first, last, xa->cmpFn);
272 Word VG_(sizeXA) ( XArray* xao )
274 struct _XArray* xa = (struct _XArray*)xao;
276 return xa->usedsizeE;
279 void VG_(dropTailXA) ( XArray* xao, Word n )
281 struct _XArray* xa = (struct _XArray*)xao;
284 vg_assert(n <= xa->usedsizeE);
288 void VG_(dropHeadXA) ( XArray* xao, Word n )
290 struct _XArray* xa = (struct _XArray*)xao;
293 vg_assert(n <= xa->usedsizeE);
297 if (n == xa->usedsizeE) {
302 vg_assert(xa->usedsizeE - n > 0);
303 VG_(memcpy)( (char*)xa->arr,
304 ((char*)xa->arr) + n * xa->elemSzB,
305 (xa->usedsizeE - n) * xa->elemSzB );
309 void VG_(getContentsXA_UNSAFE)( XArray* xao,
313 struct _XArray* xa = (struct _XArray*)xao;
315 *ctsP = (void*)xa->arr;
316 *usedP = xa->usedsizeE;
319 /* --------- Printeffery --------- */
321 static void add_char_to_XA ( HChar c, void* opaque )
323 XArray* dst = (XArray*)opaque;
324 (void) VG_(addBytesToXA)( dst, &c, 1 );
327 void VG_(xaprintf)( XArray* dst, const HChar* format, ... )
330 va_start(vargs, format);
331 VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs );
336 void VG_(xaprintf_no_f_c)( XArray* dst, const HChar* format, ... )
339 va_start(vargs, format);
340 VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs );
345 /*--------------------------------------------------------------------*/
346 /*--- end m_xarray.c ---*/
347 /*--------------------------------------------------------------------*/