constmap.c
author "Tomas Zeman <tomas.zeman@sun.com>"
Fri, 19 Oct 2007 14:06:22 +0200
changeset 0 068428edee47
permissions -rw-r--r--
Imported qmail-1.03
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     1
#include "constmap.h"
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     2
#include "alloc.h"
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     3
#include "case.h"
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     4
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     5
static constmap_hash hash(s,len)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     6
char *s;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     7
int len;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     8
{
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
     9
  unsigned char ch;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    10
  constmap_hash h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    11
  h = 5381;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    12
  while (len > 0) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    13
    ch = *s++ - 'A';
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    14
    if (ch <= 'Z' - 'A') ch += 'a' - 'A';
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    15
    h = ((h << 5) + h) ^ ch;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    16
    --len;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    17
  }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    18
  return h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    19
}
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    20
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    21
char *constmap(cm,s,len)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    22
struct constmap *cm;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    23
char *s;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    24
int len;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    25
{
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    26
  constmap_hash h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    27
  int pos;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    28
  h = hash(s,len);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    29
  pos = cm->first[h & cm->mask];
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    30
  while (pos != -1) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    31
    if (h == cm->hash[pos])
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    32
      if (len == cm->inputlen[pos])
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    33
        if (!case_diffb(cm->input[pos],len,s))
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    34
	  return cm->input[pos] + cm->inputlen[pos] + 1;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    35
    pos = cm->next[pos];
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    36
  }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    37
  return 0;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    38
}
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    39
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    40
int constmap_init(cm,s,len,flagcolon)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    41
struct constmap *cm;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    42
char *s;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    43
int len;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    44
int flagcolon;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    45
{
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    46
  int i;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    47
  int j;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    48
  int k;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    49
  int pos;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    50
  constmap_hash h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    51
 
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    52
  cm->num = 0;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    53
  for (j = 0;j < len;++j) if (!s[j]) ++cm->num;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    54
 
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    55
  h = 64;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    56
  while (h && (h < cm->num)) h += h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    57
  cm->mask = h - 1;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    58
 
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    59
  cm->first = (int *) alloc(sizeof(int) * h);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    60
  if (cm->first) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    61
    cm->input = (char **) alloc(sizeof(char *) * cm->num);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    62
    if (cm->input) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    63
      cm->inputlen = (int *) alloc(sizeof(int) * cm->num);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    64
      if (cm->inputlen) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    65
        cm->hash = (constmap_hash *) alloc(sizeof(constmap_hash) * cm->num);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    66
        if (cm->hash) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    67
	  cm->next = (int *) alloc(sizeof(int) * cm->num);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    68
	  if (cm->next) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    69
	    for (h = 0;h <= cm->mask;++h)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    70
	      cm->first[h] = -1;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    71
            pos = 0;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    72
            i = 0;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    73
            for (j = 0;j < len;++j)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    74
              if (!s[j]) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    75
	        k = j - i;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    76
	        if (flagcolon) {
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    77
		  for (k = i;k < j;++k)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    78
		    if (s[k] == ':')
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    79
		      break;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    80
		  if (k >= j) { i = j + 1; continue; }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    81
		  k -= i;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    82
		}
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    83
                cm->input[pos] = s + i;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    84
                cm->inputlen[pos] = k;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    85
                h = hash(s + i,k);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    86
                cm->hash[pos] = h;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    87
                h &= cm->mask;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    88
                cm->next[pos] = cm->first[h];
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    89
                cm->first[h] = pos;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    90
                ++pos;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    91
                i = j + 1;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    92
              }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    93
            return 1;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    94
	  }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    95
	  alloc_free(cm->hash);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    96
	}
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    97
        alloc_free(cm->inputlen);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    98
      }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
    99
      alloc_free(cm->input);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   100
    }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   101
    alloc_free(cm->first);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   102
  }
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   103
  return 0;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   104
}
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   105
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   106
void constmap_free(cm)
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   107
struct constmap *cm;
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   108
{
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   109
  alloc_free(cm->next);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   110
  alloc_free(cm->hash);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   111
  alloc_free(cm->inputlen);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   112
  alloc_free(cm->input);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   113
  alloc_free(cm->first);
068428edee47 Imported qmail-1.03
"Tomas Zeman <tomas.zeman@sun.com>"
parents:
diff changeset
   114
}