blob: 247f3cf3bf52a1102e89e8b6c1671a7f9657f26e [file] [log] [blame]
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001/***********************************************************
Guido van Rossum6610ad91995-01-04 19:07:38 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Guido van Rossum4b1302b1993-03-27 18:11:32 +00004
5 All Rights Reserved
6
Guido van Rossumd266eb41996-10-25 14:44:06 +00007Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
Guido van Rossum4b1302b1993-03-27 18:11:32 +00009provided that the above copyright notice appear in all copies and that
Guido van Rossumd266eb41996-10-25 14:44:06 +000010both that copyright notice and this permission notice appear in
Guido van Rossum4b1302b1993-03-27 18:11:32 +000011supporting documentation, and that the names of Stichting Mathematisch
Guido van Rossumd266eb41996-10-25 14:44:06 +000012Centrum or CWI or Corporation for National Research Initiatives or
13CNRI not be used in advertising or publicity pertaining to
14distribution of the software without specific, written prior
15permission.
Guido van Rossum4b1302b1993-03-27 18:11:32 +000016
Guido van Rossumd266eb41996-10-25 14:44:06 +000017While CWI is the initial source for this software, a modified version
18is made available by the Corporation for National Research Initiatives
19(CNRI) at the Internet address ftp://ftp.python.org.
20
21STICHTING MATHEMATISCH CENTRUM AND CNRI DISCLAIM ALL WARRANTIES WITH
22REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF
23MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH
24CENTRUM OR CNRI BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
25DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
26PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
27TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
28PERFORMANCE OF THIS SOFTWARE.
Guido van Rossum4b1302b1993-03-27 18:11:32 +000029
30******************************************************************/
31
32/* Mapping object implementation; using a hash table */
33
Guido van Rossum9bfef441993-03-29 10:43:31 +000034/* This file should really be called "dictobject.c", since "mapping"
35 is the generic name for objects with an unorderred arbitrary key
36 set (just like lists are sequences), but since it improves (and was
37 originally derived from) a file by that name I had to change its
38 name. For the user these objects are still called "dictionaries". */
39
Guido van Rossum4b1302b1993-03-27 18:11:32 +000040#include "allobjects.h"
Guido van Rossum4b1302b1993-03-27 18:11:32 +000041#include "modsupport.h"
42
43
44/*
45Table of primes suitable as keys, in ascending order.
46The first line are the largest primes less than some powers of two,
47the second line is the largest prime less than 6000,
Guido van Rossum1d5735e1994-08-30 08:27:36 +000048the third line is a selection from Knuth, Vol. 3, Sec. 6.1, Table 1,
49and the next three lines were suggested by Steve Kirsch.
50The final value is a sentinel.
Guido van Rossum4b1302b1993-03-27 18:11:32 +000051*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +000052static long primes[] = {
Guido van Rossum4b1302b1993-03-27 18:11:32 +000053 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093,
54 5987,
55 9551, 15683, 19609, 31397,
Guido van Rossumd7047b31995-01-02 19:07:15 +000056 65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L,
57 4194301L, 8388593L, 16777213L, 33554393L, 67108859L,
58 134217689L, 268435399L, 536870909L, 1073741789L,
Guido van Rossum1d5735e1994-08-30 08:27:36 +000059 0
Guido van Rossum4b1302b1993-03-27 18:11:32 +000060};
61
62/* Object used as dummy key to fill deleted entries */
63static object *dummy; /* Initialized by first call to newmappingobject() */
64
65/*
66Invariant for entries: when in use, de_value is not NULL and de_key is
67not NULL and not dummy; when not in use, de_value is NULL and de_key
68is either NULL or dummy. A dummy key value cannot be replaced by
69NULL, since otherwise other keys may be lost.
70*/
71typedef struct {
72 long me_hash;
73 object *me_key;
74 object *me_value;
75} mappingentry;
76
77/*
78To ensure the lookup algorithm terminates, the table size must be a
79prime number and there must be at least one NULL key in the table.
80The value ma_fill is the number of non-NULL keys; ma_used is the number
81of non-NULL, non-dummy keys.
82To avoid slowing down lookups on a near-full table, we resize the table
83when it is more than half filled.
84*/
85typedef struct {
86 OB_HEAD
87 int ma_fill;
88 int ma_used;
89 int ma_size;
90 mappingentry *ma_table;
91} mappingobject;
92
93object *
94newmappingobject()
95{
96 register mappingobject *mp;
97 if (dummy == NULL) { /* Auto-initialize dummy */
98 dummy = newstringobject("<dummy key>");
99 if (dummy == NULL)
100 return NULL;
101 }
102 mp = NEWOBJ(mappingobject, &Mappingtype);
103 if (mp == NULL)
104 return NULL;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000105 mp->ma_size = 0;
106 mp->ma_table = NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000107 mp->ma_fill = 0;
108 mp->ma_used = 0;
109 return (object *)mp;
110}
111
112/*
113The basic lookup function used by all operations.
114This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
115Open addressing is preferred over chaining since the link overhead for
116chaining would be substantial (100% with typical malloc overhead).
117
118First a 32-bit hash value, 'sum', is computed from the key string.
119The first character is added an extra time shifted by 8 to avoid hashing
120single-character keys (often heavily used variables) too close together.
121All arithmetic on sum should ignore overflow.
122
123The initial probe index is then computed as sum mod the table size.
124Subsequent probe indices are incr apart (mod table size), where incr
125is also derived from sum, with the additional requirement that it is
126relative prime to the table size (i.e., 1 <= incr < size, since the size
127is a prime number). My choice for incr is somewhat arbitrary.
128*/
129static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
130static mappingentry *
131lookmapping(mp, key, hash)
Guido van Rossum7d181591997-01-16 21:06:45 +0000132 mappingobject *mp;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000133 object *key;
134 long hash;
135{
Guido van Rossum7d181591997-01-16 21:06:45 +0000136 /* Optimizations based on observations by Jyrki Alakuijala
137 (paraphrased):
138
139 - This routine is very heavily used, so should be AFAP
140 (As Fast As Possible).
141
142 - Most of the time, the first try is a hit or a definite
143 miss; so postpone the calculation of incr until we know the
144 first try was a miss.
145
146 - Write the loop twice, so we can move the test for
147 freeslot==NULL out of the loop.
148
149 - Write the loop using pointer increments and comparisons
150 rather than using an integer loop index.
151
152 Note that it behooves the compiler to calculate the values
153 of incr*sizeof(*ep) outside the loops and use this in the
154 increment of ep. I've reduced the number of register
155 variables to the two most obvious candidates.
156
157 */
158
159 register mappingentry *ep;
160 mappingentry *end;
161 register object *ekey;
162 mappingentry *freeslot;
163 unsigned long sum;
164 int incr;
165 int size;
166
167 ep = &mp->ma_table[(unsigned long)hash%mp->ma_size];
168 ekey = ep->me_key;
169 if (ekey == NULL)
170 return ep;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000171#ifdef INTERN_STRINGS
Guido van Rossumca756f21997-01-23 19:39:29 +0000172 {
Guido van Rossum2a61e741997-01-18 07:55:05 +0000173 object *ikey;
Guido van Rossumca756f21997-01-23 19:39:29 +0000174 if (is_stringobject(key) &&
175 (ikey = ((stringobject *)key)->ob_sinterned) != NULL)
Guido van Rossum2a61e741997-01-18 07:55:05 +0000176 key = ikey;
177 }
178#endif
Guido van Rossum7d181591997-01-16 21:06:45 +0000179 if (ekey == dummy)
180 freeslot = ep;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000181 else {
Guido van Rossumca756f21997-01-23 19:39:29 +0000182 if (ekey == key)
183 return ep;
184 if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
185 return ep;
Guido van Rossum7d181591997-01-16 21:06:45 +0000186 freeslot = NULL;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000187 }
Guido van Rossum7d181591997-01-16 21:06:45 +0000188
189 size = mp->ma_size;
190 sum = hash;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000191 do {
Guido van Rossumca756f21997-01-23 19:39:29 +0000192 sum += sum + sum + 1;
Guido van Rossum310968d1996-07-30 16:45:31 +0000193 incr = sum % size;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000194 } while (incr == 0);
Guido van Rossum7d181591997-01-16 21:06:45 +0000195
196 end = mp->ma_table + size;
197
198 if (freeslot == NULL) {
199 for (;;) {
200 ep += incr;
201 if (ep >= end)
202 ep -= size;
203 ekey = ep->me_key;
204 if (ekey == NULL)
205 return ep;
206 if (ekey == dummy) {
207 freeslot = ep;
208 break;
209 }
Guido van Rossumca756f21997-01-23 19:39:29 +0000210 if (ekey == key || (ep->me_hash == hash &&
211 cmpobject(ekey, key) == 0))
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000212 return ep;
213 }
Guido van Rossum7d181591997-01-16 21:06:45 +0000214 }
215
216 for (;;) {
217 ep += incr;
218 if (ep >= end)
219 ep -= size;
220 ekey = ep->me_key;
221 if (ekey == NULL)
222 return freeslot;
Guido van Rossumca756f21997-01-23 19:39:29 +0000223 if (ekey == key ||
224 (ekey != dummy &&
225 ep->me_hash == hash && cmpobject(ekey, key) == 0))
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000226 return ep;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000227 }
228}
229
230/*
231Internal routine to insert a new item into the table.
232Used both by the internal resize routine and by the public insert routine.
233Eats a reference to key and one to value.
234*/
235static void insertmapping PROTO((mappingobject *, object *, long, object *));
236static void
237insertmapping(mp, key, hash, value)
238 register mappingobject *mp;
239 object *key;
240 long hash;
241 object *value;
242{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000243 object *old_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000244 register mappingentry *ep;
245 ep = lookmapping(mp, key, hash);
246 if (ep->me_value != NULL) {
Guido van Rossumd7047b31995-01-02 19:07:15 +0000247 old_value = ep->me_value;
248 ep->me_value = value;
249 DECREF(old_value); /* which **CAN** re-enter */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000250 DECREF(key);
251 }
252 else {
253 if (ep->me_key == NULL)
254 mp->ma_fill++;
255 else
256 DECREF(ep->me_key);
257 ep->me_key = key;
258 ep->me_hash = hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000259 ep->me_value = value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000260 mp->ma_used++;
261 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000262}
263
264/*
265Restructure the table by allocating a new table and reinserting all
266items again. When entries have been deleted, the new table may
267actually be smaller than the old one.
268*/
269static int mappingresize PROTO((mappingobject *));
270static int
271mappingresize(mp)
272 mappingobject *mp;
273{
274 register int oldsize = mp->ma_size;
275 register int newsize;
276 register mappingentry *oldtable = mp->ma_table;
277 register mappingentry *newtable;
278 register mappingentry *ep;
279 register int i;
280 newsize = mp->ma_size;
281 for (i = 0; ; i++) {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000282 if (primes[i] <= 0) {
283 /* Ran out of primes */
284 err_nomem();
285 return -1;
286 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000287 if (primes[i] > mp->ma_used*2) {
288 newsize = primes[i];
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000289 if (newsize != primes[i]) {
290 /* Integer truncation */
291 err_nomem();
292 return -1;
293 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000294 break;
295 }
296 }
297 newtable = (mappingentry *) calloc(sizeof(mappingentry), newsize);
298 if (newtable == NULL) {
299 err_nomem();
300 return -1;
301 }
302 mp->ma_size = newsize;
303 mp->ma_table = newtable;
304 mp->ma_fill = 0;
305 mp->ma_used = 0;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000306
307 /* Make two passes, so we can avoid decrefs
308 (and possible side effects) till the table is copied */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000309 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
310 if (ep->me_value != NULL)
311 insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000312 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000313 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
314 if (ep->me_value == NULL)
315 XDECREF(ep->me_key);
316 }
317
318 XDEL(oldtable);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000319 return 0;
320}
321
322object *
323mappinglookup(op, key)
324 object *op;
325 object *key;
326{
327 long hash;
328 if (!is_mappingobject(op)) {
329 err_badcall();
330 return NULL;
331 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000332 if (((mappingobject *)op)->ma_table == NULL)
333 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000334#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000335 if (!is_stringobject(key) ||
336 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000337#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000338 {
339 hash = hashobject(key);
340 if (hash == -1)
341 return NULL;
342 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000343 return lookmapping((mappingobject *)op, key, hash) -> me_value;
344}
345
346int
347mappinginsert(op, key, value)
348 register object *op;
349 object *key;
350 object *value;
351{
352 register mappingobject *mp;
353 register long hash;
354 if (!is_mappingobject(op)) {
355 err_badcall();
356 return -1;
357 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000358 mp = (mappingobject *)op;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000359#ifdef CACHE_HASH
360 if (is_stringobject(key)) {
361#ifdef INTERN_STRINGS
362 if (((stringobject *)key)->ob_sinterned != NULL) {
363 key = ((stringobject *)key)->ob_sinterned;
364 hash = ((stringobject *)key)->ob_shash;
365 }
366 else
367#endif
368 {
369 hash = ((stringobject *)key)->ob_shash;
370 if (hash == -1)
371 hash = hashobject(key);
Guido van Rossum2a61e741997-01-18 07:55:05 +0000372 }
373 }
374 else
375#endif
376 {
377 hash = hashobject(key);
378 if (hash == -1)
379 return -1;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000380 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000381 /* if fill >= 2/3 size, resize */
382 if (mp->ma_fill*3 >= mp->ma_size*2) {
383 if (mappingresize(mp) != 0) {
384 if (mp->ma_fill+1 > mp->ma_size)
385 return -1;
386 }
387 }
388 INCREF(value);
389 INCREF(key);
390 insertmapping(mp, key, hash, value);
391 return 0;
392}
393
394int
395mappingremove(op, key)
396 object *op;
397 object *key;
398{
399 register mappingobject *mp;
400 register long hash;
401 register mappingentry *ep;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000402 object *old_value, *old_key;
403
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000404 if (!is_mappingobject(op)) {
405 err_badcall();
406 return -1;
407 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000408#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000409 if (!is_stringobject(key) ||
410 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000411#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000412 {
413 hash = hashobject(key);
414 if (hash == -1)
415 return -1;
416 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000417 mp = (mappingobject *)op;
Guido van Rossumefc87131995-01-02 19:42:39 +0000418 if (((mappingobject *)op)->ma_table == NULL)
419 goto empty;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000420 ep = lookmapping(mp, key, hash);
421 if (ep->me_value == NULL) {
Guido van Rossumefc87131995-01-02 19:42:39 +0000422 empty:
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000423 err_setval(KeyError, key);
424 return -1;
425 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000426 old_key = ep->me_key;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000427 INCREF(dummy);
428 ep->me_key = dummy;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000429 old_value = ep->me_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000430 ep->me_value = NULL;
431 mp->ma_used--;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000432 DECREF(old_value);
433 DECREF(old_key);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000434 return 0;
435}
436
Guido van Rossum25831651993-05-19 14:50:45 +0000437void
438mappingclear(op)
439 object *op;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000440{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000441 int i, n;
442 register mappingentry *table;
443 mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000444 if (!is_mappingobject(op))
445 return;
446 mp = (mappingobject *)op;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000447 table = mp->ma_table;
448 if (table == NULL)
449 return;
450 n = mp->ma_size;
451 mp->ma_size = mp->ma_used = mp->ma_fill = 0;
452 mp->ma_table = NULL;
453 for (i = 0; i < n; i++) {
454 XDECREF(table[i].me_key);
455 XDECREF(table[i].me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000456 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000457 DEL(table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000458}
459
Guido van Rossum25831651993-05-19 14:50:45 +0000460int
461mappinggetnext(op, ppos, pkey, pvalue)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000462 object *op;
Guido van Rossum25831651993-05-19 14:50:45 +0000463 int *ppos;
464 object **pkey;
465 object **pvalue;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000466{
Guido van Rossum25831651993-05-19 14:50:45 +0000467 int i;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000468 register mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000469 if (!is_dictobject(op))
470 return 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000471 mp = (mappingobject *)op;
Guido van Rossum25831651993-05-19 14:50:45 +0000472 i = *ppos;
473 if (i < 0)
474 return 0;
475 while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
476 i++;
477 *ppos = i+1;
478 if (i >= mp->ma_size)
479 return 0;
480 if (pkey)
481 *pkey = mp->ma_table[i].me_key;
482 if (pvalue)
483 *pvalue = mp->ma_table[i].me_value;
484 return 1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000485}
486
487/* Methods */
488
489static void
490mapping_dealloc(mp)
491 register mappingobject *mp;
492{
493 register int i;
494 register mappingentry *ep;
495 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
496 if (ep->me_key != NULL)
497 DECREF(ep->me_key);
498 if (ep->me_value != NULL)
499 DECREF(ep->me_value);
500 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000501 XDEL(mp->ma_table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000502 DEL(mp);
503}
504
505static int
506mapping_print(mp, fp, flags)
507 register mappingobject *mp;
508 register FILE *fp;
509 register int flags;
510{
511 register int i;
512 register int any;
513 register mappingentry *ep;
514 fprintf(fp, "{");
515 any = 0;
516 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
517 if (ep->me_value != NULL) {
518 if (any++ > 0)
519 fprintf(fp, ", ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000520 if (printobject((object *)ep->me_key, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000521 return -1;
522 fprintf(fp, ": ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000523 if (printobject(ep->me_value, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000524 return -1;
525 }
526 }
527 fprintf(fp, "}");
528 return 0;
529}
530
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000531static object *
532mapping_repr(mp)
533 mappingobject *mp;
534{
535 auto object *v;
536 object *sepa, *colon;
537 register int i;
538 register int any;
539 register mappingentry *ep;
540 v = newstringobject("{");
541 sepa = newstringobject(", ");
542 colon = newstringobject(": ");
543 any = 0;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000544 for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000545 if (ep->me_value != NULL) {
546 if (any++)
547 joinstring(&v, sepa);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000548 joinstring_decref(&v, reprobject(ep->me_key));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000549 joinstring(&v, colon);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000550 joinstring_decref(&v, reprobject(ep->me_value));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000551 }
552 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000553 joinstring_decref(&v, newstringobject("}"));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000554 XDECREF(sepa);
555 XDECREF(colon);
556 return v;
557}
558
559static int
560mapping_length(mp)
561 mappingobject *mp;
562{
563 return mp->ma_used;
564}
565
566static object *
567mapping_subscript(mp, key)
568 mappingobject *mp;
569 register object *key;
570{
571 object *v;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000572 long hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000573 if (mp->ma_table == NULL) {
574 err_setval(KeyError, key);
575 return NULL;
576 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000577#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000578 if (!is_stringobject(key) ||
579 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000580#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000581 {
582 hash = hashobject(key);
583 if (hash == -1)
584 return NULL;
585 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000586 v = lookmapping(mp, key, hash) -> me_value;
587 if (v == NULL)
588 err_setval(KeyError, key);
589 else
590 INCREF(v);
591 return v;
592}
593
594static int
595mapping_ass_sub(mp, v, w)
596 mappingobject *mp;
597 object *v, *w;
598{
599 if (w == NULL)
600 return mappingremove((object *)mp, v);
601 else
602 return mappinginsert((object *)mp, v, w);
603}
604
605static mapping_methods mapping_as_mapping = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000606 (inquiry)mapping_length, /*mp_length*/
607 (binaryfunc)mapping_subscript, /*mp_subscript*/
608 (objobjargproc)mapping_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000609};
610
611static object *
612mapping_keys(mp, args)
613 register mappingobject *mp;
614 object *args;
615{
616 register object *v;
617 register int i, j;
618 if (!getnoarg(args))
619 return NULL;
620 v = newlistobject(mp->ma_used);
621 if (v == NULL)
622 return NULL;
623 for (i = 0, j = 0; i < mp->ma_size; i++) {
624 if (mp->ma_table[i].me_value != NULL) {
625 object *key = mp->ma_table[i].me_key;
626 INCREF(key);
627 setlistitem(v, j, key);
628 j++;
629 }
630 }
631 return v;
632}
633
Guido van Rossum25831651993-05-19 14:50:45 +0000634static object *
635mapping_values(mp, args)
636 register mappingobject *mp;
637 object *args;
638{
639 register object *v;
640 register int i, j;
641 if (!getnoarg(args))
642 return NULL;
643 v = newlistobject(mp->ma_used);
644 if (v == NULL)
645 return NULL;
646 for (i = 0, j = 0; i < mp->ma_size; i++) {
647 if (mp->ma_table[i].me_value != NULL) {
648 object *value = mp->ma_table[i].me_value;
649 INCREF(value);
650 setlistitem(v, j, value);
651 j++;
652 }
653 }
654 return v;
655}
656
657static object *
658mapping_items(mp, args)
659 register mappingobject *mp;
660 object *args;
661{
662 register object *v;
663 register int i, j;
664 if (!getnoarg(args))
665 return NULL;
666 v = newlistobject(mp->ma_used);
667 if (v == NULL)
668 return NULL;
669 for (i = 0, j = 0; i < mp->ma_size; i++) {
670 if (mp->ma_table[i].me_value != NULL) {
671 object *key = mp->ma_table[i].me_key;
672 object *value = mp->ma_table[i].me_value;
673 object *item = newtupleobject(2);
674 if (item == NULL) {
675 DECREF(v);
676 return NULL;
677 }
678 INCREF(key);
679 settupleitem(item, 0, key);
680 INCREF(value);
681 settupleitem(item, 1, value);
682 setlistitem(v, j, item);
683 j++;
684 }
685 }
686 return v;
687}
688
Guido van Rossum4199fac1993-11-05 10:18:44 +0000689int
690getmappingsize(mp)
691 object *mp;
692{
693 if (mp == NULL || !is_mappingobject(mp)) {
694 err_badcall();
Guido van Rossumb376a4a1993-11-23 17:53:17 +0000695 return 0;
Guido van Rossum4199fac1993-11-05 10:18:44 +0000696 }
697 return ((mappingobject *)mp)->ma_used;
698}
699
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000700object *
701getmappingkeys(mp)
702 object *mp;
703{
704 if (mp == NULL || !is_mappingobject(mp)) {
705 err_badcall();
706 return NULL;
707 }
708 return mapping_keys((mappingobject *)mp, (object *)NULL);
709}
710
Guido van Rossum25831651993-05-19 14:50:45 +0000711object *
712getmappingvalues(mp)
713 object *mp;
714{
715 if (mp == NULL || !is_mappingobject(mp)) {
716 err_badcall();
717 return NULL;
718 }
719 return mapping_values((mappingobject *)mp, (object *)NULL);
720}
721
722object *
723getmappingitems(mp)
724 object *mp;
725{
726 if (mp == NULL || !is_mappingobject(mp)) {
727 err_badcall();
728 return NULL;
729 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000730 return mapping_items((mappingobject *)mp, (object *)NULL);
Guido van Rossum25831651993-05-19 14:50:45 +0000731}
732
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000733#define NEWCMP
734
735#ifdef NEWCMP
736
737/* Subroutine which returns the smallest key in a for which b's value
738 is different or absent. The value is returned too, through the
739 pval argument. No reference counts are incremented. */
740
741static object *
742characterize(a, b, pval)
743 mappingobject *a;
744 mappingobject *b;
745 object **pval;
746{
747 object *diff = NULL;
748 int i;
749
750 *pval = NULL;
751 for (i = 0; i < a->ma_size; i++) {
752 if (a->ma_table[i].me_value != NULL) {
753 object *key = a->ma_table[i].me_key;
754 object *aval, *bval;
755 if (diff != NULL && cmpobject(key, diff) > 0)
756 continue;
757 aval = a->ma_table[i].me_value;
758 bval = mappinglookup((object *)b, key);
759 if (bval == NULL || cmpobject(aval, bval) != 0) {
760 diff = key;
761 *pval = aval;
762 }
763 }
764 }
765 return diff;
766}
767
768static int
769mapping_compare(a, b)
770 mappingobject *a, *b;
771{
772 object *adiff, *bdiff, *aval, *bval;
773 int res;
774
775 /* Compare lengths first */
776 if (a->ma_used < b->ma_used)
777 return -1; /* a is shorter */
778 else if (a->ma_used > b->ma_used)
779 return 1; /* b is shorter */
780 /* Same length -- check all keys */
781 adiff = characterize(a, b, &aval);
782 if (adiff == NULL)
783 return 0; /* a is a subset with the same length */
784 bdiff = characterize(b, a, &bval);
785 /* bdiff == NULL would be impossible now */
786 res = cmpobject(adiff, bdiff);
787 if (res == 0)
788 res = cmpobject(aval, bval);
789 return res;
790}
791
792#else /* !NEWCMP */
793
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000794static int
795mapping_compare(a, b)
796 mappingobject *a, *b;
797{
798 object *akeys, *bkeys;
799 int i, n, res;
800 if (a == b)
801 return 0;
802 if (a->ma_used == 0) {
803 if (b->ma_used != 0)
804 return -1;
805 else
806 return 0;
807 }
808 else {
809 if (b->ma_used == 0)
810 return 1;
811 }
812 akeys = mapping_keys(a, (object *)NULL);
813 bkeys = mapping_keys(b, (object *)NULL);
814 if (akeys == NULL || bkeys == NULL) {
815 /* Oops, out of memory -- what to do? */
816 /* For now, sort on address! */
817 XDECREF(akeys);
818 XDECREF(bkeys);
819 if (a < b)
820 return -1;
821 else
822 return 1;
823 }
824 sortlist(akeys);
825 sortlist(bkeys);
826 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
827 res = 0;
828 for (i = 0; i < n; i++) {
829 object *akey, *bkey, *aval, *bval;
830 long ahash, bhash;
831 akey = getlistitem(akeys, i);
832 bkey = getlistitem(bkeys, i);
833 res = cmpobject(akey, bkey);
834 if (res != 0)
835 break;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000836#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000837 if (!is_stringobject(akey) ||
838 (ahash = ((stringobject *) akey)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000839#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000840 {
841 ahash = hashobject(akey);
842 if (ahash == -1)
843 err_clear(); /* Don't want errors here */
844 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000845#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000846 if (!is_stringobject(bkey) ||
847 (bhash = ((stringobject *) bkey)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000848#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000849 {
850 bhash = hashobject(bkey);
851 if (bhash == -1)
852 err_clear(); /* Don't want errors here */
853 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000854 aval = lookmapping(a, akey, ahash) -> me_value;
855 bval = lookmapping(b, bkey, bhash) -> me_value;
856 res = cmpobject(aval, bval);
857 if (res != 0)
858 break;
859 }
860 if (res == 0) {
861 if (a->ma_used < b->ma_used)
862 res = -1;
863 else if (a->ma_used > b->ma_used)
864 res = 1;
865 }
866 DECREF(akeys);
867 DECREF(bkeys);
868 return res;
869}
870
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000871#endif /* !NEWCMP */
872
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000873static object *
874mapping_has_key(mp, args)
875 register mappingobject *mp;
876 object *args;
877{
878 object *key;
879 long hash;
880 register long ok;
881 if (!getargs(args, "O", &key))
882 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000883#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000884 if (!is_stringobject(key) ||
885 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000886#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000887 {
888 hash = hashobject(key);
889 if (hash == -1)
890 return NULL;
891 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000892 ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000893 return newintobject(ok);
894}
895
896static struct methodlist mapp_methods[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000897 {"has_key", (method)mapping_has_key},
898 {"items", (method)mapping_items},
899 {"keys", (method)mapping_keys},
900 {"values", (method)mapping_values},
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000901 {NULL, NULL} /* sentinel */
902};
903
904static object *
905mapping_getattr(mp, name)
906 mappingobject *mp;
907 char *name;
908{
909 return findmethod(mapp_methods, (object *)mp, name);
910}
911
912typeobject Mappingtype = {
913 OB_HEAD_INIT(&Typetype)
914 0,
Guido van Rossum9bfef441993-03-29 10:43:31 +0000915 "dictionary",
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000916 sizeof(mappingobject),
917 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000918 (destructor)mapping_dealloc, /*tp_dealloc*/
919 (printfunc)mapping_print, /*tp_print*/
920 (getattrfunc)mapping_getattr, /*tp_getattr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000921 0, /*tp_setattr*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000922 (cmpfunc)mapping_compare, /*tp_compare*/
923 (reprfunc)mapping_repr, /*tp_repr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000924 0, /*tp_as_number*/
925 0, /*tp_as_sequence*/
926 &mapping_as_mapping, /*tp_as_mapping*/
927};
928
929/* For backward compatibility with old dictionary interface */
930
931static object *last_name_object;
Guido van Rossum992ded81995-12-08 01:16:31 +0000932static char *last_name_char; /* NULL or == getstringvalue(last_name_object) */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000933
934object *
935getattro(v, name)
936 object *v;
937 object *name;
938{
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000939 if (v->ob_type->tp_getattro != NULL)
940 return (*v->ob_type->tp_getattro)(v, name);
941
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000942 if (name != last_name_object) {
943 XDECREF(last_name_object);
944 INCREF(name);
945 last_name_object = name;
946 last_name_char = getstringvalue(name);
947 }
948 return getattr(v, last_name_char);
949}
950
951int
952setattro(v, name, value)
953 object *v;
954 object *name;
955 object *value;
956{
Guido van Rossum2a61e741997-01-18 07:55:05 +0000957 int err;
958 INCREF(name);
959 PyString_InternInPlace(&name);
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000960 if (v->ob_type->tp_setattro != NULL)
Guido van Rossum2a61e741997-01-18 07:55:05 +0000961 err = (*v->ob_type->tp_setattro)(v, name, value);
962 else {
963 if (name != last_name_object) {
964 XDECREF(last_name_object);
965 INCREF(name);
966 last_name_object = name;
967 last_name_char = getstringvalue(name);
968 }
969 err = setattr(v, last_name_char, value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000970 }
Guido van Rossum2a61e741997-01-18 07:55:05 +0000971 DECREF(name);
972 return err;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000973}
974
975object *
976dictlookup(v, key)
977 object *v;
978 char *key;
979{
Guido van Rossum992ded81995-12-08 01:16:31 +0000980 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000981 XDECREF(last_name_object);
982 last_name_object = newstringobject(key);
983 if (last_name_object == NULL) {
984 last_name_char = NULL;
985 return NULL;
986 }
Guido van Rossum2a61e741997-01-18 07:55:05 +0000987 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +0000988 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000989 }
990 return mappinglookup(v, last_name_object);
991}
992
993int
994dictinsert(v, key, item)
995 object *v;
996 char *key;
997 object *item;
998{
Guido van Rossum992ded81995-12-08 01:16:31 +0000999 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001000 XDECREF(last_name_object);
1001 last_name_object = newstringobject(key);
1002 if (last_name_object == NULL) {
1003 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +00001004 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001005 }
Guido van Rossum2a61e741997-01-18 07:55:05 +00001006 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +00001007 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001008 }
1009 return mappinginsert(v, last_name_object, item);
1010}
1011
1012int
1013dictremove(v, key)
1014 object *v;
1015 char *key;
1016{
Guido van Rossum992ded81995-12-08 01:16:31 +00001017 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001018 XDECREF(last_name_object);
1019 last_name_object = newstringobject(key);
1020 if (last_name_object == NULL) {
1021 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +00001022 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001023 }
Guido van Rossum992ded81995-12-08 01:16:31 +00001024 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001025 }
1026 return mappingremove(v, last_name_object);
1027}