/* Copyright (c) 1993 Stephen F. White */
#include "cool.h"
#include "proto.h"
/*
* map.c - functions for manipulating mappings (associative arrays)
*
* All functions except map_copy() "eat" their arguments. That is, the
* caller should bump the refcount if necessary.
*/
void map_free (Map * map)
{
MapPair *pair, *pnext;
int i;
if (!map)
return;
if (!--map->ref) {
for (i = 0; i < map->size; i++) {
for (pair = map->table[i]; pair; pair = pnext) {
var_free (pair->from);
var_free (pair->to);
pnext = pair->next;
FREE (pair);
}
}
FREE (map);
}
}
Map *map_copy (Map * map)
{
Map *new = map_new (map->num);
int i;
MapPair *pair;
for (i = 0; i < map->size; i++) {
for (pair = map->table[i]; pair; pair = pair->next) {
map_add (new, var_dup (pair->from), var_dup (pair->to));
}
}
return new;
}
int map_find (Map * map, Var key, Var * returnval)
{
int hval = hash_var (key) % map->size;
MapPair *pair;
if (!map || !returnval) {
return -1;
}
for (pair = map->table[hval]; pair; pair = pair->next) {
if (var_eq (key, pair->from)) {
*returnval = pair->to;
return 0;
}
}
return -1;
}
Map *map_add (Map * map, Var key, Var value)
{
int hval = hash_var (key) % map->size;
MapPair *pair, *prev;
Map *new;
if (map->ref > 1) {
/* copy old map to new map */
new = map_copy (map);
map->ref--;
map = new;
}
for (prev = pair = map->table[hval]; pair; prev = pair, pair = pair->next) {
if (var_eq (key, pair->from)) {
var_free (pair->to);
pair->to = value;
var_free (key);
return map;
}
}
pair = MALLOC (MapPair, 1);
pair->from = key;
pair->to = value;
pair->next = 0;
if (prev) {
prev->next = pair;
} else {
map->table[hval] = pair;
}
map->num++;
return map;
}