/*********************************************************************
 *
 *            EZFM---EZWGL based file manager for X11
 *
 *             Copyright (C) 1998  Maorong Zou
 *
 *
 *  This file is part of EZFM.
 *
 *  EZFM 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 2, or (at your option)
 * any later version.
 *
 * EZFM 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 EZFM; see the file COPYING.  If not, write to
 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
 *
 *************************************************************************/




#define _HASH_C_
#include "ezfm.h"

typedef struct hte_ {
  char         *key;            /* hash key       */
  char         *value;          /* value, may=key */
  struct hte_  *next;           /* the chain      */
} hte;

#define  HASH_SIZE   71
/*********************************************************************/

char *lookupNameFromHashTable MY_ANSIARGS(( char *name ));
void insertNameToHashTable    MY_ANSIARGS(( char *name, char *value ));
void initNameHashTable        MY_ANSIARGS(( void ));
void destroyNameHashTable     MY_ANSIARGS(( void ));

/*********************************************************************/

static int hash MY_ANSIARGS(( char *name ));
static hte *lookupHTE MY_ANSIARGS(( char *name ));
/*********************************************************************/

static hte  nameHashTable[HASH_SIZE];
/*********************************************************************/
void initNameHashTable()
{
  int i;
  for(i = 0; i < HASH_SIZE; i++) nameHashTable[i].next = NULL;
}
void destroyNameHashTable()
{
  int i;  hte *ptr, *next;
  for(i = 0; i < HASH_SIZE; i++)
    {
      ptr = nameHashTable[i].next;
      while(ptr)
	{
	  next = ptr->next;
	  if(ptr->value != ptr->key) EZ_Free(ptr->value);
	  EZ_Free(ptr->key);
	  ptr = next;
	}
      nameHashTable[i].next = NULL;
    }
}
/*********************************************************************/
char *lookupNameFromHashTable(name)
     char *name;
{
  if(name)
    {
      int value = hash(name);
      hte *ptr = nameHashTable[value].next;
      while(ptr)
	{
	  if(!strcmp(ptr->key, name)) return(ptr->value);
	  ptr = ptr->next;
	}
    }
  return(NULL);
}
/*********************************************************************/

void insertNameToHashTable(name, rvalue)
     char *name; char *rvalue;
{
  if(name)
    {
      hte *head, *ptr = lookupHTE(name);
      if(ptr == NULL)
	{
	  int value = hash(name);
	  ptr = (hte *)EZ_Malloc(sizeof(hte));
	  bzero(ptr, sizeof(hte));
	  head = &nameHashTable[value];
	  ptr->next = head->next;
	  head->next = ptr;
	}
      else
	{
	  if(ptr->value != ptr->key) EZ_Free(ptr->value);
	  EZ_Free(ptr->key);
	  ptr->value = ptr->key = NULL;
	}
      ptr->key = (char *)EZ_Malloc(strlen(name) + 1);
      strcpy(ptr->key, name);
      if(rvalue == name || rvalue == NULL) ptr->value = ptr->key;
      else
	{
	  ptr->value = (char *)EZ_Malloc(strlen(rvalue) + 1);
	  strcpy(ptr->value, rvalue);
	}
    }
}
/*********************************************************************/
static hte *lookupHTE(name)
     char *name;
{
  if(name)
    {
      int value = hash(name);
      hte *ptr = nameHashTable[value].next;
      while(ptr)
	{
	  if(!strcmp(name, ptr->key)) return(ptr);
	  ptr = ptr->next;
	}
    }
  return(NULL);
}
/*********************************************************************/
static int hash(s)
     char *s;
{
  char *p;
  unsigned int h = 0, g;
  
  for(p = s; *p ; p++) 
    {
      h = (h << 4) + (*p);
      if (g = h & 0xf0000000) 
        {
          h = h ^ (g >> 24);
          h = h ^ g;
        }
    }
  return(h % HASH_SIZE);
}

/*********************************************************************/
int hashPathname(s) char *s;
{
  char *p;
  unsigned int h = 0, g, hsave=0;
  
  for(p = s; *p ; p++) 
    {
      h = (h << 4) + (*p);

      if(g = h & 0xf0000000) 
        {
          h = h ^ (g >> 24);
          h = h ^ g;
        }
      if(*p == '/') { hsave = h; h  = 0;}
    }
  return(h == 0? hsave: h);
}
/*********************************************************************/

#undef _HASH_C_
