comparison src/elhash.c @ 241:f955c73f5258 r20-5b19

Import from CVS: tag r20-5b19
author cvs
date Mon, 13 Aug 2007 10:16:16 +0200
parents 557eaa0339bf
children f220cc83d72e
comparison
equal deleted inserted replaced
240:835e739f3c17 241:f955c73f5258
49 static Lisp_Object Vall_weak_hashtables; 49 static Lisp_Object Vall_weak_hashtables;
50 50
51 static Lisp_Object mark_hashtable (Lisp_Object, void (*) (Lisp_Object)); 51 static Lisp_Object mark_hashtable (Lisp_Object, void (*) (Lisp_Object));
52 static void print_hashtable (Lisp_Object, Lisp_Object, int); 52 static void print_hashtable (Lisp_Object, Lisp_Object, int);
53 static int hashtable_equal (Lisp_Object t1, Lisp_Object t2, int depth); 53 static int hashtable_equal (Lisp_Object t1, Lisp_Object t2, int depth);
54 static unsigned long hashtable_hash (Lisp_Object obj, int depth);
54 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable, 55 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable,
55 mark_hashtable, print_hashtable, 0, 56 mark_hashtable, print_hashtable, 0,
56 hashtable_equal, 0, struct hashtable); 57 hashtable_equal, hashtable_hash,
58 struct hashtable);
57 59
58 static Lisp_Object 60 static Lisp_Object
59 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object)) 61 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object))
60 { 62 {
61 struct hashtable *table = XHASHTABLE (obj); 63 struct hashtable *table = XHASHTABLE (obj);
76 /* Equality of hashtables. Two hashtables are equal when they are of 78 /* Equality of hashtables. Two hashtables are equal when they are of
77 the same type and test function, they have the same number of 79 the same type and test function, they have the same number of
78 elements, and for each key in hashtable, the values are `equal'. 80 elements, and for each key in hashtable, the values are `equal'.
79 81
80 This is similar to Common Lisp `equalp' of hashtables, with the 82 This is similar to Common Lisp `equalp' of hashtables, with the
81 difference that CL requires the keys to be compared using the 83 difference that CL requires the keys to be compared with the test
82 `:test' function, which we don't do. Doing that would require 84 function, which we don't do. Doing that would require consing, and
83 consing, and consing is bad idea in `equal'. Anyway, our method 85 consing is bad idea in `equal'. Anyway, our method should provide
84 should provide the same result -- if the keys are not equal 86 the same result -- if the keys are not equal according to test
85 according to `:test', then Fgethash() in hashtable_equal_mapper() 87 function, then Fgethash() in hashtable_equal_mapper() will fail. */
86 will fail. */
87 struct hashtable_equal_closure 88 struct hashtable_equal_closure
88 { 89 {
89 int depth; 90 int depth;
90 int equal_so_far; 91 int equal;
91 Lisp_Object other_table; 92 Lisp_Object other_table;
92 }; 93 };
93 94
94 static void 95 static int
95 hashtable_equal_mapper (void *key, void *contents, void *arg) 96 hashtable_equal_mapper (void *key, void *contents, void *arg)
96 { 97 {
97 struct hashtable_equal_closure *closure = 98 struct hashtable_equal_closure *closure =
98 (struct hashtable_equal_closure *)arg; 99 (struct hashtable_equal_closure *)arg;
99 Lisp_Object keytem, valuetem; 100 Lisp_Object keytem, valuetem;
100 101 Lisp_Object value_in_other;
101 /* It would be beautiful if maphash() allowed us to bail out when C 102
102 function returns non-zero, a la map_extents() et al. #### Make 103 CVOID_TO_LISP (keytem, key);
103 it so! */ 104 CVOID_TO_LISP (valuetem, contents);
104 if (closure->equal_so_far) 105 /* Look up the key in the other hashtable, and compare the values. */
105 { 106 value_in_other = Fgethash (keytem, closure->other_table, Qunbound);
106 Lisp_Object value_in_other; 107 if (UNBOUNDP (value_in_other)
107 CVOID_TO_LISP (keytem, key); 108 || !internal_equal (valuetem, value_in_other, closure->depth))
108 CVOID_TO_LISP (valuetem, contents); 109 {
109 /* Look up the key in the other hashtable, and compare the 110 /* Give up. */
110 values. */ 111 closure->equal = 0;
111 value_in_other = Fgethash (keytem, closure->other_table, Qunbound); 112 return 1;
112 if (UNBOUNDP (value_in_other) 113 }
113 || !internal_equal (valuetem, value_in_other, closure->depth)) 114 return 0;
114 closure->equal_so_far = 0;
115 /* return 1; */
116 }
117 /* return 0; */
118 } 115 }
119 116
120 static int 117 static int
121 hashtable_equal (Lisp_Object t1, Lisp_Object t2, int depth) 118 hashtable_equal (Lisp_Object t1, Lisp_Object t2, int depth)
122 { 119 {
131 || (table1->type != table2->type) 128 || (table1->type != table2->type)
132 || (table1->fullness != table2->fullness)) 129 || (table1->fullness != table2->fullness))
133 return 0; 130 return 0;
134 131
135 closure.depth = depth + 1; 132 closure.depth = depth + 1;
136 closure.equal_so_far = 1; 133 closure.equal = 1;
137 closure.other_table = t2; 134 closure.other_table = t2;
138 elisp_maphash (hashtable_equal_mapper, t1, &closure); 135 elisp_maphash (hashtable_equal_mapper, t1, &closure);
139 return closure.equal_so_far; 136 return closure.equal;
137 }
138
139 /* Hashtable hash function. This hashes 5 key-value pairs. For EQ
140 hashtables, keys are used as the hash value themselves, whereas
141 values are hashed with internal_hash(). For EQUAL hashtables, both
142 keys and values are hashed properly. EQL tables are handled as
143 necessary. All of this should make the hash function compatible
144 with hashtable_equal(). The elements hashed are the first five
145 mapped over by maphash(). */
146
147 struct hashtable_hash_closure
148 {
149 struct hashtable *table;
150 int depth;
151 unsigned long hash;
152 int count;
153 };
154
155 /* Needed for tests. */
156 static int lisp_object_eql_equal (CONST void *x1, CONST void *x2);
157 static int lisp_object_equal_equal (CONST void *x1, CONST void *x2);
158
159 static int
160 hashtable_hash_mapper (void *key, void *contents, void *arg)
161 {
162 struct hashtable_hash_closure *closure =
163 (struct hashtable_hash_closure *)arg;
164 Lisp_Object valuetem, keytem;
165 unsigned long keyhash;
166
167 CVOID_TO_LISP (keytem, key);
168 CVOID_TO_LISP (valuetem, contents);
169
170 if (!closure->table->test_function)
171 /* For eq, use key itself as hash. */
172 keyhash = LISP_HASH (keytem);
173 else if (closure->table->test_function == lisp_object_eql_equal)
174 /* The same as eq, unless the key is float. */
175 keyhash = (FLOATP (keytem)
176 ? internal_hash (keytem, closure->depth) : LISP_HASH (keytem));
177 else
178 /* equal: hash the key properly. */
179 keyhash = internal_hash (keytem, closure->depth);
180
181 closure->hash = HASH3 (closure->hash, keyhash,
182 internal_hash (valuetem, closure->depth));
183 return (++closure->count > 5) ? 1 : 0;
184 }
185
186 static unsigned long
187 hashtable_hash (Lisp_Object obj, int depth)
188 {
189 struct hashtable_hash_closure closure;
190
191 closure.table = XHASHTABLE (obj);
192 closure.depth = depth + 1;
193 closure.hash = 0;
194 closure.count = 0;
195
196 elisp_maphash (hashtable_hash_mapper, obj, &closure);
197 return closure.hash;
140 } 198 }
141 199
142 /* Printing hashtables. 200 /* Printing hashtables.
143 201
144 This is non-trivial, because we use a readable structure-style 202 This is non-trivial, because we use a readable structure-style
155 instance: 213 instance:
156 214
157 #<hashtable size 2/13 data (key1 value1 key2 value2) 0x874d> 215 #<hashtable size 2/13 data (key1 value1 key2 value2) 0x874d>
158 216
159 The data is truncated to four pairs, and the rest is shown with 217 The data is truncated to four pairs, and the rest is shown with
160 `...'. The actual printer is non-consing. */ 218 `...'. This printer does not cons. */
161 219
162 struct print_hashtable_data_closure 220 struct print_hashtable_data_closure
163 { 221 {
164 EMACS_INT count; /* Used to implement truncation for 222 EMACS_INT count; /* Used to implement truncation for
165 non-readable printing, as well as 223 non-readable printing, as well as
166 to avoid the unnecessary space at 224 to avoid the unnecessary space at
167 the beginning. */ 225 the beginning. */
168 Lisp_Object printcharfun; 226 Lisp_Object printcharfun;
169 }; 227 };
170 228
171 static void 229 static int
172 print_hashtable_data_mapper (void *key, void *contents, void *arg) 230 print_hashtable_data_mapper (void *key, void *contents, void *arg)
173 { 231 {
174 Lisp_Object keytem, valuetem; 232 Lisp_Object keytem, valuetem;
175 struct print_hashtable_data_closure *closure = 233 struct print_hashtable_data_closure *closure =
176 (struct print_hashtable_data_closure *)arg; 234 (struct print_hashtable_data_closure *)arg;
186 print_internal (keytem, closure->printcharfun, 1); 244 print_internal (keytem, closure->printcharfun, 1);
187 write_c_string (" ", closure->printcharfun); 245 write_c_string (" ", closure->printcharfun);
188 print_internal (valuetem, closure->printcharfun, 1); 246 print_internal (valuetem, closure->printcharfun, 1);
189 } 247 }
190 ++closure->count; 248 ++closure->count;
249 return 0;
191 } 250 }
192 251
193 /* Print the data of the hashtable. This maps through a Lisp 252 /* Print the data of the hashtable. This maps through a Lisp
194 hashtable and prints key/value pairs using PRINTCHARFUN. */ 253 hashtable and prints key/value pairs using PRINTCHARFUN. */
195 static void 254 static void
202 write_c_string (" data (", printcharfun); 261 write_c_string (" data (", printcharfun);
203 elisp_maphash (print_hashtable_data_mapper, hashtable, &closure); 262 elisp_maphash (print_hashtable_data_mapper, hashtable, &closure);
204 write_c_string ((!print_readably && closure.count > 4) ? " ...)" : ")", 263 write_c_string ((!print_readably && closure.count > 4) ? " ...)" : ")",
205 printcharfun); 264 printcharfun);
206 } 265 }
207
208 /* Needed for tests. */
209 static int lisp_object_eql_equal (CONST void *x1, CONST void *x2);
210 static int lisp_object_equal_equal (CONST void *x1, CONST void *x2);
211 266
212 static void 267 static void
213 print_hashtable (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) 268 print_hashtable (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag)
214 { 269 {
215 struct hashtable *table = XHASHTABLE (obj); 270 struct hashtable *table = XHASHTABLE (obj);
224 table->type == HASHTABLE_KEY_WEAK ? "key-weak" : 279 table->type == HASHTABLE_KEY_WEAK ? "key-weak" :
225 table->type == HASHTABLE_VALUE_WEAK ? "value-weak" : 280 table->type == HASHTABLE_VALUE_WEAK ? "value-weak" :
226 "you-d-better-not-see-this")); 281 "you-d-better-not-see-this"));
227 write_c_string (buf, printcharfun); 282 write_c_string (buf, printcharfun);
228 } 283 }
229 /* These checks are way kludgy... */ 284 /* These checks have a kludgy look to them, but they are safe. Due
230 if (table->test_function == NULL) 285 to nature of hashing, you cannot use arbitrary test functions
286 anyway. */
287 if (!table->test_function)
231 write_c_string (" test eq", printcharfun); 288 write_c_string (" test eq", printcharfun);
232 else if (table->test_function == lisp_object_equal_equal) 289 else if (table->test_function == lisp_object_equal_equal)
233 write_c_string (" test equal", printcharfun); 290 write_c_string (" test equal", printcharfun);
234 else if (table->test_function == lisp_object_eql_equal) 291 else if (table->test_function == lisp_object_eql_equal)
235 DO_NOTHING; 292 DO_NOTHING;
519 causes efficiency problems, these can be resurrected. --ben */ 576 causes efficiency problems, these can be resurrected. --ben */
520 /* equality and hash functions for Lisp strings */ 577 /* equality and hash functions for Lisp strings */
521 int 578 int
522 lisp_string_equal (CONST void *x1, CONST void *x2) 579 lisp_string_equal (CONST void *x1, CONST void *x2)
523 { 580 {
581 /* This is wrong anyway. You can't use strcmp() on Lisp strings,
582 because they can contain zero characters. */
524 Lisp_Object str1, str2; 583 Lisp_Object str1, str2;
525 CVOID_TO_LISP (str1, x1); 584 CVOID_TO_LISP (str1, x1);
526 CVOID_TO_LISP (str2, x2); 585 CVOID_TO_LISP (str2, x2);
527 return !strcmp ((char *) XSTRING_DATA (str1), (char *) XSTRING_DATA (str2)); 586 return !strcmp ((char *) XSTRING_DATA (str1), (char *) XSTRING_DATA (str2));
528 } 587 }
801 return; 860 return;
802 } 861 }
803 signal_error (Qinvalid_function, list1 (function)); 862 signal_error (Qinvalid_function, list1 (function));
804 } 863 }
805 864
806 static void 865 static int
807 lisp_maphash_function (CONST void *void_key, 866 lisp_maphash_function (CONST void *void_key,
808 void *void_val, 867 void *void_val,
809 void *void_fn) 868 void *void_fn)
810 { 869 {
811 /* This function can GC */ 870 /* This function can GC */
812 Lisp_Object key, val, fn; 871 Lisp_Object key, val, fn;
813 CVOID_TO_LISP (key, void_key); 872 CVOID_TO_LISP (key, void_key);
814 VOID_TO_LISP (val, void_val); 873 VOID_TO_LISP (val, void_val);
815 VOID_TO_LISP (fn, void_fn); 874 VOID_TO_LISP (fn, void_fn);
816 call2 (fn, key, val); 875 call2 (fn, key, val);
876 return 0;
817 } 877 }
818 878
819 879
820 DEFUN ("maphash", Fmaphash, 2, 2, 0, /* 880 DEFUN ("maphash", Fmaphash, 2, 2, 0, /*
821 Map FUNCTION over entries in HASHTABLE, calling it with two args, 881 Map FUNCTION over entries in HASHTABLE, calling it with two args,
838 898
839 /* This function is for mapping a *C* function over the elements of a 899 /* This function is for mapping a *C* function over the elements of a
840 lisp hashtable. 900 lisp hashtable.
841 */ 901 */
842 void 902 void
843 elisp_maphash (maphash_function function, Lisp_Object hashtable, void *closure) 903 elisp_maphash (void (*function) (CONST void *key, void *contents,
904 void *extra_arg),
905 Lisp_Object hashtable, void *closure)
844 { 906 {
845 struct _C_hashtable htbl; 907 struct _C_hashtable htbl;
846 908
847 if (!gc_in_progress) CHECK_HASHTABLE (hashtable); 909 if (!gc_in_progress) CHECK_HASHTABLE (hashtable);
848 ht_copy_to_c (XHASHTABLE (hashtable), &htbl); 910 ht_copy_to_c (XHASHTABLE (hashtable), &htbl);
849 maphash (function, &htbl, closure); 911 maphash (function, &htbl, closure);
850 } 912 }
851 913
852 void 914 void
853 elisp_map_remhash (remhash_predicate function, Lisp_Object hashtable, 915 elisp_map_remhash (int (*function) (CONST void *key,
916 CONST void *contents,
917 void *extra_arg),
918 Lisp_Object hashtable,
854 void *closure) 919 void *closure)
855 { 920 {
856 struct _C_hashtable htbl; 921 struct _C_hashtable htbl;
857 922
858 if (!gc_in_progress) CHECK_HASHTABLE (hashtable); 923 if (!gc_in_progress) CHECK_HASHTABLE (hashtable);
931 void (*markobj) (Lisp_Object); 996 void (*markobj) (Lisp_Object);
932 enum hashtable_type type; 997 enum hashtable_type type;
933 int did_mark; 998 int did_mark;
934 }; 999 };
935 1000
936 static void 1001 static int
937 marking_mapper (CONST void *key, void *contents, void *closure) 1002 marking_mapper (CONST void *key, void *contents, void *closure)
938 { 1003 {
939 Lisp_Object keytem, valuetem; 1004 Lisp_Object keytem, valuetem;
940 struct marking_closure *fmh = 1005 struct marking_closure *fmh =
941 (struct marking_closure *) closure; 1006 (struct marking_closure *) closure;
999 1064
1000 default: 1065 default:
1001 abort (); /* Huh? */ 1066 abort (); /* Huh? */
1002 } 1067 }
1003 1068
1004 return; 1069 return 0;
1005 } 1070 }
1006 1071
1007 int 1072 int
1008 finish_marking_weak_hashtables (int (*obj_marked_p) (Lisp_Object), 1073 finish_marking_weak_hashtables (int (*obj_marked_p) (Lisp_Object),
1009 void (*markobj) (Lisp_Object)) 1074 void (*markobj) (Lisp_Object))
1187 } 1252 }
1188 1253
1189 return LISP_HASH (obj); 1254 return LISP_HASH (obj);
1190 } 1255 }
1191 1256
1257 #if 0
1258 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /*
1259 Hash value of OBJECT. For debugging.
1260 The value is returned as (HIGH . LOW).
1261 */
1262 (object))
1263 {
1264 /* This function is pretty 32bit-centric. */
1265 unsigned long hash = internal_hash (object, 0);
1266 return Fcons (hash >> 16, hash & 0xffff);
1267 }
1268 #endif
1269
1192 1270
1193 /************************************************************************/ 1271 /************************************************************************/
1194 /* initialization */ 1272 /* initialization */
1195 /************************************************************************/ 1273 /************************************************************************/
1196 1274
1207 DEFSUBR (Fmaphash); 1285 DEFSUBR (Fmaphash);
1208 DEFSUBR (Fhashtable_fullness); 1286 DEFSUBR (Fhashtable_fullness);
1209 DEFSUBR (Fmake_weak_hashtable); 1287 DEFSUBR (Fmake_weak_hashtable);
1210 DEFSUBR (Fmake_key_weak_hashtable); 1288 DEFSUBR (Fmake_key_weak_hashtable);
1211 DEFSUBR (Fmake_value_weak_hashtable); 1289 DEFSUBR (Fmake_value_weak_hashtable);
1290 #if 0
1291 DEFSUBR (Finternal_hash_value);
1292 #endif
1212 defsymbol (&Qhashtablep, "hashtablep"); 1293 defsymbol (&Qhashtablep, "hashtablep");
1213 defsymbol (&Qhashtable, "hashtable"); 1294 defsymbol (&Qhashtable, "hashtable");
1214 defsymbol (&Qweak, "weak"); 1295 defsymbol (&Qweak, "weak");
1215 defsymbol (&Qkey_weak, "key-weak"); 1296 defsymbol (&Qkey_weak, "key-weak");
1216 defsymbol (&Qvalue_weak, "value-weak"); 1297 defsymbol (&Qvalue_weak, "value-weak");