Mercurial > hg > xemacs-beta
comparison src/rangetab.c @ 185:3d6bfa290dbd r20-3b19
Import from CVS: tag r20-3b19
author | cvs |
---|---|
date | Mon, 13 Aug 2007 09:55:28 +0200 |
parents | 8eaf7971accc |
children | c5d627a313b1 |
comparison
equal
deleted
inserted
replaced
184:bcd2674570bf | 185:3d6bfa290dbd |
---|---|
24 /* Written by Ben Wing, August 1995. */ | 24 /* Written by Ben Wing, August 1995. */ |
25 | 25 |
26 #include <config.h> | 26 #include <config.h> |
27 #include "lisp.h" | 27 #include "lisp.h" |
28 | 28 |
29 typedef struct range_table_entry range_table_entry; | |
29 struct range_table_entry | 30 struct range_table_entry |
30 { | 31 { |
31 EMACS_INT first; | 32 EMACS_INT first; |
32 EMACS_INT last; | 33 EMACS_INT last; |
33 Lisp_Object val; | 34 Lisp_Object val; |
34 }; | 35 }; |
35 | 36 |
36 typedef struct range_table_entry_dynarr_type | 37 typedef struct |
37 { | 38 { |
38 Dynarr_declare (struct range_table_entry); | 39 Dynarr_declare (range_table_entry); |
39 } range_table_entry_dynarr; | 40 } range_table_entry_dynarr; |
40 | 41 |
41 struct Lisp_Range_Table | 42 struct Lisp_Range_Table |
42 { | 43 { |
43 struct lcrecord_header header; | 44 struct lcrecord_header header; |
115 struct Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2); | 116 struct Lisp_Range_Table *rt2 = XRANGE_TABLE (obj2); |
116 int i; | 117 int i; |
117 | 118 |
118 if (Dynarr_length (rt1->entries) != Dynarr_length (rt2->entries)) | 119 if (Dynarr_length (rt1->entries) != Dynarr_length (rt2->entries)) |
119 return 0; | 120 return 0; |
120 | 121 |
121 for (i = 0; i < Dynarr_length (rt1->entries); i++) | 122 for (i = 0; i < Dynarr_length (rt1->entries); i++) |
122 { | 123 { |
123 struct range_table_entry *rte1 = Dynarr_atp (rt1->entries, i); | 124 struct range_table_entry *rte1 = Dynarr_atp (rt1->entries, i); |
124 struct range_table_entry *rte2 = Dynarr_atp (rt2->entries, i); | 125 struct range_table_entry *rte2 = Dynarr_atp (rt2->entries, i); |
125 | 126 |
153 hash = HASH2 (hash, | 154 hash = HASH2 (hash, |
154 range_table_entry_hash (Dynarr_atp (rt->entries, i), | 155 range_table_entry_hash (Dynarr_atp (rt->entries, i), |
155 depth)); | 156 depth)); |
156 return hash; | 157 return hash; |
157 } | 158 } |
158 | 159 |
159 /* just pick five elements scattered throughout the array. | 160 /* just pick five elements scattered throughout the array. |
160 A slightly better approach would be to offset by some | 161 A slightly better approach would be to offset by some |
161 noise factor from the points chosen below. */ | 162 noise factor from the points chosen below. */ |
162 for (i = 0; i < 5; i++) | 163 for (i = 0; i < 5; i++) |
163 hash = HASH2 (hash, range_table_entry_hash (Dynarr_atp (rt->entries, | 164 hash = HASH2 (hash, range_table_entry_hash (Dynarr_atp (rt->entries, |
200 static Lisp_Object | 201 static Lisp_Object |
201 get_range_table (EMACS_INT pos, int nentries, struct range_table_entry *tab, | 202 get_range_table (EMACS_INT pos, int nentries, struct range_table_entry *tab, |
202 Lisp_Object default_) | 203 Lisp_Object default_) |
203 { | 204 { |
204 int left = 0, right = nentries; | 205 int left = 0, right = nentries; |
205 | 206 |
206 /* binary search for the entry. Based on similar code in | 207 /* binary search for the entry. Based on similar code in |
207 extent_list_locate(). */ | 208 extent_list_locate(). */ |
208 while (left != right) | 209 while (left != right) |
209 { | 210 { |
210 /* RIGHT might not point to a valid entry (i.e. it's at the end | 211 /* RIGHT might not point to a valid entry (i.e. it's at the end |
235 You can manipulate it using `put-range-table', `get-range-table', | 236 You can manipulate it using `put-range-table', `get-range-table', |
236 `remove-range-table', and `clear-range-table'. | 237 `remove-range-table', and `clear-range-table'. |
237 */ | 238 */ |
238 ()) | 239 ()) |
239 { | 240 { |
240 struct Lisp_Range_Table *rt; | |
241 Lisp_Object obj; | 241 Lisp_Object obj; |
242 | 242 struct Lisp_Range_Table *rt = alloc_lcrecord_type (struct Lisp_Range_Table, |
243 rt = (struct Lisp_Range_Table *) | 243 lrecord_range_table); |
244 alloc_lcrecord (sizeof (struct Lisp_Range_Table), lrecord_range_table); | 244 rt->entries = Dynarr_new (range_table_entry); |
245 rt->entries = Dynarr_new (struct range_table_entry); | |
246 XSETRANGE_TABLE (obj, rt); | 245 XSETRANGE_TABLE (obj, rt); |
247 return obj; | 246 return obj; |
248 } | 247 } |
249 | 248 |
250 DEFUN ("copy-range-table", Fcopy_range_table, 1, 1, 0, /* | 249 DEFUN ("copy-range-table", Fcopy_range_table, 1, 1, 0, /* |
256 struct Lisp_Range_Table *rt, *rtnew; | 255 struct Lisp_Range_Table *rt, *rtnew; |
257 Lisp_Object obj = Qnil; | 256 Lisp_Object obj = Qnil; |
258 | 257 |
259 CHECK_RANGE_TABLE (old_table); | 258 CHECK_RANGE_TABLE (old_table); |
260 rt = XRANGE_TABLE (old_table); | 259 rt = XRANGE_TABLE (old_table); |
261 rtnew = (struct Lisp_Range_Table *) | 260 |
262 alloc_lcrecord (sizeof (struct Lisp_Range_Table), lrecord_range_table); | 261 rtnew = alloc_lcrecord_type (struct Lisp_Range_Table, lrecord_range_table); |
263 rtnew->entries = Dynarr_new (struct range_table_entry); | 262 rtnew->entries = Dynarr_new (range_table_entry); |
264 | 263 |
265 Dynarr_add_many (rtnew->entries, Dynarr_atp (rt->entries, 0), | 264 Dynarr_add_many (rtnew->entries, Dynarr_atp (rt->entries, 0), |
266 Dynarr_length (rt->entries)); | 265 Dynarr_length (rt->entries)); |
267 XSETRANGE_TABLE (obj, rtnew); | 266 XSETRANGE_TABLE (obj, rtnew); |
268 return obj; | 267 return obj; |
329 else if (entry->first < first && entry->last > last) | 328 else if (entry->first < first && entry->last > last) |
330 /* looks like: | 329 /* looks like: |
331 | 330 |
332 [ NEW ] | 331 [ NEW ] |
333 [ EXISTING ] | 332 [ EXISTING ] |
334 | 333 |
335 */ | 334 */ |
336 /* need to split this one in two. */ | 335 /* need to split this one in two. */ |
337 { | 336 { |
338 struct range_table_entry insert_me_too; | 337 struct range_table_entry insert_me_too; |
339 | 338 |
340 insert_me_too.first = last + 1; | 339 insert_me_too.first = last + 1; |
341 insert_me_too.last = entry->last; | 340 insert_me_too.last = entry->last; |
342 insert_me_too.val = entry->val; | 341 insert_me_too.val = entry->val; |
343 entry->last = first - 1; | 342 entry->last = first - 1; |
344 Dynarr_insert_many (rt->entries, &insert_me_too, 1, i + 1); | 343 Dynarr_insert_many (rt->entries, &insert_me_too, 1, i + 1); |
345 } | 344 } |
346 else if (entry->last > last) | 345 else if (entry->last > last) |
347 { | 346 { |
348 /* looks like: | 347 /* looks like: |
349 | 348 |
350 [ NEW ] | 349 [ NEW ] |
351 [ EXISTING ] | 350 [ EXISTING ] |
352 | 351 |
353 */ | 352 */ |
354 /* truncate the start off of it. */ | 353 /* truncate the start off of it. */ |
363 } | 362 } |
364 | 363 |
365 /* Someone asked us to delete the range, not insert it. */ | 364 /* Someone asked us to delete the range, not insert it. */ |
366 if (UNBOUNDP (val)) | 365 if (UNBOUNDP (val)) |
367 return; | 366 return; |
368 | 367 |
369 /* Now insert the new entry, maybe at the end. */ | 368 /* Now insert the new entry, maybe at the end. */ |
370 | 369 |
371 if (insert_me_here < 0) | 370 if (insert_me_here < 0) |
372 insert_me_here = i; | 371 insert_me_here = i; |
373 | 372 |
374 { | 373 { |
375 struct range_table_entry insert_me; | 374 struct range_table_entry insert_me; |
376 | 375 |
377 insert_me.first = first; | 376 insert_me.first = first; |
378 insert_me.last = last; | 377 insert_me.last = last; |
379 insert_me.val = val; | 378 insert_me.val = val; |
380 | 379 |
381 Dynarr_insert_many (rt->entries, &insert_me, 1, insert_me_here); | 380 Dynarr_insert_many (rt->entries, &insert_me, 1, insert_me_here); |
382 } | 381 } |
383 | 382 |
384 /* Now see if we can combine this entry with adjacent ones just | 383 /* Now see if we can combine this entry with adjacent ones just |
385 before or after. */ | 384 before or after. */ |
386 | 385 |
387 if (insert_me_here > 0) | 386 if (insert_me_here > 0) |
388 { | 387 { |
389 struct range_table_entry *entry = Dynarr_atp (rt->entries, | 388 struct range_table_entry *entry = Dynarr_atp (rt->entries, |
390 insert_me_here - 1); | 389 insert_me_here - 1); |
391 if (EQ (val, entry->val) && entry->last == first - 1) | 390 if (EQ (val, entry->val) && entry->last == first - 1) |
498 data = Fcar (Fcdr (data)); /* skip over 'data keyword */ | 497 data = Fcar (Fcdr (data)); /* skip over 'data keyword */ |
499 while (!NILP (data)) | 498 while (!NILP (data)) |
500 { | 499 { |
501 Lisp_Object range = Fcar (data); | 500 Lisp_Object range = Fcar (data); |
502 Lisp_Object val = Fcar (Fcdr (data)); | 501 Lisp_Object val = Fcar (Fcdr (data)); |
503 | 502 |
504 data = Fcdr (Fcdr (data)); | 503 data = Fcdr (Fcdr (data)); |
505 if (CONSP (range)) | 504 if (CONSP (range)) |
506 Fput_range_table (Fcar (range), Fcar (Fcdr (range)), val, | 505 Fput_range_table (Fcar (range), Fcar (Fcdr (range)), val, |
507 rangetab); | 506 rangetab); |
508 else | 507 else |
554 for modifying a unified range table. The only operations | 553 for modifying a unified range table. The only operations |
555 you can do to unified range tables are | 554 you can do to unified range tables are |
556 | 555 |
557 -- look up a value | 556 -- look up a value |
558 -- retrieve all the ranges in an iterative fashion | 557 -- retrieve all the ranges in an iterative fashion |
559 | 558 |
560 */ | 559 */ |
561 | 560 |
562 /* The format of a unified range table is as follows: | 561 /* The format of a unified range table is as follows: |
563 | 562 |
564 -- The first byte contains the number of bytes to skip to find the | 563 -- The first byte contains the number of bytes to skip to find the |
577 struct unified_range_table | 576 struct unified_range_table |
578 { | 577 { |
579 int nentries; | 578 int nentries; |
580 struct range_table_entry first; | 579 struct range_table_entry first; |
581 }; | 580 }; |
582 | 581 |
583 /* Return size in bytes needed to store the data in a range table. */ | 582 /* Return size in bytes needed to store the data in a range table. */ |
584 | 583 |
585 int | 584 int |
586 unified_range_table_bytes_needed (Lisp_Object rangetab) | 585 unified_range_table_bytes_needed (Lisp_Object rangetab) |
587 { | 586 { |
630 return ((* ((unsigned char *) unrangetab + 1)) | 629 return ((* ((unsigned char *) unrangetab + 1)) |
631 + ((* ((unsigned char *) unrangetab + 2)) << 8) | 630 + ((* ((unsigned char *) unrangetab + 2)) << 8) |
632 + ((* ((unsigned char *) unrangetab + 3)) << 16)); | 631 + ((* ((unsigned char *) unrangetab + 3)) << 16)); |
633 } | 632 } |
634 | 633 |
635 /* Make sure the table is aligned, and move it around if it's not. */ | 634 /* Make sure the table is aligned, and move it around if it's not. */ |
636 static void | 635 static void |
637 align_the_damn_table (void *unrangetab) | 636 align_the_damn_table (void *unrangetab) |
638 { | 637 { |
639 void *cur_dest = (char *) unrangetab + * (char *) unrangetab; | 638 void *cur_dest = (char *) unrangetab + * (char *) unrangetab; |
640 #if LONGBITS == 64 | 639 #if LONGBITS == 64 |
651 /* memmove() works in the presence of overlapping data. */ | 650 /* memmove() works in the presence of overlapping data. */ |
652 memmove (new_dest, cur_dest, count); | 651 memmove (new_dest, cur_dest, count); |
653 * (char *) unrangetab = (char) ((char *) new_dest - (char *) unrangetab); | 652 * (char *) unrangetab = (char) ((char *) new_dest - (char *) unrangetab); |
654 } | 653 } |
655 } | 654 } |
656 | 655 |
657 /* Look up a value in a unified range table. */ | 656 /* Look up a value in a unified range table. */ |
658 | 657 |
659 Lisp_Object | 658 Lisp_Object |
660 unified_range_table_lookup (void *unrangetab, EMACS_INT pos, | 659 unified_range_table_lookup (void *unrangetab, EMACS_INT pos, |
661 Lisp_Object default_) | 660 Lisp_Object default_) |