comparison src/dynarr.c @ 5125:b5df3737028a ben-lisp-object

merge
author Ben Wing <ben@xemacs.org>
date Wed, 24 Feb 2010 01:58:04 -0600
parents d1247f3cc363 838630c0734f
children 2a462149bd6a
comparison
equal deleted inserted replaced
5124:623d57b7fbe8 5125:b5df3737028a
1 /* Support for dynamic arrays. 1 /* Support for dynamic arrays.
2 Copyright (C) 1993 Sun Microsystems, Inc. 2 Copyright (C) 1993 Sun Microsystems, Inc.
3 Copyright (C) 2002, 2003, 2004 Ben Wing. 3 Copyright (C) 2002, 2003, 2004, 2005, 2010 Ben Wing.
4 4
5 This file is part of XEmacs. 5 This file is part of XEmacs.
6 6
7 XEmacs is free software; you can redistribute it and/or modify it 7 XEmacs is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the 8 under the terms of the GNU General Public License as published by the
96 int Dynarr_length(d) 96 int Dynarr_length(d)
97 [MACRO] Return the number of elements currently in a dynamic array. 97 [MACRO] Return the number of elements currently in a dynamic array.
98 98
99 int Dynarr_largest(d) 99 int Dynarr_largest(d)
100 [MACRO] Return the maximum value that Dynarr_length(d) would 100 [MACRO] Return the maximum value that Dynarr_length(d) would
101 ever have returned. 101 ever have returned. This is used esp. in the redisplay code,
102 which reuses dynarrs for performance reasons.
102 103
103 type Dynarr_at(d, i) 104 type Dynarr_at(d, i)
104 [MACRO] Return the element at the specified index (no bounds checking 105 [MACRO] Return the element at the specified index (no bounds checking
105 done on the index). The element itself is returned, not a pointer 106 done on the index). The element itself is returned, not a pointer
106 to it. 107 to it.
124 */ 125 */
125 126
126 #include <config.h> 127 #include <config.h>
127 #include "lisp.h" 128 #include "lisp.h"
128 129
130 static const struct memory_description const_Ascbyte_ptr_description_1[] = {
131 { XD_ASCII_STRING, 0 },
132 { XD_END }
133 };
134
135 const struct sized_memory_description const_Ascbyte_ptr_description = {
136 sizeof (const Ascbyte *),
137 const_Ascbyte_ptr_description_1
138 };
139
140 static const struct memory_description const_Ascbyte_ptr_dynarr_description_1[] = {
141 XD_DYNARR_DESC (const_Ascbyte_ptr_dynarr, &const_Ascbyte_ptr_description),
142 { XD_END }
143 };
144
145 const struct sized_memory_description const_Ascbyte_ptr_dynarr_description = {
146 sizeof (const_Ascbyte_ptr_dynarr),
147 const_Ascbyte_ptr_dynarr_description_1
148 };
149
150
129 static int Dynarr_min_size = 8; 151 static int Dynarr_min_size = 8;
130 152
131 static void 153 static void
132 Dynarr_realloc (Dynarr *dy, int new_size) 154 Dynarr_realloc (Dynarr *dy, int new_size)
133 { 155 {
134 if (DUMPEDP (dy->base)) 156 if (DUMPEDP (dy->base))
135 { 157 {
136 void *new_base = malloc (new_size * dy->elsize); 158 void *new_base = malloc (new_size * dy->elsize);
137 memcpy (new_base, dy->base, 159 memcpy (new_base, dy->base,
138 (dy->max < new_size ? dy->max : new_size) * dy->elsize); 160 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
161 dy->elsize);
139 dy->base = new_base; 162 dy->base = new_base;
140 } 163 }
141 else 164 else
142 dy->base = xrealloc (dy->base, new_size * dy->elsize); 165 dy->base = xrealloc (dy->base, new_size * dy->elsize);
143 } 166 }
161 { 184 {
162 void *new_base = 185 void *new_base =
163 XPNTR (alloc_sized_lrecord_array (dy->elsize, new_size, dy->lisp_imp)); 186 XPNTR (alloc_sized_lrecord_array (dy->elsize, new_size, dy->lisp_imp));
164 if (dy->base) 187 if (dy->base)
165 memcpy (new_base, dy->base, 188 memcpy (new_base, dy->base,
166 (dy->max < new_size ? dy->max : new_size) * dy->elsize); 189 (Dynarr_max (dy) < new_size ? Dynarr_max (dy) : new_size) *
190 dy->elsize);
167 dy->base = new_base; 191 dy->base = new_base;
168 } 192 }
169 193
170 void * 194 void *
171 Dynarr_lisp_newf (Bytecount elsize, 195 Dynarr_lisp_newf (Bytecount elsize,
186 { 210 {
187 int newsize; 211 int newsize;
188 double multiplier; 212 double multiplier;
189 Dynarr *dy = (Dynarr *) Dynarr_verify (d); 213 Dynarr *dy = (Dynarr *) Dynarr_verify (d);
190 214
191 if (dy->max <= 8) 215 if (Dynarr_max (dy) <= 8)
192 multiplier = 2; 216 multiplier = 2;
193 else 217 else
194 multiplier = 1.5; 218 multiplier = 1.5;
195 219
196 for (newsize = dy->max; newsize < size;) 220 for (newsize = Dynarr_max (dy); newsize < size;)
197 newsize = max (Dynarr_min_size, (int) (multiplier * newsize)); 221 newsize = max (Dynarr_min_size, (int) (multiplier * newsize));
198 222
199 /* Don't do anything if the array is already big enough. */ 223 /* Don't do anything if the array is already big enough. */
200 if (newsize > dy->max) 224 if (newsize > Dynarr_max (dy))
201 { 225 {
202 #ifdef NEW_GC 226 #ifdef NEW_GC
203 if (dy->lisp_imp) 227 if (dy->lisp_imp)
204 Dynarr_lisp_realloc (dy, newsize); 228 Dynarr_lisp_realloc (dy, newsize);
205 else 229 else
206 Dynarr_realloc (dy, newsize); 230 Dynarr_realloc (dy, newsize);
207 #else /* not NEW_GC */ 231 #else /* not NEW_GC */
208 Dynarr_realloc (dy, newsize); 232 Dynarr_realloc (dy, newsize);
209 #endif /* not NEW_GC */ 233 #endif /* not NEW_GC */
210 dy->max = newsize; 234 dy->max_ = newsize;
211 } 235 }
212 } 236 }
213 237
214 /* Add a number of contiguous elements to the array starting at START. */ 238 /* Add a number of contiguous elements to the array starting at START. */
215 void 239 void
216 Dynarr_insert_many (void *d, const void *el, int len, int start) 240 Dynarr_insert_many (void *d, const void *el, int len, int start)
217 { 241 {
218 Dynarr *dy = (Dynarr *) Dynarr_verify (d); 242 Dynarr *dy = Dynarr_verify_mod (d);
219 243
220 Dynarr_resize (dy, dy->cur+len); 244 Dynarr_resize_if (dy, len);
221 #if 0 245
222 /* WTF? We should be catching these problems. */ 246 /* #### This could conceivably be wrong, if code wants to access stuff
223 /* Silently adjust start to be valid. */ 247 between len and largest. */
224 if (start > dy->cur) 248 dynarr_checking_assert (start >= 0 && start <= Dynarr_length (dy));
225 start = dy->cur; 249
226 else if (start < 0) 250 if (start != Dynarr_length (dy))
227 start = 0;
228 #else
229 assert (start >= 0 && start <= dy->cur);
230 #endif
231
232 if (start != dy->cur)
233 { 251 {
234 memmove ((char *) dy->base + (start + len)*dy->elsize, 252 memmove ((char *) dy->base + (start + len)*dy->elsize,
235 (char *) dy->base + start*dy->elsize, 253 (char *) dy->base + start*dy->elsize,
236 (dy->cur - start)*dy->elsize); 254 (Dynarr_length (dy) - start)*dy->elsize);
237 } 255 }
256 /* Some functions call us with a value of 0 to mean "reserve space but
257 don't write into it" */
238 if (el) 258 if (el)
239 memcpy ((char *) dy->base + start*dy->elsize, el, len*dy->elsize); 259 memcpy ((char *) dy->base + start*dy->elsize, el, len*dy->elsize);
240 dy->cur += len; 260
241 261 Dynarr_set_length_1 (dy, Dynarr_length (dy) + len);
242 if (dy->cur > dy->largest) 262 (void) Dynarr_verify_mod (dy);
243 dy->largest = dy->cur;
244 } 263 }
245 264
246 void 265 void
247 Dynarr_delete_many (void *d, int start, int len) 266 Dynarr_delete_many (void *d, int start, int len)
248 { 267 {
249 Dynarr *dy = (Dynarr *) Dynarr_verify (d); 268 Dynarr *dy = Dynarr_verify_mod (d);
250 269
251 assert (start >= 0 && len >= 0 && start + len <= dy->cur); 270 dynarr_checking_assert (start >= 0 && len >= 0 &&
271 start + len <= Dynarr_length (dy));
272
252 memmove ((char *) dy->base + start*dy->elsize, 273 memmove ((char *) dy->base + start*dy->elsize,
253 (char *) dy->base + (start + len)*dy->elsize, 274 (char *) dy->base + (start + len)*dy->elsize,
254 (dy->cur - start - len)*dy->elsize); 275 (Dynarr_length (dy) - start - len)*dy->elsize);
255 dy->cur -= len; 276
277 Dynarr_set_length_1 (dy, Dynarr_length (dy) - len);
278 (void) Dynarr_verify_mod (dy);
256 } 279 }
257 280
258 void 281 void
259 Dynarr_free (void *d) 282 Dynarr_free (void *d)
260 { 283 {
262 285
263 #ifdef NEW_GC 286 #ifdef NEW_GC
264 if (dy->base && !DUMPEDP (dy->base)) 287 if (dy->base && !DUMPEDP (dy->base))
265 { 288 {
266 if (!dy->lisp_imp) 289 if (!dy->lisp_imp)
267 xfree (dy->base, void *); 290 xfree (dy->base);
268 } 291 }
269 if(!DUMPEDP (dy)) 292 if(!DUMPEDP (dy))
270 { 293 {
271 if (!dy->lisp_imp) 294 if (!dy->lisp_imp)
272 xfree (dy, Dynarr *); 295 xfree (dy);
273 } 296 }
274 #else /* not NEW_GC */ 297 #else /* not NEW_GC */
275 if (dy->base && !DUMPEDP (dy->base)) 298 if (dy->base && !DUMPEDP (dy->base))
276 xfree (dy->base, void *); 299 xfree (dy->base);
277 if(!DUMPEDP (dy)) 300 if(!DUMPEDP (dy))
278 xfree (dy, Dynarr *); 301 xfree (dy);
279 #endif /* not NEW_GC */ 302 #endif /* not NEW_GC */
280 } 303 }
281 304
282 #ifdef MEMORY_USAGE_STATS 305 #ifdef MEMORY_USAGE_STATS
283 306
299 memory that malloc() will claim as "requested" was actually 322 memory that malloc() will claim as "requested" was actually
300 requested. */ 323 requested. */
301 324
302 if (dy->base) 325 if (dy->base)
303 { 326 {
304 Bytecount malloc_used = malloced_storage_size (dy->base, 327 Bytecount malloc_used =
305 dy->elsize * dy->max, 0); 328 malloced_storage_size (dy->base, dy->elsize * Dynarr_max (dy), 0);
306 /* #### This may or may not be correct. Some Dynarrs would 329 /* #### This may or may not be correct. Some Dynarrs would
307 prefer that we use dy->cur instead of dy->largest here. */ 330 prefer that we use dy->len instead of dy->largest here. */
308 Bytecount was_requested = dy->elsize * dy->largest; 331 Bytecount was_requested = dy->elsize * Dynarr_largest (dy);
309 Bytecount dynarr_overhead = dy->elsize * (dy->max - dy->largest); 332 Bytecount dynarr_overhead =
333 dy->elsize * (Dynarr_max (dy) - Dynarr_largest (dy));
310 334
311 total += malloc_used; 335 total += malloc_used;
312 stats->was_requested += was_requested; 336 stats->was_requested += was_requested;
313 stats->dynarr_overhead += dynarr_overhead; 337 stats->dynarr_overhead += dynarr_overhead;
314 /* And the remainder must be malloc overhead. */ 338 /* And the remainder must be malloc overhead. */
351 if (Dynarr_length (stack_like_free_list) > 0) 375 if (Dynarr_length (stack_like_free_list) > 0)
352 this_one = Dynarr_pop (stack_like_free_list); 376 this_one = Dynarr_pop (stack_like_free_list);
353 else 377 else
354 this_one = Dynarr_new (char); 378 this_one = Dynarr_new (char);
355 Dynarr_add (stack_like_in_use_list, this_one); 379 Dynarr_add (stack_like_in_use_list, this_one);
356 Dynarr_resize (this_one, size); 380 Dynarr_reset (this_one);
357 return Dynarr_atp (this_one, 0); 381 Dynarr_add_many (this_one, 0, size);
382 return Dynarr_begin (this_one);
358 } 383 }
359 384
360 void 385 void
361 stack_like_free (void *val) 386 stack_like_free (void *val)
362 { 387 {
364 assert (len > 0); 389 assert (len > 0);
365 /* The vast majority of times, we will be called in a last-in first-out 390 /* The vast majority of times, we will be called in a last-in first-out
366 order, and the item at the end of the list will be the one we're 391 order, and the item at the end of the list will be the one we're
367 looking for, so just check for this first and avoid any function 392 looking for, so just check for this first and avoid any function
368 calls. */ 393 calls. */
369 if (Dynarr_atp (Dynarr_at (stack_like_in_use_list, len - 1), 0) == val) 394 if (Dynarr_begin (Dynarr_at (stack_like_in_use_list, len - 1)) == val)
370 { 395 {
371 char_dynarr *this_one = Dynarr_pop (stack_like_in_use_list); 396 char_dynarr *this_one = Dynarr_pop (stack_like_in_use_list);
372 Dynarr_add (stack_like_free_list, this_one); 397 Dynarr_add (stack_like_free_list, this_one);
373 } 398 }
374 else 399 else
375 { 400 {
376 /* Find the item and delete it. */ 401 /* Find the item and delete it. */
377 int i; 402 int i;
378 assert (len >= 2); 403 assert (len >= 2);
379 for (i = len - 2; i >= 0; i--) 404 for (i = len - 2; i >= 0; i--)
380 if (Dynarr_atp (Dynarr_at (stack_like_in_use_list, i), 0) == 405 if (Dynarr_begin (Dynarr_at (stack_like_in_use_list, i)) ==
381 val) 406 val)
382 { 407 {
383 char_dynarr *this_one = Dynarr_at (stack_like_in_use_list, i); 408 char_dynarr *this_one = Dynarr_at (stack_like_in_use_list, i);
384 Dynarr_add (stack_like_free_list, this_one); 409 Dynarr_add (stack_like_free_list, this_one);
385 Dynarr_delete (stack_like_in_use_list, i); 410 Dynarr_delete (stack_like_in_use_list, i);