/*
     libscheme	
     Copyright (C) 1994 Brent Benson

     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
     the Free Software Foundation; either version 1, or (at your option)
     any later version.

     This program is distributed in the hope that it will be useful,
     but WITHOUT ANY WARRANTY; without even the implied warranty of
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.

     You should have received a copy of the GNU General Public License
     along with this program; if not, write to the Free Software
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "scheme_hash.h"
#include <string.h>

extern char *scheme_strdup (char *);
static unsigned int scheme_hash (char *key);

Scheme_Hash_Table *
scheme_hash_table (int size)
{
  Scheme_Hash_Table *table;

  table = (Scheme_Hash_Table*) scheme_malloc (sizeof (Scheme_Hash_Table));
  table->size = size;
  table->buckets = (Scheme_Bucket **) scheme_calloc (size, sizeof (Scheme_Bucket *));
  return (table);
}

void 
scheme_add_to_table (Scheme_Hash_Table *table, char *key, void *val)
{
  unsigned int h, i;
  Scheme_Bucket *bucket;

  h = i = 0;
  while ( key[i] )
    {
      h += (h << 5) + h + key[i++];
    }
  h = h % table->size;
  bucket = (Scheme_Bucket *) scheme_malloc (sizeof (Scheme_Bucket));
  bucket->key = scheme_strdup (key);
  bucket->val = val;
  bucket->next = table->buckets[h];
  table->buckets[h] = bucket;
}

void *
scheme_lookup_in_table (Scheme_Hash_Table *table, char *key)
{
  unsigned int h;
  char *str;
  Scheme_Bucket *bucket;

  h = 0;
  str = key;
  while ( *str )
    {
      h += (h << 5) + h + *str++;
    }
  h = h % table->size;
  bucket = table->buckets[h];
  while ( bucket )
    {
      if (strcmp (key, bucket->key) == 0)
	{
	  return (bucket->val);
	}
      else
	{
	  bucket = bucket->next;
	}
    }
  return (NULL);
}

void
scheme_change_in_table (Scheme_Hash_Table *table, char *key, void *new)
{
  unsigned int h, i;
  Scheme_Bucket *bucket;

  h = i = 0;
  while ( key[i] )
    {
      h += (h << 5) + h + key[i++];
    }
  h = h % table->size;
  bucket = table->buckets[h];
  while ( bucket )
    {
      if (strcmp (key, bucket->key) == 0)
	{
	  bucket->val = new;
	  return;
	}
      bucket = bucket->next;
    }
}

static unsigned int 
scheme_hash (char *key)
{
  unsigned int h;

  h = 0;
  while (*key)
    {
      h += (h << 5) + h + *key++;
    }
  return (h);
}
