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