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
|
#ifdef HAVE_CONFIG_H
# include <config.h>
#else
# define _ALL_SOURCE
# define _GNU_SOURCE
#endif
#include <string.h>
#include "sblist.h"
#include "orderedmap.h"
static void orderedmap_destroy_contents(struct orderedmap *o) {
char **p, *q;
size_t i;
htab_value *v;
if(!o) return;
if(o->values) {
while(sblist_getsize(o->values)) {
p = sblist_get(o->values, 0);
if(p) free(*p);
sblist_delete(o->values, 0);
}
sblist_free(o->values);
}
if(o->map) {
i = 0;
while((i = htab_next(o->map, i, &q, &v)))
free(q);
htab_destroy(o->map);
}
}
struct orderedmap *orderedmap_create(size_t nbuckets) {
struct orderedmap o = {0}, *new;
o.values = sblist_new(sizeof(void*), 32);
if(!o.values) goto oom;
o.map = htab_create(nbuckets);
if(!o.map) goto oom;
new = malloc(sizeof o);
if(!new) goto oom;
memcpy(new, &o, sizeof o);
return new;
oom:;
orderedmap_destroy_contents(&o);
return 0;
}
void* orderedmap_destroy(struct orderedmap *o) {
orderedmap_destroy_contents(o);
free(o);
return 0;
}
int orderedmap_append(struct orderedmap *o, const char *key, char *value) {
size_t index;
char *nk, *nv;
nk = nv = 0;
nk = strdup(key);
nv = strdup(value);
if(!nk || !nv) goto oom;
index = sblist_getsize(o->values);
if(!sblist_add(o->values, &nv)) goto oom;
if(!htab_insert(o->map, nk, HTV_N(index))) {
sblist_delete(o->values, index);
goto oom;
}
return 1;
oom:;
free(nk);
free(nv);
return 0;
}
char* orderedmap_find(struct orderedmap *o, const char *key) {
char **p;
htab_value *v = htab_find(o->map, key);
if(!v) return 0;
p = sblist_get(o->values, v->n);
return p?*p:0;
}
int orderedmap_remove(struct orderedmap *o, const char *key) {
size_t i;
char *lk;
htab_value *lv, *v = htab_find(o->map, key);
if(!v) return 0;
htab_delete(o->map, key);
sblist_delete(o->values, v->n);
i = 0;
while((i = htab_next(o->map, i, &lk, &lv))) {
if(lv->n > v->n) lv->n--;
}
return 1;
}
size_t orderedmap_next(struct orderedmap *o, size_t iter, char** key, char** value) {
size_t h_iter;
htab_value* hval;
char **p;
if(iter < sblist_getsize(o->values)) {
h_iter = 0;
while((h_iter = htab_next(o->map, h_iter, key, &hval))) {
if(hval->n == iter) {
p = sblist_get(o->values, iter);
*value = p?*p:0;
return iter+1;
}
}
}
return 0;
}
|