File: hashtable.c

package info (click to toggle)
libtlen 20041113-3
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k, sarge
  • size: 832 kB
  • ctags: 1,514
  • sloc: ansic: 13,713; sh: 214; makefile: 156
file content (128 lines) | stat: -rw-r--r-- 2,893 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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
 * Ostatnia aktualizacja:
 *
 * - $Id: hashtable.c,v 1.3 2002/12/14 19:36:11 mati Exp $
 *
 */

#include "xmldef.h"

#ifdef XML_UNICODE_WCHAR_T
#ifndef XML_UNICODE
#define XML_UNICODE
#endif
#endif

#include "hashtable.h"

#define INIT_SIZE 64

static
int keyeq(KEY s1, KEY s2)
{
    for (; *s1 == *s2; s1++, s2++)
        if (*s1 == 0)
            return 1;
    return 0;
}

static
unsigned long hash(KEY s)
{
    unsigned long h = 0;
    while (*s)
        h = (h << 5) + h + (unsigned char)*s++;
    return h;
}

NAMED *lookup(HASH_TABLE *table, KEY name, size_t createSize)
{
    size_t i;
    if (table->size == 0) {
        if (!createSize)
            return 0;
        table->v = calloc(INIT_SIZE, sizeof(NAMED *));
        if (!table->v)
            return 0;
        table->size = INIT_SIZE;
        table->usedLim = INIT_SIZE / 2;
        i = hash(name) & (table->size - 1);
    }
    else {
        unsigned long h = hash(name);
        for (i = h & (table->size - 1);
                table->v[i];
                i == 0 ? i = table->size - 1 : --i) {
            if (keyeq(name, table->v[i]->name))
                return table->v[i];
        }
        if (!createSize)
            return 0;
        if (table->used == table->usedLim) {
            /* check for overflow */
            size_t newSize = table->size * 2;
            NAMED **newV = calloc(newSize, sizeof(NAMED *));
            if (!newV)
                return 0;
            for (i = 0; i < table->size; i++)
                if (table->v[i]) {
                    size_t j;
                    for (j = hash(table->v[i]->name) & (newSize - 1);
                            newV[j];
                            j == 0 ? j = newSize - 1 : --j)
                        ;
                    newV[j] = table->v[i];
                }
            free(table->v);
            table->v = newV;
            table->size = newSize;
            table->usedLim = newSize/2;
            for (i = h & (table->size - 1);
                    table->v[i];
                    i == 0 ? i = table->size - 1 : --i)
                ;
        }
    }
    table->v[i] = calloc(1, createSize);
    if (!table->v[i])
        return 0;
    table->v[i]->name = name;
    (table->used)++;
    return table->v[i];
}

void hashTableDestroy(HASH_TABLE *table)
{
    size_t i;
    for (i = 0; i < table->size; i++) {
        NAMED *p = table->v[i];
        if (p)
            free(p);
    }
    free(table->v);
}

void hashTableInit(HASH_TABLE *p)
{
    p->size = 0;
    p->usedLim = 0;
    p->used = 0;
    p->v = 0;
}

void hashTableIterInit(HASH_TABLE_ITER *iter, const HASH_TABLE *table)
{
    iter->p = table->v;
    iter->end = iter->p + table->size;
}

NAMED *hashTableIterNext(HASH_TABLE_ITER *iter)
{
    while (iter->p != iter->end) {
        NAMED *tem = *(iter->p)++;
        if (tem)
            return tem;
    }
    return 0;
}