1 #ifndef SDB_H
2 #define SDB_H
3 
4 #if !defined(O_BINARY) && !defined(_MSC_VER)
5 #undef O_BINARY
6 #define O_BINARY 0
7 #endif
8 
9 #ifdef __cplusplus
10 extern "C" {
11 #endif
12 
13 #include "types.h"
14 #include "sdbht.h"
15 #include "ls.h"
16 #include "dict.h"
17 #include "cdb.h"
18 #include "cdb_make.h"
19 #include "sdb_version.h"
20 
21 /* Key value sizes */
22 #define SDB_MIN_VALUE 1
23 #define SDB_MAX_VALUE 0xffffff
24 #define SDB_MIN_KEY 1
25 #define SDB_MAX_KEY 0xff
26 
27 #if !defined(SZT_ADD_OVFCHK)
28 #define SZT_ADD_OVFCHK(x, y) ((SIZE_MAX - (x)) <= (y))
29 #endif
30 
31 	/* printf format check attributes */
32 #if defined(__clang__) || defined(__GNUC__)
33 #define SDB_PRINTF_CHECK(fmt, dots) __attribute__ ((format (printf, fmt, dots)))
34 #else
35 #define SDB_PRINTF_CHECK(fmt, dots)
36 #endif
37 
38 #if __SDB_WINDOWS__ && !__CYGWIN__
39 #include <windows.h>
40 #include <fcntl.h>
41 #include <stdbool.h>
42 #include <sys/types.h>
43 #include <sys/stat.h>
44 #include <io.h>
45 #ifndef _MSC_VER
46 extern __attribute__((dllimport)) void *__cdecl _aligned_malloc(size_t, size_t);
47 extern __attribute__((dllimport)) void __cdecl _aligned_free(void *memblock);
48 extern char *strdup (const char *);
49 #else
50 #include <process.h>
51 #include <windows.h>
52 #include <malloc.h> // for _aligned_malloc
53 #define ftruncate _chsize
54 #endif
55 
56 //#define SDB_MODE 0
57 #define SDB_MODE _S_IWRITE | _S_IREAD
58 #else
59 #define SDB_MODE 0644
60 //#define SDB_MODE 0600
61 #endif
62 
63 //#define SDB_RS '\x1e'
64 #define SDB_RS ','
65 #define SDB_SS ","
66 #define SDB_MAX_PATH 256
67 #define SDB_NUM_BASE 16
68 #define SDB_NUM_BUFSZ 64
69 
70 #define SDB_OPTION_NONE 0
71 #define SDB_OPTION_ALL 0xff
72 #define SDB_OPTION_SYNC    (1 << 0)
73 #define SDB_OPTION_NOSTAMP (1 << 1)
74 #define SDB_OPTION_FS      (1 << 2)
75 #define SDB_OPTION_JOURNAL (1 << 3)
76 
77 #define SDB_LIST_UNSORTED 0
78 #define SDB_LIST_SORTED 1
79 
80 // This size implies trailing zero terminator, this is 254 chars + 0
81 #define SDB_KSZ 0xff
82 #define SDB_VSZ 0xffffff
83 
84 
85 typedef struct sdb_t {
86 	char *dir; // path+name
87 	char *path;
88 	char *name;
89 	int fd;
90 	int refs; // reference counter
91 	int lock;
92 	int journal;
93 	struct cdb db;
94 	struct cdb_make m;
95 	HtPP *ht;
96 	ut32 eod;
97 	ut32 pos;
98 	int fdump;
99 	char *ndump;
100 	ut64 expire;
101 	ut64 last; // timestamp of last change
102 	int options;
103 	int ns_lock; // TODO: merge into options?
104 	SdbList *ns;
105 	SdbList *hooks;
106 	SdbKv tmpkv;
107 	ut32 depth;
108 	bool timestamped;
109 	SdbMini mht;
110 } Sdb;
111 
112 typedef struct sdb_ns_t {
113 	char *name;
114 	ut32 hash;
115 	Sdb *sdb;
116 } SdbNs;
117 
118 SDB_API Sdb* sdb_new0(void);
119 SDB_API Sdb* sdb_new(const char *path, const char *file, int lock);
120 
121 SDB_API int sdb_open(Sdb *s, const char *file);
122 SDB_API void sdb_close(Sdb *s);
123 
124 SDB_API void sdb_config(Sdb *s, int options);
125 SDB_API bool sdb_free(Sdb* s);
126 SDB_API void sdb_file(Sdb* s, const char *dir);
127 SDB_API bool sdb_merge(Sdb* d, Sdb *s);
128 SDB_API int sdb_count(Sdb* s);
129 SDB_API void sdb_reset(Sdb* s);
130 SDB_API void sdb_setup(Sdb* s, int options);
131 SDB_API void sdb_drain(Sdb*, Sdb*);
132 
133 // Copy everything, including namespaces, from src to dst
134 SDB_API void sdb_copy(Sdb *src, Sdb *dst);
135 
136 SDB_API bool sdb_stats(Sdb *s, ut32 *disk, ut32 *mem);
137 SDB_API bool sdb_dump_hasnext (Sdb* s);
138 
139 typedef bool (*SdbForeachCallback)(void *user, const char *k, const char *v);
140 SDB_API bool sdb_foreach(Sdb* s, SdbForeachCallback cb, void *user);
141 SDB_API SdbList *sdb_foreach_list(Sdb* s, bool sorted);
142 SDB_API SdbList *sdb_foreach_list_filter(Sdb* s, SdbForeachCallback filter, bool sorted);
143 SDB_API SdbList *sdb_foreach_match(Sdb* s, const char *expr, bool sorted);
144 
145 SDB_API int sdb_query(Sdb* s, const char *cmd);
146 SDB_API int sdb_queryf(Sdb* s, const char *fmt, ...);
147 SDB_API int sdb_query_lines(Sdb *s, const char *cmd);
148 SDB_API char *sdb_querys(Sdb* s, char *buf, size_t len, const char *cmd);
149 SDB_API char *sdb_querysf(Sdb* s, char *buf, size_t buflen, const char *fmt, ...);
150 SDB_API int sdb_query_file(Sdb *s, const char* file);
151 SDB_API bool sdb_exists(Sdb*, const char *key);
152 SDB_API bool sdb_remove(Sdb*, const char *key, ut32 cas);
153 SDB_API int sdb_unset(Sdb*, const char *key, ut32 cas);
154 SDB_API int sdb_unset_like(Sdb *s, const char *k);
155 SDB_API char** sdb_like(Sdb *s, const char *k, const char *v, SdbForeachCallback cb);
156 
157 // diffing
158 typedef struct sdb_diff_t {
159 	const SdbList *path;
160 	const char *k;
161 	const char *v; // if null, k is a namespace
162 	bool add;
163 } SdbDiff;
164 
165 // Format diff in a readable form into str. str, size and return are like in snprintf.
166 SDB_API int sdb_diff_format(char *str, int size, const SdbDiff *diff);
167 
168 typedef void (*SdbDiffCallback)(const SdbDiff *diff, void *user);
169 
170 // Returns true iff the contents of a and b are equal including contained namespaces
171 // If cb is non-null, it will be called subsequently with differences.
172 SDB_API bool sdb_diff(Sdb *a, Sdb *b, SdbDiffCallback cb, void *cb_user);
173 
174 // Gets a pointer to the value associated with `key`.
175 SDB_API char *sdb_get(Sdb*, const char *key, ut32 *cas);
176 
177 // Gets a pointer to the value associated with `key` and returns in `vlen` the
178 // length of the value string.
179 SDB_API char *sdb_get_len(Sdb*, const char *key, int *vlen, ut32 *cas);
180 
181 // Gets a const pointer to the value associated with `key`
182 SDB_API const char *sdb_const_get(Sdb*, const char *key, ut32 *cas);
183 
184 // Gets a const pointer to the value associated with `key` and returns in
185 // `vlen` the length of the value string.
186 SDB_API const char *sdb_const_get_len(Sdb* s, const char *key, int *vlen, ut32 *cas);
187 SDB_API int sdb_set(Sdb*, const char *key, const char *data, ut32 cas);
188 SDB_API int sdb_set_owned(Sdb* s, const char *key, char *val, ut32 cas);
189 SDB_API int sdb_concat(Sdb *s, const char *key, const char *value, ut32 cas);
190 SDB_API int sdb_uncat(Sdb *s, const char *key, const char *value, ut32 cas);
191 SDB_API int sdb_add(Sdb* s, const char *key, const char *val, ut32 cas);
192 SDB_API bool sdb_sync(Sdb*);
193 SDB_API void sdbkv_free(SdbKv *kv);
194 
195 /* num.c */
196 SDB_API bool sdb_num_exists(Sdb*, const char *key);
197 SDB_API int  sdb_num_base(const char *s);
198 SDB_API ut64 sdb_num_get(Sdb* s, const char *key, ut32 *cas);
199 SDB_API int  sdb_num_set(Sdb* s, const char *key, ut64 v, ut32 cas);
200 SDB_API int  sdb_num_add(Sdb *s, const char *key, ut64 v, ut32 cas);
201 SDB_API ut64 sdb_num_inc(Sdb* s, const char *key, ut64 n, ut32 cas);
202 SDB_API ut64 sdb_num_dec(Sdb* s, const char *key, ut64 n, ut32 cas);
203 SDB_API int  sdb_num_min(Sdb* s, const char *key, ut64 v, ut32 cas);
204 SDB_API int  sdb_num_max(Sdb* s, const char *key, ut64 v, ut32 cas);
205 
206 /* ptr */
207 SDB_API int sdb_ptr_set(Sdb *db, const char *key, void *p, ut32 cas);
208 SDB_API void* sdb_ptr_get(Sdb *db, const char *key, ut32 *cas);
209 
210 /* create db */
211 SDB_API bool sdb_disk_create(Sdb* s);
212 SDB_API bool sdb_disk_insert(Sdb* s, const char *key, const char *val);
213 SDB_API bool sdb_disk_finish(Sdb* s);
214 SDB_API bool sdb_disk_unlink(Sdb* s);
215 
216 /* plaintext sdb files */
217 SDB_API bool sdb_text_save_fd(Sdb *s, int fd, bool sort);
218 SDB_API bool sdb_text_save(Sdb *s, const char *file, bool sort);
219 SDB_API bool sdb_text_load_buf(Sdb *s, char *buf, size_t sz);
220 SDB_API bool sdb_text_load(Sdb *s, const char *file);
221 SDB_API bool sdb_text_check(Sdb *s, const char *file);
222 
223 /* iterate */
224 SDB_API void sdb_dump_begin(Sdb* s);
225 SDB_API SdbKv *sdb_dump_next(Sdb* s);
226 SDB_API bool sdb_dump_dupnext(Sdb* s, char *key, char **value, int *_vlen);
227 
228 /* journaling */
229 SDB_API bool sdb_journal_close(Sdb *s);
230 SDB_API bool sdb_journal_open(Sdb *s);
231 SDB_API int sdb_journal_load(Sdb *s);
232 SDB_API bool sdb_journal_log(Sdb *s, const char *key, const char *val);
233 SDB_API bool sdb_journal_clear(Sdb *s);
234 SDB_API bool sdb_journal_unlink(Sdb *s);
235 
236 /* numeric */
237 SDB_API char *sdb_itoa(ut64 n, char *s, int base);
238 SDB_API ut64  sdb_atoi(const char *s);
239 SDB_API const char *sdb_itoca(ut64 n);
240 
241 /* locking */
242 SDB_API bool sdb_lock(const char *s);
243 SDB_API const char *sdb_lock_file(const char *f);
244 SDB_API void sdb_unlock(const char *s);
245 SDB_API bool sdb_unlink(Sdb* s);
246 SDB_API int sdb_lock_wait(const char *s UNUSED);
247 
248 /* expiration */
249 SDB_API bool sdb_expire_set(Sdb* s, const char *key, ut64 expire, ut32 cas);
250 SDB_API ut64 sdb_expire_get(Sdb* s, const char *key, ut32 *cas);
251 SDB_API ut64 sdb_now(void);
252 SDB_API ut64 sdb_unow(void);
253 SDB_API ut32 sdb_hash(const char *key);
254 SDB_API ut32 sdb_hash_len(const char *key, ut32 *len);
255 SDB_API ut8 sdb_hash_byte(const char *s);
256 
257 /* json api */
258 // SDB_API int sdb_js0n(const unsigned char *js, RangstrType len, RangstrType *out);
259 SDB_API bool sdb_isjson(const char *k);
260 SDB_API char *sdb_json_get_str (const char *json, const char *path);
261 SDB_API bool sdb_json_get_bool(const char *json, const char *path);
262 
263 SDB_API char *sdb_json_get(Sdb* s, const char *key, const char *p, ut32 *cas);
264 SDB_API bool sdb_json_set(Sdb* s, const char *k, const char *p, const char *v, ut32 cas);
265 SDB_API int sdb_json_num_get(Sdb* s, const char *k, const char *p, ut32 *cas);
266 SDB_API int sdb_json_num_set(Sdb* s, const char *k, const char *p, int v, ut32 cas);
267 SDB_API int sdb_json_num_dec(Sdb* s, const char *k, const char *p, int n, ut32 cas);
268 SDB_API int sdb_json_num_inc(Sdb* s, const char *k, const char *p, int n, ut32 cas);
269 
270 SDB_API char *sdb_json_indent(const char *s, const char *tab);
271 SDB_API char *sdb_json_unindent(const char *s);
272 
273 typedef struct {
274 	char *buf;
275 	size_t blen;
276 	size_t len;
277 } SdbJsonString;
278 
279 SDB_API const char *sdb_json_format(SdbJsonString* s, const char *fmt, ...);
280 #define sdb_json_format_free(x) free ((x)->buf)
281 
282 // namespace
283 SDB_API Sdb* sdb_ns(Sdb *s, const char *name, int create);
284 SDB_API Sdb *sdb_ns_path(Sdb *s, const char *path, int create);
285 SDB_API void sdb_ns_init(Sdb* s);
286 SDB_API void sdb_ns_free(Sdb* s);
287 SDB_API void sdb_ns_lock(Sdb *s, int lock, int depth);
288 SDB_API void sdb_ns_sync(Sdb* s);
289 SDB_API int sdb_ns_set(Sdb *s, const char *name, Sdb *r);
290 SDB_API bool sdb_ns_unset(Sdb *s, const char *name, Sdb *r);
291 
292 // array
293 SDB_API bool sdb_array_contains(Sdb* s, const char *key, const char *val, ut32 *cas);
294 SDB_API bool sdb_array_contains_num(Sdb *s, const char *key, ut64 val, ut32 *cas);
295 SDB_API int sdb_array_indexof(Sdb *s, const char *key, const char *val, ut32 cas);
296 SDB_API int sdb_array_set(Sdb* s, const char *key, int idx, const char *val, ut32 cas);
297 SDB_API int sdb_array_set_num(Sdb* s, const char *key, int idx, ut64 val, ut32 cas);
298 SDB_API bool sdb_array_append(Sdb *s, const char *key, const char *val, ut32 cas);
299 SDB_API bool sdb_array_append_num(Sdb *s, const char *key, ut64 val, ut32 cas);
300 SDB_API bool sdb_array_prepend(Sdb *s, const char *key, const char *val, ut32 cas);
301 SDB_API bool sdb_array_prepend_num(Sdb *s, const char *key, ut64 val, ut32 cas);
302 SDB_API char *sdb_array_get(Sdb* s, const char *key, int idx, ut32 *cas);
303 SDB_API ut64 sdb_array_get_num(Sdb* s, const char *key, int idx, ut32 *cas);
304 SDB_API int sdb_array_get_idx(Sdb *s, const char *key, const char *val, ut32 cas); // agetv
305 SDB_API int sdb_array_insert(Sdb* s, const char *key, int idx, const char *val, ut32 cas);
306 SDB_API int sdb_array_insert_num(Sdb* s, const char *key, int idx, ut64 val, ut32 cas);
307 SDB_API int sdb_array_unset(Sdb* s, const char *key, int n, ut32 cas); // leaves empty bucket
308 SDB_API int sdb_array_delete(Sdb* s, const char *key, int n, ut32 cas);
309 SDB_API void sdb_array_sort(Sdb* s, const char *key, ut32 cas);
310 SDB_API void sdb_array_sort_num(Sdb* s, const char *key, ut32 cas);
311 // set
312 
313 // Adds string `val` at the end of array `key`.
314 SDB_API int sdb_array_add(Sdb* s, const char *key, const char *val, ut32 cas);
315 
316 // Adds number `val` at the end of array `key`.
317 SDB_API int sdb_array_add_num(Sdb* s, const char *key, ut64 val, ut32 cas);
318 
319 // Adds string `val` in the sorted array `key`.
320 SDB_API int sdb_array_add_sorted(Sdb *s, const char *key, const char *val, ut32 cas);
321 
322 // Adds number `val` in the sorted array `key`.
323 SDB_API int sdb_array_add_sorted_num(Sdb *s, const char *key, ut64 val, ut32 cas);
324 
325 // Removes the string `val` from the array `key`.
326 SDB_API int sdb_array_remove(Sdb *s, const char *key, const char *val, ut32 cas);
327 
328 // Removes the number `val` from the array `key`.
329 SDB_API int sdb_array_remove_num(Sdb* s, const char *key, ut64 val, ut32 cas);
330 
331 // helpers
332 SDB_API char *sdb_anext(char *str, char **next);
333 SDB_API const char *sdb_const_anext(const char *str);
334 SDB_API int sdb_alen(const char *str);
335 SDB_API int sdb_alen_ignore_empty(const char *str);
336 SDB_API int sdb_array_size(Sdb* s, const char *key);
337 SDB_API int sdb_array_length(Sdb* s, const char *key);
338 
339 int sdb_array_list(Sdb* s, const char *key);
340 
341 // Adds the string `val` to the start of array `key`.
342 SDB_API bool sdb_array_push(Sdb *s, const char *key, const char *val, ut32 cas);
343 
344 // Returns the string at the start of array `key` or
345 // NULL if there are no elements.
346 SDB_API char *sdb_array_pop(Sdb *s, const char *key, ut32 *cas);
347 
348 // Adds the number `val` to the start of array `key`.
349 SDB_API int sdb_array_push_num(Sdb *s, const char *key, ut64 num, ut32 cas);
350 
351 // Returns the number at the start of array `key`.
352 SDB_API ut64 sdb_array_pop_num(Sdb *s, const char *key, ut32 *cas);
353 
354 SDB_API char *sdb_array_pop_head(Sdb *s, const char *key, ut32 *cas);
355 SDB_API char *sdb_array_pop_tail(Sdb *s, const char *key, ut32 *cas);
356 
357 typedef void (*SdbHook)(Sdb *s, void *user, const char *k, const char *v);
358 
359 SDB_API void sdb_global_hook(SdbHook hook, void *user);
360 SDB_API bool sdb_hook(Sdb* s, SdbHook cb, void* user);
361 SDB_API bool sdb_unhook(Sdb* s, SdbHook h);
362 SDB_API int sdb_hook_call(Sdb *s, const char *k, const char *v);
363 SDB_API void sdb_hook_free(Sdb *s);
364 /* Util.c */
365 SDB_API int sdb_isnum(const char *s);
366 SDB_API bool sdb_isempty(Sdb *s);
367 
368 SDB_API const char *sdb_type(const char *k);
369 SDB_API bool sdb_match(const char *str, const char *glob);
370 SDB_API int sdb_bool_set(Sdb *db, const char *str, bool v, ut32 cas);
371 SDB_API bool sdb_bool_get(Sdb *db, const char *str, ut32 *cas);
372 
373 // base64
374 SDB_API ut8 *sdb_decode(const char *in, int *len);
375 SDB_API char *sdb_encode(const ut8 *bin, int len);
376 SDB_API void sdb_encode_raw(char *bout, const ut8 *bin, int len);
377 SDB_API int sdb_decode_raw(ut8 *bout, const char *bin, int len);
378 
379 // binfmt
380 SDB_API char *sdb_fmt(const char *fmt, ...) SDB_PRINTF_CHECK(1, 2);
381 SDB_API int sdb_fmt_init(void *p, const char *fmt);
382 SDB_API void sdb_fmt_free(void *p, const char *fmt);
383 SDB_API int sdb_fmt_tobin(const char *_str, const char *fmt, void *stru);
384 SDB_API char *sdb_fmt_tostr(void *stru, const char *fmt);
385 SDB_API char** sdb_fmt_array(const char *list);
386 SDB_API ut64* sdb_fmt_array_num(const char *list);
387 
388 // raw array helpers
389 SDB_API char *sdb_array_compact(char *p);
390 SDB_API char *sdb_aslice(char *out, int from, int to);
391 #define sdb_aforeach(x,y) \
392 	{ char *next; \
393 	if (y) for (x=y;;) { \
394 		x = sdb_anext (x, &next);
395 #define sdb_aforeach_next(x) \
396 	if (!next) break; \
397 	*(next-1) = ','; \
398 	x = next; } }
399 
400 #ifdef __cplusplus
401 }
402 #endif
403 
404 #endif
405