chiark / gitweb /
Debianization and various other fixes.
[ezmlm] / 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 /* Returns index of string in constmap. 1 = first string, 2 = second ... */
22 /* 0 not found. Use for commands */ 
23 int constmap_index(cm,s,len)
24 struct constmap *cm;
25 char *s;
26 int len;
27 {
28   constmap_hash h;
29   int pos;
30   h = hash(s,len);
31   pos = cm->first[h & cm->mask];
32   while (pos != -1) {
33     if (h == cm->hash[pos])
34       if (len == cm->inputlen[pos])
35         if (!case_diffb(cm->input[pos],len,s))
36           return pos + 1;
37     pos = cm->next[pos];
38   }
39   return 0;
40 }
41
42 /* returns pointer to sz of string with index "idx". 1 = first, 2 = second...*/
43 char *constmap_get(cm,idx)
44 struct constmap *cm;
45 int idx;
46
47 {
48   if (idx <= 0 || idx > cm->num)
49     return 0;
50   else
51     return cm->input[idx-1];
52 }
53
54 char *constmap(cm,s,len)
55 struct constmap *cm;
56 char *s;
57 int len;
58 {
59   constmap_hash h;
60   int pos;
61   h = hash(s,len);
62   pos = cm->first[h & cm->mask];
63   while (pos != -1) {
64     if (h == cm->hash[pos])
65       if (len == cm->inputlen[pos])
66         if (!case_diffb(cm->input[pos],len,s))
67           return cm->input[pos] + cm->inputlen[pos] + 1;
68     pos = cm->next[pos];
69   }
70   return 0;
71 }
72
73 int constmap_init(cm,s,len,flagcolon)
74 /* if flagcolon is true, we process only the stuff before the colon on */
75 /* each line. Otherwise, it's the entire line. Still, the entire line */
76 /* is stored! */
77 struct constmap *cm;
78 char *s;
79 int len;
80 int flagcolon;
81 {
82   int i;
83   int j;
84   int k;
85   int pos;
86   constmap_hash h;
87  
88   cm->num = 0;
89   for (j = 0;j < len;++j) if (!s[j]) ++cm->num;
90  
91   h = 64;
92   while (h && (h < cm->num)) h += h;
93   cm->mask = h - 1;
94  
95   cm->first = (int *) alloc(sizeof(int) * h);
96   if (cm->first) {
97     cm->input = (char **) alloc(sizeof(char *) * cm->num);
98     if (cm->input) {
99       cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
100       if (cm->inputlen) {
101         cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
102         if (cm->hash) {
103           cm->next = (int *) alloc(sizeof(int) * cm->num);
104           if (cm->next) {
105             for (h = 0;h <= cm->mask;++h)
106               cm->first[h] = -1;
107             pos = 0;
108             i = 0;
109             for (j = 0;j < len;++j)
110               if (!s[j]) {
111                 k = j - i;
112                 if (flagcolon) {
113                   for (k = i;k < j;++k)
114                     if (s[k] == ':')
115                       break;
116                   if (k >= j) { i = j + 1; continue; }
117                   k -= i;
118                 }
119                 cm->input[pos] = s + i;
120                 cm->inputlen[pos] = k;
121                 h = hash(s + i,k);
122                 cm->hash[pos] = h;
123                 h &= cm->mask;
124                 cm->next[pos] = cm->first[h];
125                 cm->first[h] = pos;
126                 ++pos;
127                 i = j + 1;
128               }
129             return 1;
130           }
131           alloc_free(cm->hash);
132         }
133         alloc_free(cm->inputlen);
134       }
135       alloc_free(cm->input);
136     }
137     alloc_free(cm->first);
138   }
139   return 0;
140 }
141
142 void constmap_free(cm)
143 struct constmap *cm;
144 {
145   alloc_free(cm->next);
146   alloc_free(cm->hash);
147   alloc_free(cm->inputlen);
148   alloc_free(cm->input);
149   alloc_free(cm->first);
150 }