File: key.c

package info (click to toggle)
sn 0.3.4a-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 784 kB
  • ctags: 826
  • sloc: ansic: 9,023; sh: 339; makefile: 208
file content (105 lines) | stat: -rw-r--r-- 2,063 bytes parent folder | download
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
/*
 * This file is part of the sn package.
 * Distribution of sn is covered by the GNU GPL. See file COPYING.
 * Copyright  1998-2000 Harold Tay.
 * Copyright  2000- Patrik Rdman.
 */

/*
 * Generic hash table lookup.  Store only keys, not data.  All keys
 * must be unique.  Cannot delete.  This is used in 2 places: to
 * store a list of subscribed newsgroups in snntpd; and to remember
 * seen message IDs in snfetch.
 */

#include <stdlib.h>
#include "key.h"

static const char rcsid[] = "$Id$";

struct buf {
   struct buf *next;
   char buf[1000];
};

static struct buf *head;
static int avail = 0;
static char *keybuf = 0;

struct key *key_table[KEY_TABLE_SIZE] = { 0, };
int nr_keys = 0;

static unsigned hv;

static void hash (char *key, int len)
{
   hv = 5381;
   while (len)
   {
      --len;
      hv += (hv << 5);
      hv ^= (unsigned int) *key++;
   }
   hv %= 128;
}

char *key_exists (char *key, int len)
{
   struct key *kp;

   hash(key, len);
   for (kp = key_table[hv]; kp; kp = kp->next)
      if (kp->len == len)
         if (0 == memcmp(KEY(kp), key, len))
            return (KEY(kp));
   return (0);
}

int key_add (char **keyp, int len)
{
   struct key *kp;
   char *key;
   int size;

   key = *keyp;
   if (key_exists(key, len))
      return (1);
   size = len + sizeof (*kp);
   size += 4 - (size % 4);
   if (avail < size)
   {
      struct buf *x;
      if (!(x = malloc(sizeof (struct buf))))
         return (-1);
      x->next = head;
      head = x;
      avail = 1000;
      keybuf = head->buf;
   }
   kp = (struct key *) keybuf;
   kp->len = len;
   memcpy(*keyp = KEY(kp), key, len + 1); /* Bugfix: +1 so that it copies the '\0' also. */
   kp->next = key_table[hv];
   key_table[hv] = kp;
   keybuf += size;
   avail -= size;
   nr_keys++;
   return (0);
}

void key_free (void)
{
   int i;

   for (i = 0; i < sizeof (key_table) / sizeof (*key_table); i++)
      key_table[i] = 0;
   while (head)
   {
      struct buf *tmp;

      tmp = head->next;
      free(head);
      head = tmp;
   }
   nr_keys = avail = 0;
}