github.com/moontrade/nogc@v0.1.7/collections/wormhole/kv.c (about) 1 /* 2 * Copyright (c) 2016--2021 Wu, Xingbo <wuxb45@gmail.com> 3 * 4 * All rights reserved. No warranty, explicit or implicit, provided. 5 */ 6 #define _GNU_SOURCE 7 8 // headers {{{ 9 #include <assert.h> // static_assert 10 #include <ctype.h> 11 #include "lib.h" 12 #include "ctypes.h" 13 #include "kv.h" 14 // }}} headers 15 16 // crc32c {{{ 17 inline u32 18 kv_crc32c(const void * const ptr, u32 len) 19 { 20 return crc32c_inc((const u8 *)ptr, len, KV_CRC32C_SEED); 21 } 22 23 inline u64 24 kv_crc32c_extend(const u32 lo) 25 { 26 const u64 hi = (u64)(~lo); 27 return (hi << 32) | ((u64)lo); 28 } 29 // }}} crc32c 30 31 // kv {{{ 32 33 // size {{{ 34 inline size_t 35 kv_size(const struct kv * const kv) 36 { 37 return sizeof(*kv) + kv->klen + kv->vlen; 38 } 39 40 inline size_t 41 kv_size_align(const struct kv * const kv, const u64 align) 42 { 43 debug_assert(align && ((align & (align - 1)) == 0)); 44 return (sizeof(*kv) + kv->klen + kv->vlen + (align - 1)) & (~(align - 1)); 45 } 46 47 inline size_t 48 key_size(const struct kv *const key) 49 { 50 return sizeof(*key) + key->klen; 51 } 52 53 inline size_t 54 key_size_align(const struct kv *const key, const u64 align) 55 { 56 debug_assert(align && ((align & (align - 1)) == 0)); 57 return (sizeof(*key) + key->klen + (align - 1)) & (~(align - 1)); 58 } 59 // }}} size 60 61 // construct {{{ 62 inline void 63 kv_update_hash(struct kv * const kv) 64 { 65 const u32 lo = kv_crc32c((const void *)kv->kv, kv->klen); 66 kv->hash = kv_crc32c_extend(lo); 67 } 68 69 inline void 70 kv_refill_value(struct kv * const kv, const void * const value, const u32 vlen) 71 { 72 debug_assert((vlen == 0) || value); 73 memcpy(&(kv->kv[kv->klen]), value, vlen); 74 kv->vlen = vlen; 75 } 76 77 inline void 78 kv_refill(struct kv * const kv, const void * const key, const u32 klen, 79 const void * const value, const u32 vlen) 80 { 81 debug_assert(kv); 82 kv->klen = klen; 83 memcpy(&(kv->kv[0]), key, klen); 84 kv_refill_value(kv, value, vlen); 85 kv_update_hash(kv); 86 } 87 88 inline void 89 kv_refill_str(struct kv * const kv, const char * const key, 90 const void * const value, const u32 vlen) 91 { 92 kv_refill(kv, key, (u32)strlen(key), value, vlen); 93 } 94 95 inline void 96 kv_refill_str_str(struct kv * const kv, const char * const key, 97 const char * const value) 98 { 99 kv_refill(kv, key, (u32)strlen(key), value, (u32)strlen(value)); 100 } 101 102 // the u64 key is filled in big-endian byte order for correct ordering 103 inline void 104 kv_refill_u64(struct kv * const kv, const u64 key, const void * const value, const u32 vlen) 105 { 106 kv->klen = sizeof(u64); 107 *(u64 *)(kv->kv) = __builtin_bswap64(key); // bswap on little endian 108 kv_refill_value(kv, value, vlen); 109 kv_update_hash(kv); 110 } 111 112 inline void 113 kv_refill_hex32(struct kv * const kv, const u32 hex, const void * const value, const u32 vlen) 114 { 115 kv->klen = 8; 116 strhex_32(kv->kv, hex); 117 kv_refill_value(kv, value, vlen); 118 kv_update_hash(kv); 119 } 120 121 inline void 122 kv_refill_hex64(struct kv * const kv, const u64 hex, const void * const value, const u32 vlen) 123 { 124 kv->klen = 16; 125 strhex_64(kv->kv, hex); 126 kv_refill_value(kv, value, vlen); 127 kv_update_hash(kv); 128 } 129 130 inline void 131 kv_refill_hex64_klen(struct kv * const kv, const u64 hex, 132 const u32 klen, const void * const value, const u32 vlen) 133 { 134 strhex_64(kv->kv, hex); 135 if (klen > 16) { 136 kv->klen = klen; 137 memset(kv->kv + 16, '!', klen - 16); 138 } else { 139 kv->klen = 16; 140 } 141 kv_refill_value(kv, value, vlen); 142 kv_update_hash(kv); 143 } 144 145 inline void 146 kv_refill_kref(struct kv * const kv, const struct kref * const kref) 147 { 148 kv->klen = kref->len; 149 kv->vlen = 0; 150 kv->hash = kv_crc32c_extend(kref->hash32); 151 memmove(kv->kv, kref->ptr, kref->len); 152 } 153 154 inline void 155 kv_refill_kref_v(struct kv * const kv, const struct kref * const kref, 156 const void * const value, const u32 vlen) 157 { 158 kv->klen = kref->len; 159 kv->vlen = vlen; 160 kv->hash = kv_crc32c_extend(kref->hash32); 161 memmove(kv->kv, kref->ptr, kref->len); 162 memcpy(kv->kv + kv->klen, value, vlen); 163 } 164 165 inline struct kref 166 kv_kref(const struct kv * const key) 167 { 168 return (struct kref){.ptr = key->kv, .len = key->klen, .hash32 = key->hashlo}; 169 } 170 171 inline struct kv * 172 kv_create(const void * const key, const u32 klen, const void * const value, const u32 vlen) 173 { 174 struct kv * const kv = malloc(sizeof(*kv) + klen + vlen); 175 if (kv) 176 kv_refill(kv, key, klen, value, vlen); 177 return kv; 178 } 179 180 inline struct kv * 181 kv_create_str(const char * const key, const void * const value, const u32 vlen) 182 { 183 return kv_create(key, (u32)strlen(key), value, vlen); 184 } 185 186 inline struct kv * 187 kv_create_str_str(const char * const key, const char * const value) 188 { 189 return kv_create(key, (u32)strlen(key), value, (u32)strlen(value)); 190 } 191 192 inline struct kv * 193 kv_create_kref(const struct kref * const kref, const void * const value, const u32 vlen) 194 { 195 return kv_create(kref->ptr, kref->len, value, vlen); 196 } 197 198 static struct kv __kv_null = {}; 199 200 __attribute__((constructor)) 201 static void 202 kv_null_init(void) 203 { 204 kv_update_hash(&__kv_null); 205 } 206 207 inline const struct kv * 208 kv_null(void) 209 { 210 return &__kv_null; 211 } 212 // }}} construct 213 214 // dup {{{ 215 inline struct kv * 216 kv_dup(const struct kv * const kv) 217 { 218 if (kv == NULL) 219 return NULL; 220 221 const size_t sz = kv_size(kv); 222 struct kv * const new = malloc(sz); 223 if (new) 224 memcpy(new, kv, sz); 225 return new; 226 } 227 228 inline struct kv * 229 kv_dup_key(const struct kv * const kv) 230 { 231 if (kv == NULL) 232 return NULL; 233 234 const size_t sz = key_size(kv); 235 struct kv * const new = malloc(sz); 236 if (new) { 237 memcpy(new, kv, sz); 238 new->vlen = 0; 239 } 240 return new; 241 } 242 243 inline struct kv * 244 kv_dup2(const struct kv * const from, struct kv * const to) 245 { 246 if (from == NULL) 247 return NULL; 248 const size_t sz = kv_size(from); 249 struct kv * const new = to ? to : malloc(sz); 250 if (new) 251 memcpy(new, from, sz); 252 return new; 253 } 254 255 inline struct kv * 256 kv_dup2_key(const struct kv * const from, struct kv * const to) 257 { 258 if (from == NULL) 259 return NULL; 260 const size_t sz = key_size(from); 261 struct kv * const new = to ? to : malloc(sz); 262 if (new) { 263 memcpy(new, from, sz); 264 new->vlen = 0; 265 } 266 return new; 267 } 268 269 inline struct kv * 270 kv_dup2_key_prefix(const struct kv * const from, struct kv * const to, const u32 plen) 271 { 272 if (from == NULL) 273 return NULL; 274 debug_assert(plen <= from->klen); 275 const size_t sz = key_size(from) - from->klen + plen; 276 struct kv * const new = to ? to : malloc(sz); 277 if (new) { 278 new->klen = plen; 279 memcpy(new->kv, from->kv, plen); 280 new->vlen = 0; 281 kv_update_hash(new); 282 } 283 return new; 284 } 285 // }}} dup 286 287 // compare {{{ 288 static inline int 289 klen_compare(const u32 len1, const u32 len2) 290 { 291 if (len1 < len2) 292 return -1; 293 else if (len1 > len2) 294 return 1; 295 else 296 return 0; 297 } 298 299 // compare whether the two keys are identical 300 // optimistic: do not check hash 301 inline bool 302 kv_match(const struct kv * const key1, const struct kv * const key2) 303 { 304 //cpu_prefetch0(((u8 *)key2) + 64); 305 //return (key1->hash == key2->hash) 306 // && (key1->klen == key2->klen) 307 // && (!memcmp(key1->kv, key2->kv, key1->klen)); 308 return (key1->klen == key2->klen) && (!memcmp(key1->kv, key2->kv, key1->klen)); 309 } 310 311 // compare whether the two keys are identical 312 // check hash first 313 // pessimistic: return false quickly if their hashes mismatch 314 inline bool 315 kv_match_hash(const struct kv * const key1, const struct kv * const key2) 316 { 317 return (key1->hash == key2->hash) 318 && (key1->klen == key2->klen) 319 && (!memcmp(key1->kv, key2->kv, key1->klen)); 320 } 321 322 inline bool 323 kv_match_full(const struct kv * const kv1, const struct kv * const kv2) 324 { 325 return (kv1->kvlen == kv2->kvlen) 326 && (!memcmp(kv1, kv2, sizeof(*kv1) + kv1->klen + kv1->vlen)); 327 } 328 329 bool 330 kv_match_kv128(const struct kv * const sk, const u8 * const kv128) 331 { 332 debug_assert(sk); 333 debug_assert(kv128); 334 335 u32 klen128 = 0; 336 u32 vlen128 = 0; 337 const u8 * const pdata = vi128_decode_u32(vi128_decode_u32(kv128, &klen128), &vlen128); 338 (void)vlen128; 339 return (sk->klen == klen128) && (!memcmp(sk->kv, pdata, klen128)); 340 } 341 342 inline int 343 kv_compare(const struct kv * const kv1, const struct kv * const kv2) 344 { 345 const u32 len = kv1->klen < kv2->klen ? kv1->klen : kv2->klen; 346 const int cmp = memcmp(kv1->kv, kv2->kv, (size_t)len); 347 return cmp ? cmp : klen_compare(kv1->klen, kv2->klen); 348 } 349 350 // for qsort and bsearch 351 static int 352 kv_compare_ptrs(const void * const p1, const void * const p2) 353 { 354 const struct kv * const * const pp1 = (typeof(pp1))p1; 355 const struct kv * const * const pp2 = (typeof(pp2))p2; 356 return kv_compare(*pp1, *pp2); 357 } 358 359 int 360 kv_k128_compare(const struct kv * const sk, const u8 * const k128) 361 { 362 debug_assert(sk); 363 const u32 klen1 = sk->klen; 364 u32 klen2 = 0; 365 const u8 * const ptr2 = vi128_decode_u32(k128, &klen2); 366 debug_assert(ptr2); 367 const u32 len = (klen1 < klen2) ? klen1 : klen2; 368 const int cmp = memcmp(sk->kv, ptr2, len); 369 return cmp ? cmp : klen_compare(klen1, klen2); 370 } 371 372 int 373 kv_kv128_compare(const struct kv * const sk, const u8 * const kv128) 374 { 375 debug_assert(sk); 376 const u32 klen1 = sk->klen; 377 u32 klen2 = 0; 378 u32 vlen2 = 0; 379 const u8 * const ptr2 = vi128_decode_u32(vi128_decode_u32(kv128, &klen2), &vlen2); 380 const u32 len = (klen1 < klen2) ? klen1 : klen2; 381 const int cmp = memcmp(sk->kv, ptr2, len); 382 return cmp ? cmp : klen_compare(klen1, klen2); 383 } 384 385 inline void 386 kv_qsort(struct kv ** const kvs, const size_t nr) 387 { 388 qsort(kvs, nr, sizeof(kvs[0]), kv_compare_ptrs); 389 } 390 391 // return the length of longest common prefix of the two keys 392 inline u32 393 kv_key_lcp(const struct kv * const key1, const struct kv * const key2) 394 { 395 const u32 max = (key1->klen < key2->klen) ? key1->klen : key2->klen; 396 return memlcp(key1->kv, key2->kv, max); 397 } 398 399 // return the length of longest common prefix of the two keys with a known lcp0 400 inline u32 401 kv_key_lcp_skip(const struct kv * const key1, const struct kv * const key2, const u32 lcp0) 402 { 403 const u32 max = (key1->klen < key2->klen) ? key1->klen : key2->klen; 404 debug_assert(max >= lcp0); 405 return lcp0 + memlcp(key1->kv+lcp0, key2->kv+lcp0, max-lcp0); 406 } 407 // }}} 408 409 // psort {{{ 410 static inline void 411 kv_psort_exchange(struct kv ** const kvs, const u64 i, const u64 j) 412 { 413 if (i != j) { 414 struct kv * const tmp = kvs[i]; 415 kvs[i] = kvs[j]; 416 kvs[j] = tmp; 417 } 418 } 419 420 static u64 421 kv_psort_partition(struct kv ** const kvs, const u64 lo, const u64 hi) 422 { 423 if (lo >= hi) 424 return lo; 425 426 const u64 p = (lo+hi) >> 1; 427 kv_psort_exchange(kvs, lo, p); 428 u64 i = lo; 429 u64 j = hi + 1; 430 do { 431 while (kv_compare(kvs[++i], kvs[lo]) < 0 && i < hi); 432 while (kv_compare(kvs[--j], kvs[lo]) > 0); 433 if (i >= j) 434 break; 435 kv_psort_exchange(kvs, i, j); 436 } while (true); 437 kv_psort_exchange(kvs, lo, j); 438 return j; 439 } 440 441 static void 442 kv_psort_rec(struct kv ** const kvs, const u64 lo, const u64 hi, const u64 tlo, const u64 thi) 443 { 444 if (lo >= hi) 445 return; 446 const u64 c = kv_psort_partition(kvs, lo, hi); 447 448 if (c > tlo) // go left 449 kv_psort_rec(kvs, lo, c-1, tlo, thi); 450 451 if (c < thi) // go right 452 kv_psort_rec(kvs, c+1, hi, tlo, thi); 453 } 454 455 inline void 456 kv_psort(struct kv ** const kvs, const u64 nr, const u64 tlo, const u64 thi) 457 { 458 debug_assert(tlo <= thi); 459 debug_assert(thi < nr); 460 kv_psort_rec(kvs, 0, nr-1, tlo, thi); 461 } 462 // }}} psort 463 464 // ptr {{{ 465 inline void * 466 kv_vptr(struct kv * const kv) 467 { 468 return (void *)(&(kv->kv[kv->klen])); 469 } 470 471 inline void * 472 kv_kptr(struct kv * const kv) 473 { 474 return (void *)(&(kv->kv[0])); 475 } 476 477 inline const void * 478 kv_vptr_c(const struct kv * const kv) 479 { 480 return (const void *)(&(kv->kv[kv->klen])); 481 } 482 483 inline const void * 484 kv_kptr_c(const struct kv * const kv) 485 { 486 return (const void *)(&(kv->kv[0])); 487 } 488 // }}} ptr 489 490 // print {{{ 491 // cmd "KV" K and V can be 's': string, 'x': hex, 'd': dec, or else for not printing. 492 // n for newline after kv 493 void 494 kv_print(const struct kv * const kv, const char * const cmd, FILE * const out) 495 { 496 debug_assert(cmd); 497 const u32 klen = kv->klen; 498 fprintf(out, "#%016lx k[%3u]", kv->hash, klen); 499 500 switch(cmd[0]) { 501 case 's': fprintf(out, " %.*s", klen, kv->kv); break; 502 case 'x': str_print_hex(out, kv->kv, klen); break; 503 case 'd': str_print_dec(out, kv->kv, klen); break; 504 default: break; 505 } 506 507 const u32 vlen = kv->vlen; 508 switch (cmd[1]) { 509 case 's': fprintf(out, " v[%4u] %.*s", vlen, vlen, kv->kv+klen); break; 510 case 'x': fprintf(out, " v[%4u]", vlen); str_print_hex(out, kv->kv+klen, vlen); break; 511 case 'd': fprintf(out, " v[%4u]", vlen); str_print_dec(out, kv->kv+klen, vlen); break; 512 default: break; 513 } 514 if (strchr(cmd, 'n')) 515 fprintf(out, "\n"); 516 } 517 // }}} print 518 519 // mm {{{ 520 struct kv * 521 kvmap_mm_in_noop(struct kv * const kv, void * const priv) 522 { 523 (void)priv; 524 return kv; 525 } 526 527 // copy-out 528 struct kv * 529 kvmap_mm_out_noop(struct kv * const kv, struct kv * const out) 530 { 531 (void)out; 532 return kv; 533 } 534 535 void 536 kvmap_mm_free_noop(struct kv * const kv, void * const priv) 537 { 538 (void)kv; 539 (void)priv; 540 } 541 542 // copy-in 543 struct kv * 544 kvmap_mm_in_dup(struct kv * const kv, void * const priv) 545 { 546 (void)priv; 547 return kv_dup(kv); 548 } 549 550 // copy-out 551 struct kv * 552 kvmap_mm_out_dup(struct kv * const kv, struct kv * const out) 553 { 554 return kv_dup2(kv, out); 555 } 556 557 void 558 kvmap_mm_free_free(struct kv * const kv, void * const priv) 559 { 560 (void)priv; 561 free(kv); 562 } 563 564 const struct kvmap_mm kvmap_mm_dup = { 565 .in = kvmap_mm_in_dup, 566 .out = kvmap_mm_out_dup, 567 .free = kvmap_mm_free_free, 568 .priv = NULL, 569 }; 570 571 const struct kvmap_mm kvmap_mm_ndf = { 572 .in = kvmap_mm_in_noop, 573 .out = kvmap_mm_out_dup, 574 .free = kvmap_mm_free_free, 575 .priv = NULL, 576 }; 577 578 // }}} mm 579 580 // kref {{{ 581 inline void 582 kref_ref_raw(struct kref * const kref, const u8 * const ptr, const u32 len) 583 { 584 kref->ptr = ptr; 585 kref->len = len; 586 kref->hash32 = 0; 587 } 588 589 inline void 590 kref_ref_hash32(struct kref * const kref, const u8 * const ptr, const u32 len) 591 { 592 kref->ptr = ptr; 593 kref->len = len; 594 kref->hash32 = kv_crc32c(ptr, len); 595 } 596 597 inline void 598 kref_update_hash32(struct kref * const kref) 599 { 600 kref->hash32 = kv_crc32c(kref->ptr, kref->len); 601 } 602 603 inline void 604 kref_ref_kv(struct kref * const kref, const struct kv * const kv) 605 { 606 kref->ptr = kv->kv; 607 kref->len = kv->klen; 608 kref->hash32 = kv->hashlo; 609 } 610 611 inline void 612 kref_ref_kv_hash32(struct kref * const kref, const struct kv * const kv) 613 { 614 kref->ptr = kv->kv; 615 kref->len = kv->klen; 616 kref->hash32 = kv_crc32c(kv->kv, kv->klen); 617 } 618 619 inline bool 620 kref_match(const struct kref * const k1, const struct kref * const k2) 621 { 622 return (k1->len == k2->len) && (!memcmp(k1->ptr, k2->ptr, k1->len)); 623 } 624 625 // match a kref and a key 626 inline bool 627 kref_kv_match(const struct kref * const kref, const struct kv * const k) 628 { 629 return (kref->len == k->klen) && (!memcmp(kref->ptr, k->kv, kref->len)); 630 } 631 632 inline int 633 kref_compare(const struct kref * const kref1, const struct kref * const kref2) 634 { 635 const u32 len = kref1->len < kref2->len ? kref1->len : kref2->len; 636 const int cmp = memcmp(kref1->ptr, kref2->ptr, (size_t)len); 637 return cmp ? cmp : klen_compare(kref1->len, kref2->len); 638 } 639 640 // compare a kref and a key 641 inline int 642 kref_kv_compare(const struct kref * const kref, const struct kv * const k) 643 { 644 debug_assert(kref); 645 debug_assert(k); 646 const u32 len = kref->len < k->klen ? kref->len : k->klen; 647 const int cmp = memcmp(kref->ptr, k->kv, (size_t)len); 648 return cmp ? cmp : klen_compare(kref->len, k->klen); 649 } 650 651 inline u32 652 kref_lcp(const struct kref * const k1, const struct kref * const k2) 653 { 654 const u32 max = (k1->len < k2->len) ? k1->len : k2->len; 655 return memlcp(k1->ptr, k2->ptr, max); 656 } 657 658 inline u32 659 kref_kv_lcp(const struct kref * const kref, const struct kv * const kv) 660 { 661 const u32 max = (kref->len < kv->klen) ? kref->len : kv->klen; 662 return memlcp(kref->ptr, kv->kv, max); 663 } 664 665 // klen, key, ... 666 inline int 667 kref_k128_compare(const struct kref * const sk, const u8 * const k128) 668 { 669 debug_assert(sk); 670 const u32 klen1 = sk->len; 671 u32 klen2 = 0; 672 const u8 * const ptr2 = vi128_decode_u32(k128, &klen2); 673 debug_assert(ptr2); 674 const u32 len = (klen1 < klen2) ? klen1 : klen2; 675 const int cmp = memcmp(sk->ptr, ptr2, len); 676 return cmp ? cmp : klen_compare(klen1, klen2); 677 } 678 679 // klen, vlen, key, ... 680 inline int 681 kref_kv128_compare(const struct kref * const sk, const u8 * const kv128) 682 { 683 debug_assert(sk); 684 const u32 klen1 = sk->len; 685 u32 klen2 = 0; 686 u32 vlen2 = 0; 687 const u8 * const ptr2 = vi128_decode_u32(vi128_decode_u32(kv128, &klen2), &vlen2); 688 const u32 len = (klen1 < klen2) ? klen1 : klen2; 689 const int cmp = memcmp(sk->ptr, ptr2, len); 690 return cmp ? cmp : klen_compare(klen1, klen2); 691 } 692 693 static struct kref __kref_null = {.hash32 = KV_CRC32C_SEED}; 694 695 inline const struct kref * 696 kref_null(void) 697 { 698 return &__kref_null; 699 } 700 // }}} kref 701 702 // kvref {{{ 703 inline void 704 kvref_ref_kv(struct kvref * const ref, struct kv * const kv) 705 { 706 ref->kptr = kv->kv; 707 ref->vptr = kv->kv + kv->klen; 708 ref->hdr = *kv; 709 } 710 711 struct kv * 712 kvref_dup2_kv(struct kvref * const ref, struct kv * const to) 713 { 714 if (ref == NULL) 715 return NULL; 716 const size_t sz = sizeof(*to) + ref->hdr.klen + ref->hdr.vlen; 717 struct kv * const new = to ? to : malloc(sz); 718 if (new == NULL) 719 return NULL; 720 721 *new = ref->hdr; 722 memcpy(new->kv, ref->kptr, new->klen); 723 memcpy(new->kv + new->klen, ref->vptr, new->vlen); 724 return new; 725 } 726 727 struct kv * 728 kvref_dup2_key(struct kvref * const ref, struct kv * const to) 729 { 730 if (ref == NULL) 731 return NULL; 732 const size_t sz = sizeof(*to) + ref->hdr.klen; 733 struct kv * const new = to ? to : malloc(sz); 734 if (new == NULL) 735 return NULL; 736 737 *new = ref->hdr; 738 memcpy(new->kv, ref->kptr, new->klen); 739 return new; 740 } 741 742 int 743 kvref_kv_compare(const struct kvref * const ref, const struct kv * const kv) 744 { 745 const u32 len = ref->hdr.klen < kv->klen ? ref->hdr.klen : kv->klen; 746 const int cmp = memcmp(ref->kptr, kv->kv, (size_t)len); 747 return cmp ? cmp : klen_compare(ref->hdr.klen, kv->klen); 748 } 749 // }}} kvref 750 751 // kv128 {{{ 752 // estimate the encoded size 753 inline size_t 754 kv128_estimate_kv(const struct kv * const kv) 755 { 756 return vi128_estimate_u32(kv->klen) + vi128_estimate_u32(kv->vlen) + kv->klen + kv->vlen; 757 } 758 759 // create a kv128 from kv 760 u8 * 761 kv128_encode_kv(const struct kv * const kv, u8 * const out, size_t * const pesize) 762 { 763 u8 * const ptr = out ? out : malloc(kv128_estimate_kv(kv)); 764 if (!ptr) 765 return NULL; 766 767 u8 * const pdata = vi128_encode_u32(vi128_encode_u32(ptr, kv->klen), kv->vlen); 768 memcpy(pdata, kv->kv, kv->klen + kv->vlen); 769 770 if (pesize) 771 *pesize = (size_t)(pdata - ptr) + kv->klen + kv->vlen; 772 return ptr; // return the head of the encoded kv128 773 } 774 775 // dup kv128 to a kv 776 struct kv * 777 kv128_decode_kv(const u8 * const ptr, struct kv * const out, size_t * const pesize) 778 { 779 u32 klen, vlen; 780 const u8 * const pdata = vi128_decode_u32(vi128_decode_u32(ptr, &klen), &vlen); 781 struct kv * const ret = out ? out : malloc(sizeof(struct kv) + klen + vlen); 782 if (ret) 783 kv_refill(ret, pdata, klen, pdata + klen, vlen); 784 785 if (pesize) 786 *pesize = (size_t)(pdata - ptr) + klen + vlen; 787 return ret; // return the kv 788 } 789 790 inline size_t 791 kv128_size(const u8 * const ptr) 792 { 793 u32 klen, vlen; 794 const u8 * const pdata = vi128_decode_u32(vi128_decode_u32(ptr, &klen), &vlen); 795 return ((size_t)(pdata - ptr)) + klen + vlen; 796 } 797 // }}} kv128 798 799 // }}} kv 800 801 // kvmap {{{ 802 803 // registry {{{ 804 // increase MAX if need more 805 #define KVMAP_API_MAX ((32)) 806 static struct kvmap_api_reg kvmap_api_regs[KVMAP_API_MAX]; 807 static u64 kvmap_api_regs_nr = 0; 808 809 void 810 kvmap_api_register(const int nargs, const char * const name, const char * const args_msg, 811 void * (*create)(const char *, const struct kvmap_mm *, char **), const struct kvmap_api * const api) 812 { 813 if (kvmap_api_regs_nr < KVMAP_API_MAX) { 814 kvmap_api_regs[kvmap_api_regs_nr].nargs = nargs; 815 kvmap_api_regs[kvmap_api_regs_nr].name = name; 816 kvmap_api_regs[kvmap_api_regs_nr].args_msg = args_msg; 817 kvmap_api_regs[kvmap_api_regs_nr].create = create; 818 kvmap_api_regs[kvmap_api_regs_nr].api = api; 819 kvmap_api_regs_nr++; 820 } else { 821 fprintf(stderr, "%s failed to register [%s]\n", __func__, name); 822 } 823 } 824 void 825 kvmap_api_helper_message(void) 826 { 827 fprintf(stderr, "%s Usage: api <map-type> <param1> ...\n", __func__); 828 for (u64 i = 0; i < kvmap_api_regs_nr; i++) { 829 fprintf(stderr, "%s example: api %s %s\n", __func__, 830 kvmap_api_regs[i].name, kvmap_api_regs[i].args_msg); 831 } 832 } 833 834 int 835 kvmap_api_helper(int argc, char ** const argv, const struct kvmap_mm * const mm, 836 const struct kvmap_api ** const api_out, void ** const map_out) 837 { 838 // "api" "name" "arg1", ... 839 if (argc < 2 || strcmp(argv[0], "api") != 0) 840 return -1; 841 842 for (u64 i = 0; i < kvmap_api_regs_nr; i++) { 843 const struct kvmap_api_reg * const reg = &kvmap_api_regs[i]; 844 if (0 != strcmp(argv[1], reg->name)) 845 continue; 846 847 if ((argc - 2) < reg->nargs) 848 return -1; 849 850 void * const map = reg->create(argv[1], mm, argv + 2); // skip "api" "name" 851 if (map) { 852 *api_out = reg->api; 853 *map_out = map; 854 return 2 + reg->nargs; 855 } else { 856 return -1; 857 } 858 } 859 860 // no match 861 return -1; 862 } 863 // }}} registry 864 865 // misc {{{ 866 void 867 kvmap_inp_steal_kv(struct kv * const kv, void * const priv) 868 { 869 // steal the kv pointer out so we don't need a dangerous get_key_interanl() 870 if (priv) 871 *(struct kv **)priv = kv; 872 } 873 874 inline void * 875 kvmap_ref(const struct kvmap_api * const api, void * const map) 876 { 877 return api->ref ? api->ref(map) : map; 878 } 879 880 // return the original map pointer; usually unused by caller 881 inline void * 882 kvmap_unref(const struct kvmap_api * const api, void * const ref) 883 { 884 return api->unref ? api->unref(ref) : ref; 885 } 886 // }}} misc 887 888 // kvmap_kv_op {{{ 889 inline struct kv * 890 kvmap_kv_get(const struct kvmap_api * const api, void * const ref, 891 const struct kv * const key, struct kv * const out) 892 { 893 const struct kref kref = kv_kref(key); 894 return api->get(ref, &kref, out); 895 } 896 897 inline bool 898 kvmap_kv_probe(const struct kvmap_api * const api, void * const ref, 899 const struct kv * const key) 900 { 901 const struct kref kref = kv_kref(key); 902 return api->probe(ref, &kref); 903 } 904 905 inline bool 906 kvmap_kv_put(const struct kvmap_api * const api, void * const ref, 907 struct kv * const kv) 908 { 909 return api->put(ref, kv); 910 } 911 912 inline bool 913 kvmap_kv_del(const struct kvmap_api * const api, void * const ref, 914 const struct kv * const key) 915 { 916 const struct kref kref = kv_kref(key); 917 return api->del(ref, &kref); 918 } 919 920 inline bool 921 kvmap_kv_inpr(const struct kvmap_api * const api, void * const ref, 922 const struct kv * const key, kv_inp_func uf, void * const priv) 923 { 924 const struct kref kref = kv_kref(key); 925 return api->inpr(ref, &kref, uf, priv); 926 } 927 928 inline bool 929 kvmap_kv_inpw(const struct kvmap_api * const api, void * const ref, 930 const struct kv * const key, kv_inp_func uf, void * const priv) 931 { 932 const struct kref kref = kv_kref(key); 933 return api->inpw(ref, &kref, uf, priv); 934 } 935 936 inline bool 937 kvmap_kv_merge(const struct kvmap_api * const api, void * const ref, 938 const struct kv * const key, kv_merge_func uf, void * const priv) 939 { 940 const struct kref kref = kv_kref(key); 941 return api->merge(ref, &kref, uf, priv); 942 } 943 944 inline u64 945 kvmap_kv_delr(const struct kvmap_api * const api, void * const ref, 946 const struct kv * const start, const struct kv * const end) 947 { 948 const struct kref kref0 = kv_kref(start); 949 if (end) { 950 const struct kref krefz = kv_kref(end); 951 return api->delr(ref, &kref0, &krefz); 952 } else { 953 return api->delr(ref, &kref0, NULL); 954 } 955 } 956 957 inline void 958 kvmap_kv_iter_seek(const struct kvmap_api * const api, void * const iter, 959 const struct kv * const key) 960 { 961 const struct kref kref = kv_kref(key); 962 api->iter_seek(iter, &kref); 963 } 964 // }}} kvmap_kv_op 965 966 // kvmap_raw_op {{{ 967 inline struct kv * 968 kvmap_raw_get(const struct kvmap_api * const api, void * const ref, 969 const u32 len, const u8 * const ptr, struct kv * const out) 970 { 971 const struct kref kref = {.ptr = ptr, .len = len, 972 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 973 return api->get(ref, &kref, out); 974 } 975 976 inline bool 977 kvmap_raw_probe(const struct kvmap_api * const api, void * const ref, 978 const u32 len, const u8 * const ptr) 979 { 980 const struct kref kref = {.ptr = ptr, .len = len, 981 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 982 return api->probe(ref, &kref); 983 } 984 985 inline bool 986 kvmap_raw_del(const struct kvmap_api * const api, void * const ref, 987 const u32 len, const u8 * const ptr) 988 { 989 const struct kref kref = {.ptr = ptr, .len = len, 990 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 991 return api->del(ref, &kref); 992 } 993 994 inline bool 995 kvmap_raw_inpr(const struct kvmap_api * const api, void * const ref, 996 const u32 len, const u8 * const ptr, kv_inp_func uf, void * const priv) 997 { 998 const struct kref kref = {.ptr = ptr, .len = len, 999 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 1000 return api->inpr(ref, &kref, uf, priv); 1001 } 1002 1003 inline bool 1004 kvmap_raw_inpw(const struct kvmap_api * const api, void * const ref, 1005 const u32 len, const u8 * const ptr, kv_inp_func uf, void * const priv) 1006 { 1007 const struct kref kref = {.ptr = ptr, .len = len, 1008 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 1009 return api->inpw(ref, &kref, uf, priv); 1010 } 1011 1012 inline void 1013 kvmap_raw_iter_seek(const struct kvmap_api * const api, void * const iter, 1014 const u32 len, const u8 * const ptr) 1015 { 1016 const struct kref kref = {.ptr = ptr, .len = len, 1017 .hash32 = api->hashkey ? kv_crc32c(ptr, len) : 0}; 1018 api->iter_seek(iter, &kref); 1019 } 1020 // }}}} kvmap_raw_op 1021 1022 // dump {{{ 1023 u64 1024 kvmap_dump_keys(const struct kvmap_api * const api, void * const map, const int fd) 1025 { 1026 void * const ref = kvmap_ref(api, map); 1027 void * const iter = api->iter_create(ref); 1028 api->iter_seek(iter, kref_null()); 1029 u64 i = 0; 1030 while (api->iter_valid(iter)) { 1031 struct kvref kvref; 1032 api->iter_kvref(iter, &kvref); 1033 dprintf(fd, "%010lu [%3u] %.*s [%u]\n", i, kvref.hdr.klen, kvref.hdr.klen, kvref.kptr, kvref.hdr.vlen); 1034 i++; 1035 api->iter_skip1(iter); 1036 } 1037 api->iter_destroy(iter); 1038 kvmap_unref(api, ref); 1039 return i; 1040 } 1041 // }}} dump 1042 1043 // }}} kvmap 1044 1045 // vim:fdm=marker