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