nghttp3_ksl.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. /*
  2. * nghttp3
  3. *
  4. * Copyright (c) 2019 nghttp3 contributors
  5. * Copyright (c) 2018 ngtcp2 contributors
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining
  8. * a copy of this software and associated documentation files (the
  9. * "Software"), to deal in the Software without restriction, including
  10. * without limitation the rights to use, copy, modify, merge, publish,
  11. * distribute, sublicense, and/or sell copies of the Software, and to
  12. * permit persons to whom the Software is furnished to do so, subject to
  13. * the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be
  16. * included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  19. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  20. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  21. * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  22. * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  23. * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  24. * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  25. */
  26. #include "nghttp3_ksl.h"
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <assert.h>
  30. #include <stdio.h>
  31. #include "nghttp3_macro.h"
  32. #include "nghttp3_mem.h"
  33. #include "nghttp3_range.h"
  34. static nghttp3_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}};
  35. nghttp3_objalloc_def(ksl_blk, nghttp3_ksl_blk, oplent)
  36. static size_t ksl_nodelen(size_t keylen) {
  37. assert(keylen >= sizeof(uint64_t));
  38. return (sizeof(nghttp3_ksl_node) + keylen - sizeof(uint64_t) + 0x7u) &
  39. ~(uintptr_t)0x7u;
  40. }
  41. static size_t ksl_blklen(size_t nodelen) {
  42. return sizeof(nghttp3_ksl_blk) + nodelen * NGHTTP3_KSL_MAX_NBLK -
  43. sizeof(uint64_t);
  44. }
  45. /*
  46. * ksl_node_set_key sets |key| to |node|.
  47. */
  48. static void ksl_node_set_key(nghttp3_ksl *ksl, nghttp3_ksl_node *node,
  49. const void *key) {
  50. memcpy(node->key, key, ksl->keylen);
  51. }
  52. void nghttp3_ksl_init(nghttp3_ksl *ksl, nghttp3_ksl_compar compar,
  53. nghttp3_ksl_search search, size_t keylen,
  54. const nghttp3_mem *mem) {
  55. size_t nodelen = ksl_nodelen(keylen);
  56. nghttp3_objalloc_init(&ksl->blkalloc,
  57. (ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu, mem);
  58. ksl->head = NULL;
  59. ksl->front = ksl->back = NULL;
  60. ksl->compar = compar;
  61. ksl->search = search;
  62. ksl->n = 0;
  63. ksl->keylen = keylen;
  64. ksl->nodelen = nodelen;
  65. }
  66. static nghttp3_ksl_blk *ksl_blk_objalloc_new(nghttp3_ksl *ksl) {
  67. return nghttp3_objalloc_ksl_blk_len_get(&ksl->blkalloc,
  68. ksl_blklen(ksl->nodelen));
  69. }
  70. static void ksl_blk_objalloc_del(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) {
  71. nghttp3_objalloc_ksl_blk_release(&ksl->blkalloc, blk);
  72. }
  73. static int ksl_head_init(nghttp3_ksl *ksl) {
  74. nghttp3_ksl_blk *head = ksl_blk_objalloc_new(ksl);
  75. if (!head) {
  76. return NGHTTP3_ERR_NOMEM;
  77. }
  78. head->next = head->prev = NULL;
  79. head->n = 0;
  80. head->leaf = 1;
  81. ksl->head = head;
  82. ksl->front = ksl->back = head;
  83. return 0;
  84. }
  85. #ifdef NOMEMPOOL
  86. /*
  87. * ksl_free_blk frees |blk| recursively.
  88. */
  89. static void ksl_free_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) {
  90. size_t i;
  91. if (!blk->leaf) {
  92. for (i = 0; i < blk->n; ++i) {
  93. ksl_free_blk(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk);
  94. }
  95. }
  96. ksl_blk_objalloc_del(ksl, blk);
  97. }
  98. #endif /* defined(NOMEMPOOL) */
  99. void nghttp3_ksl_free(nghttp3_ksl *ksl) {
  100. if (!ksl || !ksl->head) {
  101. return;
  102. }
  103. #ifdef NOMEMPOOL
  104. ksl_free_blk(ksl, ksl->head);
  105. #endif /* defined(NOMEMPOOL) */
  106. nghttp3_objalloc_free(&ksl->blkalloc);
  107. }
  108. /*
  109. * ksl_split_blk splits |blk| into 2 nghttp3_ksl_blk objects. The new
  110. * nghttp3_ksl_blk is always the "right" block.
  111. *
  112. * It returns the pointer to the nghttp3_ksl_blk created which is the
  113. * located at the right of |blk|, or NULL which indicates out of
  114. * memory error.
  115. */
  116. static nghttp3_ksl_blk *ksl_split_blk(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk) {
  117. nghttp3_ksl_blk *rblk;
  118. rblk = ksl_blk_objalloc_new(ksl);
  119. if (rblk == NULL) {
  120. return NULL;
  121. }
  122. rblk->next = blk->next;
  123. blk->next = rblk;
  124. if (rblk->next) {
  125. rblk->next->prev = rblk;
  126. } else if (ksl->back == blk) {
  127. ksl->back = rblk;
  128. }
  129. rblk->prev = blk;
  130. rblk->leaf = blk->leaf;
  131. rblk->n = blk->n / 2;
  132. blk->n -= rblk->n;
  133. memcpy(rblk->nodes, blk->nodes + ksl->nodelen * blk->n,
  134. ksl->nodelen * rblk->n);
  135. assert(blk->n >= NGHTTP3_KSL_MIN_NBLK);
  136. assert(rblk->n >= NGHTTP3_KSL_MIN_NBLK);
  137. return rblk;
  138. }
  139. /*
  140. * ksl_split_node splits a node included in |blk| at the position |i|
  141. * into 2 adjacent nodes. The new node is always inserted at the
  142. * position |i+1|.
  143. *
  144. * It returns 0 if it succeeds, or one of the following negative error
  145. * codes:
  146. *
  147. * NGHTTP3_ERR_NOMEM
  148. * Out of memory.
  149. */
  150. static int ksl_split_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
  151. nghttp3_ksl_node *node;
  152. nghttp3_ksl_blk *lblk = nghttp3_ksl_nth_node(ksl, blk, i)->blk, *rblk;
  153. rblk = ksl_split_blk(ksl, lblk);
  154. if (rblk == NULL) {
  155. return NGHTTP3_ERR_NOMEM;
  156. }
  157. memmove(blk->nodes + (i + 2) * ksl->nodelen,
  158. blk->nodes + (i + 1) * ksl->nodelen,
  159. ksl->nodelen * (blk->n - (i + 1)));
  160. node = nghttp3_ksl_nth_node(ksl, blk, i + 1);
  161. node->blk = rblk;
  162. ++blk->n;
  163. ksl_node_set_key(ksl, node,
  164. nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
  165. node = nghttp3_ksl_nth_node(ksl, blk, i);
  166. ksl_node_set_key(ksl, node,
  167. nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
  168. return 0;
  169. }
  170. /*
  171. * ksl_split_head splits a head (root) block. It increases the height
  172. * of skip list by 1.
  173. *
  174. * It returns 0 if it succeeds, or one of the following negative error
  175. * codes:
  176. *
  177. * NGHTTP3_ERR_NOMEM
  178. * Out of memory.
  179. */
  180. static int ksl_split_head(nghttp3_ksl *ksl) {
  181. nghttp3_ksl_blk *rblk = NULL, *lblk, *nhead = NULL;
  182. nghttp3_ksl_node *node;
  183. rblk = ksl_split_blk(ksl, ksl->head);
  184. if (rblk == NULL) {
  185. return NGHTTP3_ERR_NOMEM;
  186. }
  187. lblk = ksl->head;
  188. nhead = ksl_blk_objalloc_new(ksl);
  189. if (nhead == NULL) {
  190. ksl_blk_objalloc_del(ksl, rblk);
  191. return NGHTTP3_ERR_NOMEM;
  192. }
  193. nhead->next = nhead->prev = NULL;
  194. nhead->n = 2;
  195. nhead->leaf = 0;
  196. node = nghttp3_ksl_nth_node(ksl, nhead, 0);
  197. ksl_node_set_key(ksl, node,
  198. nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
  199. node->blk = lblk;
  200. node = nghttp3_ksl_nth_node(ksl, nhead, 1);
  201. ksl_node_set_key(ksl, node,
  202. nghttp3_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
  203. node->blk = rblk;
  204. ksl->head = nhead;
  205. return 0;
  206. }
  207. /*
  208. * ksl_insert_node inserts a node whose key is |key| with the
  209. * associated |data| at the index of |i|. This function assumes that
  210. * the number of nodes contained by |blk| is strictly less than
  211. * NGHTTP3_KSL_MAX_NBLK.
  212. */
  213. static void ksl_insert_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i,
  214. const nghttp3_ksl_key *key, void *data) {
  215. nghttp3_ksl_node *node;
  216. assert(blk->n < NGHTTP3_KSL_MAX_NBLK);
  217. memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
  218. ksl->nodelen * (blk->n - i));
  219. node = nghttp3_ksl_nth_node(ksl, blk, i);
  220. ksl_node_set_key(ksl, node, key);
  221. node->data = data;
  222. ++blk->n;
  223. }
  224. int nghttp3_ksl_insert(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
  225. const nghttp3_ksl_key *key, void *data) {
  226. nghttp3_ksl_blk *blk;
  227. nghttp3_ksl_node *node;
  228. size_t i;
  229. int rv;
  230. if (!ksl->head) {
  231. rv = ksl_head_init(ksl);
  232. if (rv != 0) {
  233. return rv;
  234. }
  235. }
  236. if (ksl->head->n == NGHTTP3_KSL_MAX_NBLK) {
  237. rv = ksl_split_head(ksl);
  238. if (rv != 0) {
  239. return rv;
  240. }
  241. }
  242. blk = ksl->head;
  243. for (;;) {
  244. i = ksl->search(ksl, blk, key);
  245. if (blk->leaf) {
  246. if (i < blk->n &&
  247. !ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) {
  248. if (it) {
  249. *it = nghttp3_ksl_end(ksl);
  250. }
  251. return NGHTTP3_ERR_INVALID_ARGUMENT;
  252. }
  253. ksl_insert_node(ksl, blk, i, key, data);
  254. ++ksl->n;
  255. if (it) {
  256. nghttp3_ksl_it_init(it, ksl, blk, i);
  257. }
  258. return 0;
  259. }
  260. if (i == blk->n) {
  261. /* This insertion extends the largest key in this subtree. */
  262. for (; !blk->leaf;) {
  263. node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1);
  264. if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) {
  265. rv = ksl_split_node(ksl, blk, blk->n - 1);
  266. if (rv != 0) {
  267. return rv;
  268. }
  269. node = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1);
  270. }
  271. ksl_node_set_key(ksl, node, key);
  272. blk = node->blk;
  273. }
  274. ksl_insert_node(ksl, blk, blk->n, key, data);
  275. ++ksl->n;
  276. if (it) {
  277. nghttp3_ksl_it_init(it, ksl, blk, blk->n - 1);
  278. }
  279. return 0;
  280. }
  281. node = nghttp3_ksl_nth_node(ksl, blk, i);
  282. if (node->blk->n == NGHTTP3_KSL_MAX_NBLK) {
  283. rv = ksl_split_node(ksl, blk, i);
  284. if (rv != 0) {
  285. return rv;
  286. }
  287. if (ksl->compar((nghttp3_ksl_key *)node->key, key)) {
  288. node = nghttp3_ksl_nth_node(ksl, blk, i + 1);
  289. if (ksl->compar((nghttp3_ksl_key *)node->key, key)) {
  290. ksl_node_set_key(ksl, node, key);
  291. }
  292. }
  293. }
  294. blk = node->blk;
  295. }
  296. }
  297. /*
  298. * ksl_remove_node removes the node included in |blk| at the index of
  299. * |i|.
  300. */
  301. static void ksl_remove_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
  302. memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen,
  303. ksl->nodelen * (blk->n - (i + 1)));
  304. --blk->n;
  305. }
  306. /*
  307. * ksl_merge_node merges 2 nodes which are the nodes at the index of
  308. * |i| and |i + 1|.
  309. *
  310. * If |blk| is the head (root) block and it contains just 2 nodes
  311. * before merging nodes, the merged block becomes head block, which
  312. * decreases the height of |ksl| by 1.
  313. *
  314. * This function returns the pointer to the merged block.
  315. */
  316. static nghttp3_ksl_blk *ksl_merge_node(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
  317. size_t i) {
  318. nghttp3_ksl_node *lnode;
  319. nghttp3_ksl_blk *lblk, *rblk;
  320. assert(i + 1 < blk->n);
  321. lnode = nghttp3_ksl_nth_node(ksl, blk, i);
  322. lblk = lnode->blk;
  323. rblk = nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk;
  324. assert(lblk->n + rblk->n < NGHTTP3_KSL_MAX_NBLK);
  325. memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes,
  326. ksl->nodelen * rblk->n);
  327. lblk->n += rblk->n;
  328. lblk->next = rblk->next;
  329. if (lblk->next) {
  330. lblk->next->prev = lblk;
  331. } else if (ksl->back == rblk) {
  332. ksl->back = lblk;
  333. }
  334. ksl_blk_objalloc_del(ksl, rblk);
  335. if (ksl->head == blk && blk->n == 2) {
  336. ksl_blk_objalloc_del(ksl, ksl->head);
  337. ksl->head = lblk;
  338. } else {
  339. ksl_remove_node(ksl, blk, i + 1);
  340. ksl_node_set_key(ksl, lnode,
  341. nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
  342. }
  343. return lblk;
  344. }
  345. /*
  346. * ksl_shift_left moves the first nodes in blk->nodes[i]->blk->nodes
  347. * to blk->nodes[i - 1]->blk->nodes in a manner that they have the
  348. * same amount of nodes as much as possible.
  349. */
  350. static void ksl_shift_left(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
  351. nghttp3_ksl_node *lnode, *rnode;
  352. nghttp3_ksl_blk *lblk, *rblk;
  353. size_t n;
  354. assert(i > 0);
  355. lnode = nghttp3_ksl_nth_node(ksl, blk, i - 1);
  356. rnode = nghttp3_ksl_nth_node(ksl, blk, i);
  357. lblk = lnode->blk;
  358. rblk = rnode->blk;
  359. assert(lblk->n < NGHTTP3_KSL_MAX_NBLK);
  360. assert(rblk->n > NGHTTP3_KSL_MIN_NBLK);
  361. n = (lblk->n + rblk->n + 1) / 2 - lblk->n;
  362. assert(n > 0);
  363. assert(lblk->n <= NGHTTP3_KSL_MAX_NBLK - n);
  364. assert(rblk->n >= NGHTTP3_KSL_MIN_NBLK + n);
  365. memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes, ksl->nodelen * n);
  366. lblk->n += (uint32_t)n;
  367. rblk->n -= (uint32_t)n;
  368. ksl_node_set_key(ksl, lnode,
  369. nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
  370. memmove(rblk->nodes, rblk->nodes + ksl->nodelen * n, ksl->nodelen * rblk->n);
  371. }
  372. /*
  373. * ksl_shift_right moves the last nodes in blk->nodes[i]->blk->nodes
  374. * to blk->nodes[i + 1]->blk->nodes in a manner that they have the
  375. * same amount of nodes as much as possible.
  376. */
  377. static void ksl_shift_right(nghttp3_ksl *ksl, nghttp3_ksl_blk *blk, size_t i) {
  378. nghttp3_ksl_node *lnode, *rnode;
  379. nghttp3_ksl_blk *lblk, *rblk;
  380. size_t n;
  381. assert(i < blk->n - 1);
  382. lnode = nghttp3_ksl_nth_node(ksl, blk, i);
  383. rnode = nghttp3_ksl_nth_node(ksl, blk, i + 1);
  384. lblk = lnode->blk;
  385. rblk = rnode->blk;
  386. assert(lblk->n > NGHTTP3_KSL_MIN_NBLK);
  387. assert(rblk->n < NGHTTP3_KSL_MAX_NBLK);
  388. n = (lblk->n + rblk->n + 1) / 2 - rblk->n;
  389. assert(n > 0);
  390. assert(lblk->n >= NGHTTP3_KSL_MIN_NBLK + n);
  391. assert(rblk->n <= NGHTTP3_KSL_MAX_NBLK - n);
  392. memmove(rblk->nodes + ksl->nodelen * n, rblk->nodes, ksl->nodelen * rblk->n);
  393. rblk->n += (uint32_t)n;
  394. lblk->n -= (uint32_t)n;
  395. memcpy(rblk->nodes, lblk->nodes + ksl->nodelen * lblk->n, ksl->nodelen * n);
  396. ksl_node_set_key(ksl, lnode,
  397. nghttp3_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
  398. }
  399. /*
  400. * key_equal returns nonzero if |lhs| and |rhs| are equal using the
  401. * function |compar|.
  402. */
  403. static int key_equal(nghttp3_ksl_compar compar, const nghttp3_ksl_key *lhs,
  404. const nghttp3_ksl_key *rhs) {
  405. return !compar(lhs, rhs) && !compar(rhs, lhs);
  406. }
  407. int nghttp3_ksl_remove_hint(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
  408. const nghttp3_ksl_it *hint,
  409. const nghttp3_ksl_key *key) {
  410. nghttp3_ksl_blk *blk = hint->blk;
  411. assert(ksl->head);
  412. if (blk->n <= NGHTTP3_KSL_MIN_NBLK) {
  413. return nghttp3_ksl_remove(ksl, it, key);
  414. }
  415. ksl_remove_node(ksl, blk, hint->i);
  416. --ksl->n;
  417. if (it) {
  418. if (hint->i == blk->n && blk->next) {
  419. nghttp3_ksl_it_init(it, ksl, blk->next, 0);
  420. } else {
  421. nghttp3_ksl_it_init(it, ksl, blk, hint->i);
  422. }
  423. }
  424. return 0;
  425. }
  426. int nghttp3_ksl_remove(nghttp3_ksl *ksl, nghttp3_ksl_it *it,
  427. const nghttp3_ksl_key *key) {
  428. nghttp3_ksl_blk *blk = ksl->head;
  429. nghttp3_ksl_node *node;
  430. size_t i;
  431. if (!blk) {
  432. return NGHTTP3_ERR_INVALID_ARGUMENT;
  433. }
  434. if (!blk->leaf && blk->n == 2 &&
  435. nghttp3_ksl_nth_node(ksl, blk, 0)->blk->n == NGHTTP3_KSL_MIN_NBLK &&
  436. nghttp3_ksl_nth_node(ksl, blk, 1)->blk->n == NGHTTP3_KSL_MIN_NBLK) {
  437. blk = ksl_merge_node(ksl, blk, 0);
  438. }
  439. for (;;) {
  440. i = ksl->search(ksl, blk, key);
  441. if (i == blk->n) {
  442. if (it) {
  443. *it = nghttp3_ksl_end(ksl);
  444. }
  445. return NGHTTP3_ERR_INVALID_ARGUMENT;
  446. }
  447. if (blk->leaf) {
  448. if (ksl->compar(key, nghttp3_ksl_nth_node(ksl, blk, i)->key)) {
  449. if (it) {
  450. *it = nghttp3_ksl_end(ksl);
  451. }
  452. return NGHTTP3_ERR_INVALID_ARGUMENT;
  453. }
  454. ksl_remove_node(ksl, blk, i);
  455. --ksl->n;
  456. if (it) {
  457. if (blk->n == i && blk->next) {
  458. nghttp3_ksl_it_init(it, ksl, blk->next, 0);
  459. } else {
  460. nghttp3_ksl_it_init(it, ksl, blk, i);
  461. }
  462. }
  463. return 0;
  464. }
  465. node = nghttp3_ksl_nth_node(ksl, blk, i);
  466. if (node->blk->n > NGHTTP3_KSL_MIN_NBLK) {
  467. blk = node->blk;
  468. continue;
  469. }
  470. assert(node->blk->n == NGHTTP3_KSL_MIN_NBLK);
  471. if (i + 1 < blk->n &&
  472. nghttp3_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGHTTP3_KSL_MIN_NBLK) {
  473. ksl_shift_left(ksl, blk, i + 1);
  474. blk = node->blk;
  475. continue;
  476. }
  477. if (i > 0 &&
  478. nghttp3_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGHTTP3_KSL_MIN_NBLK) {
  479. ksl_shift_right(ksl, blk, i - 1);
  480. blk = node->blk;
  481. continue;
  482. }
  483. if (i + 1 < blk->n) {
  484. blk = ksl_merge_node(ksl, blk, i);
  485. continue;
  486. }
  487. assert(i > 0);
  488. blk = ksl_merge_node(ksl, blk, i - 1);
  489. }
  490. }
  491. nghttp3_ksl_it nghttp3_ksl_lower_bound(const nghttp3_ksl *ksl,
  492. const nghttp3_ksl_key *key) {
  493. return nghttp3_ksl_lower_bound_search(ksl, key, ksl->search);
  494. }
  495. nghttp3_ksl_it nghttp3_ksl_lower_bound_search(const nghttp3_ksl *ksl,
  496. const nghttp3_ksl_key *key,
  497. nghttp3_ksl_search search) {
  498. nghttp3_ksl_blk *blk = ksl->head;
  499. nghttp3_ksl_it it;
  500. size_t i;
  501. if (!blk) {
  502. nghttp3_ksl_it_init(&it, ksl, &null_blk, 0);
  503. return it;
  504. }
  505. for (;;) {
  506. i = search(ksl, blk, key);
  507. if (blk->leaf) {
  508. if (i == blk->n && blk->next) {
  509. blk = blk->next;
  510. i = 0;
  511. }
  512. nghttp3_ksl_it_init(&it, ksl, blk, i);
  513. return it;
  514. }
  515. if (i == blk->n) {
  516. /* This happens if descendant has smaller key. Fast forward to
  517. find last node in this subtree. */
  518. for (; !blk->leaf; blk = nghttp3_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
  519. ;
  520. if (blk->next) {
  521. blk = blk->next;
  522. i = 0;
  523. } else {
  524. i = blk->n;
  525. }
  526. nghttp3_ksl_it_init(&it, ksl, blk, i);
  527. return it;
  528. }
  529. blk = nghttp3_ksl_nth_node(ksl, blk, i)->blk;
  530. }
  531. }
  532. void nghttp3_ksl_update_key(nghttp3_ksl *ksl, const nghttp3_ksl_key *old_key,
  533. const nghttp3_ksl_key *new_key) {
  534. nghttp3_ksl_blk *blk = ksl->head;
  535. nghttp3_ksl_node *node;
  536. size_t i;
  537. assert(ksl->head);
  538. for (;;) {
  539. i = ksl->search(ksl, blk, old_key);
  540. assert(i < blk->n);
  541. node = nghttp3_ksl_nth_node(ksl, blk, i);
  542. if (blk->leaf) {
  543. assert(key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key));
  544. ksl_node_set_key(ksl, node, new_key);
  545. return;
  546. }
  547. if (key_equal(ksl->compar, (nghttp3_ksl_key *)node->key, old_key) ||
  548. ksl->compar((nghttp3_ksl_key *)node->key, new_key)) {
  549. ksl_node_set_key(ksl, node, new_key);
  550. }
  551. blk = node->blk;
  552. }
  553. }
  554. size_t nghttp3_ksl_len(const nghttp3_ksl *ksl) { return ksl->n; }
  555. void nghttp3_ksl_clear(nghttp3_ksl *ksl) {
  556. if (!ksl->head) {
  557. return;
  558. }
  559. #ifdef NOMEMPOOL
  560. ksl_free_blk(ksl, ksl->head);
  561. #endif /* defined(NOMEMPOOL) */
  562. ksl->front = ksl->back = ksl->head = NULL;
  563. ksl->n = 0;
  564. nghttp3_objalloc_clear(&ksl->blkalloc);
  565. }
  566. #ifndef WIN32
  567. static void ksl_print(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
  568. size_t level) {
  569. size_t i;
  570. nghttp3_ksl_node *node;
  571. fprintf(stderr, "LV=%zu n=%u\n", level, blk->n);
  572. if (blk->leaf) {
  573. for (i = 0; i < blk->n; ++i) {
  574. node = nghttp3_ksl_nth_node(ksl, blk, i);
  575. fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
  576. }
  577. fprintf(stderr, "\n");
  578. return;
  579. }
  580. for (i = 0; i < blk->n; ++i) {
  581. ksl_print(ksl, nghttp3_ksl_nth_node(ksl, blk, i)->blk, level + 1);
  582. }
  583. }
  584. void nghttp3_ksl_print(const nghttp3_ksl *ksl) {
  585. if (!ksl->head) {
  586. return;
  587. }
  588. ksl_print(ksl, ksl->head, 0);
  589. }
  590. #endif /* !defined(WIN32) */
  591. nghttp3_ksl_it nghttp3_ksl_begin(const nghttp3_ksl *ksl) {
  592. nghttp3_ksl_it it;
  593. if (ksl->head) {
  594. nghttp3_ksl_it_init(&it, ksl, ksl->front, 0);
  595. } else {
  596. nghttp3_ksl_it_init(&it, ksl, &null_blk, 0);
  597. }
  598. return it;
  599. }
  600. nghttp3_ksl_it nghttp3_ksl_end(const nghttp3_ksl *ksl) {
  601. nghttp3_ksl_it it;
  602. if (ksl->head) {
  603. nghttp3_ksl_it_init(&it, ksl, ksl->back, ksl->back->n);
  604. } else {
  605. nghttp3_ksl_it_init(&it, ksl, &null_blk, 0);
  606. }
  607. return it;
  608. }
  609. void nghttp3_ksl_it_init(nghttp3_ksl_it *it, const nghttp3_ksl *ksl,
  610. nghttp3_ksl_blk *blk, size_t i) {
  611. it->ksl = ksl;
  612. it->blk = blk;
  613. it->i = i;
  614. }
  615. void nghttp3_ksl_it_prev(nghttp3_ksl_it *it) {
  616. assert(!nghttp3_ksl_it_begin(it));
  617. if (it->i == 0) {
  618. it->blk = it->blk->prev;
  619. it->i = it->blk->n - 1;
  620. } else {
  621. --it->i;
  622. }
  623. }
  624. int nghttp3_ksl_it_begin(const nghttp3_ksl_it *it) {
  625. return it->i == 0 && it->blk->prev == NULL;
  626. }
  627. int nghttp3_ksl_range_compar(const nghttp3_ksl_key *lhs,
  628. const nghttp3_ksl_key *rhs) {
  629. const nghttp3_range *a = lhs, *b = rhs;
  630. return a->begin < b->begin;
  631. }
  632. nghttp3_ksl_search_def(range, nghttp3_ksl_range_compar)
  633. size_t nghttp3_ksl_range_search(const nghttp3_ksl *ksl, nghttp3_ksl_blk *blk,
  634. const nghttp3_ksl_key *key) {
  635. return ksl_range_search(ksl, blk, key);
  636. }
  637. int nghttp3_ksl_range_exclusive_compar(const nghttp3_ksl_key *lhs,
  638. const nghttp3_ksl_key *rhs) {
  639. const nghttp3_range *a = lhs, *b = rhs;
  640. return a->begin < b->begin && !(nghttp3_max_uint64(a->begin, b->begin) <
  641. nghttp3_min_uint64(a->end, b->end));
  642. }
  643. nghttp3_ksl_search_def(range_exclusive, nghttp3_ksl_range_exclusive_compar)
  644. size_t nghttp3_ksl_range_exclusive_search(const nghttp3_ksl *ksl,
  645. nghttp3_ksl_blk *blk,
  646. const nghttp3_ksl_key *key) {
  647. return ksl_range_exclusive_search(ksl, blk, key);
  648. }
  649. int nghttp3_ksl_uint64_less(const nghttp3_ksl_key *lhs,
  650. const nghttp3_ksl_key *rhs) {
  651. return *(uint64_t *)lhs < *(uint64_t *)rhs;
  652. }
  653. nghttp3_ksl_search_def(uint64_less, nghttp3_ksl_uint64_less)
  654. size_t nghttp3_ksl_uint64_less_search(const nghttp3_ksl *ksl,
  655. nghttp3_ksl_blk *blk,
  656. const nghttp3_ksl_key *key) {
  657. return ksl_uint64_less_search(ksl, blk, key);
  658. }
  659. int nghttp3_ksl_int64_greater(const nghttp3_ksl_key *lhs,
  660. const nghttp3_ksl_key *rhs) {
  661. return *(int64_t *)lhs > *(int64_t *)rhs;
  662. }
  663. nghttp3_ksl_search_def(int64_greater, nghttp3_ksl_int64_greater)
  664. size_t nghttp3_ksl_int64_greater_search(const nghttp3_ksl *ksl,
  665. nghttp3_ksl_blk *blk,
  666. const nghttp3_ksl_key *key) {
  667. return ksl_int64_greater_search(ksl, blk, key);
  668. }