1 /* sdb - MIT - Copyright 2011-2016 - pancake */
2
3 #include "sdb.h"
4
sdb_ns_lock(Sdb * s,int lock,int depth)5 SDB_API void sdb_ns_lock(Sdb *s, int lock, int depth) {
6 SdbListIter *it;
7 SdbNs *ns;
8 s->ns_lock = lock;
9 if (depth) { // handles -1 as infinite
10 ls_foreach (s->ns, it, ns) {
11 sdb_ns_lock (ns->sdb, lock, depth-1);
12 }
13 }
14 }
15
in_list(SdbList * list,void * item)16 static int in_list(SdbList *list, void *item) {
17 SdbNs *ns;
18 SdbListIter *it;
19 if (list && item)
20 ls_foreach (list, it, ns) {
21 if (item == ns) {
22 return 1;
23 }
24 }
25 return 0;
26 }
27
ns_free(Sdb * s,SdbList * list)28 static void ns_free(Sdb *s, SdbList *list) {
29 SdbListIter next;
30 SdbListIter *it;
31 int deleted;
32 SdbNs *ns;
33 if (!list || !s) {
34 return;
35 }
36 // TODO: Implement and use ls_foreach_safe
37 if (in_list (list, s)) {
38 return;
39 }
40 ls_append (list, s);
41 ls_foreach (s->ns, it, ns) {
42 deleted = 0;
43 next.n = it->n;
44 if (!in_list (list, ns)) {
45 ls_delete (s->ns, it); // free (it)
46 free (ns->name);
47 ns->name = NULL;
48 deleted = 1;
49 if (ns->sdb) {
50 if (sdb_free (ns->sdb)) {
51 ns->sdb = NULL;
52 free (ns->name);
53 ns->name = NULL;
54 }
55 }
56 ls_append (list, ns);
57 ls_append (list, ns->sdb);
58 ns_free (ns->sdb, list);
59 sdb_free (ns->sdb);
60 }
61 if (!deleted) {
62 sdb_free (ns->sdb);
63 s->ns->free = NULL;
64 ls_delete (s->ns, it); // free (it)
65 }
66 free (ns);
67 it = &next;
68 }
69 ls_free (s->ns);
70 s->ns = NULL;
71 }
72
sdb_ns_free(Sdb * s)73 SDB_API void sdb_ns_free(Sdb *s) {
74 SdbList *list;
75 if (!s) {
76 return;
77 }
78 list = ls_new ();
79 list->free = NULL;
80 ns_free (s, list);
81 ls_free (list);
82 ls_free (s->ns);
83 s->ns = NULL;
84 }
85
sdb_ns_new(Sdb * s,const char * name,ut32 hash)86 static SdbNs *sdb_ns_new (Sdb *s, const char *name, ut32 hash) {
87 char dir[SDB_MAX_PATH];
88 SdbNs *ns;
89 if (s->dir && *s->dir && name && *name) {
90 int dir_len = strlen (s->dir);
91 int name_len = strlen (name);
92 if ((dir_len+name_len+3)>SDB_MAX_PATH) {
93 return NULL;
94 }
95 memcpy (dir, s->dir, dir_len);
96 memcpy (dir + dir_len, ".", 1);
97 memcpy (dir + dir_len + 1, name, name_len + 1);
98 } else {
99 dir[0] = 0;
100 }
101 ns = malloc (sizeof (SdbNs));
102 if (!ns) {
103 return NULL;
104 }
105 ns->hash = hash;
106 ns->name = name? strdup (name): NULL;
107 //ns->sdb = sdb_new (dir, ns->name, 0);
108 ns->sdb = sdb_new0 ();
109 // TODO: generate path
110
111 if (ns->sdb) {
112 free (ns->sdb->path);
113 ns->sdb->path = NULL;
114 if (*dir) {
115 ns->sdb->path = strdup (dir);
116 }
117 free (ns->sdb->name);
118 if (name && *name) {
119 ns->sdb->name = strdup (name);
120 }
121 } else {
122 free (ns->name);
123 free (ns);
124 ns = NULL;
125 }
126 return ns;
127 }
128
sdb_ns_unset(Sdb * s,const char * name,Sdb * r)129 SDB_API bool sdb_ns_unset (Sdb *s, const char *name, Sdb *r) {
130 SdbNs *ns;
131 SdbListIter *it;
132 if (s && (name || r)) {
133 ls_foreach (s->ns, it, ns) {
134 if (name && (!strcmp (name, ns->name))) {
135 ls_delete (s->ns, it);
136 return true;
137 }
138 if (r && ns->sdb == r) {
139 ls_delete (s->ns, it);
140 return true;
141 }
142 }
143 }
144 return false;
145 }
146
sdb_ns_set(Sdb * s,const char * name,Sdb * r)147 SDB_API int sdb_ns_set(Sdb *s, const char *name, Sdb *r) {
148 SdbNs *ns;
149 SdbListIter *it;
150 ut32 hash = sdb_hash (name);
151 if (!s || !r || !name) {
152 return 0;
153 }
154 ls_foreach (s->ns, it, ns) {
155 if (ns->hash == hash) {
156 if (ns->sdb == r) {
157 return 0;
158 }
159 sdb_free (ns->sdb);
160 r->refs++; // sdb_ref / sdb_unref //
161 ns->sdb = r;
162 return 1;
163 }
164 }
165 if (s->ns_lock) {
166 return 0;
167 }
168 ns = R_NEW (SdbNs);
169 ns->name = strdup (name);
170 ns->hash = hash;
171 ns->sdb = r;
172 r->refs++;
173 ls_append (s->ns, ns);
174 return 1;
175 }
176
sdb_ns(Sdb * s,const char * name,int create)177 SDB_API Sdb *sdb_ns(Sdb *s, const char *name, int create) {
178 SdbListIter *it;
179 SdbNs *ns;
180 ut32 hash;
181 if (!s || !name || !*name) {
182 return NULL;
183 }
184 hash = sdb_hash (name);
185 ls_foreach (s->ns, it, ns) {
186 if (ns->hash == hash) {
187 return ns->sdb;
188 }
189 }
190 if (!create) {
191 return NULL;
192 }
193 if (s->ns_lock) {
194 return NULL;
195 }
196 ns = sdb_ns_new (s, name, hash);
197 if (!ns) {
198 return NULL;
199 }
200 ls_append (s->ns, ns);
201 return ns->sdb;
202 }
203
sdb_ns_path(Sdb * s,const char * path,int create)204 SDB_API Sdb *sdb_ns_path(Sdb *s, const char *path, int create) {
205 char *ptr, *str;
206 char *slash;
207
208 if (!s || !path || !*path)
209 return s;
210 ptr = str = strdup (path);
211 do {
212 slash = strchr (ptr, '/');
213 if (slash)
214 *slash = 0;
215 s = sdb_ns (s, ptr, create);
216 if (!s) break;
217 if (slash)
218 ptr = slash+1;
219 } while (slash);
220 free (str);
221 return s;
222 }
223
ns_sync(Sdb * s,SdbList * list)224 static void ns_sync (Sdb *s, SdbList *list) {
225 SdbNs *ns;
226 SdbListIter *it;
227 ls_foreach (s->ns, it, ns) {
228 if (in_list (list, ns)) {
229 continue;
230 }
231 ls_append (list, ns);
232 ns_sync (ns->sdb, list);
233 sdb_sync (ns->sdb);
234 }
235 sdb_sync (s);
236 }
237
sdb_ns_sync(Sdb * s)238 SDB_API void sdb_ns_sync (Sdb *s) {
239 SdbList *list = ls_new ();
240 ns_sync (s, list);
241 list->free = NULL;
242 ls_free (list);
243 }
244