Mercurial > hg > xemacs-beta
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); |