source: trunk/third/rpm/python/hash.c @ 17931

Revision 17931, 4.4 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r17930, which included commits to RCS files with non-trunk default branches.
Line 
1/** \ingroup python
2 * \file python/hash.c
3 */
4
5#include <stdlib.h>
6#include <unistd.h>
7#include <stdio.h>
8#include <string.h>
9
10#include "hash.h"
11
12#define CHUNK 1
13
14struct filePath {
15    char * dir;
16    char * base;
17} ;
18
19struct bucket {
20    struct filePath * data;
21    int allocated;
22    int firstFree; /* as in data[firstFree] */
23};
24
25struct hash_table {
26    int size;
27    int entries;
28    int overHead;
29    struct bucket *bucket;
30};
31
32struct hash_table *htNewTable(int size)
33{
34    struct hash_table *res;
35    int i = 0;
36
37    res = malloc(sizeof(struct hash_table));
38    res->bucket = malloc(sizeof(struct bucket) * size);
39    res->size = size;
40    res->entries = 0;
41    res->overHead = sizeof(struct bucket) * size + CHUNK * sizeof(char *);
42
43    while (i < size) {
44        res->bucket[i].data = malloc(CHUNK * sizeof(*res->bucket[i].data));
45        res->bucket[i].allocated = CHUNK;
46        res->bucket[i].firstFree = 0;
47        i++;
48    }
49   
50    return res;
51}
52
53void htFreeHashTable(struct hash_table *ht)
54{
55    struct bucket * b;
56    int item;
57
58    b = ht->bucket;
59    while (ht->size--) {
60        for (item = 0; item < b->firstFree; item++) {
61            free(b->data[item].dir);
62            free(b->data[item].base);
63        }
64        free(b->data);
65        b++;
66    }
67    free(ht->bucket);
68    free(ht);
69}
70
71void htHashStats(const struct hash_table *t)
72{
73    int i = 0;
74    int empty = 0;
75
76    while (i < t->size) {
77        if (t->bucket[i].firstFree != 0) {
78            /*printf("Bucket %d used %d\n", i, t->bucket[i].firstFree);*/
79        } else {
80            empty++;
81        }
82        i++;
83    }
84
85    printf("Total Buckets : %d\n", t->size);
86    printf("Empty Buckets : %d\n", empty);
87    printf("Total Entries : %d\n", t->entries);
88    printf("Total Overhead: %d\n", t->overHead);
89    printf("Avergage Depth: %f\n", (double)t->entries / (double)t->size);
90}
91
92static unsigned int htHashStrings(const char * s, const char * t)
93{
94    unsigned int res = 0;
95
96    while (*s != '\0')
97        res = ((res<<1) + (int)(*(s++)));
98    while (*t != '\0')
99        res = ((res<<1) + (int)(*(t++)));
100
101    return res;
102}
103
104/* returns bucket # containing item, or -1 */
105static int in_table_aux(struct hash_table *t, int hash, const char * dir,
106                        const char * base)
107{
108    int x;
109
110    x = 0;
111    while (x < t->bucket[hash].firstFree) {
112        if (! strcmp(t->bucket[hash].data[x].dir, dir) &&
113            ! strcmp(t->bucket[hash].data[x].base, base)) {
114            return x;
115        }
116        x++;
117    }
118   
119    return -1;
120}
121
122int htInTable(struct hash_table *t,  const char * dir, const char * base)
123{
124    int hash;
125
126    hash = htHashStrings(dir, base) % t->size;
127
128    if (in_table_aux(t, hash, dir, base) == -1)
129        return 0;
130    return 1;
131}
132
133void htAddToTable(struct hash_table *t, const char * dir, const char * base)
134{
135    static int hash = 1;
136
137    if (!dir || !base)
138        return;
139   
140    hash = htHashStrings(dir, base) % t->size;
141    if (in_table_aux(t, hash, dir, base) != -1)
142        return;
143
144    if (t->bucket[hash].firstFree == t->bucket[hash].allocated) {
145        t->bucket[hash].allocated += CHUNK;
146        t->bucket[hash].data =
147            realloc(t->bucket[hash].data,
148                    t->bucket[hash].allocated * sizeof(*(t->bucket->data)));
149        /*printf("Bucket %d grew to %d\n", hash, t->bucket[hash].allocated);*/
150        t->overHead += sizeof(char *) * CHUNK;
151    }
152    /*printf("In bucket %d, item %d\n", hash, t->bucket[hash].firstFree);*/
153    t->bucket[hash].data[t->bucket[hash].firstFree].dir = strdup(dir);
154    t->bucket[hash].data[t->bucket[hash].firstFree++].base = strdup(base);
155    t->entries++;
156}
157
158void htRemoveFromTable(struct hash_table *t, const char * dir,
159                       const char * base) {
160    int hash;
161    int item;
162    int last;
163
164    hash = htHashStrings(dir, base) % t->size;
165    if ((item = in_table_aux(t, hash, dir, base)) == -1) {
166        return;
167    }
168
169    free(t->bucket[hash].data[item].dir);
170    free(t->bucket[hash].data[item].base);
171
172    last = --t->bucket[hash].firstFree;
173    t->bucket[hash].data[item] = t->bucket[hash].data[last];
174}
175
176int htNumEntries(struct hash_table *t) {
177    return t->entries;
178}
179
180void htIterStart(htIterator * iter) {
181    iter->bucket = 0;
182    iter->item = -1;
183}
184
185int htIterGetNext(struct hash_table * t, htIterator * iter,
186                  const char ** dir, const char ** base) {
187    iter->item++;
188   
189    while (iter->bucket < t->size) {
190        if (iter->item < t->bucket[iter->bucket].firstFree) {
191            *dir = t->bucket[iter->bucket].data[iter->item].dir;
192            *base = t->bucket[iter->bucket].data[iter->item].base;
193
194            return 1;
195        }
196
197        iter->item++;
198        if (iter->item >= t->bucket[iter->bucket].firstFree) {
199            iter->bucket++;
200            iter->item = 0;
201        }
202    }
203
204    return 0;
205}
Note: See TracBrowser for help on using the repository browser.