1 /***********************************************************
2 Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Mapping object implementation; using a hash table */
27 /* This file should really be called "dictobject.c", since "mapping"
28 is the generic name for objects with an unorderred arbitrary key
29 set (just like lists are sequences), but since it improves (and was
30 originally derived from) a file by that name I had to change its
31 name. For the user these objects are still called "dictionaries". */
33 #include "allobjects.h"
34 #include "modsupport.h"
38 Table of primes suitable as keys, in ascending order.
39 The first line are the largest primes less than some powers of two,
40 the second line is the largest prime less than 6000,
41 the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1,
42 and the next three lines were suggested by Steve Kirsch.
43 The final value is a sentinel.
45 static long primes
[] = {
46 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
48 9551, 15683, 19609, 31397,
49 65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
50 4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
51 134217689L, 268435399L, 536870909L, 1073741789L,
55 /* Object used as dummy key to fill deleted entries */
56 static object
*dummy
; /* Initialized by first call to newmappingobject() */
59 Invariant for entries: when in use, de_value is not NULL and de_key is
60 not NULL and not dummy; when not in use, de_value is NULL and de_key
61 is either NULL or dummy. A dummy key value cannot be replaced by
62 NULL, since otherwise other keys may be lost.
71 To ensure the lookup algorithm terminates, the table size must be a
72 prime number and there must be at least one NULL key in the table.
73 The value ma_fill is the number of non-NULL keys; ma_used is the number
74 of non-NULL, non-dummy keys.
75 To avoid slowing down lookups on a near-full table, we resize the table
76 when it is more than half filled.
83 mappingentry
*ma_table
;
89 register mappingobject
*mp
;
90 if (dummy
== NULL
) { /* Auto-initialize dummy */
91 dummy
= newstringobject("<dummy key>");
95 mp
= NEWOBJ(mappingobject
, &Mappingtype
);
106 The basic lookup function used by all operations.
107 This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
108 Open addressing is preferred over chaining since the link overhead for
109 chaining would be substantial (100% with typical malloc overhead).
111 First a 32-bit hash value, 'sum', is computed from the key string.
112 The first character is added an extra time shifted by 8 to avoid hashing
113 single-character keys (often heavily used variables) too close together.
114 All arithmetic on sum should ignore overflow.
116 The initial probe index is then computed as sum mod the table size.
117 Subsequent probe indices are incr apart (mod table size), where incr
118 is also derived from sum, with the additional requirement that it is
119 relative prime to the table size (i.e., 1 <= incr < size, since the size
120 is a prime number). My choice for incr is somewhat arbitrary.
122 static mappingentry
*lookmapping
PROTO((mappingobject
*, object
*, long));
123 static mappingentry
*
124 lookmapping(mp
, key
, hash
)
125 register mappingobject
*mp
;
129 register int i
, incr
;
130 register unsigned long sum
= (unsigned long) hash
;
131 register mappingentry
*freeslot
= NULL
;
132 /* We must come up with (i, incr) such that 0 <= i < ma_size
133 and 0 < incr < ma_size and both are a function of hash */
134 i
= sum
% mp
->ma_size
;
137 incr
= sum
% mp
->ma_size
;
140 register mappingentry
*ep
= &mp
->ma_table
[i
];
141 if (ep
->me_key
== NULL
) {
142 if (freeslot
!= NULL
)
147 if (ep
->me_key
== dummy
) {
148 if (freeslot
== NULL
)
151 else if (ep
->me_hash
== hash
&&
152 cmpobject(ep
->me_key
, key
) == 0) {
155 i
= (i
+ incr
) % mp
->ma_size
;
160 Internal routine to insert a new item into the table.
161 Used both by the internal resize routine and by the public insert routine.
162 Eats a reference to key and one to value.
164 static void insertmapping
PROTO((mappingobject
*, object
*, long, object
*));
166 insertmapping(mp
, key
, hash
, value
)
167 register mappingobject
*mp
;
173 register mappingentry
*ep
;
174 ep
= lookmapping(mp
, key
, hash
);
175 if (ep
->me_value
!= NULL
) {
176 old_value
= ep
->me_value
;
177 ep
->me_value
= value
;
178 DECREF(old_value
); /* which **CAN** re-enter */
182 if (ep
->me_key
== NULL
)
188 ep
->me_value
= value
;
194 Restructure the table by allocating a new table and reinserting all
195 items again. When entries have been deleted, the new table may
196 actually be smaller than the old one.
198 static int mappingresize
PROTO((mappingobject
*));
203 register int oldsize
= mp
->ma_size
;
204 register int newsize
;
205 register mappingentry
*oldtable
= mp
->ma_table
;
206 register mappingentry
*newtable
;
207 register mappingentry
*ep
;
209 newsize
= mp
->ma_size
;
211 if (primes
[i
] <= 0) {
212 /* Ran out of primes */
216 if (primes
[i
] > mp
->ma_used
*2) {
218 if (newsize
!= primes
[i
]) {
219 /* Integer truncation */
226 newtable
= (mappingentry
*) calloc(sizeof(mappingentry
), newsize
);
227 if (newtable
== NULL
) {
231 mp
->ma_size
= newsize
;
232 mp
->ma_table
= newtable
;
236 /* Make two passes, so we can avoid decrefs
237 (and possible side effects) till the table is copied */
238 for (i
= 0, ep
= oldtable
; i
< oldsize
; i
++, ep
++) {
239 if (ep
->me_value
!= NULL
)
240 insertmapping(mp
,ep
->me_key
,ep
->me_hash
,ep
->me_value
);
242 for (i
= 0, ep
= oldtable
; i
< oldsize
; i
++, ep
++) {
243 if (ep
->me_value
== NULL
)
252 mappinglookup(op
, key
)
257 if (!is_mappingobject(op
)) {
261 if (((mappingobject
*)op
)->ma_table
== NULL
)
264 if (!is_stringobject(key
) || (hash
= ((stringobject
*) key
)->ob_shash
) == -1)
266 hash
= hashobject(key
);
269 return lookmapping((mappingobject
*)op
, key
, hash
) -> me_value
;
273 mappinginsert(op
, key
, value
)
278 register mappingobject
*mp
;
280 if (!is_mappingobject(op
)) {
285 if (!is_stringobject(key
) || (hash
= ((stringobject
*) key
)->ob_shash
) == -1)
287 hash
= hashobject(key
);
290 mp
= (mappingobject
*)op
;
291 /* if fill >= 2/3 size, resize */
292 if (mp
->ma_fill
*3 >= mp
->ma_size
*2) {
293 if (mappingresize(mp
) != 0) {
294 if (mp
->ma_fill
+1 > mp
->ma_size
)
300 insertmapping(mp
, key
, hash
, value
);
305 mappingremove(op
, key
)
309 register mappingobject
*mp
;
311 register mappingentry
*ep
;
312 object
*old_value
, *old_key
;
314 if (!is_mappingobject(op
)) {
319 if (!is_stringobject(key
) || (hash
= ((stringobject
*) key
)->ob_shash
) == -1)
321 hash
= hashobject(key
);
324 mp
= (mappingobject
*)op
;
325 if (((mappingobject
*)op
)->ma_table
== NULL
)
327 ep
= lookmapping(mp
, key
, hash
);
328 if (ep
->me_value
== NULL
) {
330 err_setval(KeyError
, key
);
333 old_key
= ep
->me_key
;
336 old_value
= ep
->me_value
;
349 register mappingentry
*table
;
351 if (!is_mappingobject(op
))
353 mp
= (mappingobject
*)op
;
354 table
= mp
->ma_table
;
358 mp
->ma_size
= mp
->ma_used
= mp
->ma_fill
= 0;
360 for (i
= 0; i
< n
; i
++) {
361 XDECREF(table
[i
].me_key
);
362 XDECREF(table
[i
].me_value
);
368 mappinggetnext(op
, ppos
, pkey
, pvalue
)
375 register mappingobject
*mp
;
376 if (!is_dictobject(op
))
378 mp
= (mappingobject
*)op
;
382 while (i
< mp
->ma_size
&& mp
->ma_table
[i
].me_value
== NULL
)
385 if (i
>= mp
->ma_size
)
388 *pkey
= mp
->ma_table
[i
].me_key
;
390 *pvalue
= mp
->ma_table
[i
].me_value
;
398 register mappingobject
*mp
;
401 register mappingentry
*ep
;
402 for (i
= 0, ep
= mp
->ma_table
; i
< mp
->ma_size
; i
++, ep
++) {
403 if (ep
->me_key
!= NULL
)
405 if (ep
->me_value
!= NULL
)
406 DECREF(ep
->me_value
);
413 mapping_print(mp
, fp
, flags
)
414 register mappingobject
*mp
;
420 register mappingentry
*ep
;
423 for (i
= 0, ep
= mp
->ma_table
; i
< mp
->ma_size
; i
++, ep
++) {
424 if (ep
->me_value
!= NULL
) {
427 if (printobject((object
*)ep
->me_key
, fp
, 0) != 0)
430 if (printobject(ep
->me_value
, fp
, 0) != 0)
443 object
*sepa
, *colon
;
446 register mappingentry
*ep
;
447 v
= newstringobject("{");
448 sepa
= newstringobject(", ");
449 colon
= newstringobject(": ");
451 for (i
= 0, ep
= mp
->ma_table
; i
< mp
->ma_size
&& v
; i
++, ep
++) {
452 if (ep
->me_value
!= NULL
) {
454 joinstring(&v
, sepa
);
455 joinstring_decref(&v
, reprobject(ep
->me_key
));
456 joinstring(&v
, colon
);
457 joinstring_decref(&v
, reprobject(ep
->me_value
));
460 joinstring_decref(&v
, newstringobject("}"));
474 mapping_subscript(mp
, key
)
476 register object
*key
;
480 if (mp
->ma_table
== NULL
) {
481 err_setval(KeyError
, key
);
485 if (!is_stringobject(key
) || (hash
= ((stringobject
*) key
)->ob_shash
) == -1)
487 hash
= hashobject(key
);
490 v
= lookmapping(mp
, key
, hash
) -> me_value
;
492 err_setval(KeyError
, key
);
499 mapping_ass_sub(mp
, v
, w
)
504 return mappingremove((object
*)mp
, v
);
506 return mappinginsert((object
*)mp
, v
, w
);
509 static mapping_methods mapping_as_mapping
= {
510 (inquiry
)mapping_length
, /*mp_length*/
511 (binaryfunc
)mapping_subscript
, /*mp_subscript*/
512 (objobjargproc
)mapping_ass_sub
, /*mp_ass_subscript*/
516 mapping_keys(mp
, args
)
517 register mappingobject
*mp
;
524 v
= newlistobject(mp
->ma_used
);
527 for (i
= 0, j
= 0; i
< mp
->ma_size
; i
++) {
528 if (mp
->ma_table
[i
].me_value
!= NULL
) {
529 object
*key
= mp
->ma_table
[i
].me_key
;
531 setlistitem(v
, j
, key
);
539 mapping_values(mp
, args
)
540 register mappingobject
*mp
;
547 v
= newlistobject(mp
->ma_used
);
550 for (i
= 0, j
= 0; i
< mp
->ma_size
; i
++) {
551 if (mp
->ma_table
[i
].me_value
!= NULL
) {
552 object
*value
= mp
->ma_table
[i
].me_value
;
554 setlistitem(v
, j
, value
);
562 mapping_items(mp
, args
)
563 register mappingobject
*mp
;
570 v
= newlistobject(mp
->ma_used
);
573 for (i
= 0, j
= 0; i
< mp
->ma_size
; i
++) {
574 if (mp
->ma_table
[i
].me_value
!= NULL
) {
575 object
*key
= mp
->ma_table
[i
].me_key
;
576 object
*value
= mp
->ma_table
[i
].me_value
;
577 object
*item
= newtupleobject(2);
583 settupleitem(item
, 0, key
);
585 settupleitem(item
, 1, value
);
586 setlistitem(v
, j
, item
);
597 if (mp
== NULL
|| !is_mappingobject(mp
)) {
601 return ((mappingobject
*)mp
)->ma_used
;
608 if (mp
== NULL
|| !is_mappingobject(mp
)) {
612 return mapping_keys((mappingobject
*)mp
, (object
*)NULL
);
619 if (mp
== NULL
|| !is_mappingobject(mp
)) {
623 return mapping_values((mappingobject
*)mp
, (object
*)NULL
);
630 if (mp
== NULL
|| !is_mappingobject(mp
)) {
634 return mapping_items((mappingobject
*)mp
, (object
*)NULL
);
638 mapping_compare(a
, b
)
639 mappingobject
*a
, *b
;
641 object
*akeys
, *bkeys
;
645 if (a
->ma_used
== 0) {
655 akeys
= mapping_keys(a
, (object
*)NULL
);
656 bkeys
= mapping_keys(b
, (object
*)NULL
);
657 if (akeys
== NULL
|| bkeys
== NULL
) {
658 /* Oops, out of memory -- what to do? */
659 /* For now, sort on address! */
669 n
= a
->ma_used
< b
->ma_used
? a
->ma_used
: b
->ma_used
; /* smallest */
671 for (i
= 0; i
< n
; i
++) {
672 object
*akey
, *bkey
, *aval
, *bval
;
674 akey
= getlistitem(akeys
, i
);
675 bkey
= getlistitem(bkeys
, i
);
676 res
= cmpobject(akey
, bkey
);
680 if (!is_stringobject(akey
) || (ahash
= ((stringobject
*) akey
)->ob_shash
) == -1)
682 ahash
= hashobject(akey
);
684 err_clear(); /* Don't want errors here */
686 if (!is_stringobject(bkey
) || (bhash
= ((stringobject
*) bkey
)->ob_shash
) == -1)
688 bhash
= hashobject(bkey
);
690 err_clear(); /* Don't want errors here */
691 aval
= lookmapping(a
, akey
, ahash
) -> me_value
;
692 bval
= lookmapping(b
, bkey
, bhash
) -> me_value
;
693 res
= cmpobject(aval
, bval
);
698 if (a
->ma_used
< b
->ma_used
)
700 else if (a
->ma_used
> b
->ma_used
)
709 mapping_has_key(mp
, args
)
710 register mappingobject
*mp
;
716 if (!getargs(args
, "O", &key
))
719 if (!is_stringobject(key
) || (hash
= ((stringobject
*) key
)->ob_shash
) == -1)
721 hash
= hashobject(key
);
724 ok
= mp
->ma_size
!= 0 && lookmapping(mp
, key
, hash
)->me_value
!= NULL
;
725 return newintobject(ok
);
728 static struct methodlist mapp_methods
[] = {
729 {"has_key", (method
)mapping_has_key
},
730 {"items", (method
)mapping_items
},
731 {"keys", (method
)mapping_keys
},
732 {"values", (method
)mapping_values
},
733 {NULL
, NULL
} /* sentinel */
737 mapping_getattr(mp
, name
)
741 return findmethod(mapp_methods
, (object
*)mp
, name
);
744 typeobject Mappingtype
= {
745 OB_HEAD_INIT(&Typetype
)
748 sizeof(mappingobject
),
750 (destructor
)mapping_dealloc
, /*tp_dealloc*/
751 (printfunc
)mapping_print
, /*tp_print*/
752 (getattrfunc
)mapping_getattr
, /*tp_getattr*/
754 (cmpfunc
)mapping_compare
, /*tp_compare*/
755 (reprfunc
)mapping_repr
, /*tp_repr*/
757 0, /*tp_as_sequence*/
758 &mapping_as_mapping
, /*tp_as_mapping*/
761 /* For backward compatibility with old dictionary interface */
763 static object
*last_name_object
;
764 static char *last_name_char
;
771 if (name
!= last_name_object
) {
772 XDECREF(last_name_object
);
774 last_name_object
= name
;
775 last_name_char
= getstringvalue(name
);
777 return getattr(v
, last_name_char
);
781 setattro(v
, name
, value
)
786 if (name
!= last_name_object
) {
787 XDECREF(last_name_object
);
789 last_name_object
= name
;
790 last_name_char
= getstringvalue(name
);
792 return setattr(v
, last_name_char
, value
);
800 if (key
!= last_name_char
||
801 strcmp(key
, getstringvalue(last_name_object
)) != 0) {
802 XDECREF(last_name_object
);
803 last_name_object
= newstringobject(key
);
804 if (last_name_object
== NULL
) {
805 last_name_char
= NULL
;
808 last_name_char
= key
;
810 return mappinglookup(v
, last_name_object
);
814 dictinsert(v
, key
, item
)
819 if (key
!= last_name_char
||
820 strcmp(key
, getstringvalue(last_name_object
)) != 0) {
821 XDECREF(last_name_object
);
822 last_name_object
= newstringobject(key
);
823 if (last_name_object
== NULL
) {
824 last_name_char
= NULL
;
827 last_name_char
= key
;
829 return mappinginsert(v
, last_name_object
, item
);
837 if (key
!= last_name_char
||
838 strcmp(key
, getstringvalue(last_name_object
)) != 0) {
839 XDECREF(last_name_object
);
840 last_name_object
= newstringobject(key
);
841 if (last_name_object
== NULL
) {
842 last_name_char
= NULL
;
845 last_name_char
= key
;
847 return mappingremove(v
, last_name_object
);