forked from bruceg/ezmlm-idx
-
Notifications
You must be signed in to change notification settings - Fork 0
/
constmap.c
134 lines (125 loc) · 3.15 KB
/
constmap.c
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "constmap.h"
#include "alloc.h"
#include "case.h"
static constmap_hash hash(const char *s,int len)
{
unsigned char ch;
constmap_hash h;
h = 5381;
while (len > 0) {
ch = *s++ - 'A';
if (ch <= 'Z' - 'A') ch += 'a' - 'A';
h = ((h << 5) + h) ^ ch;
--len;
}
return h;
}
/* Returns index of string in constmap. 1 = first string, 2 = second ... */
/* 0 not found. Use for commands */
int constmap_index(const struct constmap *cm,const char *s,int len)
{
constmap_hash h;
int pos;
h = hash(s,len);
pos = cm->first[h & cm->mask];
while (pos != -1) {
if (h == cm->hash[pos])
if (len == cm->inputlen[pos])
if (!case_diffb(cm->input[pos],len,s))
return pos + 1;
pos = cm->next[pos];
}
return 0;
}
/* returns pointer to sz of string with index "idx". 1 = first, 2 = second...*/
const char *constmap_get(struct constmap *cm,unsigned int idx)
{
if (idx <= 0 || idx > cm->num)
return 0;
else
return cm->input[idx-1];
}
const char *constmap(struct constmap *cm,const char *s,int len)
{
constmap_hash h;
int pos;
h = hash(s,len);
pos = cm->first[h & cm->mask];
while (pos != -1) {
if (h == cm->hash[pos])
if (len == cm->inputlen[pos])
if (!case_diffb(cm->input[pos],len,s))
return cm->input[pos] + cm->inputlen[pos] + 1;
pos = cm->next[pos];
}
return 0;
}
int constmap_init(struct constmap *cm,const char *s,int len,int splitchar)
/* if splitchar is set, we process only the stuff before that character
* on each line. Otherwise, it's the entire line. Still, the entire line
* is stored! */
{
int i;
int j;
int k;
int pos;
constmap_hash h;
cm->num = 0;
for (j = 0;j < len;++j) if (!s[j]) ++cm->num;
h = 64;
while (h && (h < cm->num)) h += h;
cm->mask = h - 1;
cm->first = (int *) alloc(sizeof(int) * h);
if (cm->first) {
cm->input = (const char **) alloc(sizeof(char *) * cm->num);
if (cm->input) {
cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
if (cm->inputlen) {
cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
if (cm->hash) {
cm->next = (int *) alloc(sizeof(int) * cm->num);
if (cm->next) {
for (h = 0;h <= cm->mask;++h)
cm->first[h] = -1;
pos = 0;
i = 0;
for (j = 0;j < len;++j)
if (!s[j]) {
k = j - i;
if (splitchar) {
for (k = i;k < j;++k)
if (s[k] == splitchar)
break;
if (k >= j) { i = j + 1; continue; }
k -= i;
}
cm->input[pos] = s + i;
cm->inputlen[pos] = k;
h = hash(s + i,k);
cm->hash[pos] = h;
h &= cm->mask;
cm->next[pos] = cm->first[h];
cm->first[h] = pos;
++pos;
i = j + 1;
}
return 1;
}
alloc_free(cm->hash);
}
alloc_free(cm->inputlen);
}
alloc_free(cm->input);
}
alloc_free(cm->first);
}
return 0;
}
void constmap_free(struct constmap *cm)
{
alloc_free(cm->next);
alloc_free(cm->hash);
alloc_free(cm->inputlen);
alloc_free(cm->input);
alloc_free(cm->first);
}