blob: fbd8992841a5d84842e230fedae1a18714fc1fb7 [file]
#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;
struct constmap_entry *e;
int pos;
h = hash(s,len);
pos = cm->first[h & cm->mask];
while (pos != -1) {
e = &cm->entries[pos];
if (h == e->hash)
if (len == e->inputlen)
if (!case_diffb(e->input,len,s))
return pos + 1;
pos = e->next;
}
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->entries[idx-1].input;
}
const char *constmap(struct constmap *cm,const char *s,int len)
{
constmap_hash h;
struct constmap_entry *e;
int pos;
h = hash(s,len);
pos = cm->first[h & cm->mask];
while (pos != -1) {
e = &cm->entries[pos];
if (h == e->hash)
if (len == e->inputlen)
if (!case_diffb(e->input,len,s))
return e->input + e->inputlen + 1;
pos = e->next;
}
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;
struct constmap_entry *e;
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->entries = alloc(cm->num * sizeof *cm->entries);
if (cm->entries) {
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;
}
h = hash(s + i,k);
e = &cm->entries[pos];
e->input = s + i;
e->inputlen = k;
e->hash = h;
h &= cm->mask;
e->next = cm->first[h];
cm->first[h] = pos;
++pos;
i = j + 1;
}
return 1;
}
alloc_free(cm->first);
}
return 0;
}
void constmap_free(struct constmap *cm)
{
alloc_free(cm->entries);
alloc_free(cm->first);
}