source: tags/ms_r16q2/AISC_COM/C/struct_man.c

Last change on this file was 10985, checked in by westram, 10 years ago
  • use GBK_terminate instead of provoking trap manually
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.6 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  = 0;
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 (NULL)";
135    }
136    if (object->mh.parent) {
137        CORE;
138        return "Object already linked";
139    }
140    if (!father) {
141        CORE;
142        return "Parent is (NULL)";
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 = NULL;
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 0;
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 = NULL;
216    object->previous  = NULL;
217    object->next      = NULL;
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 0;
227}
228
229long aisc_find_lib(dllpublic_ext *parent, char *ident)
230{
231    if (!parent->hash) return 0;
232    if (!ident) return 0;
233    return aisc_read_hash((aisc_hash_node **)parent->hash, ident);
234}
235
236
237struct trf_dest_struct {
238    struct trf_dest_struct *next;
239    long                   *dest;
240};
241
242struct trf_struct {
243    struct trf_struct      *next;
244    long                    new_item;
245    long                    old;
246    struct trf_dest_struct *dests;
247};
248
249static int trf_hash(long p)
250{
251    return (p+(p>>8))&(TRF_HASH_SIZE-1);
252}
253
254static int trf_level = 0;
255static struct trf_struct **trf_sp = 0;
256
257void trf_create(long old, long new_item) {
258    long i;
259    struct trf_struct *ts;
260    struct trf_dest_struct *tds, *ntds;
261    if (!trf_sp) return;
262    i = trf_hash(old);
263    for (ts = trf_sp[i]; ts; ts = ts->next) {
264        if (ts->old == old) {
265            if (ts->new_item && (ts->new_item != new_item)) {
266                GBK_terminate("ERROR IN trf_create");
267            }
268            else {
269                ts->new_item = new_item;
270                for (tds = ts->dests; tds; tds = ntds) {
271                    *tds->dest = new_item;
272                    ntds = tds->next;
273                    free(tds);
274                }
275            }
276            return;
277        }
278    }
279    ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
280    ts->next = trf_sp[i];
281    trf_sp[i] = ts;
282    ts->new_item = new_item;
283    ts->old = old;
284}
285
286void trf_link(long old, long *dest)
287{
288    long i;
289    struct trf_struct *ts, *fts;
290    struct trf_dest_struct *tds;
291    if (!trf_sp) return;
292    i = trf_hash(old);
293    fts = 0;
294    for (ts = trf_sp[i]; ts; ts = ts->next) {
295        if (ts->old == old)     { fts = ts; break; }
296    }
297    if (!fts) {
298        ts = (struct trf_struct *)calloc(sizeof(struct trf_struct), 1);
299        ts->next = trf_sp[i];
300        trf_sp[i] = ts;
301        ts->old = old;
302        fts = ts;
303    }
304    tds = (struct trf_dest_struct *)calloc(sizeof(struct trf_dest_struct), 1);
305    tds->next = fts->dests;
306    fts->dests = tds;
307    tds->dest = dest;
308}
309
310void trf_begin() {
311    if (trf_level==0) {
312        trf_sp = (struct trf_struct **)calloc(sizeof(struct trf_struct *), TRF_HASH_SIZE);
313    }
314    trf_level ++;
315}
316
317void trf_commit(int errors) {
318    // if errors == 1 then print errors and CORE
319    struct trf_dest_struct *tds, *ntds;
320    struct trf_struct *ts, *nts;
321    trf_level--;
322    if (!trf_level) {
323        for (int i = 0; i < TRF_HASH_SIZE; i++) {
324            for (ts = trf_sp[i]; ts; ts = nts) {
325                if (errors) {
326                    if (ts->dests) {
327                        GBK_terminate("ERROR IN trf_commit");
328                    }
329                }
330                else {
331                    for (tds = ts->dests; tds; tds = ntds) {
332                        ntds = tds->next;
333                        free(tds);
334                    }
335                }
336                nts = ts->next;
337                free(ts);
338            }
339        }
340        free(trf_sp);
341        trf_sp = 0;
342    }
343}
344
Note: See TracBrowser for help on using the repository browser.