comparison src/elhash.c @ 231:557eaa0339bf r20-5b14

Import from CVS: tag r20-5b14
author cvs
date Mon, 13 Aug 2007 10:13:48 +0200
parents 2c611d1463a6
children f955c73f5258
comparison
equal deleted inserted replaced
230:39ed1d2bdd9d 231:557eaa0339bf
48 48
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 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable, 54 DEFINE_LRECORD_IMPLEMENTATION ("hashtable", hashtable,
54 mark_hashtable, print_hashtable, 0, 0, 0, 55 mark_hashtable, print_hashtable, 0,
55 struct hashtable); 56 hashtable_equal, 0, struct hashtable);
56 57
57 static Lisp_Object 58 static Lisp_Object
58 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object)) 59 mark_hashtable (Lisp_Object obj, void (*markobj) (Lisp_Object))
59 { 60 {
60 struct hashtable *table = XHASHTABLE (obj); 61 struct hashtable *table = XHASHTABLE (obj);
70 } 71 }
71 ((markobj) (table->zero_entry)); 72 ((markobj) (table->zero_entry));
72 return table->harray; 73 return table->harray;
73 } 74 }
74 75
76 /* Equality of hashtables. Two hashtables are equal when they are of
77 the same type and test function, they have the same number of
78 elements, and for each key in hashtable, the values are `equal'.
79
80 This is similar to Common Lisp `equalp' of hashtables, with the
81 difference that CL requires the keys to be compared using the
82 `:test' function, which we don't do. Doing that would require
83 consing, and consing is bad idea in `equal'. Anyway, our method
84 should provide the same result -- if the keys are not equal
85 according to `:test', then Fgethash() in hashtable_equal_mapper()
86 will fail. */
87 struct hashtable_equal_closure
88 {
89 int depth;
90 int equal_so_far;
91 Lisp_Object other_table;
92 };
93
94 static void
95 hashtable_equal_mapper (void *key, void *contents, void *arg)
96 {
97 struct hashtable_equal_closure *closure =
98 (struct hashtable_equal_closure *)arg;
99 Lisp_Object keytem, valuetem;
100
101 /* It would be beautiful if maphash() allowed us to bail out when C
102 function returns non-zero, a la map_extents() et al. #### Make
103 it so! */
104 if (closure->equal_so_far)
105 {
106 Lisp_Object value_in_other;
107 CVOID_TO_LISP (keytem, key);
108 CVOID_TO_LISP (valuetem, contents);
109 /* Look up the key in the other hashtable, and compare the
110 values. */
111 value_in_other = Fgethash (keytem, closure->other_table, Qunbound);
112 if (UNBOUNDP (value_in_other)
113 || !internal_equal (valuetem, value_in_other, closure->depth))
114 closure->equal_so_far = 0;
115 /* return 1; */
116 }
117 /* return 0; */
118 }
119
120 static int
121 hashtable_equal (Lisp_Object t1, Lisp_Object t2, int depth)
122 {
123 struct hashtable_equal_closure closure;
124 struct hashtable *table1 = XHASHTABLE (t1);
125 struct hashtable *table2 = XHASHTABLE (t2);
126
127 /* The objects are `equal' if they are of the same type, so return 0
128 if types or test functions are not the same. Obviously, the
129 number of elements must be equal, too. */
130 if ((table1->test_function != table2->test_function)
131 || (table1->type != table2->type)
132 || (table1->fullness != table2->fullness))
133 return 0;
134
135 closure.depth = depth + 1;
136 closure.equal_so_far = 1;
137 closure.other_table = t2;
138 elisp_maphash (hashtable_equal_mapper, t1, &closure);
139 return closure.equal_so_far;
140 }
141
75 /* Printing hashtables. 142 /* Printing hashtables.
76 143
77 This is non-trivial, because we use a readable structure-style 144 This is non-trivial, because we use a readable structure-style
78 syntax for hashtables. This means that a typical hashtable will be 145 syntax for hashtables. This means that a typical hashtable will be
79 readably printed in the form of: 146 readably printed in the form of:
90 #<hashtable size 2/13 data (key1 value1 key2 value2) 0x874d> 157 #<hashtable size 2/13 data (key1 value1 key2 value2) 0x874d>
91 158
92 The data is truncated to four pairs, and the rest is shown with 159 The data is truncated to four pairs, and the rest is shown with
93 `...'. The actual printer is non-consing. */ 160 `...'. The actual printer is non-consing. */
94 161
95 struct print_mapper_arg { 162 struct print_hashtable_data_closure
96 EMACS_INT count; /* Used to implement the truncation 163 {
97 for non-readable printing, as well 164 EMACS_INT count; /* Used to implement truncation for
98 as to avoid the unnecessary space 165 non-readable printing, as well as
99 at the beginning. */ 166 to avoid the unnecessary space at
167 the beginning. */
100 Lisp_Object printcharfun; 168 Lisp_Object printcharfun;
101 }; 169 };
102 170
103 static void 171 static void
104 print_hashtable_data_mapper (void *key, void *contents, void *arg) 172 print_hashtable_data_mapper (void *key, void *contents, void *arg)
105 { 173 {
106 Lisp_Object keytem, valuetem; 174 Lisp_Object keytem, valuetem;
107 struct print_mapper_arg *closure = (struct print_mapper_arg *)arg; 175 struct print_hashtable_data_closure *closure =
176 (struct print_hashtable_data_closure *)arg;
108 177
109 if (closure->count < 4 || print_readably) 178 if (closure->count < 4 || print_readably)
110 { 179 {
111 CVOID_TO_LISP (keytem, key); 180 CVOID_TO_LISP (keytem, key);
112 CVOID_TO_LISP (valuetem, contents); 181 CVOID_TO_LISP (valuetem, contents);
124 /* Print the data of the hashtable. This maps through a Lisp 193 /* Print the data of the hashtable. This maps through a Lisp
125 hashtable and prints key/value pairs using PRINTCHARFUN. */ 194 hashtable and prints key/value pairs using PRINTCHARFUN. */
126 static void 195 static void
127 print_hashtable_data (Lisp_Object hashtable, Lisp_Object printcharfun) 196 print_hashtable_data (Lisp_Object hashtable, Lisp_Object printcharfun)
128 { 197 {
129 struct print_mapper_arg closure; 198 struct print_hashtable_data_closure closure;
130 closure.count = 0; 199 closure.count = 0;
131 closure.printcharfun = printcharfun; 200 closure.printcharfun = printcharfun;
132 201
133 write_c_string (" data (", printcharfun); 202 write_c_string (" data (", printcharfun);
134 elisp_maphash (print_hashtable_data_mapper, hashtable, &closure); 203 elisp_maphash (print_hashtable_data_mapper, hashtable, &closure);
161 if (table->test_function == NULL) 230 if (table->test_function == NULL)
162 write_c_string (" test eq", printcharfun); 231 write_c_string (" test eq", printcharfun);
163 else if (table->test_function == lisp_object_equal_equal) 232 else if (table->test_function == lisp_object_equal_equal)
164 write_c_string (" test equal", printcharfun); 233 write_c_string (" test equal", printcharfun);
165 else if (table->test_function == lisp_object_eql_equal) 234 else if (table->test_function == lisp_object_eql_equal)
166 ; 235 DO_NOTHING;
167 else 236 else
168 abort (); 237 abort ();
169 if (table->fullness || !print_readably) 238 if (table->fullness || !print_readably)
170 { 239 {
171 if (print_readably) 240 if (print_readably)
172 sprintf (buf, " size %d", table->fullness); 241 sprintf (buf, " size %u", table->fullness);
173 else 242 else
174 sprintf (buf, " size %u/%ld", table->fullness, 243 sprintf (buf, " size %u/%ld", table->fullness,
175 XVECTOR_LENGTH (table->harray) / LISP_OBJECTS_PER_HENTRY); 244 XVECTOR_LENGTH (table->harray) / LISP_OBJECTS_PER_HENTRY);
176 write_c_string (buf, printcharfun); 245 write_c_string (buf, printcharfun);
177 } 246 }
557 if (NILP (sym)) return HASHTABLE_EQL; 626 if (NILP (sym)) return HASHTABLE_EQL;
558 if (EQ (sym, Qeq)) return HASHTABLE_EQ; 627 if (EQ (sym, Qeq)) return HASHTABLE_EQ;
559 if (EQ (sym, Qequal)) return HASHTABLE_EQUAL; 628 if (EQ (sym, Qequal)) return HASHTABLE_EQUAL;
560 if (EQ (sym, Qeql)) return HASHTABLE_EQL; 629 if (EQ (sym, Qeql)) return HASHTABLE_EQL;
561 630
562 signal_simple_error ("Invalid hashtable test fun", sym); 631 signal_simple_error ("Invalid hashtable test function", sym);
563 return HASHTABLE_EQ; /* not reached */ 632 return HASHTABLE_EQ; /* not reached */
564 } 633 }
565 634
566 DEFUN ("make-hashtable", Fmake_hashtable, 1, 2, 0, /* 635 DEFUN ("make-hashtable", Fmake_hashtable, 1, 2, 0, /*
567 Make a hashtable of initial size SIZE. 636 Make a hashtable of initial size SIZE.