Mercurial > hg > xemacs-beta
comparison src/elhash.c @ 5125:b5df3737028a ben-lisp-object
merge
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 24 Feb 2010 01:58:04 -0600 |
parents | 623d57b7fbe8 16112448d484 |
children | a9c41067dd88 |
comparison
equal
deleted
inserted
replaced
5124:623d57b7fbe8 | 5125:b5df3737028a |
---|---|
90 static Lisp_Object Qrehash_size, Qrehash_threshold; | 90 static Lisp_Object Qrehash_size, Qrehash_threshold; |
91 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; | 91 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; |
92 | 92 |
93 /* obsolete as of 19990901 in xemacs-21.2 */ | 93 /* obsolete as of 19990901 in xemacs-21.2 */ |
94 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak; | 94 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak; |
95 static Lisp_Object Qnon_weak, Q_type; | 95 static Lisp_Object Qnon_weak, Q_type, Q_data; |
96 | 96 |
97 struct Lisp_Hash_Table | 97 struct Lisp_Hash_Table |
98 { | 98 { |
99 LISP_OBJECT_HEADER header; | 99 LISP_OBJECT_HEADER header; |
100 Elemcount size; | 100 Elemcount size; |
182 } | 182 } |
183 return primes [high]; | 183 return primes [high]; |
184 } | 184 } |
185 | 185 |
186 | 186 |
187 #if 0 /* I don't think these are needed any more. | |
188 If using the general lisp_object_equal_*() functions | |
189 causes efficiency problems, these can be resurrected. --ben */ | |
190 /* equality and hash functions for Lisp strings */ | |
191 int | |
192 lisp_string_equal (Lisp_Object str1, Lisp_Object str2) | |
193 { | |
194 /* This is wrong anyway. You can't use strcmp() on Lisp strings, | |
195 because they can contain zero characters. */ | |
196 return !strcmp ((char *) XSTRING_DATA (str1), (char *) XSTRING_DATA (str2)); | |
197 } | |
198 | |
199 static Hashcode | |
200 lisp_string_hash (Lisp_Object obj) | |
201 { | |
202 return hash_string (XSTRING_DATA (str), XSTRING_LENGTH (str)); | |
203 } | |
204 | |
205 #endif /* 0 */ | |
206 | 187 |
207 static int | 188 static int |
208 lisp_object_eql_equal (Lisp_Object obj1, Lisp_Object obj2) | 189 lisp_object_eql_equal (Lisp_Object obj1, Lisp_Object obj2) |
209 { | 190 { |
210 return EQ (obj1, obj2) || (FLOATP (obj1) && internal_equal (obj1, obj2, 0)); | 191 return EQ (obj1, obj2) || |
192 (NON_FIXNUM_NUMBER_P (obj1) && internal_equal (obj1, obj2, 0)); | |
211 } | 193 } |
212 | 194 |
213 static Hashcode | 195 static Hashcode |
214 lisp_object_eql_hash (Lisp_Object obj) | 196 lisp_object_eql_hash (Lisp_Object obj) |
215 { | 197 { |
216 return FLOATP (obj) ? internal_hash (obj, 0) : LISP_HASH (obj); | 198 return NON_FIXNUM_NUMBER_P (obj) ? internal_hash (obj, 0) : LISP_HASH (obj); |
217 } | 199 } |
218 | 200 |
219 static int | 201 static int |
220 lisp_object_equal_equal (Lisp_Object obj1, Lisp_Object obj2) | 202 lisp_object_equal_equal (Lisp_Object obj1, Lisp_Object obj2) |
221 { | 203 { |
260 function, which we don't do. Doing that would require consing, and | 242 function, which we don't do. Doing that would require consing, and |
261 consing is a bad idea in `equal'. Anyway, our method should provide | 243 consing is a bad idea in `equal'. Anyway, our method should provide |
262 the same result -- if the keys are not equal according to the test | 244 the same result -- if the keys are not equal according to the test |
263 function, then Fgethash() in hash_table_equal_mapper() will fail. */ | 245 function, then Fgethash() in hash_table_equal_mapper() will fail. */ |
264 static int | 246 static int |
265 hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth) | 247 hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth, |
248 int foldcase) | |
266 { | 249 { |
267 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); | 250 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); |
268 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); | 251 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); |
269 htentry *e, *sentinel; | 252 htentry *e, *sentinel; |
270 | 253 |
279 if (!HTENTRY_CLEAR_P (e)) | 262 if (!HTENTRY_CLEAR_P (e)) |
280 /* Look up the key in the other hash table, and compare the values. */ | 263 /* Look up the key in the other hash table, and compare the values. */ |
281 { | 264 { |
282 Lisp_Object value_in_other = Fgethash (e->key, hash_table2, Qunbound); | 265 Lisp_Object value_in_other = Fgethash (e->key, hash_table2, Qunbound); |
283 if (UNBOUNDP (value_in_other) || | 266 if (UNBOUNDP (value_in_other) || |
284 !internal_equal (e->value, value_in_other, depth)) | 267 !internal_equal_0 (e->value, value_in_other, depth, foldcase)) |
285 return 0; /* Give up */ | 268 return 0; /* Give up */ |
286 } | 269 } |
287 | 270 |
288 return 1; | 271 return 1; |
289 } | 272 } |
302 | 285 |
303 This is non-trivial, because we use a readable structure-style | 286 This is non-trivial, because we use a readable structure-style |
304 syntax for hash tables. This means that a typical hash table will be | 287 syntax for hash tables. This means that a typical hash table will be |
305 readably printed in the form of: | 288 readably printed in the form of: |
306 | 289 |
307 #s(hash-table size 2 data (key1 value1 key2 value2)) | 290 #s(hash-table :size 2 :data (key1 value1 key2 value2)) |
308 | 291 |
309 The supported hash table structure keywords and their values are: | 292 The supported hash table structure keywords and their values are: |
310 `test' (eql (or nil), eq or equal) | 293 `:test' (eql (or nil), eq or equal) |
311 `size' (a natnum or nil) | 294 `:size' (a natnum or nil) |
312 `rehash-size' (a float) | 295 `:rehash-size' (a float) |
313 `rehash-threshold' (a float) | 296 `:rehash-threshold' (a float) |
314 `weakness' (nil, key, value, key-and-value, or key-or-value) | 297 `:weakness' (nil, key, value, key-and-value, or key-or-value) |
315 `data' (a list) | 298 `:data' (a list) |
316 | 299 |
317 If `print-readably' is nil, then a simpler syntax is used, for example | 300 If `print-readably' is nil, then a simpler syntax is used, for example |
318 | 301 |
319 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> | 302 #<hash-table size 2/13 data (key1 value1 key2 value2) 0x874d> |
320 | 303 |
328 print_hash_table_data (Lisp_Hash_Table *ht, Lisp_Object printcharfun) | 311 print_hash_table_data (Lisp_Hash_Table *ht, Lisp_Object printcharfun) |
329 { | 312 { |
330 int count = 0; | 313 int count = 0; |
331 htentry *e, *sentinel; | 314 htentry *e, *sentinel; |
332 | 315 |
333 write_c_string (printcharfun, " data ("); | 316 write_ascstring (printcharfun, " :data ("); |
334 | 317 |
335 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) | 318 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) |
336 if (!HTENTRY_CLEAR_P (e)) | 319 if (!HTENTRY_CLEAR_P (e)) |
337 { | 320 { |
338 if (count > 0) | 321 if (count > 0) |
339 write_c_string (printcharfun, " "); | 322 write_ascstring (printcharfun, " "); |
340 if (!print_readably && count > 3) | 323 if (!print_readably && count > 3) |
341 { | 324 { |
342 write_c_string (printcharfun, "..."); | 325 write_ascstring (printcharfun, "..."); |
343 break; | 326 break; |
344 } | 327 } |
345 print_internal (e->key, printcharfun, 1); | 328 print_internal (e->key, printcharfun, 1); |
346 write_fmt_string_lisp (printcharfun, " %S", 1, e->value); | 329 write_fmt_string_lisp (printcharfun, " %S", 1, e->value); |
347 count++; | 330 count++; |
348 } | 331 } |
349 | 332 |
350 write_c_string (printcharfun, ")"); | 333 write_ascstring (printcharfun, ")"); |
351 } | 334 } |
352 | 335 |
353 static void | 336 static void |
354 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, | 337 print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, |
355 int UNUSED (escapeflag)) | 338 int UNUSED (escapeflag)) |
356 { | 339 { |
357 Lisp_Hash_Table *ht = XHASH_TABLE (obj); | 340 Lisp_Hash_Table *ht = XHASH_TABLE (obj); |
358 Ascbyte pigbuf[350]; | 341 Ascbyte pigbuf[350]; |
359 | 342 |
360 write_c_string (printcharfun, | 343 write_ascstring (printcharfun, |
361 print_readably ? "#s(hash-table" : "#<hash-table"); | 344 print_readably ? "#s(hash-table" : "#<hash-table"); |
362 | 345 |
363 /* These checks have a kludgy look to them, but they are safe. | 346 /* These checks have a kludgy look to them, but they are safe. |
364 Due to nature of hashing, you cannot use arbitrary | 347 Due to nature of hashing, you cannot use arbitrary |
365 test functions anyway. */ | 348 test functions anyway. */ |
366 if (!ht->test_function) | 349 if (!ht->test_function) |
367 write_c_string (printcharfun, " test eq"); | 350 write_ascstring (printcharfun, " :test eq"); |
368 else if (ht->test_function == lisp_object_equal_equal) | 351 else if (ht->test_function == lisp_object_equal_equal) |
369 write_c_string (printcharfun, " test equal"); | 352 write_ascstring (printcharfun, " :test equal"); |
370 else if (ht->test_function == lisp_object_eql_equal) | 353 else if (ht->test_function == lisp_object_eql_equal) |
371 DO_NOTHING; | 354 DO_NOTHING; |
372 else | 355 else |
373 ABORT (); | 356 ABORT (); |
374 | 357 |
375 if (ht->count || !print_readably) | 358 if (ht->count || !print_readably) |
376 { | 359 { |
377 if (print_readably) | 360 if (print_readably) |
378 write_fmt_string (printcharfun, " size %ld", (long) ht->count); | 361 write_fmt_string (printcharfun, " :size %ld", (long) ht->count); |
379 else | 362 else |
380 write_fmt_string (printcharfun, " size %ld/%ld", (long) ht->count, | 363 write_fmt_string (printcharfun, " :size %ld/%ld", (long) ht->count, |
381 (long) ht->size); | 364 (long) ht->size); |
382 } | 365 } |
383 | 366 |
384 if (ht->weakness != HASH_TABLE_NON_WEAK) | 367 if (ht->weakness != HASH_TABLE_NON_WEAK) |
385 { | 368 { |
386 write_fmt_string | 369 write_fmt_string |
387 (printcharfun, " weakness %s", | 370 (printcharfun, " :weakness %s", |
388 (ht->weakness == HASH_TABLE_WEAK ? "key-and-value" : | 371 (ht->weakness == HASH_TABLE_WEAK ? "key-and-value" : |
389 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" : | 372 ht->weakness == HASH_TABLE_KEY_WEAK ? "key" : |
390 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : | 373 ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : |
391 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" : | 374 ht->weakness == HASH_TABLE_KEY_VALUE_WEAK ? "key-or-value" : |
392 "you-d-better-not-see-this")); | 375 "you-d-better-not-see-this")); |
393 } | 376 } |
394 | 377 |
395 if (ht->rehash_size != HASH_TABLE_DEFAULT_REHASH_SIZE) | 378 if (ht->rehash_size != HASH_TABLE_DEFAULT_REHASH_SIZE) |
396 { | 379 { |
397 float_to_string (pigbuf, ht->rehash_size); | 380 float_to_string (pigbuf, ht->rehash_size); |
398 write_fmt_string (printcharfun, " rehash-size %s", pigbuf); | 381 write_fmt_string (printcharfun, " :rehash-size %s", pigbuf); |
399 } | 382 } |
400 | 383 |
401 if (ht->rehash_threshold | 384 if (ht->rehash_threshold |
402 != HASH_TABLE_DEFAULT_REHASH_THRESHOLD (ht->size, | 385 != HASH_TABLE_DEFAULT_REHASH_THRESHOLD (ht->size, |
403 ht->test_function)) | 386 ht->test_function)) |
404 { | 387 { |
405 float_to_string (pigbuf, ht->rehash_threshold); | 388 float_to_string (pigbuf, ht->rehash_threshold); |
406 write_fmt_string (printcharfun, " rehash-threshold %s", pigbuf); | 389 write_fmt_string (printcharfun, " :rehash-threshold %s", pigbuf); |
407 } | 390 } |
408 | 391 |
409 if (ht->count) | 392 if (ht->count) |
410 print_hash_table_data (ht, printcharfun); | 393 print_hash_table_data (ht, printcharfun); |
411 | 394 |
412 if (print_readably) | 395 if (print_readably) |
413 write_c_string (printcharfun, ")"); | 396 write_ascstring (printcharfun, ")"); |
414 else | 397 else |
415 write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); | 398 write_fmt_string (printcharfun, " 0x%x>", ht->header.uid); |
416 } | 399 } |
417 | 400 |
418 #ifndef NEW_GC | 401 #ifndef NEW_GC |
432 for (e = hentries, sentinel = e + size; e < sentinel; e++) | 415 for (e = hentries, sentinel = e + size; e < sentinel; e++) |
433 * (unsigned long *) e = 0xdeadbeef; /* -559038737 base 10 */ | 416 * (unsigned long *) e = 0xdeadbeef; /* -559038737 base 10 */ |
434 #endif | 417 #endif |
435 | 418 |
436 if (!DUMPEDP (hentries)) | 419 if (!DUMPEDP (hentries)) |
437 xfree (hentries, htentry *); | 420 xfree (hentries); |
438 } | 421 } |
439 | 422 |
440 static void | 423 static void |
441 finalize_hash_table (void *header) | 424 finalize_hash_table (void *header) |
442 { | 425 { |
839 Lisp_Object rehash_size = Qnil; | 822 Lisp_Object rehash_size = Qnil; |
840 Lisp_Object rehash_threshold = Qnil; | 823 Lisp_Object rehash_threshold = Qnil; |
841 Lisp_Object weakness = Qnil; | 824 Lisp_Object weakness = Qnil; |
842 Lisp_Object data = Qnil; | 825 Lisp_Object data = Qnil; |
843 | 826 |
844 PROPERTY_LIST_LOOP_3 (key, value, plist) | 827 if (KEYWORDP (Fcar (plist))) |
845 { | 828 { |
846 if (EQ (key, Qtest)) test = value; | 829 PROPERTY_LIST_LOOP_3 (key, value, plist) |
847 else if (EQ (key, Qsize)) size = value; | 830 { |
848 else if (EQ (key, Qrehash_size)) rehash_size = value; | 831 if (EQ (key, Q_test)) test = value; |
849 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; | 832 else if (EQ (key, Q_size)) size = value; |
850 else if (EQ (key, Qweakness)) weakness = value; | 833 else if (EQ (key, Q_rehash_size)) rehash_size = value; |
851 else if (EQ (key, Qdata)) data = value; | 834 else if (EQ (key, Q_rehash_threshold)) rehash_threshold = value; |
852 else if (EQ (key, Qtype))/*obsolete*/ weakness = value; | 835 else if (EQ (key, Q_weakness)) weakness = value; |
853 else | 836 else if (EQ (key, Q_data)) data = value; |
854 ABORT (); | 837 else if (!KEYWORDP (key)) |
838 signal_error (Qinvalid_read_syntax, | |
839 "can't mix keyword and non-keyword hash table syntax", | |
840 key); | |
841 else ABORT(); | |
842 } | |
843 } | |
844 else | |
845 { | |
846 PROPERTY_LIST_LOOP_3 (key, value, plist) | |
847 { | |
848 if (EQ (key, Qtest)) test = value; | |
849 else if (EQ (key, Qsize)) size = value; | |
850 else if (EQ (key, Qrehash_size)) rehash_size = value; | |
851 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; | |
852 else if (EQ (key, Qweakness)) weakness = value; | |
853 else if (EQ (key, Qdata)) data = value; | |
854 else if (EQ (key, Qtype))/*obsolete*/ weakness = value; | |
855 else if (KEYWORDP (key)) | |
856 signal_error (Qinvalid_read_syntax, | |
857 "can't mix keyword and non-keyword hash table syntax", | |
858 key); | |
859 else ABORT(); | |
860 } | |
855 } | 861 } |
856 | 862 |
857 /* Create the hash table. */ | 863 /* Create the hash table. */ |
858 hash_table = make_standard_lisp_hash_table | 864 hash_table = make_standard_lisp_hash_table |
859 (decode_hash_table_test (test), | 865 (decode_hash_table_test (test), |
885 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) | 891 structure_type_create_hash_table_structure_name (Lisp_Object structure_name) |
886 { | 892 { |
887 struct structure_type *st; | 893 struct structure_type *st; |
888 | 894 |
889 st = define_structure_type (structure_name, 0, hash_table_instantiate); | 895 st = define_structure_type (structure_name, 0, hash_table_instantiate); |
896 | |
897 /* First the keyword syntax: */ | |
898 define_structure_type_keyword (st, Q_test, hash_table_test_validate); | |
899 define_structure_type_keyword (st, Q_size, hash_table_size_validate); | |
900 define_structure_type_keyword (st, Q_rehash_size, hash_table_rehash_size_validate); | |
901 define_structure_type_keyword (st, Q_rehash_threshold, hash_table_rehash_threshold_validate); | |
902 define_structure_type_keyword (st, Q_weakness, hash_table_weakness_validate); | |
903 define_structure_type_keyword (st, Q_data, hash_table_data_validate); | |
904 | |
905 /* Next the mutually exclusive, older, non-keyword syntax: */ | |
890 define_structure_type_keyword (st, Qtest, hash_table_test_validate); | 906 define_structure_type_keyword (st, Qtest, hash_table_test_validate); |
891 define_structure_type_keyword (st, Qsize, hash_table_size_validate); | 907 define_structure_type_keyword (st, Qsize, hash_table_size_validate); |
892 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); | 908 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); |
893 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); | 909 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); |
894 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); | 910 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); |
1090 } | 1106 } |
1091 | 1107 |
1092 memcpy (ht->hentries, new_entries, ht->size * sizeof (htentry)); | 1108 memcpy (ht->hentries, new_entries, ht->size * sizeof (htentry)); |
1093 | 1109 |
1094 #ifndef NEW_GC | 1110 #ifndef NEW_GC |
1095 xfree (new_entries, htentry *); | 1111 xfree (new_entries); |
1096 #endif /* not NEW_GC */ | 1112 #endif /* not NEW_GC */ |
1097 } | 1113 } |
1098 | 1114 |
1099 static void | 1115 static void |
1100 enlarge_hash_table (Lisp_Hash_Table *ht) | 1116 enlarge_hash_table (Lisp_Hash_Table *ht) |
1385 | 1401 |
1386 static Lisp_Object | 1402 static Lisp_Object |
1387 maphash_unwind (Lisp_Object unwind_obj) | 1403 maphash_unwind (Lisp_Object unwind_obj) |
1388 { | 1404 { |
1389 void *ptr = (void *) get_opaque_ptr (unwind_obj); | 1405 void *ptr = (void *) get_opaque_ptr (unwind_obj); |
1390 xfree (ptr, void *); | 1406 xfree (ptr); |
1391 free_opaque_ptr (unwind_obj); | 1407 free_opaque_ptr (unwind_obj); |
1392 return Qnil; | 1408 return Qnil; |
1393 } | 1409 } |
1394 | 1410 |
1395 /* Return a malloced array of alternating key/value pairs from HT. */ | 1411 /* Return a malloced array of alternating key/value pairs from HT. */ |
1829 DEFSYMBOL (Qkey_weak); /* obsolete */ | 1845 DEFSYMBOL (Qkey_weak); /* obsolete */ |
1830 DEFSYMBOL (Qkey_or_value_weak); /* obsolete */ | 1846 DEFSYMBOL (Qkey_or_value_weak); /* obsolete */ |
1831 DEFSYMBOL (Qvalue_weak); /* obsolete */ | 1847 DEFSYMBOL (Qvalue_weak); /* obsolete */ |
1832 DEFSYMBOL (Qnon_weak); /* obsolete */ | 1848 DEFSYMBOL (Qnon_weak); /* obsolete */ |
1833 | 1849 |
1850 DEFKEYWORD (Q_data); | |
1834 DEFKEYWORD (Q_test); | 1851 DEFKEYWORD (Q_test); |
1835 DEFKEYWORD (Q_size); | 1852 DEFKEYWORD (Q_size); |
1836 DEFKEYWORD (Q_rehash_size); | 1853 DEFKEYWORD (Q_rehash_size); |
1837 DEFKEYWORD (Q_rehash_threshold); | 1854 DEFKEYWORD (Q_rehash_threshold); |
1838 DEFKEYWORD (Q_weakness); | 1855 DEFKEYWORD (Q_weakness); |