11cb0ef41Sopenharmony_ci/* 21cb0ef41Sopenharmony_ci * nghttp3 31cb0ef41Sopenharmony_ci * 41cb0ef41Sopenharmony_ci * Copyright (c) 2019 nghttp3 contributors 51cb0ef41Sopenharmony_ci * Copyright (c) 2018 ngtcp2 contributors 61cb0ef41Sopenharmony_ci * 71cb0ef41Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining 81cb0ef41Sopenharmony_ci * a copy of this software and associated documentation files (the 91cb0ef41Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 101cb0ef41Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 111cb0ef41Sopenharmony_ci * distribute, sublicense, and/or sell copies of the Software, and to 121cb0ef41Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 131cb0ef41Sopenharmony_ci * the following conditions: 141cb0ef41Sopenharmony_ci * 151cb0ef41Sopenharmony_ci * The above copyright notice and this permission notice shall be 161cb0ef41Sopenharmony_ci * included in all copies or substantial portions of the Software. 171cb0ef41Sopenharmony_ci * 181cb0ef41Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 191cb0ef41Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 201cb0ef41Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 211cb0ef41Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 221cb0ef41Sopenharmony_ci * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 231cb0ef41Sopenharmony_ci * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 241cb0ef41Sopenharmony_ci * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251cb0ef41Sopenharmony_ci */ 261cb0ef41Sopenharmony_ci#include "nghttp3_ksl.h" 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci#include <stdlib.h> 291cb0ef41Sopenharmony_ci#include <string.h> 301cb0ef41Sopenharmony_ci#include <assert.h> 311cb0ef41Sopenharmony_ci#include <stdio.h> 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_ci#include "nghttp3_macro.h" 341cb0ef41Sopenharmony_ci#include "nghttp3_mem.h" 351cb0ef41Sopenharmony_ci#include "nghttp3_range.h" 361cb0ef41Sopenharmony_ci 371cb0ef41Sopenharmony_cistatic nghttp3_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}}; 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_cistatic size_t ksl_nodelen(size_t keylen) { 401cb0ef41Sopenharmony_ci return (sizeof(nghttp3_ksl_node) + keylen - sizeof(uint64_t) + 0xfu) & 411cb0ef41Sopenharmony_ci ~(uintptr_t)0xfu; 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_cistatic size_t ksl_blklen(size_t nodelen) { 451cb0ef41Sopenharmony_ci return sizeof(nghttp3_ksl_blk) + nodelen * NGHTTP3_KSL_MAX_NBLK - 461cb0ef41Sopenharmony_ci sizeof(uint64_t); 471cb0ef41Sopenharmony_ci} 481cb0ef41Sopenharmony_ci 491cb0ef41Sopenharmony_ci/* 501cb0ef41Sopenharmony_ci * ksl_node_set_key sets |key| to |node|. 511cb0ef41Sopenharmony_ci */ 521cb0ef41Sopenharmony_cistatic void ksl_node_set_key(nghttp3_ksl *ksl, nghttp3_ksl_node *node, 531cb0ef41Sopenharmony_ci const void *key) { 541cb0ef41Sopenharmony_ci memcpy(node->key, key, ksl->keylen); 551cb0ef41Sopenharmony_ci} 561cb0ef41Sopenharmony_ci 571cb0ef41Sopenharmony_civoid nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar, 581cb0ef41Sopenharmony_ci size_t keylen, const nghttp3_mem *mem) { 591cb0ef41Sopenharmony_ci size_t nodelen = ksl_nodelen(keylen); 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci nghttp3_objalloc_init(&ksl->blkalloc, 621cb0ef41Sopenharmony_ci ((ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu) * 8, 631cb0ef41Sopenharmony_ci mem); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci ksl->head = NULL; 661cb0ef41Sopenharmony_ci ksl->front = ksl->back = NULL; 671cb0ef41Sopenharmony_ci ksl->compar = compar; 681cb0ef41Sopenharmony_ci ksl->keylen = keylen; 691cb0ef41Sopenharmony_ci ksl->nodelen = nodelen; 701cb0ef41Sopenharmony_ci ksl->n = 0; 711cb0ef41Sopenharmony_ci} 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_cistatic nghttp3_ksl_blk *ksl_blk_objalloc_new(nghttp3_ksl *ksl) { 741cb0ef41Sopenharmony_ci return nghttp3_objalloc_ksl_blk_len_get(&ksl->blkalloc, 751cb0ef41Sopenharmony_ci ksl_blklen(ksl->nodelen)); 761cb0ef41Sopenharmony_ci} 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_cistatic void ksl_blk_objalloc_del(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) { 791cb0ef41Sopenharmony_ci nghttp3_objalloc_ksl_blk_release(&ksl->blkalloc, blk); 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_cistatic int ksl_head_init(nghttp3_ksl *ksl) { 831cb0ef41Sopenharmony_ci nghttp3_ksl_blk *head = ksl_blk_objalloc_new(ksl); 841cb0ef41Sopenharmony_ci if (!head) { 851cb0ef41Sopenharmony_ci return NGHTTP3_ERR_NOMEM; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci 881cb0ef41Sopenharmony_ci head->next = head->prev = NULL; 891cb0ef41Sopenharmony_ci head->n = 0; 901cb0ef41Sopenharmony_ci head->leaf = 1; 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_ci ksl->head = head; 931cb0ef41Sopenharmony_ci ksl->front = ksl->back = head; 941cb0ef41Sopenharmony_ci 951cb0ef41Sopenharmony_ci return 0; 961cb0ef41Sopenharmony_ci} 971cb0ef41Sopenharmony_ci 981cb0ef41Sopenharmony_ci#ifdef NOMEMPOOL 991cb0ef41Sopenharmony_ci/* 1001cb0ef41Sopenharmony_ci * ksl_free_blk frees |blk| recursively. 1011cb0ef41Sopenharmony_ci */ 1021cb0ef41Sopenharmony_cistatic void ksl_free_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) { 1031cb0ef41Sopenharmony_ci size_t i; 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_ci if (!blk->leaf) { 1061cb0ef41Sopenharmony_ci for (i = 0; i < blk->n; ++i) { 1071cb0ef41Sopenharmony_ci ksl_free_blk(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk); 1081cb0ef41Sopenharmony_ci } 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci ksl_blk_objalloc_del(ksl, blk); 1121cb0ef41Sopenharmony_ci} 1131cb0ef41Sopenharmony_ci#endif /* NOMEMPOOL */ 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_civoid nghttp3_ksl_free(nghttp3_ksl *ksl) { 1161cb0ef41Sopenharmony_ci if (!ksl || !ksl->head) { 1171cb0ef41Sopenharmony_ci return; 1181cb0ef41Sopenharmony_ci } 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci#ifdef NOMEMPOOL 1211cb0ef41Sopenharmony_ci ksl_free_blk(ksl, ksl->head); 1221cb0ef41Sopenharmony_ci#endif /* NOMEMPOOL */ 1231cb0ef41Sopenharmony_ci 1241cb0ef41Sopenharmony_ci nghttp3_objalloc_free(&ksl->blkalloc); 1251cb0ef41Sopenharmony_ci} 1261cb0ef41Sopenharmony_ci 1271cb0ef41Sopenharmony_ci/* 1281cb0ef41Sopenharmony_ci * ksl_split_blk splits |blk| into 2 nghttp3_ksl_blk objects. The new 1291cb0ef41Sopenharmony_ci * nghttp3_ksl_blk is always the "right" block. 1301cb0ef41Sopenharmony_ci * 1311cb0ef41Sopenharmony_ci * It returns the pointer to the nghttp3_ksl_blk created which is the 1321cb0ef41Sopenharmony_ci * located at the right of |blk|, or NULL which indicates out of 1331cb0ef41Sopenharmony_ci * memory error. 1341cb0ef41Sopenharmony_ci */ 1351cb0ef41Sopenharmony_cistatic nghttp3_ksl_blk *ksl_split_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) { 1361cb0ef41Sopenharmony_ci nghttp3_ksl_blk *rblk; 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_ci rblk = ksl_blk_objalloc_new(ksl); 1391cb0ef41Sopenharmony_ci if (rblk == NULL) { 1401cb0ef41Sopenharmony_ci return NULL; 1411cb0ef41Sopenharmony_ci } 1421cb0ef41Sopenharmony_ci 1431cb0ef41Sopenharmony_ci rblk->next = blk->next; 1441cb0ef41Sopenharmony_ci blk->next = rblk; 1451cb0ef41Sopenharmony_ci if (rblk->next) { 1461cb0ef41Sopenharmony_ci rblk->next->prev = rblk; 1471cb0ef41Sopenharmony_ci } else if (ksl->back == blk) { 1481cb0ef41Sopenharmony_ci ksl->back = rblk; 1491cb0ef41Sopenharmony_ci } 1501cb0ef41Sopenharmony_ci rblk->prev = blk; 1511cb0ef41Sopenharmony_ci rblk->leaf = blk->leaf; 1521cb0ef41Sopenharmony_ci 1531cb0ef41Sopenharmony_ci rblk->n = blk->n / 2; 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ci memcpy(rblk->nodes, blk->nodes + ksl->nodelen * (blk->n - rblk->n), 1561cb0ef41Sopenharmony_ci ksl->nodelen * rblk->n); 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci blk->n -= rblk->n; 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci assert(blk->n >= NGHTTP3_KSL_MIN_NBLK); 1611cb0ef41Sopenharmony_ci assert(rblk->n >= NGHTTP3_KSL_MIN_NBLK); 1621cb0ef41Sopenharmony_ci 1631cb0ef41Sopenharmony_ci return rblk; 1641cb0ef41Sopenharmony_ci} 1651cb0ef41Sopenharmony_ci 1661cb0ef41Sopenharmony_ci/* 1671cb0ef41Sopenharmony_ci * ksl_split_node splits a node included in |blk| at the position |i| 1681cb0ef41Sopenharmony_ci * into 2 adjacent nodes. The new node is always inserted at the 1691cb0ef41Sopenharmony_ci * position |i+1|. 1701cb0ef41Sopenharmony_ci * 1711cb0ef41Sopenharmony_ci * It returns 0 if it succeeds, or one of the following negative error 1721cb0ef41Sopenharmony_ci * codes: 1731cb0ef41Sopenharmony_ci * 1741cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM 1751cb0ef41Sopenharmony_ci * Out of memory. 1761cb0ef41Sopenharmony_ci */ 1771cb0ef41Sopenharmony_cistatic int ksl_split_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) { 1781cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 1791cb0ef41Sopenharmony_ci nghttp3_ksl_blk *lblk = nghttp3_ksl_nth_node(ksl, blk, i)->blk, *rblk; 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci rblk = ksl_split_blk(ksl, lblk); 1821cb0ef41Sopenharmony_ci if (rblk == NULL) { 1831cb0ef41Sopenharmony_ci return NGHTTP3_ERR_NOMEM; 1841cb0ef41Sopenharmony_ci } 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci memmove(blk->nodes + (i + 2) * ksl->nodelen, 1871cb0ef41Sopenharmony_ci blk->nodes + (i + 1) * ksl->nodelen, 1881cb0ef41Sopenharmony_ci ksl->nodelen * (blk->n - (i + 1))); 1891cb0ef41Sopenharmony_ci 1901cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i + 1); 1911cb0ef41Sopenharmony_ci node->blk = rblk; 1921cb0ef41Sopenharmony_ci ++blk->n; 1931cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, 1941cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 1971cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, 1981cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci return 0; 2011cb0ef41Sopenharmony_ci} 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci/* 2041cb0ef41Sopenharmony_ci * ksl_split_head splits a head (root) block. It increases the height 2051cb0ef41Sopenharmony_ci * of skip list by 1. 2061cb0ef41Sopenharmony_ci * 2071cb0ef41Sopenharmony_ci * It returns 0 if it succeeds, or one of the following negative error 2081cb0ef41Sopenharmony_ci * codes: 2091cb0ef41Sopenharmony_ci * 2101cb0ef41Sopenharmony_ci * NGHTTP3_ERR_NOMEM 2111cb0ef41Sopenharmony_ci * Out of memory. 2121cb0ef41Sopenharmony_ci */ 2131cb0ef41Sopenharmony_cistatic int ksl_split_head(nghttp3_ksl *ksl) { 2141cb0ef41Sopenharmony_ci nghttp3_ksl_blk *rblk = NULL, *lblk, *nhead = NULL; 2151cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci rblk = ksl_split_blk(ksl, ksl->head); 2181cb0ef41Sopenharmony_ci if (rblk == NULL) { 2191cb0ef41Sopenharmony_ci return NGHTTP3_ERR_NOMEM; 2201cb0ef41Sopenharmony_ci } 2211cb0ef41Sopenharmony_ci 2221cb0ef41Sopenharmony_ci lblk = ksl->head; 2231cb0ef41Sopenharmony_ci 2241cb0ef41Sopenharmony_ci nhead = ksl_blk_objalloc_new(ksl); 2251cb0ef41Sopenharmony_ci if (nhead == NULL) { 2261cb0ef41Sopenharmony_ci ksl_blk_objalloc_del(ksl, rblk); 2271cb0ef41Sopenharmony_ci return NGHTTP3_ERR_NOMEM; 2281cb0ef41Sopenharmony_ci } 2291cb0ef41Sopenharmony_ci nhead->next = nhead->prev = NULL; 2301cb0ef41Sopenharmony_ci nhead->n = 2; 2311cb0ef41Sopenharmony_ci nhead->leaf = 0; 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, nhead, 0); 2341cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, 2351cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); 2361cb0ef41Sopenharmony_ci node->blk = lblk; 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, nhead, 1); 2391cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, 2401cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key); 2411cb0ef41Sopenharmony_ci node->blk = rblk; 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci ksl->head = nhead; 2441cb0ef41Sopenharmony_ci 2451cb0ef41Sopenharmony_ci return 0; 2461cb0ef41Sopenharmony_ci} 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci/* 2491cb0ef41Sopenharmony_ci * insert_node inserts a node whose key is |key| with the associated 2501cb0ef41Sopenharmony_ci * |data| at the index of |i|. This function assumes that the number 2511cb0ef41Sopenharmony_ci * of nodes contained by |blk| is strictly less than 2521cb0ef41Sopenharmony_ci * NGHTTP3_KSL_MAX_NBLK. 2531cb0ef41Sopenharmony_ci */ 2541cb0ef41Sopenharmony_cistatic void ksl_insert_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i, 2551cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key, void *data) { 2561cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 2571cb0ef41Sopenharmony_ci 2581cb0ef41Sopenharmony_ci assert(blk->n < NGHTTP3_KSL_MAX_NBLK); 2591cb0ef41Sopenharmony_ci 2601cb0ef41Sopenharmony_ci memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen, 2611cb0ef41Sopenharmony_ci ksl->nodelen * (blk->n - i)); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 2641cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, key); 2651cb0ef41Sopenharmony_ci node->data = data; 2661cb0ef41Sopenharmony_ci 2671cb0ef41Sopenharmony_ci ++blk->n; 2681cb0ef41Sopenharmony_ci} 2691cb0ef41Sopenharmony_ci 2701cb0ef41Sopenharmony_cistatic size_t ksl_bsearch(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, 2711cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key, 2721cb0ef41Sopenharmony_ci nghttp3_ksl_compar compar) { 2731cb0ef41Sopenharmony_ci size_t i; 2741cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 2751cb0ef41Sopenharmony_ci 2761cb0ef41Sopenharmony_ci for (i = 0, node = (nghttp3_ksl_node *)(void *)blk->nodes; 2771cb0ef41Sopenharmony_ci i < blk->n && compar((nghttp3_ksl_key *)node->key, key); 2781cb0ef41Sopenharmony_ci ++i, node = (nghttp3_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen)) 2791cb0ef41Sopenharmony_ci ; 2801cb0ef41Sopenharmony_ci 2811cb0ef41Sopenharmony_ci return i; 2821cb0ef41Sopenharmony_ci} 2831cb0ef41Sopenharmony_ci 2841cb0ef41Sopenharmony_ciint nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it, 2851cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key, void *data) { 2861cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk; 2871cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 2881cb0ef41Sopenharmony_ci size_t i; 2891cb0ef41Sopenharmony_ci int rv; 2901cb0ef41Sopenharmony_ci 2911cb0ef41Sopenharmony_ci if (!ksl->head) { 2921cb0ef41Sopenharmony_ci rv = ksl_head_init(ksl); 2931cb0ef41Sopenharmony_ci if (rv != 0) { 2941cb0ef41Sopenharmony_ci return rv; 2951cb0ef41Sopenharmony_ci } 2961cb0ef41Sopenharmony_ci } 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci blk = ksl->head; 2991cb0ef41Sopenharmony_ci 3001cb0ef41Sopenharmony_ci if (blk->n == NGHTTP3_KSL_MAX_NBLK) { 3011cb0ef41Sopenharmony_ci rv = ksl_split_head(ksl); 3021cb0ef41Sopenharmony_ci if (rv != 0) { 3031cb0ef41Sopenharmony_ci return rv; 3041cb0ef41Sopenharmony_ci } 3051cb0ef41Sopenharmony_ci blk = ksl->head; 3061cb0ef41Sopenharmony_ci } 3071cb0ef41Sopenharmony_ci 3081cb0ef41Sopenharmony_ci for (;;) { 3091cb0ef41Sopenharmony_ci i = ksl_bsearch(ksl, blk, key, ksl->compar); 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci if (blk->leaf) { 3121cb0ef41Sopenharmony_ci if (i < blk->n && 3131cb0ef41Sopenharmony_ci !ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) { 3141cb0ef41Sopenharmony_ci if (it) { 3151cb0ef41Sopenharmony_ci *it = nghttp3_ksl_end(ksl); 3161cb0ef41Sopenharmony_ci } 3171cb0ef41Sopenharmony_ci return NGHTTP3_ERR_INVALID_ARGUMENT; 3181cb0ef41Sopenharmony_ci } 3191cb0ef41Sopenharmony_ci ksl_insert_node(ksl, blk, i, key, data); 3201cb0ef41Sopenharmony_ci ++ksl->n; 3211cb0ef41Sopenharmony_ci if (it) { 3221cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk, i); 3231cb0ef41Sopenharmony_ci } 3241cb0ef41Sopenharmony_ci return 0; 3251cb0ef41Sopenharmony_ci } 3261cb0ef41Sopenharmony_ci 3271cb0ef41Sopenharmony_ci if (i == blk->n) { 3281cb0ef41Sopenharmony_ci /* This insertion extends the largest key in this subtree. */ 3291cb0ef41Sopenharmony_ci for (; !blk->leaf;) { 3301cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1); 3311cb0ef41Sopenharmony_ci if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) { 3321cb0ef41Sopenharmony_ci rv = ksl_split_node(ksl, blk, blk->n - 1); 3331cb0ef41Sopenharmony_ci if (rv != 0) { 3341cb0ef41Sopenharmony_ci return rv; 3351cb0ef41Sopenharmony_ci } 3361cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1); 3371cb0ef41Sopenharmony_ci } 3381cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, key); 3391cb0ef41Sopenharmony_ci blk = node->blk; 3401cb0ef41Sopenharmony_ci } 3411cb0ef41Sopenharmony_ci ksl_insert_node(ksl, blk, blk->n, key, data); 3421cb0ef41Sopenharmony_ci ++ksl->n; 3431cb0ef41Sopenharmony_ci if (it) { 3441cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk, blk->n - 1); 3451cb0ef41Sopenharmony_ci } 3461cb0ef41Sopenharmony_ci return 0; 3471cb0ef41Sopenharmony_ci } 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 3501cb0ef41Sopenharmony_ci 3511cb0ef41Sopenharmony_ci if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) { 3521cb0ef41Sopenharmony_ci rv = ksl_split_node(ksl, blk, i); 3531cb0ef41Sopenharmony_ci if (rv != 0) { 3541cb0ef41Sopenharmony_ci return rv; 3551cb0ef41Sopenharmony_ci } 3561cb0ef41Sopenharmony_ci if (ksl->compar((nghttp3_ksl_key *)node->key, key)) { 3571cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i + 1); 3581cb0ef41Sopenharmony_ci if (ksl->compar((nghttp3_ksl_key *)node->key, key)) { 3591cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, key); 3601cb0ef41Sopenharmony_ci } 3611cb0ef41Sopenharmony_ci } 3621cb0ef41Sopenharmony_ci } 3631cb0ef41Sopenharmony_ci 3641cb0ef41Sopenharmony_ci blk = node->blk; 3651cb0ef41Sopenharmony_ci } 3661cb0ef41Sopenharmony_ci} 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci/* 3691cb0ef41Sopenharmony_ci * ksl_remove_node removes the node included in |blk| at the index of 3701cb0ef41Sopenharmony_ci * |i|. 3711cb0ef41Sopenharmony_ci */ 3721cb0ef41Sopenharmony_cistatic void ksl_remove_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) { 3731cb0ef41Sopenharmony_ci memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen, 3741cb0ef41Sopenharmony_ci ksl->nodelen * (blk->n - (i + 1))); 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci --blk->n; 3771cb0ef41Sopenharmony_ci} 3781cb0ef41Sopenharmony_ci 3791cb0ef41Sopenharmony_ci/* 3801cb0ef41Sopenharmony_ci * ksl_merge_node merges 2 nodes which are the nodes at the index of 3811cb0ef41Sopenharmony_ci * |i| and |i + 1|. 3821cb0ef41Sopenharmony_ci * 3831cb0ef41Sopenharmony_ci * If |blk| is the direct descendant of head (root) block and the head 3841cb0ef41Sopenharmony_ci * block contains just 2 nodes, the merged block becomes head block, 3851cb0ef41Sopenharmony_ci * which decreases the height of |ksl| by 1. 3861cb0ef41Sopenharmony_ci * 3871cb0ef41Sopenharmony_ci * This function returns the pointer to the merged block. 3881cb0ef41Sopenharmony_ci */ 3891cb0ef41Sopenharmony_cistatic nghttp3_ksl_blk *ksl_merge_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, 3901cb0ef41Sopenharmony_ci size_t i) { 3911cb0ef41Sopenharmony_ci nghttp3_ksl_blk *lblk, *rblk; 3921cb0ef41Sopenharmony_ci 3931cb0ef41Sopenharmony_ci assert(i + 1 < blk->n); 3941cb0ef41Sopenharmony_ci 3951cb0ef41Sopenharmony_ci lblk = nghttp3_ksl_nth_node(ksl, blk, i)->blk; 3961cb0ef41Sopenharmony_ci rblk = nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk; 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci assert(lblk->n + rblk->n < NGHTTP3_KSL_MAX_NBLK); 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, 4011cb0ef41Sopenharmony_ci ksl->nodelen * rblk->n); 4021cb0ef41Sopenharmony_ci 4031cb0ef41Sopenharmony_ci lblk->n += rblk->n; 4041cb0ef41Sopenharmony_ci lblk->next = rblk->next; 4051cb0ef41Sopenharmony_ci if (lblk->next) { 4061cb0ef41Sopenharmony_ci lblk->next->prev = lblk; 4071cb0ef41Sopenharmony_ci } else if (ksl->back == rblk) { 4081cb0ef41Sopenharmony_ci ksl->back = lblk; 4091cb0ef41Sopenharmony_ci } 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci ksl_blk_objalloc_del(ksl, rblk); 4121cb0ef41Sopenharmony_ci 4131cb0ef41Sopenharmony_ci if (ksl->head == blk && blk->n == 2) { 4141cb0ef41Sopenharmony_ci ksl_blk_objalloc_del(ksl, ksl->head); 4151cb0ef41Sopenharmony_ci ksl->head = lblk; 4161cb0ef41Sopenharmony_ci } else { 4171cb0ef41Sopenharmony_ci ksl_remove_node(ksl, blk, i + 1); 4181cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, nghttp3_ksl_nth_node(ksl, blk, i), 4191cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key); 4201cb0ef41Sopenharmony_ci } 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci return lblk; 4231cb0ef41Sopenharmony_ci} 4241cb0ef41Sopenharmony_ci 4251cb0ef41Sopenharmony_ci/* 4261cb0ef41Sopenharmony_ci * ksl_shift_left moves the first nodes in blk->nodes[i]->blk->nodes 4271cb0ef41Sopenharmony_ci * to blk->nodes[i - 1]->blk->nodes in a manner that they have the 4281cb0ef41Sopenharmony_ci * same amount of nodes as much as possible. 4291cb0ef41Sopenharmony_ci */ 4301cb0ef41Sopenharmony_cistatic void ksl_shift_left(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) { 4311cb0ef41Sopenharmony_ci nghttp3_ksl_node *lnode, *rnode; 4321cb0ef41Sopenharmony_ci size_t n; 4331cb0ef41Sopenharmony_ci 4341cb0ef41Sopenharmony_ci assert(i > 0); 4351cb0ef41Sopenharmony_ci 4361cb0ef41Sopenharmony_ci lnode = nghttp3_ksl_nth_node(ksl, blk, i - 1); 4371cb0ef41Sopenharmony_ci rnode = nghttp3_ksl_nth_node(ksl, blk, i); 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci assert(lnode->blk->n < NGHTTP3_KSL_MAX_NBLK); 4401cb0ef41Sopenharmony_ci assert(rnode->blk->n > NGHTTP3_KSL_MIN_NBLK); 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci n = (lnode->blk->n + rnode->blk->n + 1) / 2 - lnode->blk->n; 4431cb0ef41Sopenharmony_ci 4441cb0ef41Sopenharmony_ci assert(n > 0); 4451cb0ef41Sopenharmony_ci assert(lnode->blk->n <= NGHTTP3_KSL_MAX_NBLK - n); 4461cb0ef41Sopenharmony_ci assert(rnode->blk->n >= NGHTTP3_KSL_MIN_NBLK + n); 4471cb0ef41Sopenharmony_ci 4481cb0ef41Sopenharmony_ci memcpy(lnode->blk->nodes + ksl->nodelen * lnode->blk->n, rnode->blk->nodes, 4491cb0ef41Sopenharmony_ci ksl->nodelen * n); 4501cb0ef41Sopenharmony_ci 4511cb0ef41Sopenharmony_ci lnode->blk->n += (uint32_t)n; 4521cb0ef41Sopenharmony_ci rnode->blk->n -= (uint32_t)n; 4531cb0ef41Sopenharmony_ci 4541cb0ef41Sopenharmony_ci ksl_node_set_key( 4551cb0ef41Sopenharmony_ci ksl, lnode, 4561cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key); 4571cb0ef41Sopenharmony_ci 4581cb0ef41Sopenharmony_ci memmove(rnode->blk->nodes, rnode->blk->nodes + ksl->nodelen * n, 4591cb0ef41Sopenharmony_ci ksl->nodelen * rnode->blk->n); 4601cb0ef41Sopenharmony_ci} 4611cb0ef41Sopenharmony_ci 4621cb0ef41Sopenharmony_ci/* 4631cb0ef41Sopenharmony_ci * ksl_shift_right moves the last nodes in blk->nodes[i]->blk->nodes 4641cb0ef41Sopenharmony_ci * to blk->nodes[i + 1]->blk->nodes in a manner that they have the 4651cb0ef41Sopenharmony_ci * same amount of nodes as much as possible.. 4661cb0ef41Sopenharmony_ci */ 4671cb0ef41Sopenharmony_cistatic void ksl_shift_right(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) { 4681cb0ef41Sopenharmony_ci nghttp3_ksl_node *lnode, *rnode; 4691cb0ef41Sopenharmony_ci size_t n; 4701cb0ef41Sopenharmony_ci 4711cb0ef41Sopenharmony_ci assert(i < blk->n - 1); 4721cb0ef41Sopenharmony_ci 4731cb0ef41Sopenharmony_ci lnode = nghttp3_ksl_nth_node(ksl, blk, i); 4741cb0ef41Sopenharmony_ci rnode = nghttp3_ksl_nth_node(ksl, blk, i + 1); 4751cb0ef41Sopenharmony_ci 4761cb0ef41Sopenharmony_ci assert(lnode->blk->n > NGHTTP3_KSL_MIN_NBLK); 4771cb0ef41Sopenharmony_ci assert(rnode->blk->n < NGHTTP3_KSL_MAX_NBLK); 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci n = (lnode->blk->n + rnode->blk->n + 1) / 2 - rnode->blk->n; 4801cb0ef41Sopenharmony_ci 4811cb0ef41Sopenharmony_ci assert(n > 0); 4821cb0ef41Sopenharmony_ci assert(lnode->blk->n >= NGHTTP3_KSL_MIN_NBLK + n); 4831cb0ef41Sopenharmony_ci assert(rnode->blk->n <= NGHTTP3_KSL_MAX_NBLK - n); 4841cb0ef41Sopenharmony_ci 4851cb0ef41Sopenharmony_ci memmove(rnode->blk->nodes + ksl->nodelen * n, rnode->blk->nodes, 4861cb0ef41Sopenharmony_ci ksl->nodelen * rnode->blk->n); 4871cb0ef41Sopenharmony_ci 4881cb0ef41Sopenharmony_ci rnode->blk->n += (uint32_t)n; 4891cb0ef41Sopenharmony_ci lnode->blk->n -= (uint32_t)n; 4901cb0ef41Sopenharmony_ci 4911cb0ef41Sopenharmony_ci memcpy(rnode->blk->nodes, lnode->blk->nodes + ksl->nodelen * lnode->blk->n, 4921cb0ef41Sopenharmony_ci ksl->nodelen * n); 4931cb0ef41Sopenharmony_ci 4941cb0ef41Sopenharmony_ci ksl_node_set_key( 4951cb0ef41Sopenharmony_ci ksl, lnode, 4961cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key); 4971cb0ef41Sopenharmony_ci} 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci/* 5001cb0ef41Sopenharmony_ci * key_equal returns nonzero if |lhs| and |rhs| are equal using the 5011cb0ef41Sopenharmony_ci * function |compar|. 5021cb0ef41Sopenharmony_ci */ 5031cb0ef41Sopenharmony_cistatic int key_equal(nghttp3_ksl_compar compar, const nghttp3_ksl_key *lhs, 5041cb0ef41Sopenharmony_ci const nghttp3_ksl_key *rhs) { 5051cb0ef41Sopenharmony_ci return !compar(lhs, rhs) && !compar(rhs, lhs); 5061cb0ef41Sopenharmony_ci} 5071cb0ef41Sopenharmony_ci 5081cb0ef41Sopenharmony_ciint nghttp3_ksl_remove_hint(nghttp3_ksl *ksl, nghttp3_ksl_it *it, 5091cb0ef41Sopenharmony_ci const nghttp3_ksl_it *hint, 5101cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key) { 5111cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk = hint->blk; 5121cb0ef41Sopenharmony_ci 5131cb0ef41Sopenharmony_ci assert(ksl->head); 5141cb0ef41Sopenharmony_ci 5151cb0ef41Sopenharmony_ci if (blk->n <= NGHTTP3_KSL_MIN_NBLK) { 5161cb0ef41Sopenharmony_ci return nghttp3_ksl_remove(ksl, it, key); 5171cb0ef41Sopenharmony_ci } 5181cb0ef41Sopenharmony_ci 5191cb0ef41Sopenharmony_ci ksl_remove_node(ksl, blk, hint->i); 5201cb0ef41Sopenharmony_ci 5211cb0ef41Sopenharmony_ci --ksl->n; 5221cb0ef41Sopenharmony_ci 5231cb0ef41Sopenharmony_ci if (it) { 5241cb0ef41Sopenharmony_ci if (hint->i == blk->n && blk->next) { 5251cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk->next, 0); 5261cb0ef41Sopenharmony_ci } else { 5271cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk, hint->i); 5281cb0ef41Sopenharmony_ci } 5291cb0ef41Sopenharmony_ci } 5301cb0ef41Sopenharmony_ci 5311cb0ef41Sopenharmony_ci return 0; 5321cb0ef41Sopenharmony_ci} 5331cb0ef41Sopenharmony_ci 5341cb0ef41Sopenharmony_ciint nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it, 5351cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key) { 5361cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk = ksl->head; 5371cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 5381cb0ef41Sopenharmony_ci size_t i; 5391cb0ef41Sopenharmony_ci 5401cb0ef41Sopenharmony_ci if (!ksl->head) { 5411cb0ef41Sopenharmony_ci return NGHTTP3_ERR_INVALID_ARGUMENT; 5421cb0ef41Sopenharmony_ci } 5431cb0ef41Sopenharmony_ci 5441cb0ef41Sopenharmony_ci if (!blk->leaf && blk->n == 2 && 5451cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, blk, 0)->blk->n == NGHTTP3_KSL_MIN_NBLK && 5461cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, blk, 1)->blk->n == NGHTTP3_KSL_MIN_NBLK) { 5471cb0ef41Sopenharmony_ci blk = ksl_merge_node(ksl, ksl->head, 0); 5481cb0ef41Sopenharmony_ci } 5491cb0ef41Sopenharmony_ci 5501cb0ef41Sopenharmony_ci for (;;) { 5511cb0ef41Sopenharmony_ci i = ksl_bsearch(ksl, blk, key, ksl->compar); 5521cb0ef41Sopenharmony_ci 5531cb0ef41Sopenharmony_ci if (i == blk->n) { 5541cb0ef41Sopenharmony_ci if (it) { 5551cb0ef41Sopenharmony_ci *it = nghttp3_ksl_end(ksl); 5561cb0ef41Sopenharmony_ci } 5571cb0ef41Sopenharmony_ci return NGHTTP3_ERR_INVALID_ARGUMENT; 5581cb0ef41Sopenharmony_ci } 5591cb0ef41Sopenharmony_ci 5601cb0ef41Sopenharmony_ci if (blk->leaf) { 5611cb0ef41Sopenharmony_ci if (ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) { 5621cb0ef41Sopenharmony_ci if (it) { 5631cb0ef41Sopenharmony_ci *it = nghttp3_ksl_end(ksl); 5641cb0ef41Sopenharmony_ci } 5651cb0ef41Sopenharmony_ci return NGHTTP3_ERR_INVALID_ARGUMENT; 5661cb0ef41Sopenharmony_ci } 5671cb0ef41Sopenharmony_ci ksl_remove_node(ksl, blk, i); 5681cb0ef41Sopenharmony_ci --ksl->n; 5691cb0ef41Sopenharmony_ci if (it) { 5701cb0ef41Sopenharmony_ci if (blk->n == i && blk->next) { 5711cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk->next, 0); 5721cb0ef41Sopenharmony_ci } else { 5731cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(it, ksl, blk, i); 5741cb0ef41Sopenharmony_ci } 5751cb0ef41Sopenharmony_ci } 5761cb0ef41Sopenharmony_ci return 0; 5771cb0ef41Sopenharmony_ci } 5781cb0ef41Sopenharmony_ci 5791cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 5801cb0ef41Sopenharmony_ci 5811cb0ef41Sopenharmony_ci if (node->blk->n > NGHTTP3_KSL_MIN_NBLK) { 5821cb0ef41Sopenharmony_ci blk = node->blk; 5831cb0ef41Sopenharmony_ci continue; 5841cb0ef41Sopenharmony_ci } 5851cb0ef41Sopenharmony_ci 5861cb0ef41Sopenharmony_ci assert(node->blk->n == NGHTTP3_KSL_MIN_NBLK); 5871cb0ef41Sopenharmony_ci 5881cb0ef41Sopenharmony_ci if (i + 1 < blk->n && 5891cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGHTTP3_KSL_MIN_NBLK) { 5901cb0ef41Sopenharmony_ci ksl_shift_left(ksl, blk, i + 1); 5911cb0ef41Sopenharmony_ci blk = node->blk; 5921cb0ef41Sopenharmony_ci continue; 5931cb0ef41Sopenharmony_ci } 5941cb0ef41Sopenharmony_ci 5951cb0ef41Sopenharmony_ci if (i > 0 && 5961cb0ef41Sopenharmony_ci nghttp3_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGHTTP3_KSL_MIN_NBLK) { 5971cb0ef41Sopenharmony_ci ksl_shift_right(ksl, blk, i - 1); 5981cb0ef41Sopenharmony_ci blk = node->blk; 5991cb0ef41Sopenharmony_ci continue; 6001cb0ef41Sopenharmony_ci } 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci if (i + 1 < blk->n) { 6031cb0ef41Sopenharmony_ci blk = ksl_merge_node(ksl, blk, i); 6041cb0ef41Sopenharmony_ci continue; 6051cb0ef41Sopenharmony_ci } 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci assert(i > 0); 6081cb0ef41Sopenharmony_ci 6091cb0ef41Sopenharmony_ci blk = ksl_merge_node(ksl, blk, i - 1); 6101cb0ef41Sopenharmony_ci } 6111cb0ef41Sopenharmony_ci} 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_cinghttp3_ksl_it nghttp3_ksl_lower_bound(nghttp3_ksl *ksl, 6141cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key) { 6151cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk = ksl->head; 6161cb0ef41Sopenharmony_ci nghttp3_ksl_it it; 6171cb0ef41Sopenharmony_ci size_t i; 6181cb0ef41Sopenharmony_ci 6191cb0ef41Sopenharmony_ci if (!blk) { 6201cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, &null_blk, 0); 6211cb0ef41Sopenharmony_ci return it; 6221cb0ef41Sopenharmony_ci } 6231cb0ef41Sopenharmony_ci 6241cb0ef41Sopenharmony_ci for (;;) { 6251cb0ef41Sopenharmony_ci i = ksl_bsearch(ksl, blk, key, ksl->compar); 6261cb0ef41Sopenharmony_ci 6271cb0ef41Sopenharmony_ci if (blk->leaf) { 6281cb0ef41Sopenharmony_ci if (i == blk->n && blk->next) { 6291cb0ef41Sopenharmony_ci blk = blk->next; 6301cb0ef41Sopenharmony_ci i = 0; 6311cb0ef41Sopenharmony_ci } 6321cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, blk, i); 6331cb0ef41Sopenharmony_ci return it; 6341cb0ef41Sopenharmony_ci } 6351cb0ef41Sopenharmony_ci 6361cb0ef41Sopenharmony_ci if (i == blk->n) { 6371cb0ef41Sopenharmony_ci /* This happens if descendant has smaller key. Fast forward to 6381cb0ef41Sopenharmony_ci find last node in this subtree. */ 6391cb0ef41Sopenharmony_ci for (; !blk->leaf; blk = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1)->blk) 6401cb0ef41Sopenharmony_ci ; 6411cb0ef41Sopenharmony_ci if (blk->next) { 6421cb0ef41Sopenharmony_ci blk = blk->next; 6431cb0ef41Sopenharmony_ci i = 0; 6441cb0ef41Sopenharmony_ci } else { 6451cb0ef41Sopenharmony_ci i = blk->n; 6461cb0ef41Sopenharmony_ci } 6471cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, blk, i); 6481cb0ef41Sopenharmony_ci return it; 6491cb0ef41Sopenharmony_ci } 6501cb0ef41Sopenharmony_ci blk = nghttp3_ksl_nth_node(ksl, blk, i)->blk; 6511cb0ef41Sopenharmony_ci } 6521cb0ef41Sopenharmony_ci} 6531cb0ef41Sopenharmony_ci 6541cb0ef41Sopenharmony_cinghttp3_ksl_it nghttp3_ksl_lower_bound_compar(nghttp3_ksl *ksl, 6551cb0ef41Sopenharmony_ci const nghttp3_ksl_key *key, 6561cb0ef41Sopenharmony_ci nghttp3_ksl_compar compar) { 6571cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk = ksl->head; 6581cb0ef41Sopenharmony_ci nghttp3_ksl_it it; 6591cb0ef41Sopenharmony_ci size_t i; 6601cb0ef41Sopenharmony_ci 6611cb0ef41Sopenharmony_ci if (!blk) { 6621cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, &null_blk, 0); 6631cb0ef41Sopenharmony_ci return it; 6641cb0ef41Sopenharmony_ci } 6651cb0ef41Sopenharmony_ci 6661cb0ef41Sopenharmony_ci for (;;) { 6671cb0ef41Sopenharmony_ci i = ksl_bsearch(ksl, blk, key, compar); 6681cb0ef41Sopenharmony_ci 6691cb0ef41Sopenharmony_ci if (blk->leaf) { 6701cb0ef41Sopenharmony_ci if (i == blk->n && blk->next) { 6711cb0ef41Sopenharmony_ci blk = blk->next; 6721cb0ef41Sopenharmony_ci i = 0; 6731cb0ef41Sopenharmony_ci } 6741cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, blk, i); 6751cb0ef41Sopenharmony_ci return it; 6761cb0ef41Sopenharmony_ci } 6771cb0ef41Sopenharmony_ci 6781cb0ef41Sopenharmony_ci if (i == blk->n) { 6791cb0ef41Sopenharmony_ci /* This happens if descendant has smaller key. Fast forward to 6801cb0ef41Sopenharmony_ci find last node in this subtree. */ 6811cb0ef41Sopenharmony_ci for (; !blk->leaf; blk = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1)->blk) 6821cb0ef41Sopenharmony_ci ; 6831cb0ef41Sopenharmony_ci if (blk->next) { 6841cb0ef41Sopenharmony_ci blk = blk->next; 6851cb0ef41Sopenharmony_ci i = 0; 6861cb0ef41Sopenharmony_ci } else { 6871cb0ef41Sopenharmony_ci i = blk->n; 6881cb0ef41Sopenharmony_ci } 6891cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, blk, i); 6901cb0ef41Sopenharmony_ci return it; 6911cb0ef41Sopenharmony_ci } 6921cb0ef41Sopenharmony_ci blk = nghttp3_ksl_nth_node(ksl, blk, i)->blk; 6931cb0ef41Sopenharmony_ci } 6941cb0ef41Sopenharmony_ci} 6951cb0ef41Sopenharmony_ci 6961cb0ef41Sopenharmony_civoid nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key, 6971cb0ef41Sopenharmony_ci const nghttp3_ksl_key *new_key) { 6981cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk = ksl->head; 6991cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 7001cb0ef41Sopenharmony_ci size_t i; 7011cb0ef41Sopenharmony_ci 7021cb0ef41Sopenharmony_ci assert(ksl->head); 7031cb0ef41Sopenharmony_ci 7041cb0ef41Sopenharmony_ci for (;;) { 7051cb0ef41Sopenharmony_ci i = ksl_bsearch(ksl, blk, old_key, ksl->compar); 7061cb0ef41Sopenharmony_ci 7071cb0ef41Sopenharmony_ci assert(i < blk->n); 7081cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 7091cb0ef41Sopenharmony_ci 7101cb0ef41Sopenharmony_ci if (blk->leaf) { 7111cb0ef41Sopenharmony_ci assert(key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key)); 7121cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, new_key); 7131cb0ef41Sopenharmony_ci return; 7141cb0ef41Sopenharmony_ci } 7151cb0ef41Sopenharmony_ci 7161cb0ef41Sopenharmony_ci if (key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key) || 7171cb0ef41Sopenharmony_ci ksl->compar((nghttp3_ksl_key *)node->key, new_key)) { 7181cb0ef41Sopenharmony_ci ksl_node_set_key(ksl, node, new_key); 7191cb0ef41Sopenharmony_ci } 7201cb0ef41Sopenharmony_ci 7211cb0ef41Sopenharmony_ci blk = node->blk; 7221cb0ef41Sopenharmony_ci } 7231cb0ef41Sopenharmony_ci} 7241cb0ef41Sopenharmony_ci 7251cb0ef41Sopenharmony_cistatic void ksl_print(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t level) { 7261cb0ef41Sopenharmony_ci size_t i; 7271cb0ef41Sopenharmony_ci nghttp3_ksl_node *node; 7281cb0ef41Sopenharmony_ci 7291cb0ef41Sopenharmony_ci fprintf(stderr, "LV=%zu n=%u\n", level, blk->n); 7301cb0ef41Sopenharmony_ci 7311cb0ef41Sopenharmony_ci if (blk->leaf) { 7321cb0ef41Sopenharmony_ci for (i = 0; i < blk->n; ++i) { 7331cb0ef41Sopenharmony_ci node = nghttp3_ksl_nth_node(ksl, blk, i); 7341cb0ef41Sopenharmony_ci fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key); 7351cb0ef41Sopenharmony_ci } 7361cb0ef41Sopenharmony_ci fprintf(stderr, "\n"); 7371cb0ef41Sopenharmony_ci return; 7381cb0ef41Sopenharmony_ci } 7391cb0ef41Sopenharmony_ci 7401cb0ef41Sopenharmony_ci for (i = 0; i < blk->n; ++i) { 7411cb0ef41Sopenharmony_ci ksl_print(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk, level + 1); 7421cb0ef41Sopenharmony_ci } 7431cb0ef41Sopenharmony_ci} 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_cisize_t nghttp3_ksl_len(nghttp3_ksl *ksl) { return ksl->n; } 7461cb0ef41Sopenharmony_ci 7471cb0ef41Sopenharmony_civoid nghttp3_ksl_clear(nghttp3_ksl *ksl) { 7481cb0ef41Sopenharmony_ci if (!ksl->head) { 7491cb0ef41Sopenharmony_ci return; 7501cb0ef41Sopenharmony_ci } 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci#ifdef NOMEMPOOL 7531cb0ef41Sopenharmony_ci ksl_free_blk(ksl, ksl->head); 7541cb0ef41Sopenharmony_ci#endif /* NOMEMPOOL */ 7551cb0ef41Sopenharmony_ci 7561cb0ef41Sopenharmony_ci ksl->front = ksl->back = ksl->head = NULL; 7571cb0ef41Sopenharmony_ci ksl->n = 0; 7581cb0ef41Sopenharmony_ci 7591cb0ef41Sopenharmony_ci nghttp3_objalloc_clear(&ksl->blkalloc); 7601cb0ef41Sopenharmony_ci} 7611cb0ef41Sopenharmony_ci 7621cb0ef41Sopenharmony_civoid nghttp3_ksl_print(nghttp3_ksl *ksl) { 7631cb0ef41Sopenharmony_ci if (!ksl->head) { 7641cb0ef41Sopenharmony_ci return; 7651cb0ef41Sopenharmony_ci } 7661cb0ef41Sopenharmony_ci 7671cb0ef41Sopenharmony_ci ksl_print(ksl, ksl->head, 0); 7681cb0ef41Sopenharmony_ci} 7691cb0ef41Sopenharmony_ci 7701cb0ef41Sopenharmony_cinghttp3_ksl_it nghttp3_ksl_begin(const nghttp3_ksl *ksl) { 7711cb0ef41Sopenharmony_ci nghttp3_ksl_it it; 7721cb0ef41Sopenharmony_ci 7731cb0ef41Sopenharmony_ci if (ksl->head) { 7741cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, ksl->front, 0); 7751cb0ef41Sopenharmony_ci } else { 7761cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, &null_blk, 0); 7771cb0ef41Sopenharmony_ci } 7781cb0ef41Sopenharmony_ci 7791cb0ef41Sopenharmony_ci return it; 7801cb0ef41Sopenharmony_ci} 7811cb0ef41Sopenharmony_ci 7821cb0ef41Sopenharmony_cinghttp3_ksl_it nghttp3_ksl_end(const nghttp3_ksl *ksl) { 7831cb0ef41Sopenharmony_ci nghttp3_ksl_it it; 7841cb0ef41Sopenharmony_ci 7851cb0ef41Sopenharmony_ci if (ksl->head) { 7861cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, ksl->back, ksl->back->n); 7871cb0ef41Sopenharmony_ci } else { 7881cb0ef41Sopenharmony_ci nghttp3_ksl_it_init(&it, ksl, &null_blk, 0); 7891cb0ef41Sopenharmony_ci } 7901cb0ef41Sopenharmony_ci 7911cb0ef41Sopenharmony_ci return it; 7921cb0ef41Sopenharmony_ci} 7931cb0ef41Sopenharmony_ci 7941cb0ef41Sopenharmony_civoid nghttp3_ksl_it_init(nghttp3_ksl_it *it, const nghttp3_ksl *ksl, 7951cb0ef41Sopenharmony_ci nghttp3_ksl_blk *blk, size_t i) { 7961cb0ef41Sopenharmony_ci it->ksl = ksl; 7971cb0ef41Sopenharmony_ci it->blk = blk; 7981cb0ef41Sopenharmony_ci it->i = i; 7991cb0ef41Sopenharmony_ci} 8001cb0ef41Sopenharmony_ci 8011cb0ef41Sopenharmony_civoid nghttp3_ksl_it_prev(nghttp3_ksl_it *it) { 8021cb0ef41Sopenharmony_ci assert(!nghttp3_ksl_it_begin(it)); 8031cb0ef41Sopenharmony_ci 8041cb0ef41Sopenharmony_ci if (it->i == 0) { 8051cb0ef41Sopenharmony_ci it->blk = it->blk->prev; 8061cb0ef41Sopenharmony_ci it->i = it->blk->n - 1; 8071cb0ef41Sopenharmony_ci } else { 8081cb0ef41Sopenharmony_ci --it->i; 8091cb0ef41Sopenharmony_ci } 8101cb0ef41Sopenharmony_ci} 8111cb0ef41Sopenharmony_ci 8121cb0ef41Sopenharmony_ciint nghttp3_ksl_it_begin(const nghttp3_ksl_it *it) { 8131cb0ef41Sopenharmony_ci return it->i == 0 && it->blk->prev == NULL; 8141cb0ef41Sopenharmony_ci} 8151cb0ef41Sopenharmony_ci 8161cb0ef41Sopenharmony_ciint nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs, 8171cb0ef41Sopenharmony_ci const nghttp3_ksl_key *rhs) { 8181cb0ef41Sopenharmony_ci const nghttp3_range *a = lhs, *b = rhs; 8191cb0ef41Sopenharmony_ci return a->begin < b->begin; 8201cb0ef41Sopenharmony_ci} 8211cb0ef41Sopenharmony_ci 8221cb0ef41Sopenharmony_ciint nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs, 8231cb0ef41Sopenharmony_ci const nghttp3_ksl_key *rhs) { 8241cb0ef41Sopenharmony_ci const nghttp3_range *a = lhs, *b = rhs; 8251cb0ef41Sopenharmony_ci return a->begin < b->begin && 8261cb0ef41Sopenharmony_ci !(nghttp3_max(a->begin, b->begin) < nghttp3_min(a->end, b->end)); 8271cb0ef41Sopenharmony_ci} 828