blob: cdcf978615128e3dd5906ab1f7dc12a599be9809 [file] [log] [blame]
sewardjd864eb92007-02-25 11:51:13 +00001
2/*--------------------------------------------------------------------*/
3/*--- An expandable array implementation. m_xarray.h ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
sewardj9eecbbb2010-05-03 21:37:12 +000010 Copyright (C) 2007-2010 OpenWorks LLP
sewardjd864eb92007-02-25 11:51:13 +000011 info@open-works.co.uk
12
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.
17
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.
22
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
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
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 */
36
37
sewardj7df15152007-02-25 15:04:40 +000038/* See pub_tool_xarray.h for details of what this is all about. */
sewardjd864eb92007-02-25 11:51:13 +000039
40struct _XArray {
sewardj9c606bd2008-09-18 18:12:50 +000041 void* (*alloc) ( HChar*, SizeT ); /* alloc fn (nofail) */
42 HChar* cc; /* cost centre for alloc */
sewardjd864eb92007-02-25 11:51:13 +000043 void (*free) ( void* ); /* free fn */
njnb4cfa2f2007-03-28 01:27:05 +000044 Int (*cmpFn) ( void*, void* ); /* cmp fn (may be NULL) */
sewardjd864eb92007-02-25 11:51:13 +000045 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? */
50};
51
52
sewardj9c606bd2008-09-18 18:12:50 +000053XArray* VG_(newXA) ( void*(*alloc_fn)(HChar*,SizeT),
54 HChar* cc,
sewardjd864eb92007-02-25 11:51:13 +000055 void(*free_fn)(void*),
56 Word elemSzB )
57{
58 struct _XArray* xa;
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 .. */
65 vg_assert(alloc_fn);
66 vg_assert(free_fn);
67 vg_assert(elemSzB > 0);
sewardj9c606bd2008-09-18 18:12:50 +000068 xa = alloc_fn( cc, sizeof(struct _XArray) );
sewardjd864eb92007-02-25 11:51:13 +000069 vg_assert(xa);
70 xa->alloc = alloc_fn;
sewardj9c606bd2008-09-18 18:12:50 +000071 xa->cc = cc;
sewardjd864eb92007-02-25 11:51:13 +000072 xa->free = free_fn;
73 xa->cmpFn = NULL;
74 xa->elemSzB = elemSzB;
75 xa->usedsizeE = 0;
76 xa->totsizeE = 0;
77 xa->sorted = False;
78 xa->arr = NULL;
79 return xa;
80}
81
sewardj9c606bd2008-09-18 18:12:50 +000082XArray* VG_(cloneXA)( HChar* cc, XArray* xao )
sewardjb8b79ad2008-03-03 01:35:41 +000083{
84 struct _XArray* xa = (struct _XArray*)xao;
85 struct _XArray* nyu;
sewardj9c606bd2008-09-18 18:12:50 +000086 HChar* nyu_cc;
sewardjb8b79ad2008-03-03 01:35:41 +000087 vg_assert(xa);
88 vg_assert(xa->alloc);
89 vg_assert(xa->free);
90 vg_assert(xa->elemSzB >= 1);
sewardj9c606bd2008-09-18 18:12:50 +000091 nyu_cc = cc ? cc : xa->cc;
92 nyu = xa->alloc( nyu_cc, sizeof(struct _XArray) );
sewardjb8b79ad2008-03-03 01:35:41 +000093 if (!nyu)
94 return NULL;
95 /* Copy everything verbatim ... */
96 *nyu = *xa;
sewardj9c606bd2008-09-18 18:12:50 +000097 nyu->cc = nyu_cc;
sewardjb8b79ad2008-03-03 01:35:41 +000098 /* ... except we have to clone the contents-array */
99 if (nyu->arr) {
sewardj7db115a2008-08-22 23:16:06 +0000100 /* 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 .. */
sewardj9c606bd2008-09-18 18:12:50 +0000107 nyu->arr = nyu->alloc( nyu->cc, nyu->totsizeE * nyu->elemSzB );
sewardjb8b79ad2008-03-03 01:35:41 +0000108 if (!nyu->arr) {
109 nyu->free(nyu);
110 return NULL;
111 }
112 VG_(memcpy)( nyu->arr, xa->arr, nyu->totsizeE * nyu->elemSzB );
113 }
114 /* We're done! */
115 return nyu;
116}
117
sewardjd864eb92007-02-25 11:51:13 +0000118void VG_(deleteXA) ( XArray* xao )
119{
120 struct _XArray* xa = (struct _XArray*)xao;
121 vg_assert(xa);
122 vg_assert(xa->free);
sewardje783ceb2007-08-28 05:19:16 +0000123 if (xa->arr)
sewardjd864eb92007-02-25 11:51:13 +0000124 xa->free(xa->arr);
125 xa->free(xa);
126}
127
njnb4cfa2f2007-03-28 01:27:05 +0000128void VG_(setCmpFnXA) ( XArray* xao, Int (*compar)(void*,void*) )
sewardjd864eb92007-02-25 11:51:13 +0000129{
130 struct _XArray* xa = (struct _XArray*)xao;
131 vg_assert(xa);
132 vg_assert(compar);
133 xa->cmpFn = compar;
134 xa->sorted = False;
135}
136
137inline void* VG_(indexXA) ( XArray* xao, Word n )
138{
139 struct _XArray* xa = (struct _XArray*)xao;
140 vg_assert(xa);
141 vg_assert(n >= 0);
142 vg_assert(n < xa->usedsizeE);
143 return ((char*)xa->arr) + n * xa->elemSzB;
144}
145
sewardjb8b79ad2008-03-03 01:35:41 +0000146static inline void ensureSpaceXA ( struct _XArray* xa )
sewardjd864eb92007-02-25 11:51:13 +0000147{
sewardjd864eb92007-02-25 11:51:13 +0000148 if (xa->usedsizeE == xa->totsizeE) {
149 void* tmp;
150 Word newsz;
151 if (xa->totsizeE == 0)
152 vg_assert(!xa->arr);
153 if (xa->totsizeE > 0)
154 vg_assert(xa->arr);
sewardjb8b79ad2008-03-03 01:35:41 +0000155 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;
163 else newsz = 2;
164 } else {
sewardjf98e1c02008-10-25 16:22:41 +0000165 newsz = 2 + (3 * xa->totsizeE) / 2; /* 2 * xa->totsizeE; */
sewardjb8b79ad2008-03-03 01:35:41 +0000166 }
sewardj7db115a2008-08-22 23:16:06 +0000167 if (0 && xa->totsizeE >= 10000)
sewardjd864eb92007-02-25 11:51:13 +0000168 VG_(printf)("addToXA: increasing from %ld to %ld\n",
169 xa->totsizeE, newsz);
sewardj9c606bd2008-09-18 18:12:50 +0000170 tmp = xa->alloc(xa->cc, newsz * xa->elemSzB);
sewardjd864eb92007-02-25 11:51:13 +0000171 vg_assert(tmp);
172 if (xa->usedsizeE > 0)
173 VG_(memcpy)(tmp, xa->arr, xa->usedsizeE * xa->elemSzB);
174 if (xa->arr)
175 xa->free(xa->arr);
176 xa->arr = tmp;
177 xa->totsizeE = newsz;
178 }
sewardjb8b79ad2008-03-03 01:35:41 +0000179}
180
sewardjbee43c12008-08-19 08:57:49 +0000181Word VG_(addToXA) ( XArray* xao, void* elem )
sewardjb8b79ad2008-03-03 01:35:41 +0000182{
183 struct _XArray* xa = (struct _XArray*)xao;
184 vg_assert(xa);
185 vg_assert(elem);
186 vg_assert(xa->totsizeE >= 0);
187 vg_assert(xa->usedsizeE >= 0 && xa->usedsizeE <= xa->totsizeE);
188 ensureSpaceXA( xa );
sewardjd864eb92007-02-25 11:51:13 +0000189 vg_assert(xa->usedsizeE < xa->totsizeE);
190 vg_assert(xa->arr);
191 VG_(memcpy)( ((UChar*)xa->arr) + xa->usedsizeE * xa->elemSzB,
192 elem, xa->elemSzB );
193 xa->usedsizeE++;
194 xa->sorted = False;
sewardj0f631482007-02-27 16:40:53 +0000195 return xa->usedsizeE-1;
sewardjd864eb92007-02-25 11:51:13 +0000196}
197
sewardjbee43c12008-08-19 08:57:49 +0000198Word VG_(addBytesToXA) ( XArray* xao, void* bytesV, Word nbytes )
sewardjb8b79ad2008-03-03 01:35:41 +0000199{
sewardjbee43c12008-08-19 08:57:49 +0000200 Word r, i;
sewardjb8b79ad2008-03-03 01:35:41 +0000201 struct _XArray* xa = (struct _XArray*)xao;
202 vg_assert(xa);
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);
207 r = xa->usedsizeE;
208 for (i = 0; i < nbytes; i++) {
209 ensureSpaceXA( xa );
210 vg_assert(xa->usedsizeE < xa->totsizeE);
211 vg_assert(xa->arr);
212 * (((UChar*)xa->arr) + xa->usedsizeE) = ((UChar*)bytesV)[i];
213 xa->usedsizeE++;
214 }
215 xa->sorted = False;
216 return r;
217}
218
sewardjd864eb92007-02-25 11:51:13 +0000219void VG_(sortXA) ( XArray* xao )
220{
221 struct _XArray* xa = (struct _XArray*)xao;
222 vg_assert(xa);
223 vg_assert(xa->cmpFn);
njnb4cfa2f2007-03-28 01:27:05 +0000224 VG_(ssort)( xa->arr, xa->usedsizeE, xa->elemSzB, xa->cmpFn );
sewardjd864eb92007-02-25 11:51:13 +0000225 xa->sorted = True;
226}
227
sewardje2253bf2009-07-24 08:11:39 +0000228Bool VG_(lookupXA_UNSAFE) ( XArray* xao, void* key,
229 /*OUT*/Word* first, /*OUT*/Word* last,
230 Int(*cmpFn)(void*,void*) )
sewardjd864eb92007-02-25 11:51:13 +0000231{
232 Word lo, mid, hi, cres;
233 void* midv;
234 struct _XArray* xa = (struct _XArray*)xao;
235 vg_assert(xa);
sewardjd864eb92007-02-25 11:51:13 +0000236 vg_assert(first);
237 vg_assert(last);
238 lo = 0;
239 hi = xa->usedsizeE-1;
240 while (True) {
241 /* current unsearched space is from lo to hi, inclusive. */
242 if (lo > hi) return False; /* not found */
243 mid = (lo + hi) / 2;
244 midv = VG_(indexXA)( xa, mid );
sewardje2253bf2009-07-24 08:11:39 +0000245 cres = cmpFn( key, midv );
sewardjd864eb92007-02-25 11:51:13 +0000246 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. */
sewardje2253bf2009-07-24 08:11:39 +0000249 vg_assert(cmpFn( key, VG_(indexXA)(xa, lo) ) >= 0);
250 vg_assert(cmpFn( key, VG_(indexXA)(xa, hi) ) <= 0);
sewardjd864eb92007-02-25 11:51:13 +0000251 *first = *last = mid;
252 while (*first > 0
sewardje2253bf2009-07-24 08:11:39 +0000253 && 0 == cmpFn( key, VG_(indexXA)(xa, (*first)-1)))
sewardjd864eb92007-02-25 11:51:13 +0000254 (*first)--;
255 while (*last < xa->usedsizeE-1
sewardje2253bf2009-07-24 08:11:39 +0000256 && 0 == cmpFn( key, VG_(indexXA)(xa, (*last)+1)))
sewardjd864eb92007-02-25 11:51:13 +0000257 (*last)++;
258 return True;
259 }
260}
261
sewardje2253bf2009-07-24 08:11:39 +0000262Bool VG_(lookupXA) ( XArray* xao, void* key,
263 /*OUT*/Word* first, /*OUT*/Word* last )
264{
265 struct _XArray* xa = (struct _XArray*)xao;
266 vg_assert(xa);
267 vg_assert(xa->cmpFn);
268 vg_assert(xa->sorted);
269 return VG_(lookupXA_UNSAFE)(xao, key, first, last, xa->cmpFn);
270}
271
sewardjd864eb92007-02-25 11:51:13 +0000272Word VG_(sizeXA) ( XArray* xao )
273{
274 struct _XArray* xa = (struct _XArray*)xao;
275 vg_assert(xa);
276 return xa->usedsizeE;
277}
278
279void VG_(dropTailXA) ( XArray* xao, Word n )
280{
281 struct _XArray* xa = (struct _XArray*)xao;
282 vg_assert(xa);
283 vg_assert(n >= 0);
284 vg_assert(n <= xa->usedsizeE);
285 xa->usedsizeE -= n;
286}
287
sewardje2253bf2009-07-24 08:11:39 +0000288void VG_(dropHeadXA) ( XArray* xao, Word n )
289{
290 struct _XArray* xa = (struct _XArray*)xao;
291 vg_assert(xa);
292 vg_assert(n >= 0);
293 vg_assert(n <= xa->usedsizeE);
294 if (n == 0) {
295 return;
296 }
297 if (n == xa->usedsizeE) {
298 xa->usedsizeE = 0;
299 return;
300 }
301 vg_assert(n > 0);
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 );
306 xa->usedsizeE -= n;
307}
308
sewardj8f8fa172010-05-05 09:23:41 +0000309void VG_(getContentsXA_UNSAFE)( XArray* xao,
310 /*OUT*/void** ctsP,
311 /*OUT*/Word* usedP )
312{
313 struct _XArray* xa = (struct _XArray*)xao;
314 vg_assert(xa);
315 *ctsP = (void*)xa->arr;
316 *usedP = xa->usedsizeE;
317}
318
sewardj588adef2009-08-15 22:41:51 +0000319/* --------- Printeffery --------- */
320
321static void add_char_to_XA ( HChar c, void* opaque )
322{
323 XArray* dst = (XArray*)opaque;
324 (void) VG_(addBytesToXA)( dst, &c, 1 );
325}
326
327void VG_(xaprintf)( XArray* dst, const HChar* format, ... )
328{
329 va_list vargs;
330 va_start(vargs, format);
331 VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs );
332 va_end(vargs);
333}
334
335/* and again .. */
336void VG_(xaprintf_no_f_c)( XArray* dst, const HChar* format, ... )
337{
338 va_list vargs;
339 va_start(vargs, format);
340 VG_(vcbprintf)( add_char_to_XA, (void*)dst, format, vargs );
341 va_end(vargs);
342}
343
sewardjd864eb92007-02-25 11:51:13 +0000344
345/*--------------------------------------------------------------------*/
346/*--- end m_xarray.c ---*/
347/*--------------------------------------------------------------------*/