blob: 1cfa3082e0fd4561d0f15f87f4599100bc0c0a14 [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
27#include "allobjects.h"
28#include "mappingobject.h"
29#include "modsupport.h"
30
31
32/*
33Table of primes suitable as keys, in ascending order.
34The first line are the largest primes less than some powers of two,
35the second line is the largest prime less than 6000,
36and the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1.
37The final value is a sentinel and should cause the memory allocation
38of that many entries to fail (if none of the earlier values cause such
39failure already).
40*/
41static unsigned int primes[] = {
42 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
43 5987,
44 9551, 15683, 19609, 31397,
45 0xffffffff /* All bits set -- truncation OK */
46};
47
48/* Object used as dummy key to fill deleted entries */
49static object *dummy; /* Initialized by first call to newmappingobject() */
50
51/*
52Invariant for entries: when in use, de_value is not NULL and de_key is
53not NULL and not dummy; when not in use, de_value is NULL and de_key
54is either NULL or dummy. A dummy key value cannot be replaced by
55NULL, since otherwise other keys may be lost.
56*/
57typedef struct {
58 long me_hash;
59 object *me_key;
60 object *me_value;
61} mappingentry;
62
63/*
64To ensure the lookup algorithm terminates, the table size must be a
65prime number and there must be at least one NULL key in the table.
66The value ma_fill is the number of non-NULL keys; ma_used is the number
67of non-NULL, non-dummy keys.
68To avoid slowing down lookups on a near-full table, we resize the table
69when it is more than half filled.
70*/
71typedef struct {
72 OB_HEAD
73 int ma_fill;
74 int ma_used;
75 int ma_size;
76 mappingentry *ma_table;
77} mappingobject;
78
79object *
80newmappingobject()
81{
82 register mappingobject *mp;
83 if (dummy == NULL) { /* Auto-initialize dummy */
84 dummy = newstringobject("<dummy key>");
85 if (dummy == NULL)
86 return NULL;
87 }
88 mp = NEWOBJ(mappingobject, &Mappingtype);
89 if (mp == NULL)
90 return NULL;
91 mp->ma_size = primes[0];
92 mp->ma_table = (mappingentry *) calloc(sizeof(mappingentry), mp->ma_size);
93 if (mp->ma_table == NULL) {
94 DEL(mp);
95 return err_nomem();
96 }
97 mp->ma_fill = 0;
98 mp->ma_used = 0;
99 return (object *)mp;
100}
101
102/*
103The basic lookup function used by all operations.
104This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
105Open addressing is preferred over chaining since the link overhead for
106chaining would be substantial (100% with typical malloc overhead).
107
108First a 32-bit hash value, 'sum', is computed from the key string.
109The first character is added an extra time shifted by 8 to avoid hashing
110single-character keys (often heavily used variables) too close together.
111All arithmetic on sum should ignore overflow.
112
113The initial probe index is then computed as sum mod the table size.
114Subsequent probe indices are incr apart (mod table size), where incr
115is also derived from sum, with the additional requirement that it is
116relative prime to the table size (i.e., 1 <= incr < size, since the size
117is a prime number). My choice for incr is somewhat arbitrary.
118*/
119static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
120static mappingentry *
121lookmapping(mp, key, hash)
122 register mappingobject *mp;
123 object *key;
124 long hash;
125{
126 register int i, incr;
127 register unsigned long sum = (unsigned long) hash;
128 register mappingentry *freeslot = NULL;
129 /* We must come up with (i, incr) such that 0 <= i < ma_size
130 and 0 < incr < ma_size and both are a function of hash */
131 i = sum % mp->ma_size;
132 do {
133 sum = sum + sum + sum + 1;
134 incr = sum % mp->ma_size;
135 } while (incr == 0);
136 for (;;) {
137 register mappingentry *ep = &mp->ma_table[i];
138 if (ep->me_key == NULL) {
139 if (freeslot != NULL)
140 return freeslot;
141 else
142 return ep;
143 }
144 if (ep->me_key == dummy) {
145 if (freeslot != NULL)
146 freeslot = ep;
147 }
148 else if (ep->me_hash == hash &&
149 cmpobject(ep->me_key, key) == 0) {
150 return ep;
151 }
152 i = (i + incr) % mp->ma_size;
153 }
154}
155
156/*
157Internal routine to insert a new item into the table.
158Used both by the internal resize routine and by the public insert routine.
159Eats a reference to key and one to value.
160*/
161static void insertmapping PROTO((mappingobject *, object *, long, object *));
162static void
163insertmapping(mp, key, hash, value)
164 register mappingobject *mp;
165 object *key;
166 long hash;
167 object *value;
168{
169 register mappingentry *ep;
170 ep = lookmapping(mp, key, hash);
171 if (ep->me_value != NULL) {
172 DECREF(ep->me_value);
173 DECREF(key);
174 }
175 else {
176 if (ep->me_key == NULL)
177 mp->ma_fill++;
178 else
179 DECREF(ep->me_key);
180 ep->me_key = key;
181 ep->me_hash = hash;
182 mp->ma_used++;
183 }
184 ep->me_value = value;
185}
186
187/*
188Restructure the table by allocating a new table and reinserting all
189items again. When entries have been deleted, the new table may
190actually be smaller than the old one.
191*/
192static int mappingresize PROTO((mappingobject *));
193static int
194mappingresize(mp)
195 mappingobject *mp;
196{
197 register int oldsize = mp->ma_size;
198 register int newsize;
199 register mappingentry *oldtable = mp->ma_table;
200 register mappingentry *newtable;
201 register mappingentry *ep;
202 register int i;
203 newsize = mp->ma_size;
204 for (i = 0; ; i++) {
205 if (primes[i] > mp->ma_used*2) {
206 newsize = primes[i];
207 break;
208 }
209 }
210 newtable = (mappingentry *) calloc(sizeof(mappingentry), newsize);
211 if (newtable == NULL) {
212 err_nomem();
213 return -1;
214 }
215 mp->ma_size = newsize;
216 mp->ma_table = newtable;
217 mp->ma_fill = 0;
218 mp->ma_used = 0;
219 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
220 if (ep->me_value != NULL)
221 insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
222 else {
223 XDECREF(ep->me_key);
224 }
225 }
226 DEL(oldtable);
227 return 0;
228}
229
230object *
231mappinglookup(op, key)
232 object *op;
233 object *key;
234{
235 long hash;
236 if (!is_mappingobject(op)) {
237 err_badcall();
238 return NULL;
239 }
240 hash = hashobject(key);
241 if (hash == -1)
242 return NULL;
243 return lookmapping((mappingobject *)op, key, hash) -> me_value;
244}
245
246int
247mappinginsert(op, key, value)
248 register object *op;
249 object *key;
250 object *value;
251{
252 register mappingobject *mp;
253 register long hash;
254 if (!is_mappingobject(op)) {
255 err_badcall();
256 return -1;
257 }
258 hash = hashobject(key);
259 if (hash == -1)
260 return -1;
261 mp = (mappingobject *)op;
262 /* if fill >= 2/3 size, resize */
263 if (mp->ma_fill*3 >= mp->ma_size*2) {
264 if (mappingresize(mp) != 0) {
265 if (mp->ma_fill+1 > mp->ma_size)
266 return -1;
267 }
268 }
269 INCREF(value);
270 INCREF(key);
271 insertmapping(mp, key, hash, value);
272 return 0;
273}
274
275int
276mappingremove(op, key)
277 object *op;
278 object *key;
279{
280 register mappingobject *mp;
281 register long hash;
282 register mappingentry *ep;
283 if (!is_mappingobject(op)) {
284 err_badcall();
285 return -1;
286 }
287 hash = hashobject(key);
288 if (hash == -1)
289 return -1;
290 mp = (mappingobject *)op;
291 ep = lookmapping(mp, key, hash);
292 if (ep->me_value == NULL) {
293 err_setval(KeyError, key);
294 return -1;
295 }
296 DECREF(ep->me_key);
297 INCREF(dummy);
298 ep->me_key = dummy;
299 DECREF(ep->me_value);
300 ep->me_value = NULL;
301 mp->ma_used--;
302 return 0;
303}
304
305int
306getmappingsize(op)
307 register object *op;
308{
309 if (!is_mappingobject(op)) {
310 err_badcall();
311 return -1;
312 }
313 return ((mappingobject *)op) -> ma_size;
314}
315
316object *
317getmappingkey(op, i)
318 object *op;
319 register int i;
320{
321 /* XXX This can't return errors since its callers assume
322 that NULL means there was no key at that point */
323 register mappingobject *mp;
324 if (!is_mappingobject(op)) {
325 /* err_badcall(); */
326 return NULL;
327 }
328 mp = (mappingobject *)op;
329 if (i < 0 || i >= mp->ma_size) {
330 /* err_badarg(); */
331 return NULL;
332 }
333 if (mp->ma_table[i].me_value == NULL) {
334 /* Not an error! */
335 return NULL;
336 }
337 return (object *) mp->ma_table[i].me_key;
338}
339
340/* Methods */
341
342static void
343mapping_dealloc(mp)
344 register mappingobject *mp;
345{
346 register int i;
347 register mappingentry *ep;
348 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
349 if (ep->me_key != NULL)
350 DECREF(ep->me_key);
351 if (ep->me_value != NULL)
352 DECREF(ep->me_value);
353 }
354 if (mp->ma_table != NULL)
355 DEL(mp->ma_table);
356 DEL(mp);
357}
358
359static int
360mapping_print(mp, fp, flags)
361 register mappingobject *mp;
362 register FILE *fp;
363 register int flags;
364{
365 register int i;
366 register int any;
367 register mappingentry *ep;
368 fprintf(fp, "{");
369 any = 0;
370 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
371 if (ep->me_value != NULL) {
372 if (any++ > 0)
373 fprintf(fp, ", ");
374 if (printobject((object *)ep->me_key, fp, flags) != 0)
375 return -1;
376 fprintf(fp, ": ");
377 if (printobject(ep->me_value, fp, flags) != 0)
378 return -1;
379 }
380 }
381 fprintf(fp, "}");
382 return 0;
383}
384
385static void
386js(pv, w)
387 object **pv;
388 object *w;
389{
390 joinstring(pv, w);
391 XDECREF(w);
392}
393
394static object *
395mapping_repr(mp)
396 mappingobject *mp;
397{
398 auto object *v;
399 object *sepa, *colon;
400 register int i;
401 register int any;
402 register mappingentry *ep;
403 v = newstringobject("{");
404 sepa = newstringobject(", ");
405 colon = newstringobject(": ");
406 any = 0;
407 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
408 if (ep->me_value != NULL) {
409 if (any++)
410 joinstring(&v, sepa);
411 js(&v, reprobject(ep->me_key));
412 joinstring(&v, colon);
413 js(&v, reprobject(ep->me_value));
414 }
415 }
416 js(&v, newstringobject("}"));
417 XDECREF(sepa);
418 XDECREF(colon);
419 return v;
420}
421
422static int
423mapping_length(mp)
424 mappingobject *mp;
425{
426 return mp->ma_used;
427}
428
429static object *
430mapping_subscript(mp, key)
431 mappingobject *mp;
432 register object *key;
433{
434 object *v;
435 long hash = hashobject(key);
436 if (hash == -1)
437 return NULL;
438 v = lookmapping(mp, key, hash) -> me_value;
439 if (v == NULL)
440 err_setval(KeyError, key);
441 else
442 INCREF(v);
443 return v;
444}
445
446static int
447mapping_ass_sub(mp, v, w)
448 mappingobject *mp;
449 object *v, *w;
450{
451 if (w == NULL)
452 return mappingremove((object *)mp, v);
453 else
454 return mappinginsert((object *)mp, v, w);
455}
456
457static mapping_methods mapping_as_mapping = {
458 mapping_length, /*mp_length*/
459 mapping_subscript, /*mp_subscript*/
460 mapping_ass_sub, /*mp_ass_subscript*/
461};
462
463static object *
464mapping_keys(mp, args)
465 register mappingobject *mp;
466 object *args;
467{
468 register object *v;
469 register int i, j;
470 if (!getnoarg(args))
471 return NULL;
472 v = newlistobject(mp->ma_used);
473 if (v == NULL)
474 return NULL;
475 for (i = 0, j = 0; i < mp->ma_size; i++) {
476 if (mp->ma_table[i].me_value != NULL) {
477 object *key = mp->ma_table[i].me_key;
478 INCREF(key);
479 setlistitem(v, j, key);
480 j++;
481 }
482 }
483 return v;
484}
485
486object *
487getmappingkeys(mp)
488 object *mp;
489{
490 if (mp == NULL || !is_mappingobject(mp)) {
491 err_badcall();
492 return NULL;
493 }
494 return mapping_keys((mappingobject *)mp, (object *)NULL);
495}
496
497static int
498mapping_compare(a, b)
499 mappingobject *a, *b;
500{
501 object *akeys, *bkeys;
502 int i, n, res;
503 if (a == b)
504 return 0;
505 if (a->ma_used == 0) {
506 if (b->ma_used != 0)
507 return -1;
508 else
509 return 0;
510 }
511 else {
512 if (b->ma_used == 0)
513 return 1;
514 }
515 akeys = mapping_keys(a, (object *)NULL);
516 bkeys = mapping_keys(b, (object *)NULL);
517 if (akeys == NULL || bkeys == NULL) {
518 /* Oops, out of memory -- what to do? */
519 /* For now, sort on address! */
520 XDECREF(akeys);
521 XDECREF(bkeys);
522 if (a < b)
523 return -1;
524 else
525 return 1;
526 }
527 sortlist(akeys);
528 sortlist(bkeys);
529 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
530 res = 0;
531 for (i = 0; i < n; i++) {
532 object *akey, *bkey, *aval, *bval;
533 long ahash, bhash;
534 akey = getlistitem(akeys, i);
535 bkey = getlistitem(bkeys, i);
536 res = cmpobject(akey, bkey);
537 if (res != 0)
538 break;
539 ahash = hashobject(akey);
540 if (ahash == -1)
541 err_clear(); /* Don't want errors here */
542 bhash = hashobject(bkey);
543 if (bhash == -1)
544 err_clear(); /* Don't want errors here */
545 aval = lookmapping(a, akey, ahash) -> me_value;
546 bval = lookmapping(b, bkey, bhash) -> me_value;
547 res = cmpobject(aval, bval);
548 if (res != 0)
549 break;
550 }
551 if (res == 0) {
552 if (a->ma_used < b->ma_used)
553 res = -1;
554 else if (a->ma_used > b->ma_used)
555 res = 1;
556 }
557 DECREF(akeys);
558 DECREF(bkeys);
559 return res;
560}
561
562static object *
563mapping_has_key(mp, args)
564 register mappingobject *mp;
565 object *args;
566{
567 object *key;
568 long hash;
569 register long ok;
570 if (!getargs(args, "O", &key))
571 return NULL;
572 hash = hashobject(key);
573 if (hash == -1)
574 return NULL;
575 ok = lookmapping(mp, key, hash)->me_value != NULL;
576 return newintobject(ok);
577}
578
579static struct methodlist mapp_methods[] = {
580 {"keys", mapping_keys},
581 {"has_key", mapping_has_key},
582 {NULL, NULL} /* sentinel */
583};
584
585static object *
586mapping_getattr(mp, name)
587 mappingobject *mp;
588 char *name;
589{
590 return findmethod(mapp_methods, (object *)mp, name);
591}
592
593typeobject Mappingtype = {
594 OB_HEAD_INIT(&Typetype)
595 0,
596 "mapping",
597 sizeof(mappingobject),
598 0,
599 mapping_dealloc, /*tp_dealloc*/
600 mapping_print, /*tp_print*/
601 mapping_getattr, /*tp_getattr*/
602 0, /*tp_setattr*/
603 mapping_compare, /*tp_compare*/
604 mapping_repr, /*tp_repr*/
605 0, /*tp_as_number*/
606 0, /*tp_as_sequence*/
607 &mapping_as_mapping, /*tp_as_mapping*/
608};
609
610/* For backward compatibility with old dictionary interface */
611
612static object *last_name_object;
613static char *last_name_char;
614
615object *
616getattro(v, name)
617 object *v;
618 object *name;
619{
620 if (name != last_name_object) {
621 XDECREF(last_name_object);
622 INCREF(name);
623 last_name_object = name;
624 last_name_char = getstringvalue(name);
625 }
626 return getattr(v, last_name_char);
627}
628
629int
630setattro(v, name, value)
631 object *v;
632 object *name;
633 object *value;
634{
635 if (name != last_name_object) {
636 XDECREF(last_name_object);
637 INCREF(name);
638 last_name_object = name;
639 last_name_char = getstringvalue(name);
640 }
641 return setattr(v, last_name_char, value);
642}
643
644object *
645dictlookup(v, key)
646 object *v;
647 char *key;
648{
649 if (key != last_name_char) {
650 XDECREF(last_name_object);
651 last_name_object = newstringobject(key);
652 if (last_name_object == NULL) {
653 last_name_char = NULL;
654 return NULL;
655 }
656 last_name_char = key;
657 }
658 return mappinglookup(v, last_name_object);
659}
660
661int
662dictinsert(v, key, item)
663 object *v;
664 char *key;
665 object *item;
666{
667 if (key != last_name_char) {
668 XDECREF(last_name_object);
669 last_name_object = newstringobject(key);
670 if (last_name_object == NULL) {
671 last_name_char = NULL;
672 return NULL;
673 }
674 last_name_char = key;
675 }
676 return mappinginsert(v, last_name_object, item);
677}
678
679int
680dictremove(v, key)
681 object *v;
682 char *key;
683{
684 if (key != last_name_char) {
685 XDECREF(last_name_object);
686 last_name_object = newstringobject(key);
687 if (last_name_object == NULL) {
688 last_name_char = NULL;
689 return NULL;
690 }
691 last_name_char = key;
692 }
693 return mappingremove(v, last_name_object);
694}
695
696char *
697getdictkey(v, i)
698 object *v;
699 int i;
700{
701 object *key = getmappingkey(v, i);
702 if (key == NULL)
703 return NULL;
704 return getstringvalue(key);
705}