blob: a8767d7e30a695a3376b22d7d639217206fe1a01 [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;
Guido van Rossum2a61e741997-01-18 07:55:05 +000090#ifdef INTERN_STRINGS
91 int ma_fast;
92#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +000093 mappingentry *ma_table;
94} mappingobject;
95
96object *
97newmappingobject()
98{
99 register mappingobject *mp;
100 if (dummy == NULL) { /* Auto-initialize dummy */
101 dummy = newstringobject("<dummy key>");
102 if (dummy == NULL)
103 return NULL;
104 }
105 mp = NEWOBJ(mappingobject, &Mappingtype);
106 if (mp == NULL)
107 return NULL;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000108 mp->ma_size = 0;
109 mp->ma_table = NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000110 mp->ma_fill = 0;
111 mp->ma_used = 0;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000112#ifdef INTERN_STRINGS
113 mp->ma_fast = 1;
114#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000115 return (object *)mp;
116}
117
118/*
119The basic lookup function used by all operations.
120This is essentially Algorithm D from Knuth Vol. 3, Sec. 6.4.
121Open addressing is preferred over chaining since the link overhead for
122chaining would be substantial (100% with typical malloc overhead).
123
124First a 32-bit hash value, 'sum', is computed from the key string.
125The first character is added an extra time shifted by 8 to avoid hashing
126single-character keys (often heavily used variables) too close together.
127All arithmetic on sum should ignore overflow.
128
129The initial probe index is then computed as sum mod the table size.
130Subsequent probe indices are incr apart (mod table size), where incr
131is also derived from sum, with the additional requirement that it is
132relative prime to the table size (i.e., 1 <= incr < size, since the size
133is a prime number). My choice for incr is somewhat arbitrary.
134*/
135static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
136static mappingentry *
137lookmapping(mp, key, hash)
Guido van Rossum7d181591997-01-16 21:06:45 +0000138 mappingobject *mp;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000139 object *key;
140 long hash;
141{
Guido van Rossum7d181591997-01-16 21:06:45 +0000142 /* Optimizations based on observations by Jyrki Alakuijala
143 (paraphrased):
144
145 - This routine is very heavily used, so should be AFAP
146 (As Fast As Possible).
147
148 - Most of the time, the first try is a hit or a definite
149 miss; so postpone the calculation of incr until we know the
150 first try was a miss.
151
152 - Write the loop twice, so we can move the test for
153 freeslot==NULL out of the loop.
154
155 - Write the loop using pointer increments and comparisons
156 rather than using an integer loop index.
157
158 Note that it behooves the compiler to calculate the values
159 of incr*sizeof(*ep) outside the loops and use this in the
160 increment of ep. I've reduced the number of register
161 variables to the two most obvious candidates.
162
163 */
164
165 register mappingentry *ep;
166 mappingentry *end;
167 register object *ekey;
168 mappingentry *freeslot;
169 unsigned long sum;
170 int incr;
171 int size;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000172#ifdef INTERN_STRINGS
173 int fast;
174#endif
Guido van Rossum7d181591997-01-16 21:06:45 +0000175
176 ep = &mp->ma_table[(unsigned long)hash%mp->ma_size];
177 ekey = ep->me_key;
178 if (ekey == NULL)
179 return ep;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000180#ifdef INTERN_STRINGS
181 if ((fast = mp->ma_fast)) {
182 object *ikey;
183 if (!is_stringobject(key) ||
184 (ikey = ((stringobject *)key)->ob_sinterned) == NULL)
185 fast = 0;
186 else
187 key = ikey;
188 }
189#endif
Guido van Rossum7d181591997-01-16 21:06:45 +0000190 if (ekey == dummy)
191 freeslot = ep;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000192 else {
193#ifdef INTERN_STRINGS
194 if (fast) {
195 if (ekey == key)
196 return ep;
197 }
198 else
199#endif
200 {
201 if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
202 return ep;
203 }
Guido van Rossum7d181591997-01-16 21:06:45 +0000204 freeslot = NULL;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000205 }
Guido van Rossum7d181591997-01-16 21:06:45 +0000206
207 size = mp->ma_size;
208 sum = hash;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000209 do {
Guido van Rossum5fe60581995-03-09 12:12:50 +0000210 sum = 3*sum + 1;
Guido van Rossum310968d1996-07-30 16:45:31 +0000211 incr = sum % size;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000212 } while (incr == 0);
Guido van Rossum7d181591997-01-16 21:06:45 +0000213
214 end = mp->ma_table + size;
215
Guido van Rossum2a61e741997-01-18 07:55:05 +0000216#ifdef INTERN_STRINGS
217 if (fast) {
218 if (freeslot == NULL) {
219 for (;;) {
220 ep += incr;
221 if (ep >= end)
222 ep -= size;
223 ekey = ep->me_key;
224 if (ekey == NULL || ekey == key)
225 return ep;
226 if (ekey == dummy) {
227 freeslot = ep;
228 break;
229 }
230 }
231 }
232
233 for (;;) {
234 ep += incr;
235 if (ep >= end)
236 ep -= size;
237 ekey = ep->me_key;
238 if (ekey == NULL)
239 return freeslot;
240 if (ekey == key)
241 return ep;
242 }
243 }
244#endif
245
Guido van Rossum7d181591997-01-16 21:06:45 +0000246 if (freeslot == NULL) {
247 for (;;) {
248 ep += incr;
249 if (ep >= end)
250 ep -= size;
251 ekey = ep->me_key;
252 if (ekey == NULL)
253 return ep;
254 if (ekey == dummy) {
255 freeslot = ep;
256 break;
257 }
258 if (ep->me_hash == hash && cmpobject(ekey, key) == 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000259 return ep;
260 }
Guido van Rossum7d181591997-01-16 21:06:45 +0000261 }
262
263 for (;;) {
264 ep += incr;
265 if (ep >= end)
266 ep -= size;
267 ekey = ep->me_key;
268 if (ekey == NULL)
269 return freeslot;
270 if (ekey != dummy &&
271 ep->me_hash == hash && cmpobject(ekey, key) == 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000272 return ep;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000273 }
274}
275
276/*
277Internal routine to insert a new item into the table.
278Used both by the internal resize routine and by the public insert routine.
279Eats a reference to key and one to value.
280*/
281static void insertmapping PROTO((mappingobject *, object *, long, object *));
282static void
283insertmapping(mp, key, hash, value)
284 register mappingobject *mp;
285 object *key;
286 long hash;
287 object *value;
288{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000289 object *old_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000290 register mappingentry *ep;
291 ep = lookmapping(mp, key, hash);
292 if (ep->me_value != NULL) {
Guido van Rossumd7047b31995-01-02 19:07:15 +0000293 old_value = ep->me_value;
294 ep->me_value = value;
295 DECREF(old_value); /* which **CAN** re-enter */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000296 DECREF(key);
297 }
298 else {
299 if (ep->me_key == NULL)
300 mp->ma_fill++;
301 else
302 DECREF(ep->me_key);
303 ep->me_key = key;
304 ep->me_hash = hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000305 ep->me_value = value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000306 mp->ma_used++;
307 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000308}
309
310/*
311Restructure the table by allocating a new table and reinserting all
312items again. When entries have been deleted, the new table may
313actually be smaller than the old one.
314*/
315static int mappingresize PROTO((mappingobject *));
316static int
317mappingresize(mp)
318 mappingobject *mp;
319{
320 register int oldsize = mp->ma_size;
321 register int newsize;
322 register mappingentry *oldtable = mp->ma_table;
323 register mappingentry *newtable;
324 register mappingentry *ep;
325 register int i;
326 newsize = mp->ma_size;
327 for (i = 0; ; i++) {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000328 if (primes[i] <= 0) {
329 /* Ran out of primes */
330 err_nomem();
331 return -1;
332 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000333 if (primes[i] > mp->ma_used*2) {
334 newsize = primes[i];
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000335 if (newsize != primes[i]) {
336 /* Integer truncation */
337 err_nomem();
338 return -1;
339 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000340 break;
341 }
342 }
343 newtable = (mappingentry *) calloc(sizeof(mappingentry), newsize);
344 if (newtable == NULL) {
345 err_nomem();
346 return -1;
347 }
348 mp->ma_size = newsize;
349 mp->ma_table = newtable;
350 mp->ma_fill = 0;
351 mp->ma_used = 0;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000352
353 /* Make two passes, so we can avoid decrefs
354 (and possible side effects) till the table is copied */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000355 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
356 if (ep->me_value != NULL)
357 insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000358 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000359 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
360 if (ep->me_value == NULL)
361 XDECREF(ep->me_key);
362 }
363
364 XDEL(oldtable);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000365 return 0;
366}
367
368object *
369mappinglookup(op, key)
370 object *op;
371 object *key;
372{
373 long hash;
374 if (!is_mappingobject(op)) {
375 err_badcall();
376 return NULL;
377 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000378 if (((mappingobject *)op)->ma_table == NULL)
379 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000380#ifdef CACHE_HASH
381 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
382#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000383 hash = hashobject(key);
384 if (hash == -1)
385 return NULL;
386 return lookmapping((mappingobject *)op, key, hash) -> me_value;
387}
388
389int
390mappinginsert(op, key, value)
391 register object *op;
392 object *key;
393 object *value;
394{
395 register mappingobject *mp;
396 register long hash;
397 if (!is_mappingobject(op)) {
398 err_badcall();
399 return -1;
400 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000401 mp = (mappingobject *)op;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000402#ifdef CACHE_HASH
403 if (is_stringobject(key)) {
404#ifdef INTERN_STRINGS
405 if (((stringobject *)key)->ob_sinterned != NULL) {
406 key = ((stringobject *)key)->ob_sinterned;
407 hash = ((stringobject *)key)->ob_shash;
408 }
409 else
410#endif
411 {
412 hash = ((stringobject *)key)->ob_shash;
413 if (hash == -1)
414 hash = hashobject(key);
415#ifdef INTERN_STRINGS
416 mp->ma_fast = 0;
417#endif
418 }
419 }
420 else
421#endif
422 {
423 hash = hashobject(key);
424 if (hash == -1)
425 return -1;
426#ifdef INTERN_STRINGS
427 mp->ma_fast = 0;
428#endif
429 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000430 /* if fill >= 2/3 size, resize */
431 if (mp->ma_fill*3 >= mp->ma_size*2) {
432 if (mappingresize(mp) != 0) {
433 if (mp->ma_fill+1 > mp->ma_size)
434 return -1;
435 }
436 }
437 INCREF(value);
438 INCREF(key);
439 insertmapping(mp, key, hash, value);
440 return 0;
441}
442
443int
444mappingremove(op, key)
445 object *op;
446 object *key;
447{
448 register mappingobject *mp;
449 register long hash;
450 register mappingentry *ep;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000451 object *old_value, *old_key;
452
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000453 if (!is_mappingobject(op)) {
454 err_badcall();
455 return -1;
456 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000457#ifdef CACHE_HASH
458 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
459#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000460 hash = hashobject(key);
461 if (hash == -1)
462 return -1;
463 mp = (mappingobject *)op;
Guido van Rossumefc87131995-01-02 19:42:39 +0000464 if (((mappingobject *)op)->ma_table == NULL)
465 goto empty;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000466 ep = lookmapping(mp, key, hash);
467 if (ep->me_value == NULL) {
Guido van Rossumefc87131995-01-02 19:42:39 +0000468 empty:
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000469 err_setval(KeyError, key);
470 return -1;
471 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000472 old_key = ep->me_key;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000473 INCREF(dummy);
474 ep->me_key = dummy;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000475 old_value = ep->me_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000476 ep->me_value = NULL;
477 mp->ma_used--;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000478 DECREF(old_value);
479 DECREF(old_key);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000480 return 0;
481}
482
Guido van Rossum25831651993-05-19 14:50:45 +0000483void
484mappingclear(op)
485 object *op;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000486{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000487 int i, n;
488 register mappingentry *table;
489 mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000490 if (!is_mappingobject(op))
491 return;
492 mp = (mappingobject *)op;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000493 table = mp->ma_table;
494 if (table == NULL)
495 return;
496 n = mp->ma_size;
497 mp->ma_size = mp->ma_used = mp->ma_fill = 0;
498 mp->ma_table = NULL;
499 for (i = 0; i < n; i++) {
500 XDECREF(table[i].me_key);
501 XDECREF(table[i].me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000502 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000503 DEL(table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000504}
505
Guido van Rossum25831651993-05-19 14:50:45 +0000506int
507mappinggetnext(op, ppos, pkey, pvalue)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000508 object *op;
Guido van Rossum25831651993-05-19 14:50:45 +0000509 int *ppos;
510 object **pkey;
511 object **pvalue;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000512{
Guido van Rossum25831651993-05-19 14:50:45 +0000513 int i;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000514 register mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000515 if (!is_dictobject(op))
516 return 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000517 mp = (mappingobject *)op;
Guido van Rossum25831651993-05-19 14:50:45 +0000518 i = *ppos;
519 if (i < 0)
520 return 0;
521 while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
522 i++;
523 *ppos = i+1;
524 if (i >= mp->ma_size)
525 return 0;
526 if (pkey)
527 *pkey = mp->ma_table[i].me_key;
528 if (pvalue)
529 *pvalue = mp->ma_table[i].me_value;
530 return 1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000531}
532
533/* Methods */
534
535static void
536mapping_dealloc(mp)
537 register mappingobject *mp;
538{
539 register int i;
540 register mappingentry *ep;
541 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
542 if (ep->me_key != NULL)
543 DECREF(ep->me_key);
544 if (ep->me_value != NULL)
545 DECREF(ep->me_value);
546 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000547 XDEL(mp->ma_table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000548 DEL(mp);
549}
550
551static int
552mapping_print(mp, fp, flags)
553 register mappingobject *mp;
554 register FILE *fp;
555 register int flags;
556{
557 register int i;
558 register int any;
559 register mappingentry *ep;
560 fprintf(fp, "{");
561 any = 0;
562 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
563 if (ep->me_value != NULL) {
564 if (any++ > 0)
565 fprintf(fp, ", ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000566 if (printobject((object *)ep->me_key, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000567 return -1;
568 fprintf(fp, ": ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000569 if (printobject(ep->me_value, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000570 return -1;
571 }
572 }
573 fprintf(fp, "}");
574 return 0;
575}
576
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000577static object *
578mapping_repr(mp)
579 mappingobject *mp;
580{
581 auto object *v;
582 object *sepa, *colon;
583 register int i;
584 register int any;
585 register mappingentry *ep;
586 v = newstringobject("{");
587 sepa = newstringobject(", ");
588 colon = newstringobject(": ");
589 any = 0;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000590 for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000591 if (ep->me_value != NULL) {
592 if (any++)
593 joinstring(&v, sepa);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000594 joinstring_decref(&v, reprobject(ep->me_key));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000595 joinstring(&v, colon);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000596 joinstring_decref(&v, reprobject(ep->me_value));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000597 }
598 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000599 joinstring_decref(&v, newstringobject("}"));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000600 XDECREF(sepa);
601 XDECREF(colon);
602 return v;
603}
604
605static int
606mapping_length(mp)
607 mappingobject *mp;
608{
609 return mp->ma_used;
610}
611
612static object *
613mapping_subscript(mp, key)
614 mappingobject *mp;
615 register object *key;
616{
617 object *v;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000618 long hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000619 if (mp->ma_table == NULL) {
620 err_setval(KeyError, key);
621 return NULL;
622 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000623#ifdef CACHE_HASH
624 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
625#endif
626 hash = hashobject(key);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000627 if (hash == -1)
628 return NULL;
629 v = lookmapping(mp, key, hash) -> me_value;
630 if (v == NULL)
631 err_setval(KeyError, key);
632 else
633 INCREF(v);
634 return v;
635}
636
637static int
638mapping_ass_sub(mp, v, w)
639 mappingobject *mp;
640 object *v, *w;
641{
642 if (w == NULL)
643 return mappingremove((object *)mp, v);
644 else
645 return mappinginsert((object *)mp, v, w);
646}
647
648static mapping_methods mapping_as_mapping = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000649 (inquiry)mapping_length, /*mp_length*/
650 (binaryfunc)mapping_subscript, /*mp_subscript*/
651 (objobjargproc)mapping_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000652};
653
654static object *
655mapping_keys(mp, args)
656 register mappingobject *mp;
657 object *args;
658{
659 register object *v;
660 register int i, j;
661 if (!getnoarg(args))
662 return NULL;
663 v = newlistobject(mp->ma_used);
664 if (v == NULL)
665 return NULL;
666 for (i = 0, j = 0; i < mp->ma_size; i++) {
667 if (mp->ma_table[i].me_value != NULL) {
668 object *key = mp->ma_table[i].me_key;
669 INCREF(key);
670 setlistitem(v, j, key);
671 j++;
672 }
673 }
674 return v;
675}
676
Guido van Rossum25831651993-05-19 14:50:45 +0000677static object *
678mapping_values(mp, args)
679 register mappingobject *mp;
680 object *args;
681{
682 register object *v;
683 register int i, j;
684 if (!getnoarg(args))
685 return NULL;
686 v = newlistobject(mp->ma_used);
687 if (v == NULL)
688 return NULL;
689 for (i = 0, j = 0; i < mp->ma_size; i++) {
690 if (mp->ma_table[i].me_value != NULL) {
691 object *value = mp->ma_table[i].me_value;
692 INCREF(value);
693 setlistitem(v, j, value);
694 j++;
695 }
696 }
697 return v;
698}
699
700static object *
701mapping_items(mp, args)
702 register mappingobject *mp;
703 object *args;
704{
705 register object *v;
706 register int i, j;
707 if (!getnoarg(args))
708 return NULL;
709 v = newlistobject(mp->ma_used);
710 if (v == NULL)
711 return NULL;
712 for (i = 0, j = 0; i < mp->ma_size; i++) {
713 if (mp->ma_table[i].me_value != NULL) {
714 object *key = mp->ma_table[i].me_key;
715 object *value = mp->ma_table[i].me_value;
716 object *item = newtupleobject(2);
717 if (item == NULL) {
718 DECREF(v);
719 return NULL;
720 }
721 INCREF(key);
722 settupleitem(item, 0, key);
723 INCREF(value);
724 settupleitem(item, 1, value);
725 setlistitem(v, j, item);
726 j++;
727 }
728 }
729 return v;
730}
731
Guido van Rossum4199fac1993-11-05 10:18:44 +0000732int
733getmappingsize(mp)
734 object *mp;
735{
736 if (mp == NULL || !is_mappingobject(mp)) {
737 err_badcall();
Guido van Rossumb376a4a1993-11-23 17:53:17 +0000738 return 0;
Guido van Rossum4199fac1993-11-05 10:18:44 +0000739 }
740 return ((mappingobject *)mp)->ma_used;
741}
742
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000743object *
744getmappingkeys(mp)
745 object *mp;
746{
747 if (mp == NULL || !is_mappingobject(mp)) {
748 err_badcall();
749 return NULL;
750 }
751 return mapping_keys((mappingobject *)mp, (object *)NULL);
752}
753
Guido van Rossum25831651993-05-19 14:50:45 +0000754object *
755getmappingvalues(mp)
756 object *mp;
757{
758 if (mp == NULL || !is_mappingobject(mp)) {
759 err_badcall();
760 return NULL;
761 }
762 return mapping_values((mappingobject *)mp, (object *)NULL);
763}
764
765object *
766getmappingitems(mp)
767 object *mp;
768{
769 if (mp == NULL || !is_mappingobject(mp)) {
770 err_badcall();
771 return NULL;
772 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000773 return mapping_items((mappingobject *)mp, (object *)NULL);
Guido van Rossum25831651993-05-19 14:50:45 +0000774}
775
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000776#define NEWCMP
777
778#ifdef NEWCMP
779
780/* Subroutine which returns the smallest key in a for which b's value
781 is different or absent. The value is returned too, through the
782 pval argument. No reference counts are incremented. */
783
784static object *
785characterize(a, b, pval)
786 mappingobject *a;
787 mappingobject *b;
788 object **pval;
789{
790 object *diff = NULL;
791 int i;
792
793 *pval = NULL;
794 for (i = 0; i < a->ma_size; i++) {
795 if (a->ma_table[i].me_value != NULL) {
796 object *key = a->ma_table[i].me_key;
797 object *aval, *bval;
798 if (diff != NULL && cmpobject(key, diff) > 0)
799 continue;
800 aval = a->ma_table[i].me_value;
801 bval = mappinglookup((object *)b, key);
802 if (bval == NULL || cmpobject(aval, bval) != 0) {
803 diff = key;
804 *pval = aval;
805 }
806 }
807 }
808 return diff;
809}
810
811static int
812mapping_compare(a, b)
813 mappingobject *a, *b;
814{
815 object *adiff, *bdiff, *aval, *bval;
816 int res;
817
818 /* Compare lengths first */
819 if (a->ma_used < b->ma_used)
820 return -1; /* a is shorter */
821 else if (a->ma_used > b->ma_used)
822 return 1; /* b is shorter */
823 /* Same length -- check all keys */
824 adiff = characterize(a, b, &aval);
825 if (adiff == NULL)
826 return 0; /* a is a subset with the same length */
827 bdiff = characterize(b, a, &bval);
828 /* bdiff == NULL would be impossible now */
829 res = cmpobject(adiff, bdiff);
830 if (res == 0)
831 res = cmpobject(aval, bval);
832 return res;
833}
834
835#else /* !NEWCMP */
836
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000837static int
838mapping_compare(a, b)
839 mappingobject *a, *b;
840{
841 object *akeys, *bkeys;
842 int i, n, res;
843 if (a == b)
844 return 0;
845 if (a->ma_used == 0) {
846 if (b->ma_used != 0)
847 return -1;
848 else
849 return 0;
850 }
851 else {
852 if (b->ma_used == 0)
853 return 1;
854 }
855 akeys = mapping_keys(a, (object *)NULL);
856 bkeys = mapping_keys(b, (object *)NULL);
857 if (akeys == NULL || bkeys == NULL) {
858 /* Oops, out of memory -- what to do? */
859 /* For now, sort on address! */
860 XDECREF(akeys);
861 XDECREF(bkeys);
862 if (a < b)
863 return -1;
864 else
865 return 1;
866 }
867 sortlist(akeys);
868 sortlist(bkeys);
869 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
870 res = 0;
871 for (i = 0; i < n; i++) {
872 object *akey, *bkey, *aval, *bval;
873 long ahash, bhash;
874 akey = getlistitem(akeys, i);
875 bkey = getlistitem(bkeys, i);
876 res = cmpobject(akey, bkey);
877 if (res != 0)
878 break;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000879#ifdef CACHE_HASH
880 if (!is_stringobject(akey) || (ahash = ((stringobject *) akey)->ob_shash) == -1)
881#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000882 ahash = hashobject(akey);
883 if (ahash == -1)
884 err_clear(); /* Don't want errors here */
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000885#ifdef CACHE_HASH
886 if (!is_stringobject(bkey) || (bhash = ((stringobject *) bkey)->ob_shash) == -1)
887#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000888 bhash = hashobject(bkey);
889 if (bhash == -1)
890 err_clear(); /* Don't want errors here */
891 aval = lookmapping(a, akey, ahash) -> me_value;
892 bval = lookmapping(b, bkey, bhash) -> me_value;
893 res = cmpobject(aval, bval);
894 if (res != 0)
895 break;
896 }
897 if (res == 0) {
898 if (a->ma_used < b->ma_used)
899 res = -1;
900 else if (a->ma_used > b->ma_used)
901 res = 1;
902 }
903 DECREF(akeys);
904 DECREF(bkeys);
905 return res;
906}
907
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000908#endif /* !NEWCMP */
909
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000910static object *
911mapping_has_key(mp, args)
912 register mappingobject *mp;
913 object *args;
914{
915 object *key;
916 long hash;
917 register long ok;
918 if (!getargs(args, "O", &key))
919 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000920#ifdef CACHE_HASH
921 if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1)
922#endif
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000923 hash = hashobject(key);
924 if (hash == -1)
925 return NULL;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000926 ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000927 return newintobject(ok);
928}
929
930static struct methodlist mapp_methods[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000931 {"has_key", (method)mapping_has_key},
932 {"items", (method)mapping_items},
933 {"keys", (method)mapping_keys},
934 {"values", (method)mapping_values},
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000935 {NULL, NULL} /* sentinel */
936};
937
938static object *
939mapping_getattr(mp, name)
940 mappingobject *mp;
941 char *name;
942{
943 return findmethod(mapp_methods, (object *)mp, name);
944}
945
946typeobject Mappingtype = {
947 OB_HEAD_INIT(&Typetype)
948 0,
Guido van Rossum9bfef441993-03-29 10:43:31 +0000949 "dictionary",
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000950 sizeof(mappingobject),
951 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000952 (destructor)mapping_dealloc, /*tp_dealloc*/
953 (printfunc)mapping_print, /*tp_print*/
954 (getattrfunc)mapping_getattr, /*tp_getattr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000955 0, /*tp_setattr*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000956 (cmpfunc)mapping_compare, /*tp_compare*/
957 (reprfunc)mapping_repr, /*tp_repr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000958 0, /*tp_as_number*/
959 0, /*tp_as_sequence*/
960 &mapping_as_mapping, /*tp_as_mapping*/
961};
962
963/* For backward compatibility with old dictionary interface */
964
965static object *last_name_object;
Guido van Rossum992ded81995-12-08 01:16:31 +0000966static char *last_name_char; /* NULL or == getstringvalue(last_name_object) */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000967
968object *
969getattro(v, name)
970 object *v;
971 object *name;
972{
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000973 if (v->ob_type->tp_getattro != NULL)
974 return (*v->ob_type->tp_getattro)(v, name);
975
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000976 if (name != last_name_object) {
977 XDECREF(last_name_object);
978 INCREF(name);
979 last_name_object = name;
980 last_name_char = getstringvalue(name);
981 }
982 return getattr(v, last_name_char);
983}
984
985int
986setattro(v, name, value)
987 object *v;
988 object *name;
989 object *value;
990{
Guido van Rossum2a61e741997-01-18 07:55:05 +0000991 int err;
992 INCREF(name);
993 PyString_InternInPlace(&name);
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000994 if (v->ob_type->tp_setattro != NULL)
Guido van Rossum2a61e741997-01-18 07:55:05 +0000995 err = (*v->ob_type->tp_setattro)(v, name, value);
996 else {
997 if (name != last_name_object) {
998 XDECREF(last_name_object);
999 INCREF(name);
1000 last_name_object = name;
1001 last_name_char = getstringvalue(name);
1002 }
1003 err = setattr(v, last_name_char, value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001004 }
Guido van Rossum2a61e741997-01-18 07:55:05 +00001005 DECREF(name);
1006 return err;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001007}
1008
1009object *
1010dictlookup(v, key)
1011 object *v;
1012 char *key;
1013{
Guido van Rossum992ded81995-12-08 01:16:31 +00001014 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001015 XDECREF(last_name_object);
1016 last_name_object = newstringobject(key);
1017 if (last_name_object == NULL) {
1018 last_name_char = NULL;
1019 return NULL;
1020 }
Guido van Rossum2a61e741997-01-18 07:55:05 +00001021 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +00001022 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001023 }
1024 return mappinglookup(v, last_name_object);
1025}
1026
1027int
1028dictinsert(v, key, item)
1029 object *v;
1030 char *key;
1031 object *item;
1032{
Guido van Rossum992ded81995-12-08 01:16:31 +00001033 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001034 XDECREF(last_name_object);
1035 last_name_object = newstringobject(key);
1036 if (last_name_object == NULL) {
1037 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +00001038 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001039 }
Guido van Rossum2a61e741997-01-18 07:55:05 +00001040 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +00001041 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001042 }
1043 return mappinginsert(v, last_name_object, item);
1044}
1045
1046int
1047dictremove(v, key)
1048 object *v;
1049 char *key;
1050{
Guido van Rossum992ded81995-12-08 01:16:31 +00001051 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001052 XDECREF(last_name_object);
1053 last_name_object = newstringobject(key);
1054 if (last_name_object == NULL) {
1055 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +00001056 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001057 }
Guido van Rossum992ded81995-12-08 01:16:31 +00001058 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001059 }
1060 return mappingremove(v, last_name_object);
1061}