comparison src/elhash.c @ 5191:71ee43b8a74d

Add #'equalp as a hash test by default; add #'define-hash-table-test, GNU API tests/ChangeLog addition: 2010-04-05 Aidan Kehoe <kehoea@parhasard.net> * automated/hash-table-tests.el: Test the new built-in #'equalp hash table test. Test #'define-hash-table-test. * automated/lisp-tests.el: When asserting that two objects are #'equalp, also assert that their #'equalp-hash is identical. man/ChangeLog addition: 2010-04-03 Aidan Kehoe <kehoea@parhasard.net> * lispref/hash-tables.texi (Introduction to Hash Tables): Document that we now support #'equalp as a hash table test by default, and mention #'define-hash-table-test. (Working With Hash Tables): Document #'define-hash-table-test. src/ChangeLog addition: 2010-04-05 Aidan Kehoe <kehoea@parhasard.net> * elhash.h: * elhash.c (struct Hash_Table_Test, lisp_object_eql_equal) (lisp_object_eql_hash, lisp_object_equal_equal) (lisp_object_equal_hash, lisp_object_equalp_hash) (lisp_object_equalp_equal, lisp_object_general_hash) (lisp_object_general_equal, Feq_hash, Feql_hash, Fequal_hash) (Fequalp_hash, define_hash_table_test, Fdefine_hash_table_test) (init_elhash_once_early, mark_hash_table_tests, string_equalp_hash): * glyphs.c (vars_of_glyphs): Add a new hash table test in C, #'equalp. Make it possible to specify new hash table tests with functions define_hash_table_test, #'define-hash-table-test. Use define_hash_table_test() in glyphs.c. Expose the hash functions (besides that used for #'equal) to Lisp, for people writing functions to be used with #'define-hash-table-test. Call define_hash_table_test() very early in temacs, to create the built-in hash table tests. * ui-gtk.c (emacs_gtk_boxed_hash): * specifier.h (struct specifier_methods): * specifier.c (specifier_hash): * rangetab.c (range_table_entry_hash, range_table_hash): * number.c (bignum_hash, ratio_hash, bigfloat_hash): * marker.c (marker_hash): * lrecord.h (struct lrecord_implementation): * keymap.c (keymap_hash): * gui.c (gui_item_id_hash, gui_item_hash): * glyphs.c (image_instance_hash, glyph_hash): * glyphs-x.c (x_image_instance_hash): * glyphs-msw.c (mswindows_image_instance_hash): * glyphs-gtk.c (gtk_image_instance_hash): * frame-msw.c (mswindows_set_title_from_ibyte): * fontcolor.c (color_instance_hash, font_instance_hash): * fontcolor-x.c (x_color_instance_hash): * fontcolor-tty.c (tty_color_instance_hash): * fontcolor-msw.c (mswindows_color_instance_hash): * fontcolor-gtk.c (gtk_color_instance_hash): * fns.c (bit_vector_hash): * floatfns.c (float_hash): * faces.c (face_hash): * extents.c (extent_hash): * events.c (event_hash): * data.c (weak_list_hash, weak_box_hash): * chartab.c (char_table_entry_hash, char_table_hash): * bytecode.c (compiled_function_hash): * alloc.c (vector_hash): Change the various object hash methods to take a new EQUALP parameter, hashing appropriately for #'equalp if it is true.
author Aidan Kehoe <kehoea@parhasard.net>
date Mon, 05 Apr 2010 13:03:35 +0100
parents 6c6d78781d59
children 41ac827cb71b
comparison
equal deleted inserted replaced
5190:1c1d8843de5e 5191:71ee43b8a74d
81 #include "lisp.h" 81 #include "lisp.h"
82 #include "bytecode.h" 82 #include "bytecode.h"
83 #include "elhash.h" 83 #include "elhash.h"
84 #include "gc.h" 84 #include "gc.h"
85 #include "opaque.h" 85 #include "opaque.h"
86 #include "buffer.h"
86 87
87 Lisp_Object Qhash_tablep; 88 Lisp_Object Qhash_tablep;
89 Lisp_Object Qeq, Qeql, Qequal, Qequalp;
90 Lisp_Object Qeq_hash, Qeql_hash, Qequal_hash, Qequalp_hash;
91
88 static Lisp_Object Qhashtable, Qhash_table, Qmake_hash_table; 92 static Lisp_Object Qhashtable, Qhash_table, Qmake_hash_table;
89 static Lisp_Object Qweakness, Qvalue, Qkey_or_value, Qkey_and_value; 93 static Lisp_Object Qweakness, Qvalue, Qkey_or_value, Qkey_and_value;
90 static Lisp_Object Vall_weak_hash_tables; 94 static Lisp_Object Vall_weak_hash_tables;
91 static Lisp_Object Qrehash_size, Qrehash_threshold; 95 static Lisp_Object Qrehash_size, Qrehash_threshold;
92 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; 96 static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold;
97 static Lisp_Object Vhash_table_test_eq, Vhash_table_test_eql;
98 static Lisp_Object Vhash_table_test_weak_list;
93 99
94 /* obsolete as of 19990901 in xemacs-21.2 */ 100 /* obsolete as of 19990901 in xemacs-21.2 */
95 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak; 101 static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qkey_or_value_weak;
96 static Lisp_Object Qnon_weak, Q_type, Q_data; 102 static Lisp_Object Qnon_weak, Q_type, Q_data;
103
104 /* A hash table test, with its associated hash function. equal_function may
105 call lisp_equal_function, and hash_function similarly may call
106 lisp_hash_function. */
107 struct Hash_Table_Test
108 {
109 NORMAL_LISP_OBJECT_HEADER header;
110 Lisp_Object name;
111 hash_table_equal_function_t equal_function;
112 hash_table_hash_function_t hash_function;
113 Lisp_Object lisp_equal_function;
114 Lisp_Object lisp_hash_function;
115 };
116
117 static Lisp_Object
118 mark_hash_table_test (Lisp_Object obj)
119 {
120 Hash_Table_Test *http = XHASH_TABLE_TEST (obj);
121
122 mark_object (http->name);
123 mark_object (http->lisp_equal_function);
124 mark_object (http->lisp_hash_function);
125
126 return Qnil;
127 }
128
129 static const struct memory_description hash_table_test_description_1[] =
130 {
131 { XD_LISP_OBJECT, offsetof (struct Hash_Table_Test, name) },
132 { XD_LISP_OBJECT, offsetof (struct Hash_Table_Test, lisp_equal_function) },
133 { XD_LISP_OBJECT, offsetof (struct Hash_Table_Test, lisp_hash_function) },
134 { XD_END }
135 };
136
137 static const struct sized_memory_description hash_table_test_description =
138 {
139 sizeof (struct Hash_Table_Test),
140 hash_table_test_description_1
141 };
142
143 DEFINE_DUMPABLE_INTERNAL_LISP_OBJECT ("hash-table-test", hash_table_test,
144 mark_hash_table_test,
145 hash_table_test_description_1,
146 Hash_Table_Test);
147 /* A hash table. */
97 148
98 struct Lisp_Hash_Table 149 struct Lisp_Hash_Table
99 { 150 {
100 NORMAL_LISP_OBJECT_HEADER header; 151 NORMAL_LISP_OBJECT_HEADER header;
101 Elemcount size; 152 Elemcount size;
102 Elemcount count; 153 Elemcount count;
103 Elemcount rehash_count; 154 Elemcount rehash_count;
104 double rehash_size; 155 double rehash_size;
105 double rehash_threshold; 156 double rehash_threshold;
106 Elemcount golden_ratio; 157 Elemcount golden_ratio;
107 hash_table_hash_function_t hash_function;
108 hash_table_test_function_t test_function;
109 htentry *hentries; 158 htentry *hentries;
159 Lisp_Object test;
110 enum hash_table_weakness weakness; 160 enum hash_table_weakness weakness;
111 Lisp_Object next_weak; /* Used to chain together all of the weak 161 Lisp_Object next_weak; /* Used to chain together all of the weak
112 hash tables. Don't mark through this. */ 162 hash tables. Don't mark through this. */
113 }; 163 };
114 164
117 (*(EMACS_UINT*)(&((htentry)->value))) = 0) 167 (*(EMACS_UINT*)(&((htentry)->value))) = 0)
118 168
119 #define HASH_TABLE_DEFAULT_SIZE 16 169 #define HASH_TABLE_DEFAULT_SIZE 16
120 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 170 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3
121 #define HASH_TABLE_MIN_SIZE 10 171 #define HASH_TABLE_MIN_SIZE 10
122 #define HASH_TABLE_DEFAULT_REHASH_THRESHOLD(size, test_function) \ 172 #define HASH_TABLE_DEFAULT_REHASH_THRESHOLD(size, test) \
123 (((size) > 4096 && NULL == (test_function)) ? 0.7 : 0.6) 173 (((size) > 4096 && EQ (Vhash_table_test_eq, test)) ? 0.7 : 0.6)
124 174
125 #define HASHCODE(key, ht) \ 175 #define HASHCODE(key, ht, http) \
126 ((((ht)->hash_function ? (ht)->hash_function (key) : LISP_HASH (key)) \ 176 ((((!EQ (Vhash_table_test_eq, ht->test)) ? \
127 * (ht)->golden_ratio) \ 177 (http)->hash_function (http, key) : \
128 % (ht)->size) 178 LISP_HASH (key)) * (ht)->golden_ratio) % (ht)->size)
129 179
130 #define KEYS_EQUAL_P(key1, key2, testfun) \ 180 #define KEYS_EQUAL_P(key1, key2, test, http) \
131 (EQ (key1, key2) || ((testfun) && (testfun) (key1, key2))) 181 (EQ (key1, key2) || ((!EQ (Vhash_table_test_eq, test) && \
182 (http->equal_function) (http, key1, key2))))
132 183
133 #define LINEAR_PROBING_LOOP(probe, entries, size) \ 184 #define LINEAR_PROBING_LOOP(probe, entries, size) \
134 for (; \ 185 for (; \
135 !HTENTRY_CLEAR_P (probe) || \ 186 !HTENTRY_CLEAR_P (probe) || \
136 (probe == entries + size ? \ 187 (probe == entries + size ? \
185 } 236 }
186 237
187 238
188 239
189 static int 240 static int
190 lisp_object_eql_equal (Lisp_Object obj1, Lisp_Object obj2) 241 lisp_object_eql_equal (const Hash_Table_Test *UNUSED (http), Lisp_Object obj1,
242 Lisp_Object obj2)
191 { 243 {
192 return EQ (obj1, obj2) || 244 return EQ (obj1, obj2) ||
193 (NON_FIXNUM_NUMBER_P (obj1) && internal_equal (obj1, obj2, 0)); 245 (NON_FIXNUM_NUMBER_P (obj1) && internal_equal (obj1, obj2, 0));
194 } 246 }
195 247
196 static Hashcode 248 static Hashcode
197 lisp_object_eql_hash (Lisp_Object obj) 249 lisp_object_eql_hash (const Hash_Table_Test *UNUSED (http), Lisp_Object obj)
198 { 250 {
199 return NON_FIXNUM_NUMBER_P (obj) ? internal_hash (obj, 0) : LISP_HASH (obj); 251 return NON_FIXNUM_NUMBER_P (obj) ?
252 internal_hash (obj, 0, 0) : LISP_HASH (obj);
200 } 253 }
201 254
202 static int 255 static int
203 lisp_object_equal_equal (Lisp_Object obj1, Lisp_Object obj2) 256 lisp_object_equal_equal (const Hash_Table_Test *UNUSED (http),
257 Lisp_Object obj1, Lisp_Object obj2)
204 { 258 {
205 return internal_equal (obj1, obj2, 0); 259 return internal_equal (obj1, obj2, 0);
206 } 260 }
207 261
208 static Hashcode 262 static Hashcode
209 lisp_object_equal_hash (Lisp_Object obj) 263 lisp_object_equal_hash (const Hash_Table_Test *UNUSED (http), Lisp_Object obj)
210 { 264 {
211 return internal_hash (obj, 0); 265 return internal_hash (obj, 0, 0);
266 }
267
268 static Hashcode
269 lisp_object_equalp_hash (const Hash_Table_Test *UNUSED (http), Lisp_Object obj)
270 {
271 return internal_hash (obj, 0, 1);
272 }
273
274 static int
275 lisp_object_equalp_equal (const Hash_Table_Test *UNUSED (http),
276 Lisp_Object obj1, Lisp_Object obj2)
277 {
278 return internal_equalp (obj1, obj2, 0);
279 }
280
281 static Hashcode
282 lisp_object_general_hash (const Hash_Table_Test *http, Lisp_Object obj)
283 {
284 struct gcpro gcpro1;
285 Lisp_Object args[2] = { http->lisp_hash_function, obj }, res;
286
287 /* Make sure any weakly referenced objects don't get collected before the
288 funcall: */
289 GCPRO1 (args[0]);
290 gcpro1.nvars = countof (args);
291 res = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
292 UNGCPRO;
293
294 if (INTP (res))
295 {
296 return (Hashcode) (XINT (res));
297 }
298
299 #ifdef HAVE_BIGNUM
300 if (BIGNUMP (res))
301 {
302 if (bignum_fits_emacs_int_p (XBIGNUM_DATA (res)))
303 {
304 return (Hashcode) bignum_to_emacs_int (XBIGNUM_DATA (res));
305 }
306
307 signal_error (Qrange_error, "Not a valid hash code", res);
308 }
309 #endif
310
311 dead_wrong_type_argument (Qintegerp, res);
312 }
313
314 static int
315 lisp_object_general_equal (const Hash_Table_Test *http, Lisp_Object obj1,
316 Lisp_Object obj2)
317 {
318 struct gcpro gcpro1;
319 Lisp_Object args[] = { http->lisp_equal_function, obj1, obj2 }, res;
320
321 GCPRO1 (args[0]);
322 gcpro1.nvars = countof (args);
323 res = IGNORE_MULTIPLE_VALUES (Ffuncall (countof (args), args));
324 UNGCPRO;
325
326 return !(NILP (res));
212 } 327 }
213 328
214 329
215 static Lisp_Object 330 static Lisp_Object
216 mark_hash_table (Lisp_Object obj) 331 mark_hash_table (Lisp_Object obj)
229 { 344 {
230 mark_object (e->key); 345 mark_object (e->key);
231 mark_object (e->value); 346 mark_object (e->value);
232 } 347 }
233 } 348 }
349
350 mark_object (ht->test);
351
234 return Qnil; 352 return Qnil;
235 } 353 }
236 354
237 /* Equality of hash tables. Two hash tables are equal when they are of 355 /* Equality of hash tables. Two hash tables are equal when they are of
238 the same weakness and test function, they have the same number of 356 the same weakness and test function, they have the same number of
250 { 368 {
251 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1); 369 Lisp_Hash_Table *ht1 = XHASH_TABLE (hash_table1);
252 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2); 370 Lisp_Hash_Table *ht2 = XHASH_TABLE (hash_table2);
253 htentry *e, *sentinel; 371 htentry *e, *sentinel;
254 372
255 if ((ht1->test_function != ht2->test_function) || 373 if (!(EQ (ht1->test, ht2->test)) ||
256 (ht1->weakness != ht2->weakness) || 374 (ht1->weakness != ht2->weakness) ||
257 (ht1->count != ht2->count)) 375 (ht1->count != ht2->count))
258 return 0; 376 return 0;
259 377
260 depth++; 378 depth++;
261 379
274 392
275 /* This is not a great hash function, but it _is_ correct and fast. 393 /* This is not a great hash function, but it _is_ correct and fast.
276 Examining all entries is too expensive, and examining a random 394 Examining all entries is too expensive, and examining a random
277 subset does not yield a correct hash function. */ 395 subset does not yield a correct hash function. */
278 static Hashcode 396 static Hashcode
279 hash_table_hash (Lisp_Object hash_table, int UNUSED (depth)) 397 hash_table_hash (Lisp_Object hash_table, int UNUSED (depth),
398 int UNUSED (equalp))
280 { 399 {
281 return XHASH_TABLE (hash_table)->count; 400 return XHASH_TABLE (hash_table)->count;
282 } 401 }
283 402
284 #ifdef MEMORY_USAGE_STATS 403 #ifdef MEMORY_USAGE_STATS
364 Ascbyte pigbuf[350]; 483 Ascbyte pigbuf[350];
365 484
366 write_ascstring (printcharfun, 485 write_ascstring (printcharfun,
367 print_readably ? "#s(hash-table" : "#<hash-table"); 486 print_readably ? "#s(hash-table" : "#<hash-table");
368 487
369 /* These checks have a kludgy look to them, but they are safe. 488 if (!(EQ (ht->test, Vhash_table_test_eql)))
370 Due to nature of hashing, you cannot use arbitrary 489 {
371 test functions anyway. */ 490 write_fmt_string_lisp (printcharfun, " :test %S",
372 if (!ht->test_function) 491 1, XHASH_TABLE_TEST (ht->test)->name);
373 write_ascstring (printcharfun, " :test eq"); 492 }
374 else if (ht->test_function == lisp_object_equal_equal)
375 write_ascstring (printcharfun, " :test equal");
376 else if (ht->test_function == lisp_object_eql_equal)
377 DO_NOTHING;
378 else
379 ABORT ();
380 493
381 if (ht->count || !print_readably) 494 if (ht->count || !print_readably)
382 { 495 {
383 if (print_readably) 496 if (print_readably)
384 write_fmt_string (printcharfun, " :size %ld", (long) ht->count); 497 write_fmt_string (printcharfun, " :size %ld", (long) ht->count);
403 float_to_string (pigbuf, ht->rehash_size); 516 float_to_string (pigbuf, ht->rehash_size);
404 write_fmt_string (printcharfun, " :rehash-size %s", pigbuf); 517 write_fmt_string (printcharfun, " :rehash-size %s", pigbuf);
405 } 518 }
406 519
407 if (ht->rehash_threshold 520 if (ht->rehash_threshold
408 != HASH_TABLE_DEFAULT_REHASH_THRESHOLD (ht->size, 521 != HASH_TABLE_DEFAULT_REHASH_THRESHOLD (ht->size, ht->test))
409 ht->test_function))
410 { 522 {
411 float_to_string (pigbuf, ht->rehash_threshold); 523 float_to_string (pigbuf, ht->rehash_threshold);
412 write_fmt_string (printcharfun, " :rehash-threshold %s", pigbuf); 524 write_fmt_string (printcharfun, " :rehash-threshold %s", pigbuf);
413 } 525 }
414 526
505 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) }, 617 { XD_ELEMCOUNT, offsetof (Lisp_Hash_Table, size) },
506 { XD_INT, offsetof (Lisp_Hash_Table, weakness) }, 618 { XD_INT, offsetof (Lisp_Hash_Table, weakness) },
507 { XD_UNION, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (1, 0), 619 { XD_UNION, offsetof (Lisp_Hash_Table, hentries), XD_INDIRECT (1, 0),
508 { &htentry_union_description } }, 620 { &htentry_union_description } },
509 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) }, 621 { XD_LO_LINK, offsetof (Lisp_Hash_Table, next_weak) },
622 { XD_LISP_OBJECT,offsetof (Lisp_Hash_Table, test) },
510 { XD_END } 623 { XD_END }
511 }; 624 };
512 625
513 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table, 626 DEFINE_DUMPABLE_LISP_OBJECT ("hash-table", hash_table,
514 mark_hash_table, print_hash_table, 627 mark_hash_table, print_hash_table,
551 #else /* not NEW_GC */ 664 #else /* not NEW_GC */
552 return xnew_array_and_zero (htentry, size); 665 return xnew_array_and_zero (htentry, size);
553 #endif /* not NEW_GC */ 666 #endif /* not NEW_GC */
554 } 667 }
555 668
669 static Lisp_Object decode_hash_table_test (Lisp_Object obj);
670
556 Lisp_Object 671 Lisp_Object
557 make_standard_lisp_hash_table (enum hash_table_test test, 672 make_general_lisp_hash_table (Lisp_Object test,
558 Elemcount size,
559 double rehash_size,
560 double rehash_threshold,
561 enum hash_table_weakness weakness)
562 {
563 hash_table_hash_function_t hash_function = 0;
564 hash_table_test_function_t test_function = 0;
565
566 switch (test)
567 {
568 case HASH_TABLE_EQ:
569 test_function = 0;
570 hash_function = 0;
571 break;
572
573 case HASH_TABLE_EQL:
574 test_function = lisp_object_eql_equal;
575 hash_function = lisp_object_eql_hash;
576 break;
577
578 case HASH_TABLE_EQUAL:
579 test_function = lisp_object_equal_equal;
580 hash_function = lisp_object_equal_hash;
581 break;
582
583 default:
584 ABORT ();
585 }
586
587 return make_general_lisp_hash_table (hash_function, test_function,
588 size, rehash_size, rehash_threshold,
589 weakness);
590 }
591
592 Lisp_Object
593 make_general_lisp_hash_table (hash_table_hash_function_t hash_function,
594 hash_table_test_function_t test_function,
595 Elemcount size, 673 Elemcount size,
596 double rehash_size, 674 double rehash_size,
597 double rehash_threshold, 675 double rehash_threshold,
598 enum hash_table_weakness weakness) 676 enum hash_table_weakness weakness)
599 { 677 {
600 Lisp_Object hash_table = ALLOC_NORMAL_LISP_OBJECT (hash_table); 678 Lisp_Object hash_table = ALLOC_NORMAL_LISP_OBJECT (hash_table);
601 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); 679 Lisp_Hash_Table *ht = XHASH_TABLE (hash_table);
602 680
603 ht->test_function = test_function; 681 assert (HASH_TABLE_TESTP (test));
604 ht->hash_function = hash_function; 682
683 ht->test = test;
605 ht->weakness = weakness; 684 ht->weakness = weakness;
606 685
607 ht->rehash_size = 686 ht->rehash_size =
608 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE; 687 rehash_size > 1.0 ? rehash_size : HASH_TABLE_DEFAULT_REHASH_SIZE;
609 688
610 ht->rehash_threshold = 689 ht->rehash_threshold =
611 rehash_threshold > 0.0 ? rehash_threshold : 690 rehash_threshold > 0.0 ? rehash_threshold :
612 HASH_TABLE_DEFAULT_REHASH_THRESHOLD (size, ht->test_function); 691 HASH_TABLE_DEFAULT_REHASH_THRESHOLD (size, ht->test);
613 692
614 if (size < HASH_TABLE_MIN_SIZE) 693 if (size < HASH_TABLE_MIN_SIZE)
615 size = HASH_TABLE_MIN_SIZE; 694 size = HASH_TABLE_MIN_SIZE;
616 ht->size = hash_table_size ((Elemcount) (((double) size / ht->rehash_threshold) 695 ht->size = hash_table_size ((Elemcount) (((double) size / ht->rehash_threshold)
617 + 1.0)); 696 + 1.0));
629 708
630 return hash_table; 709 return hash_table;
631 } 710 }
632 711
633 Lisp_Object 712 Lisp_Object
634 make_lisp_hash_table (Elemcount size, 713 make_lisp_hash_table (Elemcount size, enum hash_table_weakness weakness,
635 enum hash_table_weakness weakness, 714 Lisp_Object test)
636 enum hash_table_test test) 715 {
637 { 716 test = decode_hash_table_test (test);
638 return make_standard_lisp_hash_table (test, size, -1.0, -1.0, weakness); 717 return make_general_lisp_hash_table (test, size, -1.0, -1.0, weakness);
639 } 718 }
640 719
641 /* Pretty reading of hash tables. 720 /* Pretty reading of hash tables.
642 721
643 Here we use the existing structures mechanism (which is, 722 Here we use the existing structures mechanism (which is,
676 if (EQ (value, Qkey)) return 1; 755 if (EQ (value, Qkey)) return 1;
677 if (EQ (value, Qkey_and_value)) return 1; 756 if (EQ (value, Qkey_and_value)) return 1;
678 if (EQ (value, Qkey_or_value)) return 1; 757 if (EQ (value, Qkey_or_value)) return 1;
679 if (EQ (value, Qvalue)) return 1; 758 if (EQ (value, Qvalue)) return 1;
680 759
760 #ifndef NO_NEED_TO_HANDLE_21_4_CODE
681 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ 761 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
682 if (EQ (value, Qnon_weak)) return 1; 762 if (EQ (value, Qnon_weak)) return 1;
683 if (EQ (value, Qweak)) return 1; 763 if (EQ (value, Qweak)) return 1;
684 if (EQ (value, Qkey_weak)) return 1; 764 if (EQ (value, Qkey_weak)) return 1;
685 if (EQ (value, Qkey_or_value_weak)) return 1; 765 if (EQ (value, Qkey_or_value_weak)) return 1;
686 if (EQ (value, Qvalue_weak)) return 1; 766 if (EQ (value, Qvalue_weak)) return 1;
767 #endif
687 768
688 maybe_invalid_constant ("Invalid hash table weakness", 769 maybe_invalid_constant ("Invalid hash table weakness",
689 value, Qhash_table, errb); 770 value, Qhash_table, errb);
690 return 0; 771 return 0;
691 } 772 }
698 if (EQ (obj, Qkey_and_value)) return HASH_TABLE_WEAK; 779 if (EQ (obj, Qkey_and_value)) return HASH_TABLE_WEAK;
699 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK; 780 if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK;
700 if (EQ (obj, Qkey_or_value)) return HASH_TABLE_KEY_VALUE_WEAK; 781 if (EQ (obj, Qkey_or_value)) return HASH_TABLE_KEY_VALUE_WEAK;
701 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK; 782 if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK;
702 783
784 #ifndef NO_NEED_TO_HANDLE_21_4_CODE
703 /* Following values are obsolete as of 19990901 in xemacs-21.2 */ 785 /* Following values are obsolete as of 19990901 in xemacs-21.2 */
704 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; 786 if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK;
705 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; 787 if (EQ (obj, Qweak)) return HASH_TABLE_WEAK;
706 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; 788 if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK;
707 if (EQ (obj, Qkey_or_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK; 789 if (EQ (obj, Qkey_or_value_weak)) return HASH_TABLE_KEY_VALUE_WEAK;
708 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; 790 if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK;
791 #endif
709 792
710 invalid_constant ("Invalid hash table weakness", obj); 793 invalid_constant ("Invalid hash table weakness", obj);
711 RETURN_NOT_REACHED (HASH_TABLE_NON_WEAK); 794 RETURN_NOT_REACHED (HASH_TABLE_NON_WEAK);
712 } 795 }
713 796
714 static int 797 static int
715 hash_table_test_validate (Lisp_Object UNUSED (keyword), Lisp_Object value, 798 hash_table_test_validate (Lisp_Object UNUSED (keyword), Lisp_Object value,
716 Error_Behavior errb) 799 Error_Behavior errb)
717 { 800 {
718 if (EQ (value, Qnil)) return 1; 801 Lisp_Object lookup;
719 if (EQ (value, Qeq)) return 1; 802
720 if (EQ (value, Qequal)) return 1; 803 if (NILP (value))
721 if (EQ (value, Qeql)) return 1; 804 {
722 805 return 1;
723 maybe_invalid_constant ("Invalid hash table test", 806 }
724 value, Qhash_table, errb); 807
725 return 0; 808 lookup = Fassq (value, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
726 } 809 if (NILP (lookup))
727 810 {
728 static enum hash_table_test 811 maybe_invalid_constant ("Invalid hash table test",
812 value, Qhash_table, errb);
813 }
814
815 return 1;
816 }
817
818 static Lisp_Object
729 decode_hash_table_test (Lisp_Object obj) 819 decode_hash_table_test (Lisp_Object obj)
730 { 820 {
731 if (EQ (obj, Qnil)) return HASH_TABLE_EQL; 821 Lisp_Object result;
732 if (EQ (obj, Qeq)) return HASH_TABLE_EQ; 822
733 if (EQ (obj, Qequal)) return HASH_TABLE_EQUAL; 823 if (NILP (obj))
734 if (EQ (obj, Qeql)) return HASH_TABLE_EQL; 824 {
735 825 obj = Qeql;
736 invalid_constant ("Invalid hash table test", obj); 826 }
737 RETURN_NOT_REACHED (HASH_TABLE_EQ); 827
828 result = Fassq (obj, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
829 if (NILP (result))
830 {
831 invalid_constant ("Invalid hash table test", obj);
832 }
833
834 return XCDR (result);
738 } 835 }
739 836
740 static int 837 static int
741 hash_table_rehash_size_validate (Lisp_Object UNUSED (keyword), 838 hash_table_rehash_size_validate (Lisp_Object UNUSED (keyword),
742 Lisp_Object value, Error_Behavior errb) 839 Lisp_Object value, Error_Behavior errb)
863 else if (EQ (key, Qsize)) size = value; 960 else if (EQ (key, Qsize)) size = value;
864 else if (EQ (key, Qrehash_size)) rehash_size = value; 961 else if (EQ (key, Qrehash_size)) rehash_size = value;
865 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; 962 else if (EQ (key, Qrehash_threshold)) rehash_threshold = value;
866 else if (EQ (key, Qweakness)) weakness = value; 963 else if (EQ (key, Qweakness)) weakness = value;
867 else if (EQ (key, Qdata)) data = value; 964 else if (EQ (key, Qdata)) data = value;
965 #ifndef NO_NEED_TO_HANDLE_21_4_CODE
868 else if (EQ (key, Qtype))/*obsolete*/ weakness = value; 966 else if (EQ (key, Qtype))/*obsolete*/ weakness = value;
967 #endif
869 else if (KEYWORDP (key)) 968 else if (KEYWORDP (key))
870 signal_error (Qinvalid_read_syntax, 969 signal_error (Qinvalid_read_syntax,
871 "can't mix keyword and non-keyword hash table syntax", 970 "can't mix keyword and non-keyword hash table syntax",
872 key); 971 key);
873 else ABORT(); 972 else ABORT();
874 } 973 }
875 } 974 }
876 975
877 /* Create the hash table. */ 976 /* Create the hash table. */
878 hash_table = make_standard_lisp_hash_table 977 hash_table = make_general_lisp_hash_table
879 (decode_hash_table_test (test), 978 (decode_hash_table_test (test),
880 decode_hash_table_size (size), 979 decode_hash_table_size (size),
881 decode_hash_table_rehash_size (rehash_size), 980 decode_hash_table_rehash_size (rehash_size),
882 decode_hash_table_rehash_threshold (rehash_threshold), 981 decode_hash_table_rehash_threshold (rehash_threshold),
883 decode_hash_table_weakness (weakness)); 982 decode_hash_table_weakness (weakness));
884 983
885 /* I'm not sure whether this can GC, but better safe than sorry. */ 984 /* This can GC with a user-specified test. */
886 { 985 {
887 struct gcpro gcpro1; 986 struct gcpro gcpro1;
888 GCPRO1 (hash_table); 987 GCPRO1 (hash_table);
889 988
890 /* And fill it with data. */ 989 /* And fill it with data. */
922 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); 1021 define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate);
923 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); 1022 define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate);
924 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); 1023 define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate);
925 define_structure_type_keyword (st, Qdata, hash_table_data_validate); 1024 define_structure_type_keyword (st, Qdata, hash_table_data_validate);
926 1025
1026 #ifndef NO_NEED_TO_HANDLE_21_4_CODE
927 /* obsolete as of 19990901 in xemacs-21.2 */ 1027 /* obsolete as of 19990901 in xemacs-21.2 */
928 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate); 1028 define_structure_type_keyword (st, Qtype, hash_table_weakness_validate);
1029 #endif
929 } 1030 }
930 1031
931 /* Create a built-in Lisp structure type named `hash-table'. 1032 /* Create a built-in Lisp structure type named `hash-table'.
932 We make #s(hashtable ...) equivalent to #s(hash-table ...), 1033 We make #s(hashtable ...) equivalent to #s(hash-table ...),
933 for backward compatibility. 1034 for backward compatibility.
954 1055
955 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* 1056 DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /*
956 Return a new empty hash table object. 1057 Return a new empty hash table object.
957 Use Common Lisp style keywords to specify hash table properties. 1058 Use Common Lisp style keywords to specify hash table properties.
958 1059
959 Keyword :test can be `eq', `eql' (default) or `equal'. 1060 Keyword :test can be `eq', `eql' (default), `equal' or `equalp'.
960 Comparison between keys is done using this function. 1061 Comparison between keys is done using this function. If speed is important,
961 If speed is important, consider using `eq'. 1062 consider using `eq'. When storing strings in the hash table, you will
962 When storing strings in the hash table, you will likely need to use `equal'. 1063 likely need to use `equal' or `equalp' (for case-insensitivity). With other
1064 objects, consider using a test function defined with
1065 `define-hash-table-test', an emacs extension to this Common Lisp hash table
1066 API.
963 1067
964 Keyword :size specifies the number of keys likely to be inserted. 1068 Keyword :size specifies the number of keys likely to be inserted.
965 This number of entries can be inserted without enlarging the hash table. 1069 This number of entries can be inserted without enlarging the hash table.
966 1070
967 Keyword :rehash-size must be a float greater than 1.0, and specifies 1071 Keyword :rehash-size must be a float greater than 1.0, and specifies
1004 (int nargs, Lisp_Object *args)) 1108 (int nargs, Lisp_Object *args))
1005 { 1109 {
1006 #ifdef NO_NEED_TO_HANDLE_21_4_CODE 1110 #ifdef NO_NEED_TO_HANDLE_21_4_CODE
1007 PARSE_KEYWORDS (Qmake_hash_table, nargs, args, 0, 5, 1111 PARSE_KEYWORDS (Qmake_hash_table, nargs, args, 0, 5,
1008 (test, size, rehash_size, rehash_threshold, weakness), 1112 (test, size, rehash_size, rehash_threshold, weakness),
1009 NULL, weakness = Qunbound), 0); 1113 NULL, 0);
1010 #else 1114 #else
1011 PARSE_KEYWORDS (Qmake_hash_table, nargs, args, 0, 6, 1115 PARSE_KEYWORDS (Qmake_hash_table, nargs, args, 0, 6,
1012 (test, size, rehash_size, rehash_threshold, weakness, 1116 (test, size, rehash_size, rehash_threshold, weakness,
1013 type), (type = Qunbound, weakness = Qunbound), 0); 1117 type), (type = Qunbound, weakness = Qunbound), 0);
1014 1118
1032 VALIDATE_VAR (size); 1136 VALIDATE_VAR (size);
1033 VALIDATE_VAR (rehash_size); 1137 VALIDATE_VAR (rehash_size);
1034 VALIDATE_VAR (rehash_threshold); 1138 VALIDATE_VAR (rehash_threshold);
1035 VALIDATE_VAR (weakness); 1139 VALIDATE_VAR (weakness);
1036 1140
1037 return make_standard_lisp_hash_table 1141 return make_general_lisp_hash_table
1038 (decode_hash_table_test (test), 1142 (decode_hash_table_test (test),
1039 decode_hash_table_size (size), 1143 decode_hash_table_size (size),
1040 decode_hash_table_rehash_size (rehash_size), 1144 decode_hash_table_rehash_size (rehash_size),
1041 decode_hash_table_rehash_threshold (rehash_threshold), 1145 decode_hash_table_rehash_threshold (rehash_threshold),
1042 decode_hash_table_weakness (weakness)); 1146 decode_hash_table_weakness (weakness));
1069 static void 1173 static void
1070 resize_hash_table (Lisp_Hash_Table *ht, Elemcount new_size) 1174 resize_hash_table (Lisp_Hash_Table *ht, Elemcount new_size)
1071 { 1175 {
1072 htentry *old_entries, *new_entries, *sentinel, *e; 1176 htentry *old_entries, *new_entries, *sentinel, *e;
1073 Elemcount old_size; 1177 Elemcount old_size;
1178 Hash_Table_Test *http = XHASH_TABLE_TEST (ht->test);
1074 1179
1075 old_size = ht->size; 1180 old_size = ht->size;
1076 ht->size = new_size; 1181 ht->size = new_size;
1077 1182
1078 old_entries = ht->hentries; 1183 old_entries = ht->hentries;
1084 compute_hash_table_derived_values (ht); 1189 compute_hash_table_derived_values (ht);
1085 1190
1086 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++) 1191 for (e = old_entries, sentinel = e + old_size; e < sentinel; e++)
1087 if (!HTENTRY_CLEAR_P (e)) 1192 if (!HTENTRY_CLEAR_P (e))
1088 { 1193 {
1089 htentry *probe = new_entries + HASHCODE (e->key, ht); 1194 htentry *probe = new_entries + HASHCODE (e->key, ht, http);
1090 LINEAR_PROBING_LOOP (probe, new_entries, new_size) 1195 LINEAR_PROBING_LOOP (probe, new_entries, new_size)
1091 ; 1196 ;
1092 *probe = *e; 1197 *probe = *e;
1093 } 1198 }
1094 1199
1105 { 1210 {
1106 const Lisp_Hash_Table *ht = xhash_table (hash_table); 1211 const Lisp_Hash_Table *ht = xhash_table (hash_table);
1107 /* We leave room for one never-occupied sentinel htentry at the end. */ 1212 /* We leave room for one never-occupied sentinel htentry at the end. */
1108 htentry *new_entries = allocate_hash_table_entries (ht->size + 1); 1213 htentry *new_entries = allocate_hash_table_entries (ht->size + 1);
1109 htentry *e, *sentinel; 1214 htentry *e, *sentinel;
1215 Hash_Table_Test *http = XHASH_TABLE_TEST (ht->test);
1110 1216
1111 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) 1217 for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++)
1112 if (!HTENTRY_CLEAR_P (e)) 1218 if (!HTENTRY_CLEAR_P (e))
1113 { 1219 {
1114 htentry *probe = new_entries + HASHCODE (e->key, ht); 1220 htentry *probe = new_entries + HASHCODE (e->key, ht, http);
1115 LINEAR_PROBING_LOOP (probe, new_entries, ht->size) 1221 LINEAR_PROBING_LOOP (probe, new_entries, ht->size)
1116 ; 1222 ;
1117 *probe = *e; 1223 *probe = *e;
1118 } 1224 }
1119 1225
1133 } 1239 }
1134 1240
1135 htentry * 1241 htentry *
1136 find_htentry (Lisp_Object key, const Lisp_Hash_Table *ht) 1242 find_htentry (Lisp_Object key, const Lisp_Hash_Table *ht)
1137 { 1243 {
1138 hash_table_test_function_t test_function = ht->test_function; 1244 Lisp_Object test = ht->test;
1245 Hash_Table_Test *http = XHASH_TABLE_TEST (test);
1246
1139 htentry *entries = ht->hentries; 1247 htentry *entries = ht->hentries;
1140 htentry *probe = entries + HASHCODE (key, ht); 1248 htentry *probe = entries + HASHCODE (key, ht, http);
1141 1249
1142 LINEAR_PROBING_LOOP (probe, entries, ht->size) 1250 LINEAR_PROBING_LOOP (probe, entries, ht->size)
1143 if (KEYS_EQUAL_P (probe->key, key, test_function)) 1251 if (KEYS_EQUAL_P (probe->key, key, test, http))
1144 break; 1252 break;
1145 1253
1146 return probe; 1254 return probe;
1147 } 1255 }
1148 1256
1149 /* A version of Fputhash() that increments the value by the specified 1257 /* A version of Fputhash() that increments the value by the specified
1150 amount and dispenses will all error checks. Assumes that tables does 1258 amount and dispenses with all error checks. Assumes that tables does
1151 comparison using EQ. Used by the profiling routines to avoid 1259 comparison using EQ. Used by the profiling routines to avoid
1152 overhead -- profiling overhead was being recorded at up to 15% of the 1260 overhead -- profiling overhead was being recorded at up to 15% of the
1153 total time. */ 1261 total time. */
1154 1262
1155 void 1263 void
1156 inchash_eq (Lisp_Object key, Lisp_Object table, EMACS_INT offset) 1264 inchash_eq (Lisp_Object key, Lisp_Object table, EMACS_INT offset)
1157 { 1265 {
1158 Lisp_Hash_Table *ht = XHASH_TABLE (table); 1266 Lisp_Hash_Table *ht = XHASH_TABLE (table);
1267 Hash_Table_Test *http = XHASH_TABLE_TEST (ht->test);
1159 htentry *entries = ht->hentries; 1268 htentry *entries = ht->hentries;
1160 htentry *probe = entries + HASHCODE (key, ht); 1269 htentry *probe = entries + HASHCODE (key, ht, http);
1161 1270
1162 LINEAR_PROBING_LOOP (probe, entries, ht->size) 1271 LINEAR_PROBING_LOOP (probe, entries, ht->size)
1163 if (EQ (probe->key, key)) 1272 if (EQ (probe->key, key))
1164 break; 1273 break;
1165 1274
1211 Subsequent entries are removed and reinserted. 1320 Subsequent entries are removed and reinserted.
1212 We don't use tombstones - too wasteful. */ 1321 We don't use tombstones - too wasteful. */
1213 static void 1322 static void
1214 remhash_1 (Lisp_Hash_Table *ht, htentry *entries, htentry *probe) 1323 remhash_1 (Lisp_Hash_Table *ht, htentry *entries, htentry *probe)
1215 { 1324 {
1325 Hash_Table_Test *http = XHASH_TABLE_TEST (ht->test);
1216 Elemcount size = ht->size; 1326 Elemcount size = ht->size;
1217 CLEAR_HTENTRY (probe); 1327 CLEAR_HTENTRY (probe);
1218 probe++; 1328 probe++;
1219 ht->count--; 1329 ht->count--;
1220 1330
1221 LINEAR_PROBING_LOOP (probe, entries, size) 1331 LINEAR_PROBING_LOOP (probe, entries, size)
1222 { 1332 {
1223 Lisp_Object key = probe->key; 1333 Lisp_Object key = probe->key;
1224 htentry *probe2 = entries + HASHCODE (key, ht); 1334 htentry *probe2 = entries + HASHCODE (key, ht, http);
1225 LINEAR_PROBING_LOOP (probe2, entries, size) 1335 LINEAR_PROBING_LOOP (probe2, entries, size)
1226 if (EQ (probe2->key, key)) 1336 if (EQ (probe2->key, key))
1227 /* htentry at probe doesn't need to move. */ 1337 /* htentry at probe doesn't need to move. */
1228 goto continue_outer_loop; 1338 goto continue_outer_loop;
1229 /* Move htentry from probe to new home at probe2. */ 1339 /* Move htentry from probe to new home at probe2. */
1277 { 1387 {
1278 return make_int (xhash_table (hash_table)->count); 1388 return make_int (xhash_table (hash_table)->count);
1279 } 1389 }
1280 1390
1281 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* 1391 DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /*
1282 Return the test function of HASH-TABLE. 1392 Return HASH-TABLE's test.
1283 This can be one of `eq', `eql' or `equal'. 1393
1394 This can be one of `eq', `eql', `equal', `equalp', or some symbol supplied
1395 as the NAME argument to `define-hash-table-test', which see.
1284 */ 1396 */
1285 (hash_table)) 1397 (hash_table))
1286 { 1398 {
1287 hash_table_test_function_t fun = xhash_table (hash_table)->test_function; 1399 CHECK_HASH_TABLE (hash_table);
1288 1400 return XHASH_TABLE_TEST (XHASH_TABLE (hash_table)->test)->name;
1289 return (fun == lisp_object_eql_equal ? Qeql :
1290 fun == lisp_object_equal_equal ? Qequal :
1291 Qeq);
1292 } 1401 }
1293 1402
1294 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* 1403 DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /*
1295 Return the size of HASH-TABLE. 1404 Return the size of HASH-TABLE.
1296 This is the current number of slots in HASH-TABLE, whether occupied or not. 1405 This is the current number of slots in HASH-TABLE, whether occupied or not.
1709 } 1818 }
1710 1819
1711 /* Return a hash value for an array of Lisp_Objects of size SIZE. */ 1820 /* Return a hash value for an array of Lisp_Objects of size SIZE. */
1712 1821
1713 Hashcode 1822 Hashcode
1714 internal_array_hash (Lisp_Object *arr, int size, int depth) 1823 internal_array_hash (Lisp_Object *arr, int size, int depth, Boolint equalp)
1715 { 1824 {
1716 int i; 1825 int i;
1717 Hashcode hash = 0; 1826 Hashcode hash = 0;
1718 depth++; 1827 depth++;
1719 1828
1720 if (size <= 5) 1829 if (size <= 5)
1721 { 1830 {
1722 for (i = 0; i < size; i++) 1831 for (i = 0; i < size; i++)
1723 hash = HASH2 (hash, internal_hash (arr[i], depth)); 1832 hash = HASH2 (hash, internal_hash (arr[i], depth, equalp));
1724 return hash; 1833 return hash;
1725 } 1834 }
1726 1835
1727 /* just pick five elements scattered throughout the array. 1836 /* just pick five elements scattered throughout the array.
1728 A slightly better approach would be to offset by some 1837 A slightly better approach would be to offset by some
1729 noise factor from the points chosen below. */ 1838 noise factor from the points chosen below. */
1730 for (i = 0; i < 5; i++) 1839 for (i = 0; i < 5; i++)
1731 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth)); 1840 hash = HASH2 (hash, internal_hash (arr[i*size/5], depth, equalp));
1732 1841
1733 return hash; 1842 return hash;
1843 }
1844
1845 /* This needs to be algorithmically the same as
1846 internal_array_hash(). Unfortunately, for strings with non-ASCII content,
1847 it has to be O(2N), I don't see a reasonable alternative to hashing
1848 sequence relying on their length. It is O(1) for pure ASCII strings,
1849 though. */
1850
1851 static Hashcode
1852 string_equalp_hash (Lisp_Object string)
1853 {
1854 Bytecount len = XSTRING_LENGTH (string),
1855 ascii_begin = (Bytecount) XSTRING_ASCII_BEGIN (string);
1856 const Ibyte *ptr = XSTRING_DATA (string), *pend = ptr + len;
1857 Charcount clen;
1858 Hashcode hash = 0;
1859
1860 if (len == ascii_begin)
1861 {
1862 clen = len;
1863 }
1864 else
1865 {
1866 clen = string_char_length (string);
1867 }
1868
1869 if (clen <= 5)
1870 {
1871 while (ptr < pend)
1872 {
1873 hash = HASH2 (hash,
1874 LISP_HASH (make_char (CANONCASE (NULL,
1875 itext_ichar (ptr)))));
1876 INC_IBYTEPTR (ptr);
1877 }
1878 }
1879 else
1880 {
1881 int ii;
1882
1883 if (clen == len)
1884 {
1885 for (ii = 0; ii < 5; ii++)
1886 {
1887 hash = HASH2 (hash,
1888 LISP_HASH (make_char
1889 (CANONCASE (NULL,
1890 ptr[ii * clen / 5]))));
1891 }
1892 }
1893 else
1894 {
1895 Charcount this_char = 0, last_char = 0;
1896 for (ii = 0; ii < 5; ii++)
1897 {
1898 this_char = ii * clen / 5;
1899 ptr = itext_n_addr (ptr, this_char - last_char);
1900 last_char = this_char;
1901
1902 hash = HASH2 (hash,
1903 LISP_HASH (make_char
1904 (CANONCASE (NULL, itext_ichar (ptr)))));
1905 }
1906 }
1907 }
1908
1909 return HASH2 (clen, hash);
1734 } 1910 }
1735 1911
1736 /* Return a hash value for a Lisp_Object. This is for use when hashing 1912 /* Return a hash value for a Lisp_Object. This is for use when hashing
1737 objects with the comparison being `equal' (for `eq', you can just 1913 objects with the comparison being `equal' (for `eq', you can just
1738 use the Lisp_Object itself as the hash value). You need to make a 1914 use the Lisp_Object itself as the hash value). You need to make a
1744 and only hash at most 5 elements out of a vector. Theoretically 1920 and only hash at most 5 elements out of a vector. Theoretically
1745 we could still take 5^5 time (a big big number) to compute a 1921 we could still take 5^5 time (a big big number) to compute a
1746 hash, but practically this won't ever happen. */ 1922 hash, but practically this won't ever happen. */
1747 1923
1748 Hashcode 1924 Hashcode
1749 internal_hash (Lisp_Object obj, int depth) 1925 internal_hash (Lisp_Object obj, int depth, Boolint equalp)
1750 { 1926 {
1751 if (depth > 5) 1927 if (depth > 5)
1752 return 0; 1928 return 0;
1753 1929
1754 if (CONSP(obj)) 1930 if (CONSP(obj))
1759 depth += 1; 1935 depth += 1;
1760 1936
1761 if (!CONSP(XCDR(obj))) 1937 if (!CONSP(XCDR(obj)))
1762 { 1938 {
1763 /* special case for '(a . b) conses */ 1939 /* special case for '(a . b) conses */
1764 return HASH2(internal_hash(XCAR(obj), depth), 1940 return HASH2(internal_hash(XCAR(obj), depth, equalp),
1765 internal_hash(XCDR(obj), depth)); 1941 internal_hash(XCDR(obj), depth, equalp));
1766 } 1942 }
1767 1943
1768 /* Don't simply tail recurse; we want to hash lists with the 1944 /* Don't simply tail recurse; we want to hash lists with the
1769 same contents in distinct orders differently. */ 1945 same contents in distinct orders differently. */
1770 hash = internal_hash(XCAR(obj), depth); 1946 hash = internal_hash(XCAR(obj), depth, equalp);
1771 1947
1772 obj = XCDR(obj); 1948 obj = XCDR(obj);
1773 for (s = 1; s < 6 && CONSP(obj); obj = XCDR(obj), s++) 1949 for (s = 1; s < 6 && CONSP(obj); obj = XCDR(obj), s++)
1774 { 1950 {
1775 h = internal_hash(XCAR(obj), depth); 1951 h = internal_hash(XCAR(obj), depth, equalp);
1776 hash = HASH3(hash, h, s); 1952 hash = HASH3(hash, h, s);
1777 } 1953 }
1778 1954
1779 return hash; 1955 return hash;
1780 } 1956 }
1781 if (STRINGP (obj)) 1957 if (STRINGP (obj))
1782 { 1958 {
1959 if (equalp)
1960 {
1961 return string_equalp_hash (obj);
1962 }
1963
1783 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj)); 1964 return hash_string (XSTRING_DATA (obj), XSTRING_LENGTH (obj));
1784 } 1965 }
1785 if (LRECORDP (obj)) 1966 if (LRECORDP (obj))
1786 { 1967 {
1787 const struct lrecord_implementation 1968 const struct lrecord_implementation
1788 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj); 1969 *imp = XRECORD_LHEADER_IMPLEMENTATION (obj);
1789 if (imp->hash) 1970 if (imp->hash)
1790 return imp->hash (obj, depth); 1971 return imp->hash (obj, depth, equalp);
1972 }
1973
1974 if (equalp)
1975 {
1976 if (CHARP (obj))
1977 {
1978 /* Characters and numbers of the same numeric value hash
1979 differently, which is fine, they're not equalp. */
1980 return LISP_HASH (make_char (CANONCASE (NULL, XCHAR (obj))));
1981 }
1982
1983 if (INTP (obj))
1984 {
1985 return FLOAT_HASHCODE_FROM_DOUBLE ((double) (XINT (obj)));
1986 }
1791 } 1987 }
1792 1988
1793 return LISP_HASH (obj); 1989 return LISP_HASH (obj);
1794 } 1990 }
1795 1991
1796 DEFUN ("sxhash", Fsxhash, 1, 1, 0, /* 1992 DEFUN ("eq-hash", Feq_hash, 1, 1, 0, /*
1797 Return a hash value for OBJECT. 1993 Return a hash value for OBJECT appropriate for use with `eq.'
1798 \(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)).
1799 */ 1994 */
1800 (object)) 1995 (object))
1801 { 1996 {
1802 return make_int (internal_hash (object, 0)); 1997 return make_integer (XPNTRVAL (object));
1803 } 1998 }
1804 1999
1805 #if 0 2000 DEFUN ("eql-hash", Feql_hash, 1, 1, 0, /*
1806 DEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* 2001 Return a hash value for OBJECT appropriate for use with `eql.'
1807 Hash value of OBJECT. For debugging.
1808 The value is returned as (HIGH . LOW).
1809 */ 2002 */
1810 (object)) 2003 (object))
1811 { 2004 {
1812 /* This function is pretty 32bit-centric. */ 2005 EMACS_INT hashed = lisp_object_eql_hash (NULL, object);
1813 Hashcode hash = internal_hash (object, 0); 2006 return make_integer (hashed);
1814 return Fcons (hash >> 16, hash & 0xffff); 2007 }
1815 } 2008
1816 #endif 2009 DEFUN ("equal-hash", Fequal_hash, 1, 1, 0, /*
1817 2010 Return a hash value for OBJECT appropriate for use with `equal.'
2011 \(equal obj1 obj2) implies (= (equal-hash obj1) (equal-hash obj2)).
2012 */
2013 (object))
2014 {
2015 EMACS_INT hashed = internal_hash (object, 0, 0);
2016 return make_integer (hashed);
2017 }
2018
2019 DEFUN ("equalp-hash", Fequalp_hash, 1, 1, 0, /*
2020 Return a hash value for OBJECT appropriate for use with `equalp.'
2021 */
2022 (object))
2023 {
2024 EMACS_INT hashed = internal_hash (object, 0, 1);
2025 return make_integer (hashed);
2026 }
2027
2028 static Lisp_Object
2029 make_hash_table_test (Lisp_Object name,
2030 hash_table_equal_function_t equal_function,
2031 hash_table_hash_function_t hash_function,
2032 Lisp_Object lisp_equal_function,
2033 Lisp_Object lisp_hash_function)
2034 {
2035 Lisp_Object result = ALLOC_NORMAL_LISP_OBJECT (hash_table_test);
2036 Hash_Table_Test *http = XHASH_TABLE_TEST (result);
2037
2038 http->name = name;
2039 http->equal_function = equal_function;
2040 http->hash_function = hash_function;
2041 http->lisp_equal_function = lisp_equal_function;
2042 http->lisp_hash_function = lisp_hash_function;
2043
2044 return result;
2045 }
2046
2047 Lisp_Object
2048 define_hash_table_test (Lisp_Object name,
2049 hash_table_equal_function_t equal_function,
2050 hash_table_hash_function_t hash_function,
2051 Lisp_Object lisp_equal_function,
2052 Lisp_Object lisp_hash_function)
2053 {
2054 Lisp_Object result = make_hash_table_test (name, equal_function,
2055 hash_function,
2056 lisp_equal_function,
2057 lisp_hash_function);
2058 XWEAK_LIST_LIST (Vhash_table_test_weak_list)
2059 = Fcons (Fcons (name, result),
2060 XWEAK_LIST_LIST (Vhash_table_test_weak_list));
2061
2062 return result;
2063 }
2064
2065 DEFUN ("define-hash-table-test", Fdefine_hash_table_test, 3, 3, 0, /*
2066 Define a new hash table test with name NAME, a symbol.
2067
2068 In a hash table created with NAME as its test, use EQUAL-FUNCTION to compare
2069 keys, and HASH-FUNCTION for computing hash codes of keys.
2070
2071 EQUAL-FUNCTION must be a function taking two arguments and returning non-nil
2072 if both arguments are the same. HASH-FUNCTION must be a function taking one
2073 argument and returning an integer that is the hash code of the argument.
2074
2075 Computation should use the whole value range of the underlying machine long
2076 type. In XEmacs this will necessitate bignums for values above
2077 `most-positive-fixnum' but below (1+ (* most-positive-fixnum 2)) and
2078 analagous values below `most-negative-fixnum'. Relatively poor hashing
2079 performance is guaranteed in a build without bignums.
2080
2081 This function returns t if successful, and errors if NAME
2082 cannot be defined as a hash table test.
2083 */
2084 (name, equal_function, hash_function))
2085 {
2086 Lisp_Object min, max, lookup;
2087
2088 CHECK_SYMBOL (name);
2089
2090 lookup = Fassq (name, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
2091
2092 if (!NILP (lookup))
2093 {
2094 invalid_change ("Cannot redefine existing hash table test", name);
2095 }
2096
2097 min = Ffunction_min_args (equal_function);
2098 max = Ffunction_max_args (equal_function);
2099
2100 if (!((XINT (min) <= 2) && (NILP (max) || 2 <= XINT (max))))
2101 {
2102 signal_wrong_number_of_arguments_error (equal_function, 2);
2103 }
2104
2105 min = Ffunction_min_args (hash_function);
2106 max = Ffunction_max_args (hash_function);
2107
2108 if (!((XINT (min) <= 1) && (NILP (max) || 1 <= XINT (max))))
2109 {
2110 signal_wrong_number_of_arguments_error (hash_function, 1);
2111 }
2112
2113 define_hash_table_test (name, lisp_object_general_equal,
2114 lisp_object_general_hash, equal_function,
2115 hash_function);
2116 return Qt;
2117 }
2118
2119 DEFUN ("valid-hash-table-test-p", Fvalid_hash_table_test_p, 1, 1, 0, /*
2120 Return t if OBJECT names a hash table test, nil otherwise.
2121
2122 A valid hash table test is one of the symbols `eq', `eql', `equal',
2123 `equalp', or some symbol passed as the NAME argument to
2124 `define-hash-table-test'. As a special case, `nil' is regarded as
2125 equivalent to `eql'.
2126 */
2127 (object))
2128 {
2129 Lisp_Object lookup;
2130
2131 if (NILP (object))
2132 {
2133 return Qt;
2134 }
2135
2136 lookup = Fassq (object, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
2137
2138 if (!NILP (lookup))
2139 {
2140 return Qt;
2141 }
2142
2143 return Qnil;
2144 }
2145
2146 DEFUN ("hash-table-test-list", Fhash_table_test_list, 0, 0, 0, /*
2147 Return a list of symbols naming valid hash table tests.
2148 These can be passed as the value of the TEST keyword to `make-hash-table'.
2149 This list does not include nil, regarded as equivalent to `eql' by
2150 `make-hash-table'.
2151 */
2152 ())
2153 {
2154 Lisp_Object result = Qnil;
2155
2156 LIST_LOOP_2 (test, XWEAK_LIST_LIST (Vhash_table_test_weak_list))
2157 {
2158 if (!UNBOUNDP (XCAR (test)))
2159 {
2160 result = Fcons (XCAR (test), result);
2161 }
2162 }
2163
2164 return result;
2165 }
2166
2167 DEFUN ("hash-table-test-equal-function",
2168 Fhash_table_test_equal_function, 1, 1, 0, /*
2169 Return the comparison function used for hash table test TEST.
2170 See `define-hash-table-test' and `make-hash-table'.
2171 */
2172 (test))
2173 {
2174 Lisp_Object lookup;
2175
2176 if (NILP (test))
2177 {
2178 test = Qeql;
2179 }
2180
2181 lookup = Fassq (test, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
2182 if (NILP (lookup))
2183 {
2184 invalid_argument ("Not a defined hash table test", test);
2185 }
2186
2187 return XHASH_TABLE_TEST (XCDR (lookup))->lisp_equal_function;
2188 }
2189
2190 DEFUN ("hash-table-test-hash-function",
2191 Fhash_table_test_hash_function, 1, 1, 0, /*
2192 Return the hash function used for hash table test TEST.
2193 See `define-hash-table-test' and `make-hash-table'.
2194 */
2195 (test))
2196 {
2197 Lisp_Object lookup;
2198
2199 if (NILP (test))
2200 {
2201 test = Qeql;
2202 }
2203
2204 lookup = Fassq (test, XWEAK_LIST_LIST (Vhash_table_test_weak_list));
2205 if (NILP (lookup))
2206 {
2207 invalid_argument ("Not a defined hash table test", test);
2208 }
2209
2210 return XHASH_TABLE_TEST (XCDR (lookup))->lisp_hash_function;
2211 }
1818 2212
1819 /************************************************************************/ 2213 /************************************************************************/
1820 /* initialization */ 2214 /* initialization */
1821 /************************************************************************/ 2215 /************************************************************************/
1822 2216
1844 DEFSUBR (Fhash_table_size); 2238 DEFSUBR (Fhash_table_size);
1845 DEFSUBR (Fhash_table_rehash_size); 2239 DEFSUBR (Fhash_table_rehash_size);
1846 DEFSUBR (Fhash_table_rehash_threshold); 2240 DEFSUBR (Fhash_table_rehash_threshold);
1847 DEFSUBR (Fhash_table_weakness); 2241 DEFSUBR (Fhash_table_weakness);
1848 DEFSUBR (Fhash_table_type); /* obsolete */ 2242 DEFSUBR (Fhash_table_type); /* obsolete */
1849 DEFSUBR (Fsxhash); 2243
1850 #if 0 2244 DEFSUBR (Feq_hash);
1851 DEFSUBR (Finternal_hash_value); 2245 DEFSUBR (Feql_hash);
1852 #endif 2246 DEFSUBR (Fequal_hash);
2247 Ffset (intern ("sxhash"), intern ("equal-hash"));
2248 DEFSUBR (Fequalp_hash);
2249
2250 DEFSUBR (Fdefine_hash_table_test);
2251 DEFSUBR (Fvalid_hash_table_test_p);
2252 DEFSUBR (Fhash_table_test_list);
2253 DEFSUBR (Fhash_table_test_equal_function);
2254 DEFSUBR (Fhash_table_test_hash_function);
1853 2255
1854 DEFSYMBOL_MULTIWORD_PREDICATE (Qhash_tablep); 2256 DEFSYMBOL_MULTIWORD_PREDICATE (Qhash_tablep);
2257
1855 DEFSYMBOL (Qhash_table); 2258 DEFSYMBOL (Qhash_table);
1856 DEFSYMBOL (Qhashtable); 2259 DEFSYMBOL (Qhashtable);
1857 DEFSYMBOL (Qmake_hash_table); 2260 DEFSYMBOL (Qmake_hash_table);
1858 DEFSYMBOL (Qweakness); 2261 DEFSYMBOL (Qweakness);
1859 DEFSYMBOL (Qvalue); 2262 DEFSYMBOL (Qvalue);
1878 } 2281 }
1879 2282
1880 void 2283 void
1881 vars_of_elhash (void) 2284 vars_of_elhash (void)
1882 { 2285 {
2286 Lisp_Object weak_list_list = XWEAK_LIST_LIST (Vhash_table_test_weak_list);
2287
2288 /* This var was staticpro'd and initialised in
2289 init_elhash_once_early, but its Vall_weak_lists isn't sane, since
2290 that was done before vars_of_data() was called. Create a sane
2291 weak list object now, set its list appropriately, assert that our
2292 data haven't been garbage collected. */
2293 assert (!NILP (Fassq (Qeq, weak_list_list)));
2294 assert (!NILP (Fassq (Qeql, weak_list_list)));
2295 assert (!NILP (Fassq (Qequal, weak_list_list)));
2296 assert (!NILP (Fassq (Qequalp, weak_list_list)));
2297 assert (4 == XINT (Flength (weak_list_list)));
2298
2299 Vhash_table_test_weak_list = make_weak_list (WEAK_LIST_KEY_ASSOC);
2300 XWEAK_LIST_LIST (Vhash_table_test_weak_list) = weak_list_list;
2301
1883 #ifdef MEMORY_USAGE_STATS 2302 #ifdef MEMORY_USAGE_STATS
1884 OBJECT_HAS_PROPERTY 2303 OBJECT_HAS_PROPERTY
1885 (hash_table, memusage_stats_list, list1 (intern ("hash-entries"))); 2304 (hash_table, memusage_stats_list, list1 (intern ("hash-entries")));
1886 #endif /* MEMORY_USAGE_STATS */ 2305 #endif /* MEMORY_USAGE_STATS */
1887 } 2306 }
1888 2307
1889 void 2308 void
1890 init_elhash_once_early (void) 2309 init_elhash_once_early (void)
1891 { 2310 {
1892 INIT_LISP_OBJECT (hash_table); 2311 INIT_LISP_OBJECT (hash_table);
2312 INIT_LISP_OBJECT (hash_table_test);
2313
1893 #ifdef NEW_GC 2314 #ifdef NEW_GC
1894 INIT_LISP_OBJECT (hash_table_entry); 2315 INIT_LISP_OBJECT (hash_table_entry);
1895 #endif /* NEW_GC */ 2316 #endif /* NEW_GC */
1896 2317
2318 /* init_elhash_once_early() is called very early, we can't have these
2319 DEFSYMBOLs in syms_of_elhash(), unfortunately. */
2320
2321 DEFSYMBOL (Qeq);
2322 DEFSYMBOL (Qeql);
2323 DEFSYMBOL (Qequal);
2324 DEFSYMBOL (Qequalp);
2325
2326 DEFSYMBOL (Qeq_hash);
2327 DEFSYMBOL (Qeql_hash);
2328 DEFSYMBOL (Qequal_hash);
2329 DEFSYMBOL (Qequalp_hash);
2330
1897 /* This must NOT be staticpro'd */ 2331 /* This must NOT be staticpro'd */
1898 Vall_weak_hash_tables = Qnil; 2332 Vall_weak_hash_tables = Qnil;
1899 dump_add_weak_object_chain (&Vall_weak_hash_tables); 2333 dump_add_weak_object_chain (&Vall_weak_hash_tables);
1900 } 2334
2335 staticpro (&Vhash_table_test_weak_list);
2336 Vhash_table_test_weak_list = make_weak_list (WEAK_LIST_KEY_ASSOC);
2337
2338 staticpro (&Vhash_table_test_eq);
2339 Vhash_table_test_eq = define_hash_table_test (Qeq, NULL, NULL, Qeq, Qeq_hash);
2340 staticpro (&Vhash_table_test_eql);
2341 Vhash_table_test_eql
2342 = define_hash_table_test (Qeql, lisp_object_eql_equal,
2343 lisp_object_eql_hash, Qeql, Qeql_hash);
2344 (void) define_hash_table_test (Qequal, lisp_object_equal_equal,
2345 lisp_object_equal_hash, Qequal, Qequal_hash);
2346 (void) define_hash_table_test (Qequalp, lisp_object_equalp_equal,
2347 lisp_object_equalp_hash, Qequalp, Qequalp_hash);
2348 }