Mercurial > hg > xemacs-beta
comparison src/rangetab.c @ 5168:cf900a2f1fa3
extract gap array from extents.c, use in range tables
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-03-22 Ben Wing <ben@xemacs.org>
* Makefile.in.in (objs):
* array.c:
* array.c (gap_array_adjust_markers):
* array.c (gap_array_move_gap):
* array.c (gap_array_make_gap):
* array.c (gap_array_insert_els):
* array.c (gap_array_delete_els):
* array.c (gap_array_make_marker):
* array.c (gap_array_delete_marker):
* array.c (gap_array_delete_all_markers):
* array.c (gap_array_clone):
* array.h:
* depend:
* emacs.c (main_1):
* extents.c:
* extents.c (EXTENT_GAP_ARRAY_AT):
* extents.c (extent_list_num_els):
* extents.c (extent_list_locate):
* extents.c (extent_list_at):
* extents.c (extent_list_delete_all):
* extents.c (allocate_extent_list):
* extents.c (syms_of_extents):
* extents.h:
* extents.h (XEXTENT_LIST_MARKER):
* lisp.h:
* rangetab.c:
* rangetab.c (mark_range_table):
* rangetab.c (print_range_table):
* rangetab.c (range_table_equal):
* rangetab.c (range_table_hash):
* rangetab.c (verify_range_table):
* rangetab.c (get_range_table_pos):
* rangetab.c (Fmake_range_table):
* rangetab.c (Fcopy_range_table):
* rangetab.c (Fget_range_table):
* rangetab.c (put_range_table):
* rangetab.c (Fclear_range_table):
* rangetab.c (Fmap_range_table):
* rangetab.c (unified_range_table_bytes_needed):
* rangetab.c (unified_range_table_copy_data):
* rangetab.c (unified_range_table_lookup):
* rangetab.h:
* rangetab.h (struct range_table_entry):
* rangetab.h (struct Lisp_Range_Table):
* rangetab.h (rangetab_gap_array_at):
* symsinit.h:
Rename dynarr.c to array.c. Move gap array from extents.c to array.c.
Extract dynarr, gap array and stack-like malloc into new file array.h.
Rename GAP_ARRAY_NUM_ELS -> gap_array_length(). Add gap_array_at(),
gap_array_atp().
Rewrite range table code to use gap arrays. Make put_range_table()
smarter so that its operation is O(log n) for adding a localized
range.
* gc.c (lispdesc_block_size_1):
Don't ABORT() when two elements are located at the same place.
This will happen with a size-0 gap array -- both parts of the array
(before and after gap) are in the same place.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Mon, 22 Mar 2010 19:12:15 -0500 |
parents | 88bd4f3ef8e4 |
children | 6c6d78781d59 |
comparison
equal
deleted
inserted
replaced
5167:e374ea766cc1 | 5168:cf900a2f1fa3 |
---|---|
88 mark_range_table (Lisp_Object obj) | 88 mark_range_table (Lisp_Object obj) |
89 { | 89 { |
90 Lisp_Range_Table *rt = XRANGE_TABLE (obj); | 90 Lisp_Range_Table *rt = XRANGE_TABLE (obj); |
91 int i; | 91 int i; |
92 | 92 |
93 for (i = 0; i < Dynarr_length (rt->entries); i++) | 93 for (i = 0; i < gap_array_length (rt->entries); i++) |
94 mark_object (Dynarr_at (rt->entries, i).val); | 94 mark_object (rangetab_gap_array_at (rt->entries, i).val); |
95 | 95 |
96 return Qnil; | 96 return Qnil; |
97 } | 97 } |
98 | 98 |
99 static void | 99 static void |
106 if (print_readably) | 106 if (print_readably) |
107 write_fmt_string_lisp (printcharfun, "#s(range-table type %s data (", | 107 write_fmt_string_lisp (printcharfun, "#s(range-table type %s data (", |
108 1, range_table_type_to_symbol (rt->type)); | 108 1, range_table_type_to_symbol (rt->type)); |
109 else | 109 else |
110 write_ascstring (printcharfun, "#<range-table "); | 110 write_ascstring (printcharfun, "#<range-table "); |
111 for (i = 0; i < Dynarr_length (rt->entries); i++) | 111 for (i = 0; i < gap_array_length (rt->entries); i++) |
112 { | 112 { |
113 struct range_table_entry *rte = Dynarr_atp (rt->entries, i); | 113 struct range_table_entry rte = rangetab_gap_array_at (rt->entries, i); |
114 int so, ec; | 114 int so, ec; |
115 if (i > 0) | 115 if (i > 0) |
116 write_ascstring (printcharfun, " "); | 116 write_ascstring (printcharfun, " "); |
117 switch (rt->type) | 117 switch (rt->type) |
118 { | 118 { |
122 case RANGE_START_OPEN_END_CLOSED: so = 1; ec = 1; break; | 122 case RANGE_START_OPEN_END_CLOSED: so = 1; ec = 1; break; |
123 default: ABORT (); so = 0, ec = 0; break; | 123 default: ABORT (); so = 0, ec = 0; break; |
124 } | 124 } |
125 write_fmt_string (printcharfun, "%c%ld %ld%c ", | 125 write_fmt_string (printcharfun, "%c%ld %ld%c ", |
126 print_readably ? '(' : so ? '(' : '[', | 126 print_readably ? '(' : so ? '(' : '[', |
127 (long) (rte->first - so), | 127 (long) (rte.first - so), |
128 (long) (rte->last - ec), | 128 (long) (rte.last - ec), |
129 print_readably ? ')' : ec ? ']' : ')' | 129 print_readably ? ')' : ec ? ']' : ')' |
130 ); | 130 ); |
131 print_internal (rte->val, printcharfun, 1); | 131 print_internal (rte.val, printcharfun, 1); |
132 } | 132 } |
133 if (print_readably) | 133 if (print_readably) |
134 write_ascstring (printcharfun, "))"); | 134 write_ascstring (printcharfun, "))"); |
135 else | 135 else |
136 write_fmt_string (printcharfun, " 0x%x>", LISP_OBJECT_UID (obj)); | 136 write_fmt_string (printcharfun, " 0x%x>", LISP_OBJECT_UID (obj)); |
141 { | 141 { |
142 Lisp_Range_Table *rt1 = XRANGE_TABLE (obj1); | 142 Lisp_Range_Table *rt1 = XRANGE_TABLE (obj1); |
143 Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2); | 143 Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2); |
144 int i; | 144 int i; |
145 | 145 |
146 if (Dynarr_length (rt1->entries) != Dynarr_length (rt2->entries)) | 146 if (gap_array_length (rt1->entries) != gap_array_length (rt2->entries)) |
147 return 0; | 147 return 0; |
148 | 148 |
149 for (i = 0; i < Dynarr_length (rt1->entries); i++) | 149 for (i = 0; i < gap_array_length (rt1->entries); i++) |
150 { | 150 { |
151 struct range_table_entry *rte1 = Dynarr_atp (rt1->entries, i); | 151 struct range_table_entry *rte1 = |
152 struct range_table_entry *rte2 = Dynarr_atp (rt2->entries, i); | 152 rangetab_gap_array_atp (rt1->entries, i); |
153 struct range_table_entry *rte2 = | |
154 rangetab_gap_array_atp (rt2->entries, i); | |
153 | 155 |
154 if (rte1->first != rte2->first | 156 if (rte1->first != rte2->first |
155 || rte1->last != rte2->last | 157 || rte1->last != rte2->last |
156 || !internal_equal_0 (rte1->val, rte2->val, depth + 1, foldcase)) | 158 || !internal_equal_0 (rte1->val, rte2->val, depth + 1, foldcase)) |
157 return 0; | 159 return 0; |
169 static Hashcode | 171 static Hashcode |
170 range_table_hash (Lisp_Object obj, int depth) | 172 range_table_hash (Lisp_Object obj, int depth) |
171 { | 173 { |
172 Lisp_Range_Table *rt = XRANGE_TABLE (obj); | 174 Lisp_Range_Table *rt = XRANGE_TABLE (obj); |
173 int i; | 175 int i; |
174 int size = Dynarr_length (rt->entries); | 176 int size = gap_array_length (rt->entries); |
175 Hashcode hash = size; | 177 Hashcode hash = size; |
176 | 178 |
177 /* approach based on internal_array_hash(). */ | 179 /* approach based on internal_array_hash(). */ |
178 if (size <= 5) | 180 if (size <= 5) |
179 { | 181 { |
180 for (i = 0; i < size; i++) | 182 for (i = 0; i < size; i++) |
181 hash = HASH2 (hash, | 183 hash = HASH2 (hash, |
182 range_table_entry_hash (Dynarr_atp (rt->entries, i), | 184 range_table_entry_hash |
183 depth)); | 185 (rangetab_gap_array_atp (rt->entries, i), depth)); |
184 return hash; | 186 return hash; |
185 } | 187 } |
186 | 188 |
187 /* just pick five elements scattered throughout the array. | 189 /* just pick five elements scattered throughout the array. |
188 A slightly better approach would be to offset by some | 190 A slightly better approach would be to offset by some |
189 noise factor from the points chosen below. */ | 191 noise factor from the points chosen below. */ |
190 for (i = 0; i < 5; i++) | 192 for (i = 0; i < 5; i++) |
191 hash = HASH2 (hash, range_table_entry_hash (Dynarr_atp (rt->entries, | 193 hash = HASH2 (hash, |
192 i*size/5), | 194 range_table_entry_hash |
193 depth)); | 195 (rangetab_gap_array_atp (rt->entries, i*size/5), depth)); |
194 return hash; | 196 return hash; |
195 } | 197 } |
196 | 198 |
197 static const struct memory_description rte_description_1[] = { | 199 static const struct memory_description rte_description_1[] = { |
198 { XD_LISP_OBJECT, offsetof (range_table_entry, val) }, | 200 { XD_LISP_OBJECT, offsetof (range_table_entry, val) }, |
202 static const struct sized_memory_description rte_description = { | 204 static const struct sized_memory_description rte_description = { |
203 sizeof (range_table_entry), | 205 sizeof (range_table_entry), |
204 rte_description_1 | 206 rte_description_1 |
205 }; | 207 }; |
206 | 208 |
207 static const struct memory_description rted_description_1[] = { | 209 static const struct memory_description rtega_description_1[] = { |
208 XD_DYNARR_DESC (range_table_entry_dynarr, &rte_description), | 210 XD_GAP_ARRAY_DESC (&rte_description), |
209 { XD_END } | 211 { XD_END } |
210 }; | 212 }; |
211 | 213 |
212 static const struct sized_memory_description rted_description = { | 214 static const struct sized_memory_description rtega_description = { |
213 sizeof (range_table_entry_dynarr), | 215 0, rtega_description_1 |
214 rted_description_1 | |
215 }; | 216 }; |
216 | 217 |
217 static const struct memory_description range_table_description[] = { | 218 static const struct memory_description range_table_description[] = { |
218 { XD_BLOCK_PTR, offsetof (Lisp_Range_Table, entries), 1, | 219 { XD_BLOCK_PTR, offsetof (Lisp_Range_Table, entries), 1, |
219 { &rted_description } }, | 220 { &rtega_description } }, |
220 { XD_END } | 221 { XD_END } |
221 }; | 222 }; |
222 | 223 |
223 DEFINE_DUMPABLE_LISP_OBJECT ("range-table", range_table, | 224 DEFINE_DUMPABLE_LISP_OBJECT ("range-table", range_table, |
224 mark_range_table, print_range_table, 0, | 225 mark_range_table, print_range_table, 0, |
235 static void | 236 static void |
236 verify_range_table (Lisp_Range_Table *rt) | 237 verify_range_table (Lisp_Range_Table *rt) |
237 { | 238 { |
238 int i; | 239 int i; |
239 | 240 |
240 for (i = 0; i < Dynarr_length (rt->entries); i++) | 241 for (i = 0; i < gap_array_length (rt->entries); i++) |
241 { | 242 { |
242 struct range_table_entry *rte = Dynarr_atp (rt->entries, i); | 243 struct range_table_entry *rte = rangetab_gap_array_atp (rt->entries, i); |
243 assert (rte->last >= rte->first); | 244 assert (rte->last >= rte->first); |
244 if (i > 0) | 245 if (i > 0) |
245 assert (Dynarr_at (rt->entries, i - 1).last <= rte->first); | 246 assert (rangetab_gap_array_at (rt->entries, i - 1).last <= rte->first); |
246 } | 247 } |
247 } | 248 } |
248 | 249 |
249 #else | 250 #else |
250 | 251 |
251 #define verify_range_table(rt) | 252 #define verify_range_table(rt) |
252 | 253 |
253 #endif | 254 #endif |
254 | 255 |
255 /* Look up in a range table without the Dynarr wrapper. | 256 /* Locate the range table entry corresponding to the value POS, and return |
256 Used also by the unified range table format. */ | 257 it. If found, FOUNDP is set to 1 and the return value specifies an entry |
257 | 258 that encloses POS. Otherwise, FOUNDP is set to 0 and the return value |
258 static Lisp_Object | 259 specifies where an entry that encloses POS would be inserted. */ |
259 get_range_table (EMACS_INT pos, int nentries, struct range_table_entry *tab, | 260 |
260 Lisp_Object default_) | 261 static Elemcount |
261 { | 262 get_range_table_pos (Elemcount pos, Elemcount nentries, |
262 int left = 0, right = nentries; | 263 struct range_table_entry *tab, |
264 Elemcount gappos, Elemcount gapsize, | |
265 int *foundp) | |
266 { | |
267 Elemcount left = 0, right = nentries; | |
263 | 268 |
264 /* binary search for the entry. Based on similar code in | 269 /* binary search for the entry. Based on similar code in |
265 extent_list_locate(). */ | 270 extent_list_locate(). */ |
266 while (left != right) | 271 while (left != right) |
267 { | 272 { |
268 /* RIGHT might not point to a valid entry (i.e. it's at the end | 273 /* RIGHT might not point to a valid entry (i.e. it's at the end |
269 of the list), so NEWPOS must round down. */ | 274 of the list), so NEWPOS must round down. */ |
270 int newpos = (left + right) >> 1; | 275 Elemcount newpos = (left + right) >> 1; |
271 struct range_table_entry *entry = tab + newpos; | 276 struct range_table_entry *entry = |
277 tab + GAP_ARRAY_ARRAY_TO_MEMORY_POS_1 (newpos, gappos, gapsize); | |
272 if (pos >= entry->last) | 278 if (pos >= entry->last) |
273 left = newpos + 1; | 279 left = newpos + 1; |
274 else if (pos < entry->first) | 280 else if (pos < entry->first) |
275 right = newpos; | 281 right = newpos; |
276 else | 282 else |
277 return entry->val; | 283 { |
284 *foundp = 1; | |
285 return newpos; | |
286 } | |
287 } | |
288 | |
289 *foundp = 0; | |
290 return left; | |
291 } | |
292 | |
293 /* Look up in a range table without the gap array wrapper. | |
294 Used also by the unified range table format. */ | |
295 | |
296 static Lisp_Object | |
297 get_range_table (Elemcount pos, Elemcount nentries, | |
298 struct range_table_entry *tab, | |
299 Elemcount gappos, Elemcount gapsize, | |
300 Lisp_Object default_) | |
301 { | |
302 int foundp; | |
303 Elemcount entrypos = get_range_table_pos (pos, nentries, tab, gappos, | |
304 gapsize, &foundp); | |
305 if (foundp) | |
306 { | |
307 struct range_table_entry *entry = | |
308 tab + GAP_ARRAY_ARRAY_TO_MEMORY_POS_1 (entrypos, gappos, gapsize); | |
309 return entry->val; | |
278 } | 310 } |
279 | 311 |
280 return default_; | 312 return default_; |
281 } | 313 } |
282 | 314 |
331 */ | 363 */ |
332 (type)) | 364 (type)) |
333 { | 365 { |
334 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (range_table); | 366 Lisp_Object obj = ALLOC_NORMAL_LISP_OBJECT (range_table); |
335 Lisp_Range_Table *rt = XRANGE_TABLE (obj); | 367 Lisp_Range_Table *rt = XRANGE_TABLE (obj); |
336 rt->entries = Dynarr_new (range_table_entry); | 368 rt->entries = make_gap_array (sizeof (struct range_table_entry), 0); |
337 rt->type = range_table_symbol_to_type (type); | 369 rt->type = range_table_symbol_to_type (type); |
338 return obj; | 370 return obj; |
339 } | 371 } |
340 | 372 |
341 DEFUN ("copy-range-table", Fcopy_range_table, 1, 1, 0, /* | 373 DEFUN ("copy-range-table", Fcopy_range_table, 1, 1, 0, /* |
345 */ | 377 */ |
346 (range_table)) | 378 (range_table)) |
347 { | 379 { |
348 Lisp_Range_Table *rt, *rtnew; | 380 Lisp_Range_Table *rt, *rtnew; |
349 Lisp_Object obj; | 381 Lisp_Object obj; |
382 Elemcount i; | |
350 | 383 |
351 CHECK_RANGE_TABLE (range_table); | 384 CHECK_RANGE_TABLE (range_table); |
352 rt = XRANGE_TABLE (range_table); | 385 rt = XRANGE_TABLE (range_table); |
353 | 386 |
354 obj = ALLOC_NORMAL_LISP_OBJECT (range_table); | 387 obj = ALLOC_NORMAL_LISP_OBJECT (range_table); |
355 rtnew = XRANGE_TABLE (obj); | 388 rtnew = XRANGE_TABLE (obj); |
356 rtnew->entries = Dynarr_new (range_table_entry); | 389 rtnew->entries = make_gap_array (sizeof (struct range_table_entry), 0); |
357 rtnew->type = rt->type; | 390 rtnew->type = rt->type; |
358 | 391 |
359 Dynarr_add_many (rtnew->entries, Dynarr_begin (rt->entries), | 392 for (i = 0; i < gap_array_length (rt->entries); i++) |
360 Dynarr_length (rt->entries)); | 393 rtnew->entries = |
394 gap_array_insert_els (rtnew->entries, i, | |
395 rangetab_gap_array_atp (rt->entries, i), 1); | |
361 return obj; | 396 return obj; |
362 } | 397 } |
363 | 398 |
364 DEFUN ("get-range-table", Fget_range_table, 2, 3, 0, /* | 399 DEFUN ("get-range-table", Fget_range_table, 2, 3, 0, /* |
365 Find value for position POS in RANGE-TABLE. | 400 Find value for position POS in RANGE-TABLE. |
372 CHECK_RANGE_TABLE (range_table); | 407 CHECK_RANGE_TABLE (range_table); |
373 rt = XRANGE_TABLE (range_table); | 408 rt = XRANGE_TABLE (range_table); |
374 | 409 |
375 CHECK_INT_COERCE_CHAR (pos); | 410 CHECK_INT_COERCE_CHAR (pos); |
376 | 411 |
377 return get_range_table (XINT (pos), Dynarr_length (rt->entries), | 412 return get_range_table (XINT (pos), gap_array_length (rt->entries), |
378 Dynarr_begin (rt->entries), default_); | 413 gap_array_begin (rt->entries, |
414 struct range_table_entry), | |
415 gap_array_gappos (rt->entries), | |
416 gap_array_gapsize (rt->entries), | |
417 default_); | |
379 } | 418 } |
380 | 419 |
381 static void | 420 static void |
382 external_to_internal_adjust_ends (enum range_table_type type, | 421 external_to_internal_adjust_ends (enum range_table_type type, |
383 EMACS_INT *first, EMACS_INT *last) | 422 EMACS_INT *first, EMACS_INT *last) |
413 EMACS_INT last, Lisp_Object val) | 452 EMACS_INT last, Lisp_Object val) |
414 { | 453 { |
415 int i; | 454 int i; |
416 int insert_me_here = -1; | 455 int insert_me_here = -1; |
417 Lisp_Range_Table *rt = XRANGE_TABLE (table); | 456 Lisp_Range_Table *rt = XRANGE_TABLE (table); |
457 int foundp; | |
418 | 458 |
419 external_to_internal_adjust_ends (rt->type, &first, &last); | 459 external_to_internal_adjust_ends (rt->type, &first, &last); |
420 if (first == last) | 460 if (first == last) |
421 return; | 461 return; |
422 if (first > last) | 462 if (first > last) |
423 /* This will happen if originally first == last and both ends are | 463 /* This will happen if originally first == last and both ends are |
424 open. #### Should we signal an error? */ | 464 open. #### Should we signal an error? */ |
425 return; | 465 return; |
426 | 466 |
467 if (DUMPEDP (rt->entries)) | |
468 rt->entries = gap_array_clone (rt->entries); | |
469 | |
470 i = get_range_table_pos (first, gap_array_length (rt->entries), | |
471 gap_array_begin (rt->entries, | |
472 struct range_table_entry), | |
473 gap_array_gappos (rt->entries), | |
474 gap_array_gapsize (rt->entries), &foundp); | |
475 | |
476 #ifdef ERROR_CHECK_TYPES | |
477 if (foundp) | |
478 { | |
479 if (i < gap_array_length (rt->entries)) | |
480 { | |
481 struct range_table_entry *entry = | |
482 rangetab_gap_array_atp (rt->entries, i); | |
483 assert (first >= entry->first && first < entry->last); | |
484 } | |
485 } | |
486 else | |
487 { | |
488 if (i < gap_array_length (rt->entries)) | |
489 { | |
490 struct range_table_entry *entry = | |
491 rangetab_gap_array_atp (rt->entries, i); | |
492 assert (first < entry->first); | |
493 } | |
494 if (i > 0) | |
495 { | |
496 struct range_table_entry *entry = | |
497 rangetab_gap_array_atp (rt->entries, i - 1); | |
498 assert (first >= entry->last); | |
499 } | |
500 } | |
501 #endif /* ERROR_CHECK_TYPES */ | |
502 | |
503 /* If the beginning of the new range isn't within any existing range, | |
504 it might still be just grazing the end of an end-open range (remember, | |
505 internally all ranges are start-close end-open); so back up one | |
506 so we consider this range. */ | |
507 if (!foundp && i > 0) | |
508 i--; | |
509 | |
427 /* Now insert in the proper place. This gets tricky because | 510 /* Now insert in the proper place. This gets tricky because |
428 we may be overlapping one or more existing ranges and need | 511 we may be overlapping one or more existing ranges and need |
429 to fix them up. */ | 512 to fix them up. */ |
430 | 513 |
431 /* First delete all sections of any existing ranges that overlap | 514 /* First delete all sections of any existing ranges that overlap |
432 the new range. */ | 515 the new range. */ |
433 for (i = 0; i < Dynarr_length (rt->entries); i++) | 516 for (; i < gap_array_length (rt->entries); i++) |
434 { | 517 { |
435 struct range_table_entry *entry = Dynarr_atp (rt->entries, i); | 518 struct range_table_entry *entry = |
519 rangetab_gap_array_atp (rt->entries, i); | |
436 /* We insert before the first range that begins at or after the | 520 /* We insert before the first range that begins at or after the |
437 new range. */ | 521 new range. */ |
438 if (entry->first >= first && insert_me_here < 0) | 522 if (entry->first >= first && insert_me_here < 0) |
439 insert_me_here = i; | 523 insert_me_here = i; |
440 if (entry->last < first) | 524 if (entry->last < first) |
474 | 558 |
475 insert_me_too.first = last; | 559 insert_me_too.first = last; |
476 insert_me_too.last = entry->last; | 560 insert_me_too.last = entry->last; |
477 insert_me_too.val = entry->val; | 561 insert_me_too.val = entry->val; |
478 entry->last = first; | 562 entry->last = first; |
479 Dynarr_insert_many (rt->entries, &insert_me_too, 1, i + 1); | 563 rt->entries = |
564 gap_array_insert_els (rt->entries, i + 1, &insert_me_too, 1); | |
480 } | 565 } |
481 else if (entry->last >= last) | 566 else if (entry->last >= last) |
482 { | 567 { |
483 /* looks like: | 568 /* looks like: |
484 | 569 |
495 entry->first = last; | 580 entry->first = last; |
496 } | 581 } |
497 else | 582 else |
498 { | 583 { |
499 /* existing is entirely within new. */ | 584 /* existing is entirely within new. */ |
500 Dynarr_delete_many (rt->entries, i, 1); | 585 gap_array_delete_els (rt->entries, i, 1); |
501 i--; /* back up since everything shifted one to the left. */ | 586 i--; /* back up since everything shifted one to the left. */ |
502 } | 587 } |
503 } | 588 } |
504 | 589 |
505 /* Someone asked us to delete the range, not insert it. */ | 590 /* Someone asked us to delete the range, not insert it. */ |
516 | 601 |
517 insert_me.first = first; | 602 insert_me.first = first; |
518 insert_me.last = last; | 603 insert_me.last = last; |
519 insert_me.val = val; | 604 insert_me.val = val; |
520 | 605 |
521 Dynarr_insert_many (rt->entries, &insert_me, 1, insert_me_here); | 606 rt->entries = |
607 gap_array_insert_els (rt->entries, insert_me_here, &insert_me, 1); | |
522 } | 608 } |
523 | 609 |
524 /* Now see if we can combine this entry with adjacent ones just | 610 /* Now see if we can combine this entry with adjacent ones just |
525 before or after. */ | 611 before or after. */ |
526 | 612 |
527 if (insert_me_here > 0) | 613 if (insert_me_here > 0) |
528 { | 614 { |
529 struct range_table_entry *entry = Dynarr_atp (rt->entries, | 615 struct range_table_entry *entry = |
530 insert_me_here - 1); | 616 rangetab_gap_array_atp (rt->entries, insert_me_here - 1); |
531 if (EQ (val, entry->val) && entry->last == first) | 617 if (EQ (val, entry->val) && entry->last == first) |
532 { | 618 { |
533 entry->last = last; | 619 entry->last = last; |
534 Dynarr_delete_many (rt->entries, insert_me_here, 1); | 620 gap_array_delete_els (rt->entries, insert_me_here, 1); |
535 insert_me_here--; | 621 insert_me_here--; |
536 /* We have morphed into a larger range. Update our records | 622 /* We have morphed into a larger range. Update our records |
537 in case we also combine with the one after. */ | 623 in case we also combine with the one after. */ |
538 first = entry->first; | 624 first = entry->first; |
539 } | 625 } |
540 } | 626 } |
541 | 627 |
542 if (insert_me_here < Dynarr_length (rt->entries) - 1) | 628 if (insert_me_here < gap_array_length (rt->entries) - 1) |
543 { | 629 { |
544 struct range_table_entry *entry = Dynarr_atp (rt->entries, | 630 struct range_table_entry *entry = |
545 insert_me_here + 1); | 631 rangetab_gap_array_atp (rt->entries, insert_me_here + 1); |
546 if (EQ (val, entry->val) && entry->first == last) | 632 if (EQ (val, entry->val) && entry->first == last) |
547 { | 633 { |
548 entry->first = first; | 634 entry->first = first; |
549 Dynarr_delete_many (rt->entries, insert_me_here, 1); | 635 gap_array_delete_els (rt->entries, insert_me_here, 1); |
550 } | 636 } |
551 } | 637 } |
552 } | 638 } |
553 | 639 |
554 DEFUN ("put-range-table", Fput_range_table, 4, 4, 0, /* | 640 DEFUN ("put-range-table", Fput_range_table, 4, 4, 0, /* |
583 Flush RANGE-TABLE. | 669 Flush RANGE-TABLE. |
584 */ | 670 */ |
585 (range_table)) | 671 (range_table)) |
586 { | 672 { |
587 CHECK_RANGE_TABLE (range_table); | 673 CHECK_RANGE_TABLE (range_table); |
588 Dynarr_reset (XRANGE_TABLE (range_table)->entries); | 674 gap_array_delete_all_els (XRANGE_TABLE (range_table)->entries); |
589 return Qnil; | 675 return Qnil; |
590 } | 676 } |
591 | 677 |
592 DEFUN ("map-range-table", Fmap_range_table, 2, 2, 0, /* | 678 DEFUN ("map-range-table", Fmap_range_table, 2, 2, 0, /* |
593 Map FUNCTION over entries in RANGE-TABLE, calling it with three args, | 679 Map FUNCTION over entries in RANGE-TABLE, calling it with three args, |
609 | 695 |
610 rt = XRANGE_TABLE (range_table); | 696 rt = XRANGE_TABLE (range_table); |
611 | 697 |
612 /* Do not "optimize" by pulling out the length computation below! | 698 /* Do not "optimize" by pulling out the length computation below! |
613 FUNCTION may have changed the table. */ | 699 FUNCTION may have changed the table. */ |
614 for (i = 0; i < Dynarr_length (rt->entries); i++) | 700 for (i = 0; i < gap_array_length (rt->entries); i++) |
615 { | 701 { |
616 struct range_table_entry *entry = Dynarr_atp (rt->entries, i); | 702 struct range_table_entry entry = |
703 rangetab_gap_array_at (rt->entries, i); | |
617 EMACS_INT first, last; | 704 EMACS_INT first, last; |
618 Lisp_Object args[4]; | 705 Lisp_Object args[4]; |
619 int oldlen; | 706 int oldlen; |
620 | 707 |
621 again: | 708 again: |
622 first = entry->first; | 709 first = entry.first; |
623 last = entry->last; | 710 last = entry.last; |
624 oldlen = Dynarr_length (rt->entries); | 711 oldlen = gap_array_length (rt->entries); |
625 args[0] = function; | 712 args[0] = function; |
626 /* Fix up the numbers in accordance with the open/closedness of the | 713 /* Fix up the numbers in accordance with the open/closedness of the |
627 table. */ | 714 table. */ |
628 { | 715 { |
629 EMACS_INT premier = first, dernier = last; | 716 EMACS_INT premier = first, dernier = last; |
630 internal_to_external_adjust_ends (rt->type, &premier, &dernier); | 717 internal_to_external_adjust_ends (rt->type, &premier, &dernier); |
631 args[1] = make_int (premier); | 718 args[1] = make_int (premier); |
632 args[2] = make_int (dernier); | 719 args[2] = make_int (dernier); |
633 } | 720 } |
634 args[3] = entry->val; | 721 args[3] = entry.val; |
635 Ffuncall (countof (args), args); | 722 Ffuncall (countof (args), args); |
636 /* Has FUNCTION removed the entry? */ | 723 /* Has FUNCTION removed the entry? */ |
637 if (oldlen > Dynarr_length (rt->entries) | 724 if (oldlen > gap_array_length (rt->entries) |
638 && i < Dynarr_length (rt->entries) | 725 && i < gap_array_length (rt->entries) |
639 && (first != entry->first || last != entry->last)) | 726 && (first != entry.first || last != entry.last)) |
640 goto again; | 727 goto again; |
641 } | 728 } |
642 | 729 |
643 return Qnil; | 730 return Qnil; |
644 } | 731 } |
776 | 863 |
777 int | 864 int |
778 unified_range_table_bytes_needed (Lisp_Object rangetab) | 865 unified_range_table_bytes_needed (Lisp_Object rangetab) |
779 { | 866 { |
780 return (sizeof (struct range_table_entry) * | 867 return (sizeof (struct range_table_entry) * |
781 (Dynarr_length (XRANGE_TABLE (rangetab)->entries) - 1) + | 868 (gap_array_length (XRANGE_TABLE (rangetab)->entries) - 1) + |
782 sizeof (struct unified_range_table) + | 869 sizeof (struct unified_range_table) + |
783 /* ALIGNOF a struct may be too big. */ | 870 /* ALIGNOF a struct may be too big. */ |
784 /* We have four bytes for the size numbers, and an extra | 871 /* We have four bytes for the size numbers, and an extra |
785 four or eight bytes for making sure we get the alignment | 872 four or eight bytes for making sure we get the alignment |
786 OK. */ | 873 OK. */ |
796 { | 883 { |
797 /* We cast to the above structure rather than just casting to | 884 /* We cast to the above structure rather than just casting to |
798 char * and adding sizeof(int), because that will lead to | 885 char * and adding sizeof(int), because that will lead to |
799 mis-aligned data on the Alpha machines. */ | 886 mis-aligned data on the Alpha machines. */ |
800 struct unified_range_table *un; | 887 struct unified_range_table *un; |
801 range_table_entry_dynarr *rted = XRANGE_TABLE (rangetab)->entries; | 888 Gap_Array *rtega = XRANGE_TABLE (rangetab)->entries; |
802 int total_needed = unified_range_table_bytes_needed (rangetab); | 889 int total_needed = unified_range_table_bytes_needed (rangetab); |
803 void *new_dest = ALIGN_PTR ((char *) dest + 4, EMACS_INT); | 890 void *new_dest = ALIGN_PTR ((char *) dest + 4, EMACS_INT); |
891 Elemcount i; | |
804 | 892 |
805 * (char *) dest = (char) ((char *) new_dest - (char *) dest); | 893 * (char *) dest = (char) ((char *) new_dest - (char *) dest); |
806 * ((unsigned char *) dest + 1) = total_needed & 0xFF; | 894 * ((unsigned char *) dest + 1) = total_needed & 0xFF; |
807 total_needed >>= 8; | 895 total_needed >>= 8; |
808 * ((unsigned char *) dest + 2) = total_needed & 0xFF; | 896 * ((unsigned char *) dest + 2) = total_needed & 0xFF; |
809 total_needed >>= 8; | 897 total_needed >>= 8; |
810 * ((unsigned char *) dest + 3) = total_needed & 0xFF; | 898 * ((unsigned char *) dest + 3) = total_needed & 0xFF; |
811 un = (struct unified_range_table *) new_dest; | 899 un = (struct unified_range_table *) new_dest; |
812 un->nentries = Dynarr_length (rted); | 900 un->nentries = gap_array_length (rtega); |
813 un->type = XRANGE_TABLE (rangetab)->type; | 901 un->type = XRANGE_TABLE (rangetab)->type; |
814 memcpy (&un->first, Dynarr_begin (rted), | 902 for (i = 0; i < gap_array_length (rtega); i++) |
815 sizeof (struct range_table_entry) * Dynarr_length (rted)); | 903 (&un->first)[i] = rangetab_gap_array_at (rtega, i); |
816 } | 904 } |
817 | 905 |
818 /* Return number of bytes actually used by a unified range table. */ | 906 /* Return number of bytes actually used by a unified range table. */ |
819 | 907 |
820 int | 908 int |
853 | 941 |
854 align_the_damn_table (unrangetab); | 942 align_the_damn_table (unrangetab); |
855 new_dest = (char *) unrangetab + * (char *) unrangetab; | 943 new_dest = (char *) unrangetab + * (char *) unrangetab; |
856 un = (struct unified_range_table *) new_dest; | 944 un = (struct unified_range_table *) new_dest; |
857 | 945 |
858 return get_range_table (pos, un->nentries, &un->first, default_); | 946 return get_range_table (pos, un->nentries, &un->first, 0, 0, default_); |
859 } | 947 } |
860 | 948 |
861 /* Return number of entries in a unified range table. */ | 949 /* Return number of entries in a unified range table. */ |
862 | 950 |
863 int | 951 int |