summaryrefslogtreecommitdiff
path: root/cpp/hash.c
blob: 6013c54b2d9645a8beade8244c8d3c9a9ce82cb8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

#include <stdio.h>
#ifdef __STDC__
#include <stdlib.h>
#include <string.h>
#else
#include <malloc.h>
#endif
#include "cc.h"

/*
 * Two functions:
 * char * set_entry(int namespace, char * name, void * value);
 *        returns a pointer to the copy of the name;
 *
 * void * read_entry(int namespace, char * name);
 *        returns the value;
 */

struct hashentry
{
   struct hashentry * next;
   void * value;
   int    namespace;
   char	  word[1];
};

struct hashentry ** hashtable;
int  hashsize  = 0xFF;	/* 2^X -1 */
int  hashcount = 0;
static int hashvalue P((int namespace, char * word));

void *
read_entry(namespace, word)
int namespace;
char * word;
{
   int hash_val;
   struct hashentry * hashline;
   if( hashtable == 0 ) return 0;
   hash_val = hashvalue(namespace, word);

   hashline = hashtable[hash_val];

   for(; hashline; hashline = hashline->next)
   {
      if(namespace != hashline->namespace) continue;
      if(word[0] != hashline->word[0])     continue;
      if(strcmp(word, hashline->word) )    continue;
      return hashline->value;
   }
   return 0;
}

char *
set_entry(namespace, word, value)
int namespace;
char * word;
void * value;
{
   int hash_val, i;
   struct hashentry * hashline, *prev;
   hash_val = hashvalue(namespace, word);

   if( hashtable )
   {
      hashline = hashtable[hash_val];

      for(prev=0; hashline; prev=hashline, hashline = hashline->next)
      {
         if(namespace != hashline->namespace) continue;
         if(word[0] != hashline->word[0])     continue;
         if(strcmp(word, hashline->word) )    continue;
         if( value ) hashline->value = value;
         else
         {
            if( prev == 0 ) hashtable[hash_val] = hashline->next;
            else            prev->next = hashline->next;
            free(hashline);
            return 0;
         }
         return hashline->word;
      }
   }
   if( value == 0 ) return 0;
   if( hashtable == 0 )
   {
      hashtable = malloc((hashsize+1)*sizeof(char*));
      if( hashtable == 0 ) cfatal("Out of memory");
      for(i=0; i<=hashsize; i++) hashtable[i] = 0;
   }
   /* Add record */
   hashline = malloc(sizeof(struct hashentry)+strlen(word));
   if( hashline == 0 ) cfatal("Out of memory");
   else
   {
      hashline->next  = hashtable[hash_val];
      hashline->namespace = namespace;
      hashline->value = value;
      strcpy(hashline->word, word);
      hashtable[hash_val] = hashline;
   }
   return hashline->word;
}

static int hashvalue(namespace, word)
int namespace;
char * word;
{
   int val = namespace;
   char *p = word;

   while(*p)
   {
      val = ((val<<4)^((val>>12)&0xF)^((*p++)&0xFF));
   }
   val &= hashsize;
   return val;
}