chiark / gitweb /
Upstream qmail 1.01
[qmail] / constmap.c
1 #include "constmap.h"
2 #include "alloc.h"
3 #include "case.h"
4
5 static constmap_hash hash(s,len)
6 char *s;
7 int len;
8 {
9  unsigned char ch;
10  constmap_hash h;
11  h = 5381;
12  while (len > 0)
13   {
14    ch = *s++ - 'A';
15    if (ch <= 'Z' - 'A') ch += 'a' - 'A';
16    h = ((h << 5) + h) ^ ch;
17    --len;
18   }
19  return h;
20 }
21
22 char *constmap(cm,s,len)
23 struct constmap *cm;
24 char *s;
25 int len;
26 {
27  constmap_hash h;
28  int pos;
29  h = hash(s,len);
30  pos = cm->first[h & cm->mask];
31  while (pos != -1)
32   {
33    if (h == cm->hash[pos])
34      if (len == cm->inputlen[pos])
35        if (!case_diffb(cm->input[pos],len,s))
36          return cm->input[pos] + cm->inputlen[pos] + 1;
37    pos = cm->next[pos];
38   }
39  return 0;
40 }
41
42 int constmap_init(cm,s,len,flagcolon)
43 struct constmap *cm;
44 char *s;
45 int len;
46 int flagcolon;
47 {
48  int i;
49  int j;
50  int k;
51  int pos;
52  constmap_hash h;
53
54  cm->num = 0;
55  for (j = 0;j < len;++j) if (!s[j]) ++cm->num;
56
57  h = 64;
58  while (h && (h < cm->num)) h += h;
59  cm->mask = h - 1;
60
61  cm->first = (int *) alloc(sizeof(int) * h);
62  if (cm->first)
63   {
64    cm->input = (char **) alloc(sizeof(char *) * cm->num);
65    if (cm->input)
66     {
67      cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
68      if (cm->inputlen)
69       {
70        cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
71        if (cm->hash)
72         {
73          cm->next = (int *) alloc(sizeof(int) * cm->num);
74          if (cm->next)
75           {
76            for (h = 0;h <= cm->mask;++h)
77              cm->first[h] = -1;
78            pos = 0;
79            i = 0;
80            for (j = 0;j < len;++j)
81              if (!s[j])
82               {
83                k = j - i;
84                if (flagcolon)
85                 {
86                  for (k = i;k < j;++k)
87                    if (s[k] == ':')
88                      break;
89                  if (k >= j) { i = j + 1; continue; }
90                  k -= i;
91                 }
92                cm->input[pos] = s + i;
93                cm->inputlen[pos] = k;
94                h = hash(s + i,k);
95                cm->hash[pos] = h;
96                h &= cm->mask;
97                cm->next[pos] = cm->first[h];
98                cm->first[h] = pos;
99                ++pos;
100                i = j + 1;
101               }
102            return 1;
103           }
104          alloc_free(cm->hash);
105         }
106        alloc_free(cm->inputlen);
107       }
108      alloc_free(cm->input);
109     }
110    alloc_free(cm->first);
111   }
112  return 0;
113 }
114
115 void constmap_free(cm)
116 struct constmap *cm;
117 {
118  alloc_free(cm->next);
119  alloc_free(cm->hash);
120  alloc_free(cm->inputlen);
121  alloc_free(cm->input);
122  alloc_free(cm->first);
123 }