diff options
Diffstat (limited to 'Objects/mappingobject.c')
-rw-r--r-- | Objects/mappingobject.c | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/Objects/mappingobject.c b/Objects/mappingobject.c index e40ac8d..89fd314 100644 --- a/Objects/mappingobject.c +++ b/Objects/mappingobject.c @@ -46,9 +46,9 @@ static long primes[] = { 3, 7, 13, 31, 61, 127, 251, 509, 1021, 2017, 4093, 5987, 9551, 15683, 19609, 31397, - 65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L, - 4194301L, 8388593L, 16777213L, 33554393L, 67108859L, - 134217689L, 268435399L, 536870909L, 1073741789L, + 65521L, 131071L, 262139L, 524287L, 1048573L, 2097143L, + 4194301L, 8388593L, 16777213L, 33554393L, 67108859L, + 134217689L, 268435399L, 536870909L, 1073741789L, 0 }; @@ -95,12 +95,8 @@ newmappingobject() mp = NEWOBJ(mappingobject, &Mappingtype); if (mp == NULL) return NULL; - mp->ma_size = primes[0]; - mp->ma_table = (mappingentry *) calloc(sizeof(mappingentry), mp->ma_size); - if (mp->ma_table == NULL) { - DEL(mp); - return err_nomem(); - } + mp->ma_size = 0; + mp->ma_table = NULL; mp->ma_fill = 0; mp->ma_used = 0; return (object *)mp; @@ -173,10 +169,13 @@ insertmapping(mp, key, hash, value) long hash; object *value; { + object *old_value; register mappingentry *ep; ep = lookmapping(mp, key, hash); if (ep->me_value != NULL) { - DECREF(ep->me_value); + old_value = ep->me_value; + ep->me_value = value; + DECREF(old_value); /* which **CAN** re-enter */ DECREF(key); } else { @@ -186,9 +185,9 @@ insertmapping(mp, key, hash, value) DECREF(ep->me_key); ep->me_key = key; ep->me_hash = hash; + ep->me_value = value; mp->ma_used++; } - ep->me_value = value; } /* @@ -233,14 +232,19 @@ mappingresize(mp) mp->ma_table = newtable; mp->ma_fill = 0; mp->ma_used = 0; + + /* Make two passes, so we can avoid decrefs + (and possible side effects) till the table is copied */ for (i = 0, ep = oldtable; i < oldsize; i++, ep++) { if (ep->me_value != NULL) insertmapping(mp,ep->me_key,ep->me_hash,ep->me_value); - else { + } + for (i = 0, ep = oldtable; i < oldsize; i++, ep++) { + if (ep->me_value == NULL) XDECREF(ep->me_key); - } } - DEL(oldtable); + + XDEL(oldtable); return 0; } @@ -254,6 +258,8 @@ mappinglookup(op, key) err_badcall(); return NULL; } + if (((mappingobject *)op)->ma_table == NULL) + return NULL; #ifdef CACHE_HASH if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1) #endif @@ -303,6 +309,8 @@ mappingremove(op, key) register mappingobject *mp; register long hash; register mappingentry *ep; + object *old_value, *old_key; + if (!is_mappingobject(op)) { err_badcall(); return -1; @@ -319,12 +327,14 @@ mappingremove(op, key) err_setval(KeyError, key); return -1; } - DECREF(ep->me_key); + old_key = ep->me_key; INCREF(dummy); ep->me_key = dummy; - DECREF(ep->me_value); + old_value = ep->me_value; ep->me_value = NULL; mp->ma_used--; + DECREF(old_value); + DECREF(old_key); return 0; } @@ -332,18 +342,23 @@ void mappingclear(op) object *op; { - int i; - register mappingobject *mp; + int i, n; + register mappingentry *table; + mappingobject *mp; if (!is_mappingobject(op)) return; mp = (mappingobject *)op; - for (i = 0; i < mp->ma_size; i++) { - XDECREF(mp->ma_table[i].me_key); - XDECREF(mp->ma_table[i].me_value); - mp->ma_table[i].me_key = NULL; - mp->ma_table[i].me_value = NULL; + table = mp->ma_table; + if (table == NULL) + return; + n = mp->ma_size; + mp->ma_size = mp->ma_used = mp->ma_fill = 0; + mp->ma_table = NULL; + for (i = 0; i < n; i++) { + XDECREF(table[i].me_key); + XDECREF(table[i].me_value); } - mp->ma_used = 0; + DEL(table); } int @@ -387,8 +402,7 @@ mapping_dealloc(mp) if (ep->me_value != NULL) DECREF(ep->me_value); } - if (mp->ma_table != NULL) - DEL(mp->ma_table); + XDEL(mp->ma_table); DEL(mp); } @@ -460,6 +474,10 @@ mapping_subscript(mp, key) { object *v; long hash; + if (mp->ma_table == NULL) { + err_setval(KeyError, key); + return NULL; + } #ifdef CACHE_HASH if (!is_stringobject(key) || (hash = ((stringobject *) key)->ob_shash) == -1) #endif @@ -700,7 +718,7 @@ mapping_has_key(mp, args) hash = hashobject(key); if (hash == -1) return NULL; - ok = lookmapping(mp, key, hash)->me_value != NULL; + ok = mp->ma_size != 0 && lookmapping(mp, key, hash)->me_value != NULL; return newintobject(ok); } |