blob: c50b35a335e745b8bc647bdd58bb6a1ae4d01b13 [file] [log] [blame]
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001/***********************************************************
2Copyright 1991, 1992, 1993 by Stichting Mathematisch Centrum,
3Amsterdam, The Netherlands.
4
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Mapping object implementation; using a hash table */
26
Guido van Rossum9bfef441993-03-29 10:43:31 +000027/* 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". */
32
Guido van Rossum4b1302b1993-03-27 18:11:32 +000033#include "allobjects.h"
Guido van Rossum4b1302b1993-03-27 18:11:32 +000034#include "modsupport.h"
35
36
37/*
38Table of primes suitable as keys, in ascending order.
39The first line are the largest primes less than some powers of two,
40the second line is the largest prime less than 6000,
41and the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
42The final value is a sentinel and should cause the memory allocation
43of that many entries to fail (if none of the earlier values cause such
44failure already).
45*/
46static unsigned int primes[] = {
47 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
48 5987,
49 9551, 15683, 19609, 31397,
50 0xffffffff /* All bits set -- truncation OK */
51};
52
53/* Object used as dummy key to fill deleted entries */
54static object *dummy; /* Initialized by first call to newmappingobject() */
55
56/*
57Invariant for entries: when in use, de_value is not NULL and de_key is
58not NULL and not dummy; when not in use, de_value is NULL and de_key
59is either NULL or dummy. A dummy key value cannot be replaced by
60NULL, since otherwise other keys may be lost.
61*/
62typedef struct {
63 long me_hash;
64 object *me_key;
65 object *me_value;
66} mappingentry;
67
68/*
69To ensure the lookup algorithm terminates, the table size must be a
70prime number and there must be at least one NULL key in the table.
71The value ma_fill is the number of non-NULL keys; ma_used is the number
72of non-NULL, non-dummy keys.
73To avoid slowing down lookups on a near-full table, we resize the table
74when it is more than half filled.
75*/
76typedef struct {
77 OB_HEAD
78 int ma_fill;
79 int ma_used;
80 int ma_size;
81 mappingentry *ma_table;
82} mappingobject;
83
84object *
85newmappingobject()
86{
87 register mappingobject *mp;
88 if (dummy == NULL) { /* Auto-initialize dummy */
89 dummy = newstringobject("<dummy key>");
90 if (dummy == NULL)
91 return NULL;
92 }
93 mp = NEWOBJ(mappingobject, &Mappingtype);
94 if (mp == NULL)
95 return NULL;
96 mp->ma_size = primes[0];
97 mp->ma_table = (mappingentry *) calloc(sizeof(mappingentry), mp->ma_size);
98 if (mp->ma_table == NULL) {
99 DEL(mp);
100 return err_nomem();
101 }
102 mp->ma_fill = 0;
103 mp->ma_used = 0;
104 return (object *)mp;
105}
106
107/*
108The basic lookup function used by all operations.
109This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
110Open addressing is preferred over chaining since the link overhead for
111chaining would be substantial (100% with typical malloc overhead).
112
113First a 32-bit hash value, 'sum', is computed from the key string.
114The first character is added an extra time shifted by 8 to avoid hashing
115single-character keys (often heavily used variables) too close together.
116All arithmetic on sum should ignore overflow.
117
118The initial probe index is then computed as sum mod the table size.
119Subsequent probe indices are incr apart (mod table size), where incr
120is also derived from sum, with the additional requirement that it is
121relative prime to the table size (i.e., 1 <= incr < size, since the size
122is a prime number). My choice for incr is somewhat arbitrary.
123*/
124static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
125static mappingentry *
126lookmapping(mp, key, hash)
127 register mappingobject *mp;
128 object *key;
129 long hash;
130{
131 register int i, incr;
132 register unsigned long sum = (unsigned long) hash;
133 register mappingentry *freeslot = NULL;
134 /* We must come up with (i, incr) such that 0 <= i < ma_size
135 and 0 < incr < ma_size and both are a function of hash */
136 i = sum % mp->ma_size;
137 do {
138 sum = sum + sum + sum + 1;
139 incr = sum % mp->ma_size;
140 } while (incr == 0);
141 for (;;) {
142 register mappingentry *ep = &mp->ma_table[i];
143 if (ep->me_key == NULL) {
144 if (freeslot != NULL)
145 return freeslot;
146 else
147 return ep;
148 }
149 if (ep->me_key == dummy) {
150 if (freeslot != NULL)
151 freeslot = ep;
152 }
153 else if (ep->me_hash == hash &&
154 cmpobject(ep->me_key, key) == 0) {
155 return ep;
156 }
157 i = (i + incr) % mp->ma_size;
158 }
159}
160
161/*
162Internal routine to insert a new item into the table.
163Used both by the internal resize routine and by the public insert routine.
164Eats a reference to key and one to value.
165*/
166static void insertmapping PROTO((mappingobject *, object *, long, object *));
167static void
168insertmapping(mp, key, hash, value)
169 register mappingobject *mp;
170 object *key;
171 long hash;
172 object *value;
173{
174 register mappingentry *ep;
175 ep = lookmapping(mp, key, hash);
176 if (ep->me_value != NULL) {
177 DECREF(ep->me_value);
178 DECREF(key);
179 }
180 else {
181 if (ep->me_key == NULL)
182 mp->ma_fill++;
183 else
184 DECREF(ep->me_key);
185 ep->me_key = key;
186 ep->me_hash = hash;
187 mp->ma_used++;
188 }
189 ep->me_value = value;
190}
191
192/*
193Restructure the table by allocating a new table and reinserting all
194items again. When entries have been deleted, the new table may
195actually be smaller than the old one.
196*/
197static int mappingresize PROTO((mappingobject *));
198static int
199mappingresize(mp)
200 mappingobject *mp;
201{
202 register int oldsize = mp->ma_size;
203 register int newsize;
204 register mappingentry *oldtable = mp->ma_table;
205 register mappingentry *newtable;
206 register mappingentry *ep;
207 register int i;
208 newsize = mp->ma_size;
209 for (i = 0; ; i++) {
210 if (primes[i] > mp->ma_used*2) {
211 newsize = primes[i];
212 break;
213 }
214 }
215 newtable = (mappingentry *) calloc(sizeof(mappingentry), newsize);
216 if (newtable == NULL) {
217 err_nomem();
218 return -1;
219 }
220 mp->ma_size = newsize;
221 mp->ma_table = newtable;
222 mp->ma_fill = 0;
223 mp->ma_used = 0;
224 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
225 if (ep->me_value != NULL)
226 insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
227 else {
228 XDECREF(ep->me_key);
229 }
230 }
231 DEL(oldtable);
232 return 0;
233}
234
235object *
236mappinglookup(op, key)
237 object *op;
238 object *key;
239{
240 long hash;
241 if (!is_mappingobject(op)) {
242 err_badcall();
243 return NULL;
244 }
245 hash = hashobject(key);
246 if (hash == -1)
247 return NULL;
248 return lookmapping((mappingobject *)op, key, hash) -> me_value;
249}
250
251int
252mappinginsert(op, key, value)
253 register object *op;
254 object *key;
255 object *value;
256{
257 register mappingobject *mp;
258 register long hash;
259 if (!is_mappingobject(op)) {
260 err_badcall();
261 return -1;
262 }
263 hash = hashobject(key);
264 if (hash == -1)
265 return -1;
266 mp = (mappingobject *)op;
267 /* if fill >= 2/3 size, resize */
268 if (mp->ma_fill*3 >= mp->ma_size*2) {
269 if (mappingresize(mp) != 0) {
270 if (mp->ma_fill+1 > mp->ma_size)
271 return -1;
272 }
273 }
274 INCREF(value);
275 INCREF(key);
276 insertmapping(mp, key, hash, value);
277 return 0;
278}
279
280int
281mappingremove(op, key)
282 object *op;
283 object *key;
284{
285 register mappingobject *mp;
286 register long hash;
287 register mappingentry *ep;
288 if (!is_mappingobject(op)) {
289 err_badcall();
290 return -1;
291 }
292 hash = hashobject(key);
293 if (hash == -1)
294 return -1;
295 mp = (mappingobject *)op;
296 ep = lookmapping(mp, key, hash);
297 if (ep->me_value == NULL) {
298 err_setval(KeyError, key);
299 return -1;
300 }
301 DECREF(ep->me_key);
302 INCREF(dummy);
303 ep->me_key = dummy;
304 DECREF(ep->me_value);
305 ep->me_value = NULL;
306 mp->ma_used--;
307 return 0;
308}
309
Guido van Rossum25831651993-05-19 14:50:45 +0000310void
311mappingclear(op)
312 object *op;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000313{
Guido van Rossum25831651993-05-19 14:50:45 +0000314 int i;
315 register mappingobject *mp;
316 if (!is_mappingobject(op))
317 return;
318 mp = (mappingobject *)op;
319 for (i = 0; i < mp->ma_size; i++) {
320 XDECREF(mp->ma_table[i].me_key);
321 XDECREF(mp->ma_table[i].me_value);
322 mp->ma_table[i].me_key = NULL;
323 mp->ma_table[i].me_value = NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000324 }
Guido van Rossum25831651993-05-19 14:50:45 +0000325 mp->ma_used = 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000326}
327
Guido van Rossum25831651993-05-19 14:50:45 +0000328int
329mappinggetnext(op, ppos, pkey, pvalue)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000330 object *op;
Guido van Rossum25831651993-05-19 14:50:45 +0000331 int *ppos;
332 object **pkey;
333 object **pvalue;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000334{
Guido van Rossum25831651993-05-19 14:50:45 +0000335 int i;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000336 register mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000337 if (!is_dictobject(op))
338 return 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000339 mp = (mappingobject *)op;
Guido van Rossum25831651993-05-19 14:50:45 +0000340 i = *ppos;
341 if (i < 0)
342 return 0;
343 while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
344 i++;
345 *ppos = i+1;
346 if (i >= mp->ma_size)
347 return 0;
348 if (pkey)
349 *pkey = mp->ma_table[i].me_key;
350 if (pvalue)
351 *pvalue = mp->ma_table[i].me_value;
352 return 1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000353}
354
355/* Methods */
356
357static void
358mapping_dealloc(mp)
359 register mappingobject *mp;
360{
361 register int i;
362 register mappingentry *ep;
363 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
364 if (ep->me_key != NULL)
365 DECREF(ep->me_key);
366 if (ep->me_value != NULL)
367 DECREF(ep->me_value);
368 }
369 if (mp->ma_table != NULL)
370 DEL(mp->ma_table);
371 DEL(mp);
372}
373
374static int
375mapping_print(mp, fp, flags)
376 register mappingobject *mp;
377 register FILE *fp;
378 register int flags;
379{
380 register int i;
381 register int any;
382 register mappingentry *ep;
383 fprintf(fp, "{");
384 any = 0;
385 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
386 if (ep->me_value != NULL) {
387 if (any++ > 0)
388 fprintf(fp, ", ");
389 if (printobject((object *)ep->me_key, fp, flags) != 0)
390 return -1;
391 fprintf(fp, ": ");
392 if (printobject(ep->me_value, fp, flags) != 0)
393 return -1;
394 }
395 }
396 fprintf(fp, "}");
397 return 0;
398}
399
400static void
401js(pv, w)
402 object **pv;
403 object *w;
404{
405 joinstring(pv, w);
406 XDECREF(w);
407}
408
409static object *
410mapping_repr(mp)
411 mappingobject *mp;
412{
413 auto object *v;
414 object *sepa, *colon;
415 register int i;
416 register int any;
417 register mappingentry *ep;
418 v = newstringobject("{");
419 sepa = newstringobject(", ");
420 colon = newstringobject(": ");
421 any = 0;
422 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
423 if (ep->me_value != NULL) {
424 if (any++)
425 joinstring(&v, sepa);
426 js(&v, reprobject(ep->me_key));
427 joinstring(&v, colon);
428 js(&v, reprobject(ep->me_value));
429 }
430 }
431 js(&v, newstringobject("}"));
432 XDECREF(sepa);
433 XDECREF(colon);
434 return v;
435}
436
437static int
438mapping_length(mp)
439 mappingobject *mp;
440{
441 return mp->ma_used;
442}
443
444static object *
445mapping_subscript(mp, key)
446 mappingobject *mp;
447 register object *key;
448{
449 object *v;
450 long hash = hashobject(key);
451 if (hash == -1)
452 return NULL;
453 v = lookmapping(mp, key, hash) -> me_value;
454 if (v == NULL)
455 err_setval(KeyError, key);
456 else
457 INCREF(v);
458 return v;
459}
460
461static int
462mapping_ass_sub(mp, v, w)
463 mappingobject *mp;
464 object *v, *w;
465{
466 if (w == NULL)
467 return mappingremove((object *)mp, v);
468 else
469 return mappinginsert((object *)mp, v, w);
470}
471
472static mapping_methods mapping_as_mapping = {
473 mapping_length, /*mp_length*/
474 mapping_subscript, /*mp_subscript*/
475 mapping_ass_sub, /*mp_ass_subscript*/
476};
477
478static object *
479mapping_keys(mp, args)
480 register mappingobject *mp;
481 object *args;
482{
483 register object *v;
484 register int i, j;
485 if (!getnoarg(args))
486 return NULL;
487 v = newlistobject(mp->ma_used);
488 if (v == NULL)
489 return NULL;
490 for (i = 0, j = 0; i < mp->ma_size; i++) {
491 if (mp->ma_table[i].me_value != NULL) {
492 object *key = mp->ma_table[i].me_key;
493 INCREF(key);
494 setlistitem(v, j, key);
495 j++;
496 }
497 }
498 return v;
499}
500
Guido van Rossum25831651993-05-19 14:50:45 +0000501static object *
502mapping_values(mp, args)
503 register mappingobject *mp;
504 object *args;
505{
506 register object *v;
507 register int i, j;
508 if (!getnoarg(args))
509 return NULL;
510 v = newlistobject(mp->ma_used);
511 if (v == NULL)
512 return NULL;
513 for (i = 0, j = 0; i < mp->ma_size; i++) {
514 if (mp->ma_table[i].me_value != NULL) {
515 object *value = mp->ma_table[i].me_value;
516 INCREF(value);
517 setlistitem(v, j, value);
518 j++;
519 }
520 }
521 return v;
522}
523
524static object *
525mapping_items(mp, args)
526 register mappingobject *mp;
527 object *args;
528{
529 register object *v;
530 register int i, j;
531 if (!getnoarg(args))
532 return NULL;
533 v = newlistobject(mp->ma_used);
534 if (v == NULL)
535 return NULL;
536 for (i = 0, j = 0; i < mp->ma_size; i++) {
537 if (mp->ma_table[i].me_value != NULL) {
538 object *key = mp->ma_table[i].me_key;
539 object *value = mp->ma_table[i].me_value;
540 object *item = newtupleobject(2);
541 if (item == NULL) {
542 DECREF(v);
543 return NULL;
544 }
545 INCREF(key);
546 settupleitem(item, 0, key);
547 INCREF(value);
548 settupleitem(item, 1, value);
549 setlistitem(v, j, item);
550 j++;
551 }
552 }
553 return v;
554}
555
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000556object *
557getmappingkeys(mp)
558 object *mp;
559{
560 if (mp == NULL || !is_mappingobject(mp)) {
561 err_badcall();
562 return NULL;
563 }
564 return mapping_keys((mappingobject *)mp, (object *)NULL);
565}
566
Guido van Rossum25831651993-05-19 14:50:45 +0000567object *
568getmappingvalues(mp)
569 object *mp;
570{
571 if (mp == NULL || !is_mappingobject(mp)) {
572 err_badcall();
573 return NULL;
574 }
575 return mapping_values((mappingobject *)mp, (object *)NULL);
576}
577
578object *
579getmappingitems(mp)
580 object *mp;
581{
582 if (mp == NULL || !is_mappingobject(mp)) {
583 err_badcall();
584 return NULL;
585 }
586 return mapping_values((mappingobject *)mp, (object *)NULL);
587}
588
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000589static int
590mapping_compare(a, b)
591 mappingobject *a, *b;
592{
593 object *akeys, *bkeys;
594 int i, n, res;
595 if (a == b)
596 return 0;
597 if (a->ma_used == 0) {
598 if (b->ma_used != 0)
599 return -1;
600 else
601 return 0;
602 }
603 else {
604 if (b->ma_used == 0)
605 return 1;
606 }
607 akeys = mapping_keys(a, (object *)NULL);
608 bkeys = mapping_keys(b, (object *)NULL);
609 if (akeys == NULL || bkeys == NULL) {
610 /* Oops, out of memory -- what to do? */
611 /* For now, sort on address! */
612 XDECREF(akeys);
613 XDECREF(bkeys);
614 if (a < b)
615 return -1;
616 else
617 return 1;
618 }
619 sortlist(akeys);
620 sortlist(bkeys);
621 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
622 res = 0;
623 for (i = 0; i < n; i++) {
624 object *akey, *bkey, *aval, *bval;
625 long ahash, bhash;
626 akey = getlistitem(akeys, i);
627 bkey = getlistitem(bkeys, i);
628 res = cmpobject(akey, bkey);
629 if (res != 0)
630 break;
631 ahash = hashobject(akey);
632 if (ahash == -1)
633 err_clear(); /* Don't want errors here */
634 bhash = hashobject(bkey);
635 if (bhash == -1)
636 err_clear(); /* Don't want errors here */
637 aval = lookmapping(a, akey, ahash) -> me_value;
638 bval = lookmapping(b, bkey, bhash) -> me_value;
639 res = cmpobject(aval, bval);
640 if (res != 0)
641 break;
642 }
643 if (res == 0) {
644 if (a->ma_used < b->ma_used)
645 res = -1;
646 else if (a->ma_used > b->ma_used)
647 res = 1;
648 }
649 DECREF(akeys);
650 DECREF(bkeys);
651 return res;
652}
653
654static object *
655mapping_has_key(mp, args)
656 register mappingobject *mp;
657 object *args;
658{
659 object *key;
660 long hash;
661 register long ok;
662 if (!getargs(args, "O", &key))
663 return NULL;
664 hash = hashobject(key);
665 if (hash == -1)
666 return NULL;
667 ok = lookmapping(mp, key, hash)->me_value != NULL;
668 return newintobject(ok);
669}
670
671static struct methodlist mapp_methods[] = {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000672 {"has_key", mapping_has_key},
Guido van Rossum25831651993-05-19 14:50:45 +0000673 {"items", mapping_items},
674 {"keys", mapping_keys},
675 {"values", mapping_values},
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000676 {NULL, NULL} /* sentinel */
677};
678
679static object *
680mapping_getattr(mp, name)
681 mappingobject *mp;
682 char *name;
683{
684 return findmethod(mapp_methods, (object *)mp, name);
685}
686
687typeobject Mappingtype = {
688 OB_HEAD_INIT(&Typetype)
689 0,
Guido van Rossum9bfef441993-03-29 10:43:31 +0000690 "dictionary",
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000691 sizeof(mappingobject),
692 0,
693 mapping_dealloc, /*tp_dealloc*/
694 mapping_print, /*tp_print*/
695 mapping_getattr, /*tp_getattr*/
696 0, /*tp_setattr*/
697 mapping_compare, /*tp_compare*/
698 mapping_repr, /*tp_repr*/
699 0, /*tp_as_number*/
700 0, /*tp_as_sequence*/
701 &mapping_as_mapping, /*tp_as_mapping*/
702};
703
704/* For backward compatibility with old dictionary interface */
705
706static object *last_name_object;
707static char *last_name_char;
708
709object *
710getattro(v, name)
711 object *v;
712 object *name;
713{
714 if (name != last_name_object) {
715 XDECREF(last_name_object);
716 INCREF(name);
717 last_name_object = name;
718 last_name_char = getstringvalue(name);
719 }
720 return getattr(v, last_name_char);
721}
722
723int
724setattro(v, name, value)
725 object *v;
726 object *name;
727 object *value;
728{
729 if (name != last_name_object) {
730 XDECREF(last_name_object);
731 INCREF(name);
732 last_name_object = name;
733 last_name_char = getstringvalue(name);
734 }
735 return setattr(v, last_name_char, value);
736}
737
738object *
739dictlookup(v, key)
740 object *v;
741 char *key;
742{
743 if (key != last_name_char) {
744 XDECREF(last_name_object);
745 last_name_object = newstringobject(key);
746 if (last_name_object == NULL) {
747 last_name_char = NULL;
748 return NULL;
749 }
750 last_name_char = key;
751 }
752 return mappinglookup(v, last_name_object);
753}
754
755int
756dictinsert(v, key, item)
757 object *v;
758 char *key;
759 object *item;
760{
761 if (key != last_name_char) {
762 XDECREF(last_name_object);
763 last_name_object = newstringobject(key);
764 if (last_name_object == NULL) {
765 last_name_char = NULL;
766 return NULL;
767 }
768 last_name_char = key;
769 }
770 return mappinginsert(v, last_name_object, item);
771}
772
773int
774dictremove(v, key)
775 object *v;
776 char *key;
777{
778 if (key != last_name_char) {
779 XDECREF(last_name_object);
780 last_name_object = newstringobject(key);
781 if (last_name_object == NULL) {
782 last_name_char = NULL;
783 return NULL;
784 }
785 last_name_char = key;
786 }
787 return mappingremove(v, last_name_object);
788}