blob: b89b7b2786a079c48fd5eefb30c53bfb11e5c0a1 [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 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000245#ifdef CACHE_HASH
246 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
247#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000248 hash = hashobject(key);
249 if (hash == -1)
250 return NULL;
251 return lookmapping((mappingobject *)op, key, hash) -> me_value;
252}
253
254int
255mappinginsert(op, key, value)
256 register object *op;
257 object *key;
258 object *value;
259{
260 register mappingobject *mp;
261 register long hash;
262 if (!is_mappingobject(op)) {
263 err_badcall();
264 return -1;
265 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000266#ifdef CACHE_HASH
267 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
268#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000269 hash = hashobject(key);
270 if (hash == -1)
271 return -1;
272 mp = (mappingobject *)op;
273 /* if fill >= 2/3 size, resize */
274 if (mp->ma_fill*3 >= mp->ma_size*2) {
275 if (mappingresize(mp) != 0) {
276 if (mp->ma_fill+1 > mp->ma_size)
277 return -1;
278 }
279 }
280 INCREF(value);
281 INCREF(key);
282 insertmapping(mp, key, hash, value);
283 return 0;
284}
285
286int
287mappingremove(op, key)
288 object *op;
289 object *key;
290{
291 register mappingobject *mp;
292 register long hash;
293 register mappingentry *ep;
294 if (!is_mappingobject(op)) {
295 err_badcall();
296 return -1;
297 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000298#ifdef CACHE_HASH
299 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
300#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000301 hash = hashobject(key);
302 if (hash == -1)
303 return -1;
304 mp = (mappingobject *)op;
305 ep = lookmapping(mp, key, hash);
306 if (ep->me_value == NULL) {
307 err_setval(KeyError, key);
308 return -1;
309 }
310 DECREF(ep->me_key);
311 INCREF(dummy);
312 ep->me_key = dummy;
313 DECREF(ep->me_value);
314 ep->me_value = NULL;
315 mp->ma_used--;
316 return 0;
317}
318
Guido van Rossum25831651993-05-19 14:50:45 +0000319void
320mappingclear(op)
321 object *op;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000322{
Guido van Rossum25831651993-05-19 14:50:45 +0000323 int i;
324 register mappingobject *mp;
325 if (!is_mappingobject(op))
326 return;
327 mp = (mappingobject *)op;
328 for (i = 0; i < mp->ma_size; i++) {
329 XDECREF(mp->ma_table[i].me_key);
330 XDECREF(mp->ma_table[i].me_value);
331 mp->ma_table[i].me_key = NULL;
332 mp->ma_table[i].me_value = NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000333 }
Guido van Rossum25831651993-05-19 14:50:45 +0000334 mp->ma_used = 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000335}
336
Guido van Rossum25831651993-05-19 14:50:45 +0000337int
338mappinggetnext(op, ppos, pkey, pvalue)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000339 object *op;
Guido van Rossum25831651993-05-19 14:50:45 +0000340 int *ppos;
341 object **pkey;
342 object **pvalue;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000343{
Guido van Rossum25831651993-05-19 14:50:45 +0000344 int i;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000345 register mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000346 if (!is_dictobject(op))
347 return 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000348 mp = (mappingobject *)op;
Guido van Rossum25831651993-05-19 14:50:45 +0000349 i = *ppos;
350 if (i < 0)
351 return 0;
352 while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
353 i++;
354 *ppos = i+1;
355 if (i >= mp->ma_size)
356 return 0;
357 if (pkey)
358 *pkey = mp->ma_table[i].me_key;
359 if (pvalue)
360 *pvalue = mp->ma_table[i].me_value;
361 return 1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000362}
363
364/* Methods */
365
366static void
367mapping_dealloc(mp)
368 register mappingobject *mp;
369{
370 register int i;
371 register mappingentry *ep;
372 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
373 if (ep->me_key != NULL)
374 DECREF(ep->me_key);
375 if (ep->me_value != NULL)
376 DECREF(ep->me_value);
377 }
378 if (mp->ma_table != NULL)
379 DEL(mp->ma_table);
380 DEL(mp);
381}
382
383static int
384mapping_print(mp, fp, flags)
385 register mappingobject *mp;
386 register FILE *fp;
387 register int flags;
388{
389 register int i;
390 register int any;
391 register mappingentry *ep;
392 fprintf(fp, "{");
393 any = 0;
394 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
395 if (ep->me_value != NULL) {
396 if (any++ > 0)
397 fprintf(fp, ", ");
398 if (printobject((object *)ep->me_key, fp, flags) != 0)
399 return -1;
400 fprintf(fp, ": ");
401 if (printobject(ep->me_value, fp, flags) != 0)
402 return -1;
403 }
404 }
405 fprintf(fp, "}");
406 return 0;
407}
408
409static void
410js(pv, w)
411 object **pv;
412 object *w;
413{
414 joinstring(pv, w);
415 XDECREF(w);
416}
417
418static object *
419mapping_repr(mp)
420 mappingobject *mp;
421{
422 auto object *v;
423 object *sepa, *colon;
424 register int i;
425 register int any;
426 register mappingentry *ep;
427 v = newstringobject("{");
428 sepa = newstringobject(", ");
429 colon = newstringobject(": ");
430 any = 0;
431 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
432 if (ep->me_value != NULL) {
433 if (any++)
434 joinstring(&v, sepa);
435 js(&v, reprobject(ep->me_key));
436 joinstring(&v, colon);
437 js(&v, reprobject(ep->me_value));
438 }
439 }
440 js(&v, newstringobject("}"));
441 XDECREF(sepa);
442 XDECREF(colon);
443 return v;
444}
445
446static int
447mapping_length(mp)
448 mappingobject *mp;
449{
450 return mp->ma_used;
451}
452
453static object *
454mapping_subscript(mp, key)
455 mappingobject *mp;
456 register object *key;
457{
458 object *v;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000459 long hash;
460#ifdef CACHE_HASH
461 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
462#endif
463 hash = hashobject(key);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000464 if (hash == -1)
465 return NULL;
466 v = lookmapping(mp, key, hash) -> me_value;
467 if (v == NULL)
468 err_setval(KeyError, key);
469 else
470 INCREF(v);
471 return v;
472}
473
474static int
475mapping_ass_sub(mp, v, w)
476 mappingobject *mp;
477 object *v, *w;
478{
479 if (w == NULL)
480 return mappingremove((object *)mp, v);
481 else
482 return mappinginsert((object *)mp, v, w);
483}
484
485static mapping_methods mapping_as_mapping = {
486 mapping_length, /*mp_length*/
487 mapping_subscript, /*mp_subscript*/
488 mapping_ass_sub, /*mp_ass_subscript*/
489};
490
491static object *
492mapping_keys(mp, args)
493 register mappingobject *mp;
494 object *args;
495{
496 register object *v;
497 register int i, j;
498 if (!getnoarg(args))
499 return NULL;
500 v = newlistobject(mp->ma_used);
501 if (v == NULL)
502 return NULL;
503 for (i = 0, j = 0; i < mp->ma_size; i++) {
504 if (mp->ma_table[i].me_value != NULL) {
505 object *key = mp->ma_table[i].me_key;
506 INCREF(key);
507 setlistitem(v, j, key);
508 j++;
509 }
510 }
511 return v;
512}
513
Guido van Rossum25831651993-05-19 14:50:45 +0000514static object *
515mapping_values(mp, args)
516 register mappingobject *mp;
517 object *args;
518{
519 register object *v;
520 register int i, j;
521 if (!getnoarg(args))
522 return NULL;
523 v = newlistobject(mp->ma_used);
524 if (v == NULL)
525 return NULL;
526 for (i = 0, j = 0; i < mp->ma_size; i++) {
527 if (mp->ma_table[i].me_value != NULL) {
528 object *value = mp->ma_table[i].me_value;
529 INCREF(value);
530 setlistitem(v, j, value);
531 j++;
532 }
533 }
534 return v;
535}
536
537static object *
538mapping_items(mp, args)
539 register mappingobject *mp;
540 object *args;
541{
542 register object *v;
543 register int i, j;
544 if (!getnoarg(args))
545 return NULL;
546 v = newlistobject(mp->ma_used);
547 if (v == NULL)
548 return NULL;
549 for (i = 0, j = 0; i < mp->ma_size; i++) {
550 if (mp->ma_table[i].me_value != NULL) {
551 object *key = mp->ma_table[i].me_key;
552 object *value = mp->ma_table[i].me_value;
553 object *item = newtupleobject(2);
554 if (item == NULL) {
555 DECREF(v);
556 return NULL;
557 }
558 INCREF(key);
559 settupleitem(item, 0, key);
560 INCREF(value);
561 settupleitem(item, 1, value);
562 setlistitem(v, j, item);
563 j++;
564 }
565 }
566 return v;
567}
568
Guido van Rossum4199fac1993-11-05 10:18:44 +0000569int
570getmappingsize(mp)
571 object *mp;
572{
573 if (mp == NULL || !is_mappingobject(mp)) {
574 err_badcall();
575 return NULL;
576 }
577 return ((mappingobject *)mp)->ma_used;
578}
579
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000580object *
581getmappingkeys(mp)
582 object *mp;
583{
584 if (mp == NULL || !is_mappingobject(mp)) {
585 err_badcall();
586 return NULL;
587 }
588 return mapping_keys((mappingobject *)mp, (object *)NULL);
589}
590
Guido van Rossum25831651993-05-19 14:50:45 +0000591object *
592getmappingvalues(mp)
593 object *mp;
594{
595 if (mp == NULL || !is_mappingobject(mp)) {
596 err_badcall();
597 return NULL;
598 }
599 return mapping_values((mappingobject *)mp, (object *)NULL);
600}
601
602object *
603getmappingitems(mp)
604 object *mp;
605{
606 if (mp == NULL || !is_mappingobject(mp)) {
607 err_badcall();
608 return NULL;
609 }
610 return mapping_values((mappingobject *)mp, (object *)NULL);
611}
612
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000613static int
614mapping_compare(a, b)
615 mappingobject *a, *b;
616{
617 object *akeys, *bkeys;
618 int i, n, res;
619 if (a == b)
620 return 0;
621 if (a->ma_used == 0) {
622 if (b->ma_used != 0)
623 return -1;
624 else
625 return 0;
626 }
627 else {
628 if (b->ma_used == 0)
629 return 1;
630 }
631 akeys = mapping_keys(a, (object *)NULL);
632 bkeys = mapping_keys(b, (object *)NULL);
633 if (akeys == NULL || bkeys == NULL) {
634 /* Oops, out of memory -- what to do? */
635 /* For now, sort on address! */
636 XDECREF(akeys);
637 XDECREF(bkeys);
638 if (a < b)
639 return -1;
640 else
641 return 1;
642 }
643 sortlist(akeys);
644 sortlist(bkeys);
645 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
646 res = 0;
647 for (i = 0; i < n; i++) {
648 object *akey, *bkey, *aval, *bval;
649 long ahash, bhash;
650 akey = getlistitem(akeys, i);
651 bkey = getlistitem(bkeys, i);
652 res = cmpobject(akey, bkey);
653 if (res != 0)
654 break;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000655#ifdef CACHE_HASH
656 if (!is_stringobject(akey) || (ahash = ((stringobject *) akey)->ob_shash) == -1)
657#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000658 ahash = hashobject(akey);
659 if (ahash == -1)
660 err_clear(); /* Don't want errors here */
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000661#ifdef CACHE_HASH
662 if (!is_stringobject(bkey) || (bhash = ((stringobject *) bkey)->ob_shash) == -1)
663#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000664 bhash = hashobject(bkey);
665 if (bhash == -1)
666 err_clear(); /* Don't want errors here */
667 aval = lookmapping(a, akey, ahash) -> me_value;
668 bval = lookmapping(b, bkey, bhash) -> me_value;
669 res = cmpobject(aval, bval);
670 if (res != 0)
671 break;
672 }
673 if (res == 0) {
674 if (a->ma_used < b->ma_used)
675 res = -1;
676 else if (a->ma_used > b->ma_used)
677 res = 1;
678 }
679 DECREF(akeys);
680 DECREF(bkeys);
681 return res;
682}
683
684static object *
685mapping_has_key(mp, args)
686 register mappingobject *mp;
687 object *args;
688{
689 object *key;
690 long hash;
691 register long ok;
692 if (!getargs(args, "O", &key))
693 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000694#ifdef CACHE_HASH
695 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
696#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000697 hash = hashobject(key);
698 if (hash == -1)
699 return NULL;
700 ok = lookmapping(mp, key, hash)->me_value != NULL;
701 return newintobject(ok);
702}
703
704static struct methodlist mapp_methods[] = {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000705 {"has_key", mapping_has_key},
Guido van Rossum25831651993-05-19 14:50:45 +0000706 {"items", mapping_items},
707 {"keys", mapping_keys},
708 {"values", mapping_values},
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000709 {NULL, NULL} /* sentinel */
710};
711
712static object *
713mapping_getattr(mp, name)
714 mappingobject *mp;
715 char *name;
716{
717 return findmethod(mapp_methods, (object *)mp, name);
718}
719
720typeobject Mappingtype = {
721 OB_HEAD_INIT(&Typetype)
722 0,
Guido van Rossum9bfef441993-03-29 10:43:31 +0000723 "dictionary",
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000724 sizeof(mappingobject),
725 0,
726 mapping_dealloc, /*tp_dealloc*/
727 mapping_print, /*tp_print*/
728 mapping_getattr, /*tp_getattr*/
729 0, /*tp_setattr*/
730 mapping_compare, /*tp_compare*/
731 mapping_repr, /*tp_repr*/
732 0, /*tp_as_number*/
733 0, /*tp_as_sequence*/
734 &mapping_as_mapping, /*tp_as_mapping*/
735};
736
737/* For backward compatibility with old dictionary interface */
738
739static object *last_name_object;
740static char *last_name_char;
741
742object *
743getattro(v, name)
744 object *v;
745 object *name;
746{
747 if (name != last_name_object) {
748 XDECREF(last_name_object);
749 INCREF(name);
750 last_name_object = name;
751 last_name_char = getstringvalue(name);
752 }
753 return getattr(v, last_name_char);
754}
755
756int
757setattro(v, name, value)
758 object *v;
759 object *name;
760 object *value;
761{
762 if (name != last_name_object) {
763 XDECREF(last_name_object);
764 INCREF(name);
765 last_name_object = name;
766 last_name_char = getstringvalue(name);
767 }
768 return setattr(v, last_name_char, value);
769}
770
771object *
772dictlookup(v, key)
773 object *v;
774 char *key;
775{
776 if (key != last_name_char) {
777 XDECREF(last_name_object);
778 last_name_object = newstringobject(key);
779 if (last_name_object == NULL) {
780 last_name_char = NULL;
781 return NULL;
782 }
783 last_name_char = key;
784 }
785 return mappinglookup(v, last_name_object);
786}
787
788int
789dictinsert(v, key, item)
790 object *v;
791 char *key;
792 object *item;
793{
794 if (key != last_name_char) {
795 XDECREF(last_name_object);
796 last_name_object = newstringobject(key);
797 if (last_name_object == NULL) {
798 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +0000799 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000800 }
801 last_name_char = key;
802 }
803 return mappinginsert(v, last_name_object, item);
804}
805
806int
807dictremove(v, key)
808 object *v;
809 char *key;
810{
811 if (key != last_name_char) {
812 XDECREF(last_name_object);
813 last_name_object = newstringobject(key);
814 if (last_name_object == NULL) {
815 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +0000816 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000817 }
818 last_name_char = key;
819 }
820 return mappingremove(v, last_name_object);
821}