source: trunk/AISC_COM/C/struct_man.c

Last change on this file was 16766, checked in by westram, 7 years ago
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.7 KB
Line 
1// ==============================================================
2/*                                                                */
3//   File      : struct_man.c
4//   Purpose   :
5/*                                                                */
6//   Institute of Microbiology (Technical University Munich)
7//   http://www.arb-home.de/
8 /*                                                                */
9 // ==============================================================
10
11
12#include <aisc.h>
13#include <struct_man.h>
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18
19// AISC_MKPT_PROMOTE:struct aisc_hash_node;
20
21// ---------------------
22//      hash tables
23
24
25#define CORE
26#define HASH_SIZE 103123
27#define TRF_HASH_SIZE 103123
28
29struct aisc_hash_node {
30    char           *key;
31    long            data;
32    aisc_hash_node *next;
33};
34
35
36static aisc_hash_node **aisc_init_hash(int size) {
37    struct aisc_hash_node **tab;
38    tab = (aisc_hash_node **) calloc(sizeof(aisc_hash_node *), size);
39    tab[0] = (aisc_hash_node *) calloc(sizeof(aisc_hash_node), 1);
40    tab[0]->data = size;
41    tab[0]->key = (char *)strdup("len_of_hash_table_(c) oliver_strunk 1.3.93");
42    return tab;
43}
44
45static int aisc_hash(const char *key, int size) {
46    unsigned int i, len, x;
47    len = strlen(key);
48    x = 0;
49    for (i=0; i<len; i++) {
50        x = x<<2 ^ key[i];
51    }
52    x = x%size;
53    return x;
54}
55
56static void aisc_free_key(aisc_hash_node **table, char *key) {
57    if (table && table[0]) {
58        long size = table[0]->data;
59        long i    = aisc_hash(key, (int)size);
60
61        aisc_hash_node *hn, *hhn;
62        for (hn = hhn = table[i]; hn; hn = hn->next) {
63            if (strcmp(key, hn->key)) {
64                hhn = hn;
65                continue;
66            }
67            if (hn != hhn)
68                hhn->next = hn->next;
69            else {
70                table[i] = hhn->next;
71            }
72            free(hn->key);
73            free(hn);
74            break;
75        }
76    }
77}
78
79static void aisc_free_hash(aisc_hash_node **table) {
80    long end = table[0]->data;
81    for (long i=0; i<end; i++) {
82        aisc_hash_node *hn, *hnn;
83        for (hn = table[i]; hn; hn=hnn) {
84            hnn = hn->next;
85            free(hn->key);
86            free(hn);
87        }
88    }
89    free(table);
90}
91
92
93static void aisc_insert_hash(aisc_hash_node **table, char *key, long data) {
94    long            size = table[0]->data;
95    long            i    = aisc_hash(key, (int)size);
96
97    aisc_hash_node *hnl = NULp;
98    aisc_hash_node *hn;
99    for (hn=table[i]; hn; hn=hn->next) {
100        hnl = hn;
101        if (strcmp(key, hn->key) == 0) {
102            hn->data = data;
103            return;
104        }
105    }
106    hn = (aisc_hash_node *)calloc(sizeof(aisc_hash_node), 1);
107    hn->key = (char *)strdup(key);
108    hn->data = data;
109    if (hnl) {
110        hnl->next = hn;
111    }
112    else {
113        table[i] = hn;
114    }
115}
116
117long aisc_read_hash(aisc_hash_node **table, const char *key) {
118    if (table && table[0]) {
119        long size = table[0]->data;
120        long i = aisc_hash(key, (int)size);
121        for (aisc_hash_node *hn=table[i]; hn; hn=hn->next) {
122            if (strcmp(key, hn->key) == 0) return hn->data;
123        }
124    }
125    return 0;
126}
127
128// ----------------------
129//      link control
130
131const char *aisc_link(dllpublic_ext *father, dllheader_ext *object) {
132    if (!object) {
133        CORE;
134        return "Object is (NULp)";
135    }
136    if (object->mh.parent) {
137        CORE;
138        return "Object already linked";
139    }
140    if (!father) {
141        CORE;
142        return "Parent is (NULp)";
143    }
144    if (father->key != object->mh.key) {
145        CORE;
146        return "Parent key doesn't match Object key";
147    }
148    if (object->mh.ident) {
149        if (strlen(object->mh.ident) <= 0) {
150            CORE;
151            return "Too short ident";
152        }
153        if (father->hash) {
154            if (aisc_read_hash((aisc_hash_node **)father->hash, object->mh.ident)) {
155                CORE;
156                return "Object already in list";
157            }
158            else {
159                aisc_insert_hash((aisc_hash_node **)father->hash, object->mh.ident, (long)object);
160            }
161        }
162        else {
163            father->hash = (long)aisc_init_hash(HASH_SIZE);
164            aisc_insert_hash((aisc_hash_node **)father->hash, object->mh.ident, (long)object);
165        }
166    }
167    object->next = object->previous = NULp;
168    if (!father->first) {
169        father->cnt   = 1;
170        father->first = object;
171        father->last  = object;
172    }
173    else {
174        father->cnt++;
175        object->previous   = father->last;
176        father->last->next = object;
177        father->last       = object;
178    }
179    object->mh.parent = father;
180    return NULp;
181}
182
183
184
185const char *aisc_unlink(dllheader_ext *object) {
186    dllpublic_ext *father = (dllpublic_ext *)object->mh.parent;
187
188    if (!father) {
189        CORE;
190        return "Object not linked";
191    }
192    if (father->hash) {
193        aisc_free_key((aisc_hash_node **)father->hash, object->mh.ident);
194    }
195    if (father->cnt <= 0) {
196        CORE;
197        return "Parent count is 0";
198    }
199    if (object->previous) {
200        if (object->previous->next != object) {
201            CORE;
202            return "Fatal Error: Object is a copy, not original";
203        }
204        object->previous->next = object->next;
205    }
206    else {
207        father->first = object->next;
208    }
209    if (object->next) {
210        object->next->previous = object->previous;
211    }
212    else {
213        father->last = object->previous;
214    }
215    object->mh.parent = NULp;
216    object->previous  = NULp;
217    object->next      = NULp;
218
219    father->cnt--;
220    if (!father->cnt) {
221        if (father->hash) {
222            aisc_free_hash((aisc_hash_node **)father->hash);
223            father->hash = 0;
224        }
225    }
226    return NULp;
227}
228
229long aisc_find_lib(dllpublic_ext *parent, char *ident) {
230    if (!parent->hash) return 0;
231    if (!ident) return 0;
232    return aisc_read_hash((aisc_hash_node **)parent->hash, ident);
233}
234
235
236struct trf_dest_struct {
237    struct trf_dest_struct *next;
238    long                   *dest;
239};
240
241struct trf_struct {
242    struct trf_struct      *next;
243    long                    new_item;
244    long                    old;
245    struct trf_dest_struct *dests;
246};
247
248static int trf_hash(long p) {
249    return (p+(p>>8)) & (TRF_HASH_SIZE-1);
250}
251
252static int                 trf_level = 0;
253static struct trf_struct **trf_sp    = NULp;
254
255void trf_create(long old, long new_item) {
256    long i;
257    struct trf_struct *ts;
258    struct trf_dest_struct *tds, *ntds;
259    if (!trf_sp) return;
260    i = trf_hash(old);
261    for (ts = trf_sp[i]; ts; ts = ts->next) {
262        if (ts->old == old) {
263            if (ts->new_item && (ts->new_item != new_item)) {
264                GBK_terminate("ERROR IN trf_create");
265            }
266            else {
267                ts->new_item = new_item;
268                for (tds = ts->dests; tds; tds = ntds) {
269                    *tds->dest = new_item;
270                    ntds = tds->next;
271                    free(tds);
272                }
273            }
274            return;
275        }
276    }
277    ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
278    ts->next = trf_sp[i];
279    trf_sp[i] = ts;
280    ts->new_item = new_item;
281    ts->old = old;
282}
283
284void trf_link(long old, long *dest) {
285    long i;
286    struct trf_struct *ts, *fts;
287    struct trf_dest_struct *tds;
288    if (!trf_sp) return;
289    i = trf_hash(old);
290    fts = NULp;
291    for (ts = trf_sp[i]; ts; ts = ts->next) {
292        if (ts->old == old)     { fts = ts; break; }
293    }
294    if (!fts) {
295        ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
296        ts->next = trf_sp[i];
297        trf_sp[i] = ts;
298        ts->old = old;
299        fts = ts;
300    }
301    tds = (struct trf_dest_struct *)calloc(sizeof(struct trf_dest_struct), 1);
302    tds->next = fts->dests;
303    fts->dests = tds;
304    tds->dest = dest;
305}
306
307void trf_begin() {
308    if (trf_level==0) {
309        trf_sp = (struct trf_struct **)calloc(sizeof(struct trf_struct *), TRF_HASH_SIZE);
310    }
311    trf_level ++;
312}
313
314void trf_commit(int errors) {
315    // if errors == 1 then print errors and CORE
316    struct trf_dest_struct *tds, *ntds;
317    struct trf_struct *ts, *nts;
318    trf_level--;
319    if (!trf_level) {
320        for (int i = 0; i < TRF_HASH_SIZE; i++) {
321            for (ts = trf_sp[i]; ts; ts = nts) {
322                if (errors) {
323                    if (ts->dests) {
324                        GBK_terminate("ERROR IN trf_commit");
325                    }
326                }
327                else {
328                    for (tds = ts->dests; tds; tds = ntds) {
329                        ntds = tds->next;
330                        free(tds);
331                    }
332                }
333                nts = ts->next;
334                free(ts);
335            }
336        }
337        free(trf_sp);
338        trf_sp = NULp;
339    }
340}
341
Note: See TracBrowser for help on using the repository browser.