diff --git a/ase/awk/map.c b/ase/awk/map.c index 5b4bc0c2..945dedeb 100644 --- a/ase/awk/map.c +++ b/ase/awk/map.c @@ -1,5 +1,5 @@ /* - * $Id: map.c,v 1.11 2006-04-16 04:31:38 bacon Exp $ + * $Id: map.c,v 1.12 2006-04-18 14:49:42 bacon Exp $ */ #include @@ -102,6 +102,7 @@ xp_awk_pair_t* xp_awk_map_get (xp_awk_map_t* map, xp_char_t* key) xp_awk_pair_t* xp_awk_map_put (xp_awk_map_t* map, xp_char_t* key, void* val) { +/* xp_awk_pair_t* pair; xp_size_t hc; @@ -133,6 +134,54 @@ xp_awk_pair_t* xp_awk_map_put (xp_awk_map_t* map, xp_char_t* key, void* val) map->size++; return pair; +*/ + int n; + xp_awk_pair_t* px; + + n = xp_awk_map_putx (map, key, val, &px); + if (n < 0) return XP_NULL; + return px; +} + +int xp_awk_map_putx (xp_awk_map_t* map, xp_char_t* key, void* val, xp_awk_pair_t** px) +{ + xp_awk_pair_t* pair; + xp_size_t hc; + + hc = __hash(key) % map->capa; + pair = map->buck[hc]; + + while (pair != XP_NULL) + { + if (xp_strcmp(pair->key,key) == 0) + { + if (pair->key != key) + { + xp_free ((xp_char_t*)pair->key); + pair->key = key; + } + + if (px != XP_NULL) + *px = xp_awk_map_setpair (map, pair, val); + else + xp_awk_map_setpair (map, pair, val); + + return 0; /* value changed for the existing key */ + } + pair = pair->next; + } + + pair = (xp_awk_pair_t*) xp_malloc (xp_sizeof(xp_awk_pair_t)); + if (pair == XP_NULL) return -1; /* error */ + + pair->key = key; + pair->val = val; + pair->next = map->buck[hc]; + map->buck[hc] = pair; + map->size++; + + if (px != XP_NULL) *px = pair; + return 1; /* new key added */ } xp_awk_pair_t* xp_awk_map_set (xp_awk_map_t* map, xp_char_t* key, void* val) diff --git a/ase/awk/map.h b/ase/awk/map.h index adf2a8a9..0afa0cc4 100644 --- a/ase/awk/map.h +++ b/ase/awk/map.h @@ -1,5 +1,5 @@ /* - * $Id: map.h,v 1.7 2006-04-16 04:31:38 bacon Exp $ + * $Id: map.h,v 1.8 2006-04-18 14:49:42 bacon Exp $ */ #ifndef _XP_AWK_MAP_H_ @@ -49,6 +49,7 @@ void xp_awk_map_clear (xp_awk_map_t* map); xp_awk_pair_t* xp_awk_map_get (xp_awk_map_t* map, xp_char_t* key); xp_awk_pair_t* xp_awk_map_put (xp_awk_map_t* map, xp_char_t* key, void* val); +int xp_awk_map_putx (xp_awk_map_t* map, xp_char_t* key, void* val, xp_awk_pair_t** px); xp_awk_pair_t* xp_awk_map_set (xp_awk_map_t* map, xp_char_t* key, void* val); xp_awk_pair_t* xp_awk_map_getpair ( diff --git a/ase/awk/run.c b/ase/awk/run.c index 769f3e07..61a65000 100644 --- a/ase/awk/run.c +++ b/ase/awk/run.c @@ -1,5 +1,5 @@ /* - * $Id: run.c,v 1.56 2006-04-18 11:26:48 bacon Exp $ + * $Id: run.c,v 1.57 2006-04-18 14:49:42 bacon Exp $ */ #include @@ -841,7 +841,7 @@ static xp_awk_val_t* __do_assignment_map ( xp_awk_val_map_t* map; xp_awk_nde_t* nde; xp_char_t* str; - xp_awk_pair_t* pair; + int n; xp_assert ( (var->type == XP_AWK_NDE_GLOBALIDX || @@ -862,6 +862,8 @@ static xp_awk_val_t* __do_assignment_map ( tmp = xp_awk_makemapval (awk); if (tmp == XP_NULL) PANIC (awk, XP_AWK_ENOMEM); + /* decrease the reference count of the previous value - + * in fact, this is not necessary as map is always xp_awk_val_nil here. */ xp_awk_refdownval (awk, (xp_awk_val_t*)map); if (var->type == XP_AWK_NDE_GLOBALIDX) @@ -909,22 +911,19 @@ static xp_awk_val_t* __do_assignment_map ( /* xp_printf (XP_TEXT("**** index str=>%s, map->ref=%d, map->type=%d\n"), str, map->ref, map->type); */ - pair = xp_awk_map_get (map->map, str); - if (xp_awk_map_put(map->map, str, val) == XP_NULL) + n = xp_awk_map_putx(map->map, str, val, XP_NULL); + if (n < 0) { xp_free (str); PANIC (awk, XP_AWK_ENOMEM); } - if (pair != XP_NULL) + if (n == 0) { - /* str is freed only if the key is in the map. + /* the value for the existing key has changed. + * str is freed only if the key is in the map. * otherwise, it will be taken by the map */ xp_free (str); - - /* decrease the reference count for the old value - * only when the assignment is successful */ - xp_awk_refdownval (awk, pair->val); } xp_awk_refupval (val);