blob: bcd615df08192364103e020687fa30c4e0012684 [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/*
Guido van Rossum16e93a81997-01-28 00:00:11 +000045 * MINSIZE is the minimum size of a mapping.
46 */
47
48#define MINSIZE 4
49
50/*
51Table of irreducible polynomials to efficiently cycle through
52GF(2^n)-{0}, 2<=n<=30.
Guido van Rossum4b1302b1993-03-27 18:11:32 +000053*/
Guido van Rossum16e93a81997-01-28 00:00:11 +000054static long polys[] = {
Guido van Rossum9e5656c1997-01-29 04:45:16 +000055 4 + 3,
56 8 + 3,
57 16 + 3,
58 32 + 5,
59 64 + 3,
60 128 + 3,
61 256 + 29,
62 512 + 17,
63 1024 + 9,
64 2048 + 5,
65 4096 + 83,
66 8192 + 27,
67 16384 + 43,
68 32768 + 3,
69 65536 + 45,
70 131072 + 9,
71 262144 + 39,
72 524288 + 39,
73 1048576 + 9,
74 2097152 + 5,
75 4194304 + 3,
76 8388608 + 33,
77 16777216 + 27,
78 33554432 + 9,
79 67108864 + 71,
80 134217728 + 39,
81 268435456 + 9,
82 536870912 + 5,
83 1073741824 + 83,
84 0
Guido van Rossum4b1302b1993-03-27 18:11:32 +000085};
86
87/* Object used as dummy key to fill deleted entries */
88static object *dummy; /* Initialized by first call to newmappingobject() */
89
90/*
91Invariant for entries: when in use, de_value is not NULL and de_key is
92not NULL and not dummy; when not in use, de_value is NULL and de_key
93is either NULL or dummy. A dummy key value cannot be replaced by
94NULL, since otherwise other keys may be lost.
95*/
96typedef struct {
97 long me_hash;
98 object *me_key;
99 object *me_value;
100} mappingentry;
101
102/*
103To ensure the lookup algorithm terminates, the table size must be a
104prime number and there must be at least one NULL key in the table.
105The value ma_fill is the number of non-NULL keys; ma_used is the number
106of non-NULL, non-dummy keys.
107To avoid slowing down lookups on a near-full table, we resize the table
108when it is more than half filled.
109*/
110typedef struct {
111 OB_HEAD
112 int ma_fill;
113 int ma_used;
114 int ma_size;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000115 int ma_poly;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000116 mappingentry *ma_table;
117} mappingobject;
118
119object *
120newmappingobject()
121{
122 register mappingobject *mp;
123 if (dummy == NULL) { /* Auto-initialize dummy */
124 dummy = newstringobject("<dummy key>");
125 if (dummy == NULL)
126 return NULL;
127 }
128 mp = NEWOBJ(mappingobject, &Mappingtype);
129 if (mp == NULL)
130 return NULL;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000131 mp->ma_size = 0;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000132 mp->ma_poly = 0;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000133 mp->ma_table = NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000134 mp->ma_fill = 0;
135 mp->ma_used = 0;
136 return (object *)mp;
137}
138
139/*
140The basic lookup function used by all operations.
Guido van Rossum16e93a81997-01-28 00:00:11 +0000141This is based on Algorithm D from Knuth Vol. 3, Sec. 6.4.
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000142Open addressing is preferred over chaining since the link overhead for
143chaining would be substantial (100% with typical malloc overhead).
Guido van Rossum16e93a81997-01-28 00:00:11 +0000144However, instead of going through the table at constant steps, we cycle
145through the values of GF(2^n)-{0}. This avoids modulo computations, being
146much cheaper on RISC machines, without leading to clustering.
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000147
148First a 32-bit hash value, 'sum', is computed from the key string.
149The first character is added an extra time shifted by 8 to avoid hashing
150single-character keys (often heavily used variables) too close together.
151All arithmetic on sum should ignore overflow.
152
153The initial probe index is then computed as sum mod the table size.
Guido van Rossum16e93a81997-01-28 00:00:11 +0000154Subsequent probe indices use the values of x^i in GF(2^n) as an offset,
155where x is a root. The initial value is derived from sum, too.
156
157(This version is due to Reimer Behrends, some ideas are also due to
158Jyrki Alakuijala.)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000159*/
160static mappingentry *lookmapping PROTO((mappingobject *, object *, long));
161static mappingentry *
162lookmapping(mp, key, hash)
Guido van Rossum7d181591997-01-16 21:06:45 +0000163 mappingobject *mp;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000164 object *key;
165 long hash;
166{
Guido van Rossum16e93a81997-01-28 00:00:11 +0000167 register int i;
168 register unsigned incr;
169 register unsigned long sum = (unsigned long) hash;
170 register mappingentry *freeslot = NULL;
171 register int mask = mp->ma_size-1;
172 register mappingentry *ep = &mp->ma_table[i];
173 /* We must come up with (i, incr) such that 0 <= i < ma_size
174 and 0 < incr < ma_size and both are a function of hash */
175 i = (~sum) & mask;
176 /* We use ~sum instead if sum, as degenerate hash functions, such
177 as for ints <sigh>, can have lots of leading zeros. It's not
178 really a performance risk, but better safe than sorry. */
179 ep = &mp->ma_table[i];
180 if (ep->me_key == NULL)
Guido van Rossum7d181591997-01-16 21:06:45 +0000181 return ep;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000182 if (ep->me_key == dummy)
Guido van Rossum7d181591997-01-16 21:06:45 +0000183 freeslot = ep;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000184 else if (ep->me_key == key ||
185 (ep->me_hash == hash && cmpobject(ep->me_key, key) == 0)) {
186 return ep;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000187 }
Guido van Rossum16e93a81997-01-28 00:00:11 +0000188 /* Derive incr from i, just to make it more arbitrary. Note that
189 incr must not be 0, or we will get into an infinite loop.*/
190 incr = i << 1;
191 if (!incr)
192 incr = mask;
193 if (incr > mask) /* Cycle through GF(2^n)-{0} */
194 incr ^= mp->ma_poly; /* This will implicitly clear the
195 highest bit */
196 for (;;) {
197 ep = &mp->ma_table[(i+incr)&mask];
198 if (ep->me_key == NULL) {
199 if (freeslot != NULL)
200 return freeslot;
201 else
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000202 return ep;
203 }
Guido van Rossum16e93a81997-01-28 00:00:11 +0000204 if (ep->me_key == dummy) {
205 if (freeslot == NULL)
206 freeslot = ep;
207 }
208 else if (ep->me_key == key ||
209 (ep->me_hash == hash &&
210 cmpobject(ep->me_key, key) == 0)) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000211 return ep;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000212 }
213 /* Cycle through GF(2^n)-{0} */
214 incr = incr << 1;
215 if (incr > mask)
216 incr ^= mp->ma_poly;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000217 }
218}
219
220/*
221Internal routine to insert a new item into the table.
222Used both by the internal resize routine and by the public insert routine.
223Eats a reference to key and one to value.
224*/
225static void insertmapping PROTO((mappingobject *, object *, long, object *));
226static void
227insertmapping(mp, key, hash, value)
228 register mappingobject *mp;
229 object *key;
230 long hash;
231 object *value;
232{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000233 object *old_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000234 register mappingentry *ep;
235 ep = lookmapping(mp, key, hash);
236 if (ep->me_value != NULL) {
Guido van Rossumd7047b31995-01-02 19:07:15 +0000237 old_value = ep->me_value;
238 ep->me_value = value;
239 DECREF(old_value); /* which **CAN** re-enter */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000240 DECREF(key);
241 }
242 else {
243 if (ep->me_key == NULL)
244 mp->ma_fill++;
245 else
246 DECREF(ep->me_key);
247 ep->me_key = key;
248 ep->me_hash = hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000249 ep->me_value = value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000250 mp->ma_used++;
251 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000252}
253
254/*
255Restructure the table by allocating a new table and reinserting all
256items again. When entries have been deleted, the new table may
257actually be smaller than the old one.
258*/
259static int mappingresize PROTO((mappingobject *));
260static int
261mappingresize(mp)
262 mappingobject *mp;
263{
264 register int oldsize = mp->ma_size;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000265 register int newsize, newpoly;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000266 register mappingentry *oldtable = mp->ma_table;
267 register mappingentry *newtable;
268 register mappingentry *ep;
269 register int i;
270 newsize = mp->ma_size;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000271 for (i = 0, newsize = MINSIZE; ; i++, newsize <<= 1) {
272 if (i > sizeof(polys)/sizeof(polys[0])) {
273 /* Ran out of polynomials */
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000274 err_nomem();
275 return -1;
276 }
Guido van Rossum16e93a81997-01-28 00:00:11 +0000277 if (newsize > mp->ma_used*2) {
278 newpoly = polys[i];
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000279 break;
280 }
281 }
282 newtable = (mappingentry *) calloc(sizeof(mappingentry), newsize);
283 if (newtable == NULL) {
284 err_nomem();
285 return -1;
286 }
287 mp->ma_size = newsize;
Guido van Rossum16e93a81997-01-28 00:00:11 +0000288 mp->ma_poly = newpoly;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000289 mp->ma_table = newtable;
290 mp->ma_fill = 0;
291 mp->ma_used = 0;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000292
293 /* Make two passes, so we can avoid decrefs
294 (and possible side effects) till the table is copied */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000295 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
296 if (ep->me_value != NULL)
297 insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000298 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000299 for (i = 0, ep = oldtable; i < oldsize; i++, ep++) {
300 if (ep->me_value == NULL)
301 XDECREF(ep->me_key);
302 }
303
304 XDEL(oldtable);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000305 return 0;
306}
307
308object *
309mappinglookup(op, key)
310 object *op;
311 object *key;
312{
313 long hash;
314 if (!is_mappingobject(op)) {
315 err_badcall();
316 return NULL;
317 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000318 if (((mappingobject *)op)->ma_table == NULL)
319 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000320#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000321 if (!is_stringobject(key) ||
322 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000323#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000324 {
325 hash = hashobject(key);
326 if (hash == -1)
327 return NULL;
328 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000329 return lookmapping((mappingobject *)op, key, hash) -> me_value;
330}
331
332int
333mappinginsert(op, key, value)
334 register object *op;
335 object *key;
336 object *value;
337{
338 register mappingobject *mp;
339 register long hash;
340 if (!is_mappingobject(op)) {
341 err_badcall();
342 return -1;
343 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000344 mp = (mappingobject *)op;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000345#ifdef CACHE_HASH
346 if (is_stringobject(key)) {
347#ifdef INTERN_STRINGS
348 if (((stringobject *)key)->ob_sinterned != NULL) {
349 key = ((stringobject *)key)->ob_sinterned;
350 hash = ((stringobject *)key)->ob_shash;
351 }
352 else
353#endif
354 {
355 hash = ((stringobject *)key)->ob_shash;
356 if (hash == -1)
357 hash = hashobject(key);
Guido van Rossum2a61e741997-01-18 07:55:05 +0000358 }
359 }
360 else
361#endif
362 {
363 hash = hashobject(key);
364 if (hash == -1)
365 return -1;
Guido van Rossum2a61e741997-01-18 07:55:05 +0000366 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000367 /* if fill >= 2/3 size, resize */
368 if (mp->ma_fill*3 >= mp->ma_size*2) {
369 if (mappingresize(mp) != 0) {
370 if (mp->ma_fill+1 > mp->ma_size)
371 return -1;
372 }
373 }
374 INCREF(value);
375 INCREF(key);
376 insertmapping(mp, key, hash, value);
377 return 0;
378}
379
380int
381mappingremove(op, key)
382 object *op;
383 object *key;
384{
385 register mappingobject *mp;
386 register long hash;
387 register mappingentry *ep;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000388 object *old_value, *old_key;
389
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000390 if (!is_mappingobject(op)) {
391 err_badcall();
392 return -1;
393 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000394#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000395 if (!is_stringobject(key) ||
396 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000397#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000398 {
399 hash = hashobject(key);
400 if (hash == -1)
401 return -1;
402 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000403 mp = (mappingobject *)op;
Guido van Rossumefc87131995-01-02 19:42:39 +0000404 if (((mappingobject *)op)->ma_table == NULL)
405 goto empty;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000406 ep = lookmapping(mp, key, hash);
407 if (ep->me_value == NULL) {
Guido van Rossumefc87131995-01-02 19:42:39 +0000408 empty:
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000409 err_setval(KeyError, key);
410 return -1;
411 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000412 old_key = ep->me_key;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000413 INCREF(dummy);
414 ep->me_key = dummy;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000415 old_value = ep->me_value;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000416 ep->me_value = NULL;
417 mp->ma_used--;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000418 DECREF(old_value);
419 DECREF(old_key);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000420 return 0;
421}
422
Guido van Rossum25831651993-05-19 14:50:45 +0000423void
424mappingclear(op)
425 object *op;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000426{
Guido van Rossumd7047b31995-01-02 19:07:15 +0000427 int i, n;
428 register mappingentry *table;
429 mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000430 if (!is_mappingobject(op))
431 return;
432 mp = (mappingobject *)op;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000433 table = mp->ma_table;
434 if (table == NULL)
435 return;
436 n = mp->ma_size;
437 mp->ma_size = mp->ma_used = mp->ma_fill = 0;
438 mp->ma_table = NULL;
439 for (i = 0; i < n; i++) {
440 XDECREF(table[i].me_key);
441 XDECREF(table[i].me_value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000442 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000443 DEL(table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000444}
445
Guido van Rossum25831651993-05-19 14:50:45 +0000446int
447mappinggetnext(op, ppos, pkey, pvalue)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000448 object *op;
Guido van Rossum25831651993-05-19 14:50:45 +0000449 int *ppos;
450 object **pkey;
451 object **pvalue;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000452{
Guido van Rossum25831651993-05-19 14:50:45 +0000453 int i;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000454 register mappingobject *mp;
Guido van Rossum25831651993-05-19 14:50:45 +0000455 if (!is_dictobject(op))
456 return 0;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000457 mp = (mappingobject *)op;
Guido van Rossum25831651993-05-19 14:50:45 +0000458 i = *ppos;
459 if (i < 0)
460 return 0;
461 while (i < mp->ma_size && mp->ma_table[i].me_value == NULL)
462 i++;
463 *ppos = i+1;
464 if (i >= mp->ma_size)
465 return 0;
466 if (pkey)
467 *pkey = mp->ma_table[i].me_key;
468 if (pvalue)
469 *pvalue = mp->ma_table[i].me_value;
470 return 1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000471}
472
473/* Methods */
474
475static void
476mapping_dealloc(mp)
477 register mappingobject *mp;
478{
479 register int i;
480 register mappingentry *ep;
481 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
482 if (ep->me_key != NULL)
483 DECREF(ep->me_key);
484 if (ep->me_value != NULL)
485 DECREF(ep->me_value);
486 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000487 XDEL(mp->ma_table);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000488 DEL(mp);
489}
490
491static int
492mapping_print(mp, fp, flags)
493 register mappingobject *mp;
494 register FILE *fp;
495 register int flags;
496{
497 register int i;
498 register int any;
499 register mappingentry *ep;
500 fprintf(fp, "{");
501 any = 0;
502 for (i = 0, ep = mp->ma_table; i < mp->ma_size; i++, ep++) {
503 if (ep->me_value != NULL) {
504 if (any++ > 0)
505 fprintf(fp, ", ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000506 if (printobject((object *)ep->me_key, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000507 return -1;
508 fprintf(fp, ": ");
Guido van Rossuma3d78fb1993-11-10 09:23:53 +0000509 if (printobject(ep->me_value, fp, 0) != 0)
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000510 return -1;
511 }
512 }
513 fprintf(fp, "}");
514 return 0;
515}
516
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000517static object *
518mapping_repr(mp)
519 mappingobject *mp;
520{
521 auto object *v;
522 object *sepa, *colon;
523 register int i;
524 register int any;
525 register mappingentry *ep;
526 v = newstringobject("{");
527 sepa = newstringobject(", ");
528 colon = newstringobject(": ");
529 any = 0;
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000530 for (i = 0, ep = mp->ma_table; i < mp->ma_size && v; i++, ep++) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000531 if (ep->me_value != NULL) {
532 if (any++)
533 joinstring(&v, sepa);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000534 joinstring_decref(&v, reprobject(ep->me_key));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000535 joinstring(&v, colon);
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000536 joinstring_decref(&v, reprobject(ep->me_value));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000537 }
538 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000539 joinstring_decref(&v, newstringobject("}"));
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000540 XDECREF(sepa);
541 XDECREF(colon);
542 return v;
543}
544
545static int
546mapping_length(mp)
547 mappingobject *mp;
548{
549 return mp->ma_used;
550}
551
552static object *
553mapping_subscript(mp, key)
554 mappingobject *mp;
555 register object *key;
556{
557 object *v;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000558 long hash;
Guido van Rossumd7047b31995-01-02 19:07:15 +0000559 if (mp->ma_table == NULL) {
560 err_setval(KeyError, key);
561 return NULL;
562 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000563#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000564 if (!is_stringobject(key) ||
565 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000566#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000567 {
568 hash = hashobject(key);
569 if (hash == -1)
570 return NULL;
571 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000572 v = lookmapping(mp, key, hash) -> me_value;
573 if (v == NULL)
574 err_setval(KeyError, key);
575 else
576 INCREF(v);
577 return v;
578}
579
580static int
581mapping_ass_sub(mp, v, w)
582 mappingobject *mp;
583 object *v, *w;
584{
585 if (w == NULL)
586 return mappingremove((object *)mp, v);
587 else
588 return mappinginsert((object *)mp, v, w);
589}
590
591static mapping_methods mapping_as_mapping = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000592 (inquiry)mapping_length, /*mp_length*/
593 (binaryfunc)mapping_subscript, /*mp_subscript*/
594 (objobjargproc)mapping_ass_sub, /*mp_ass_subscript*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000595};
596
597static object *
598mapping_keys(mp, args)
599 register mappingobject *mp;
600 object *args;
601{
602 register object *v;
603 register int i, j;
604 if (!getnoarg(args))
605 return NULL;
606 v = newlistobject(mp->ma_used);
607 if (v == NULL)
608 return NULL;
609 for (i = 0, j = 0; i < mp->ma_size; i++) {
610 if (mp->ma_table[i].me_value != NULL) {
611 object *key = mp->ma_table[i].me_key;
612 INCREF(key);
613 setlistitem(v, j, key);
614 j++;
615 }
616 }
617 return v;
618}
619
Guido van Rossum25831651993-05-19 14:50:45 +0000620static object *
621mapping_values(mp, args)
622 register mappingobject *mp;
623 object *args;
624{
625 register object *v;
626 register int i, j;
627 if (!getnoarg(args))
628 return NULL;
629 v = newlistobject(mp->ma_used);
630 if (v == NULL)
631 return NULL;
632 for (i = 0, j = 0; i < mp->ma_size; i++) {
633 if (mp->ma_table[i].me_value != NULL) {
634 object *value = mp->ma_table[i].me_value;
635 INCREF(value);
636 setlistitem(v, j, value);
637 j++;
638 }
639 }
640 return v;
641}
642
643static object *
644mapping_items(mp, args)
645 register mappingobject *mp;
646 object *args;
647{
648 register object *v;
649 register int i, j;
650 if (!getnoarg(args))
651 return NULL;
652 v = newlistobject(mp->ma_used);
653 if (v == NULL)
654 return NULL;
655 for (i = 0, j = 0; i < mp->ma_size; i++) {
656 if (mp->ma_table[i].me_value != NULL) {
657 object *key = mp->ma_table[i].me_key;
658 object *value = mp->ma_table[i].me_value;
659 object *item = newtupleobject(2);
660 if (item == NULL) {
661 DECREF(v);
662 return NULL;
663 }
664 INCREF(key);
665 settupleitem(item, 0, key);
666 INCREF(value);
667 settupleitem(item, 1, value);
668 setlistitem(v, j, item);
669 j++;
670 }
671 }
672 return v;
673}
674
Guido van Rossum4199fac1993-11-05 10:18:44 +0000675int
676getmappingsize(mp)
677 object *mp;
678{
679 if (mp == NULL || !is_mappingobject(mp)) {
680 err_badcall();
Guido van Rossumb376a4a1993-11-23 17:53:17 +0000681 return 0;
Guido van Rossum4199fac1993-11-05 10:18:44 +0000682 }
683 return ((mappingobject *)mp)->ma_used;
684}
685
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000686object *
687getmappingkeys(mp)
688 object *mp;
689{
690 if (mp == NULL || !is_mappingobject(mp)) {
691 err_badcall();
692 return NULL;
693 }
694 return mapping_keys((mappingobject *)mp, (object *)NULL);
695}
696
Guido van Rossum25831651993-05-19 14:50:45 +0000697object *
698getmappingvalues(mp)
699 object *mp;
700{
701 if (mp == NULL || !is_mappingobject(mp)) {
702 err_badcall();
703 return NULL;
704 }
705 return mapping_values((mappingobject *)mp, (object *)NULL);
706}
707
708object *
709getmappingitems(mp)
710 object *mp;
711{
712 if (mp == NULL || !is_mappingobject(mp)) {
713 err_badcall();
714 return NULL;
715 }
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000716 return mapping_items((mappingobject *)mp, (object *)NULL);
Guido van Rossum25831651993-05-19 14:50:45 +0000717}
718
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000719#define NEWCMP
720
721#ifdef NEWCMP
722
723/* Subroutine which returns the smallest key in a for which b's value
724 is different or absent. The value is returned too, through the
725 pval argument. No reference counts are incremented. */
726
727static object *
728characterize(a, b, pval)
729 mappingobject *a;
730 mappingobject *b;
731 object **pval;
732{
733 object *diff = NULL;
734 int i;
735
736 *pval = NULL;
737 for (i = 0; i < a->ma_size; i++) {
738 if (a->ma_table[i].me_value != NULL) {
739 object *key = a->ma_table[i].me_key;
740 object *aval, *bval;
741 if (diff != NULL && cmpobject(key, diff) > 0)
742 continue;
743 aval = a->ma_table[i].me_value;
744 bval = mappinglookup((object *)b, key);
745 if (bval == NULL || cmpobject(aval, bval) != 0) {
746 diff = key;
747 *pval = aval;
748 }
749 }
750 }
751 return diff;
752}
753
754static int
755mapping_compare(a, b)
756 mappingobject *a, *b;
757{
758 object *adiff, *bdiff, *aval, *bval;
759 int res;
760
761 /* Compare lengths first */
762 if (a->ma_used < b->ma_used)
763 return -1; /* a is shorter */
764 else if (a->ma_used > b->ma_used)
765 return 1; /* b is shorter */
766 /* Same length -- check all keys */
767 adiff = characterize(a, b, &aval);
768 if (adiff == NULL)
769 return 0; /* a is a subset with the same length */
770 bdiff = characterize(b, a, &bval);
771 /* bdiff == NULL would be impossible now */
772 res = cmpobject(adiff, bdiff);
773 if (res == 0)
774 res = cmpobject(aval, bval);
775 return res;
776}
777
778#else /* !NEWCMP */
779
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000780static int
781mapping_compare(a, b)
782 mappingobject *a, *b;
783{
784 object *akeys, *bkeys;
785 int i, n, res;
786 if (a == b)
787 return 0;
788 if (a->ma_used == 0) {
789 if (b->ma_used != 0)
790 return -1;
791 else
792 return 0;
793 }
794 else {
795 if (b->ma_used == 0)
796 return 1;
797 }
798 akeys = mapping_keys(a, (object *)NULL);
799 bkeys = mapping_keys(b, (object *)NULL);
800 if (akeys == NULL || bkeys == NULL) {
801 /* Oops, out of memory -- what to do? */
802 /* For now, sort on address! */
803 XDECREF(akeys);
804 XDECREF(bkeys);
805 if (a < b)
806 return -1;
807 else
808 return 1;
809 }
810 sortlist(akeys);
811 sortlist(bkeys);
812 n = a->ma_used < b->ma_used ? a->ma_used : b->ma_used; /* smallest */
813 res = 0;
814 for (i = 0; i < n; i++) {
815 object *akey, *bkey, *aval, *bval;
816 long ahash, bhash;
817 akey = getlistitem(akeys, i);
818 bkey = getlistitem(bkeys, i);
819 res = cmpobject(akey, bkey);
820 if (res != 0)
821 break;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000822#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000823 if (!is_stringobject(akey) ||
824 (ahash = ((stringobject *) akey)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000825#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000826 {
827 ahash = hashobject(akey);
828 if (ahash == -1)
829 err_clear(); /* Don't want errors here */
830 }
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000831#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000832 if (!is_stringobject(bkey) ||
833 (bhash = ((stringobject *) bkey)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000834#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000835 {
836 bhash = hashobject(bkey);
837 if (bhash == -1)
838 err_clear(); /* Don't want errors here */
839 }
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000840 aval = lookmapping(a, akey, ahash) -> me_value;
841 bval = lookmapping(b, bkey, bhash) -> me_value;
842 res = cmpobject(aval, bval);
843 if (res != 0)
844 break;
845 }
846 if (res == 0) {
847 if (a->ma_used < b->ma_used)
848 res = -1;
849 else if (a->ma_used > b->ma_used)
850 res = 1;
851 }
852 DECREF(akeys);
853 DECREF(bkeys);
854 return res;
855}
856
Guido van Rossuma0a69b81996-12-05 21:55:55 +0000857#endif /* !NEWCMP */
858
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000859static object *
860mapping_has_key(mp, args)
861 register mappingobject *mp;
862 object *args;
863{
864 object *key;
865 long hash;
866 register long ok;
867 if (!getargs(args, "O", &key))
868 return NULL;
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000869#ifdef CACHE_HASH
Guido van Rossumca756f21997-01-23 19:39:29 +0000870 if (!is_stringobject(key) ||
871 (hash = ((stringobject *) key)->ob_shash) == -1)
Sjoerd Mullender3bb8a051993-10-22 12:04:32 +0000872#endif
Guido van Rossumca756f21997-01-23 19:39:29 +0000873 {
874 hash = hashobject(key);
875 if (hash == -1)
876 return NULL;
877 }
Guido van Rossumd7047b31995-01-02 19:07:15 +0000878 ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000879 return newintobject(ok);
880}
881
882static struct methodlist mapp_methods[] = {
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000883 {"has_key", (method)mapping_has_key},
884 {"items", (method)mapping_items},
885 {"keys", (method)mapping_keys},
886 {"values", (method)mapping_values},
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000887 {NULL, NULL} /* sentinel */
888};
889
890static object *
891mapping_getattr(mp, name)
892 mappingobject *mp;
893 char *name;
894{
895 return findmethod(mapp_methods, (object *)mp, name);
896}
897
898typeobject Mappingtype = {
899 OB_HEAD_INIT(&Typetype)
900 0,
Guido van Rossum9bfef441993-03-29 10:43:31 +0000901 "dictionary",
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000902 sizeof(mappingobject),
903 0,
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000904 (destructor)mapping_dealloc, /*tp_dealloc*/
905 (printfunc)mapping_print, /*tp_print*/
906 (getattrfunc)mapping_getattr, /*tp_getattr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000907 0, /*tp_setattr*/
Guido van Rossum1d5735e1994-08-30 08:27:36 +0000908 (cmpfunc)mapping_compare, /*tp_compare*/
909 (reprfunc)mapping_repr, /*tp_repr*/
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000910 0, /*tp_as_number*/
911 0, /*tp_as_sequence*/
912 &mapping_as_mapping, /*tp_as_mapping*/
913};
914
915/* For backward compatibility with old dictionary interface */
916
917static object *last_name_object;
Guido van Rossum992ded81995-12-08 01:16:31 +0000918static char *last_name_char; /* NULL or == getstringvalue(last_name_object) */
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000919
920object *
921getattro(v, name)
922 object *v;
923 object *name;
924{
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000925 if (v->ob_type->tp_getattro != NULL)
926 return (*v->ob_type->tp_getattro)(v, name);
927
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000928 if (name != last_name_object) {
929 XDECREF(last_name_object);
930 INCREF(name);
931 last_name_object = name;
932 last_name_char = getstringvalue(name);
933 }
934 return getattr(v, last_name_char);
935}
936
937int
938setattro(v, name, value)
939 object *v;
940 object *name;
941 object *value;
942{
Guido van Rossum2a61e741997-01-18 07:55:05 +0000943 int err;
944 INCREF(name);
945 PyString_InternInPlace(&name);
Guido van Rossumd8eb1b31996-08-09 20:52:03 +0000946 if (v->ob_type->tp_setattro != NULL)
Guido van Rossum2a61e741997-01-18 07:55:05 +0000947 err = (*v->ob_type->tp_setattro)(v, name, value);
948 else {
949 if (name != last_name_object) {
950 XDECREF(last_name_object);
951 INCREF(name);
952 last_name_object = name;
953 last_name_char = getstringvalue(name);
954 }
955 err = setattr(v, last_name_char, value);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000956 }
Guido van Rossum2a61e741997-01-18 07:55:05 +0000957 DECREF(name);
958 return err;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000959}
960
961object *
962dictlookup(v, key)
963 object *v;
964 char *key;
965{
Guido van Rossum992ded81995-12-08 01:16:31 +0000966 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000967 XDECREF(last_name_object);
968 last_name_object = newstringobject(key);
969 if (last_name_object == NULL) {
970 last_name_char = NULL;
971 return NULL;
972 }
Guido van Rossum2a61e741997-01-18 07:55:05 +0000973 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +0000974 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000975 }
976 return mappinglookup(v, last_name_object);
977}
978
979int
980dictinsert(v, key, item)
981 object *v;
982 char *key;
983 object *item;
984{
Guido van Rossum992ded81995-12-08 01:16:31 +0000985 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000986 XDECREF(last_name_object);
987 last_name_object = newstringobject(key);
988 if (last_name_object == NULL) {
989 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +0000990 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000991 }
Guido van Rossum2a61e741997-01-18 07:55:05 +0000992 PyString_InternInPlace(&last_name_object);
Guido van Rossum992ded81995-12-08 01:16:31 +0000993 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +0000994 }
995 return mappinginsert(v, last_name_object, item);
996}
997
998int
999dictremove(v, key)
1000 object *v;
1001 char *key;
1002{
Guido van Rossum992ded81995-12-08 01:16:31 +00001003 if (key != last_name_char) {
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001004 XDECREF(last_name_object);
1005 last_name_object = newstringobject(key);
1006 if (last_name_object == NULL) {
1007 last_name_char = NULL;
Guido van Rossum1fc238a1993-07-29 08:25:09 +00001008 return -1;
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001009 }
Guido van Rossum992ded81995-12-08 01:16:31 +00001010 last_name_char = getstringvalue(last_name_object);
Guido van Rossum4b1302b1993-03-27 18:11:32 +00001011 }
1012 return mappingremove(v, last_name_object);
1013}