1 /*
2 * ngtcp2
3 *
4 * Copyright (c) 2018 ngtcp2 contributors
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25 #include "ngtcp2_ksl.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <stdio.h>
31
32 #include "ngtcp2_macro.h"
33 #include "ngtcp2_mem.h"
34 #include "ngtcp2_range.h"
35
36 static ngtcp2_ksl_blk null_blk = {{{NULL, NULL, 0, 0, {0}}}};
37
ksl_nodelen(size_t keylen)38 static size_t ksl_nodelen(size_t keylen) {
39 return (sizeof(ngtcp2_ksl_node) + keylen - sizeof(uint64_t) + 0xfu) &
40 ~(uintptr_t)0xfu;
41 }
42
ksl_blklen(size_t nodelen)43 static size_t ksl_blklen(size_t nodelen) {
44 return sizeof(ngtcp2_ksl_blk) + nodelen * NGTCP2_KSL_MAX_NBLK -
45 sizeof(uint64_t);
46 }
47
48 /*
49 * ksl_node_set_key sets |key| to |node|.
50 */
ksl_node_set_key(ngtcp2_ksl * ksl,ngtcp2_ksl_node * node,const void * key)51 static void ksl_node_set_key(ngtcp2_ksl *ksl, ngtcp2_ksl_node *node,
52 const void *key) {
53 memcpy(node->key, key, ksl->keylen);
54 }
55
ngtcp2_ksl_init(ngtcp2_ksl * ksl,ngtcp2_ksl_compar compar,size_t keylen,const ngtcp2_mem * mem)56 void ngtcp2_ksl_init(ngtcp2_ksl *ksl, ngtcp2_ksl_compar compar, size_t keylen,
57 const ngtcp2_mem *mem) {
58 size_t nodelen = ksl_nodelen(keylen);
59
60 ngtcp2_objalloc_init(&ksl->blkalloc,
61 ((ksl_blklen(nodelen) + 0xfu) & ~(uintptr_t)0xfu) * 8,
62 mem);
63
64 ksl->head = NULL;
65 ksl->front = ksl->back = NULL;
66 ksl->compar = compar;
67 ksl->keylen = keylen;
68 ksl->nodelen = nodelen;
69 ksl->n = 0;
70 }
71
ksl_blk_objalloc_new(ngtcp2_ksl * ksl)72 static ngtcp2_ksl_blk *ksl_blk_objalloc_new(ngtcp2_ksl *ksl) {
73 return ngtcp2_objalloc_ksl_blk_len_get(&ksl->blkalloc,
74 ksl_blklen(ksl->nodelen));
75 }
76
ksl_blk_objalloc_del(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk)77 static void ksl_blk_objalloc_del(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
78 ngtcp2_objalloc_ksl_blk_release(&ksl->blkalloc, blk);
79 }
80
ksl_head_init(ngtcp2_ksl * ksl)81 static int ksl_head_init(ngtcp2_ksl *ksl) {
82 ngtcp2_ksl_blk *head = ksl_blk_objalloc_new(ksl);
83 if (!head) {
84 return NGTCP2_ERR_NOMEM;
85 }
86
87 head->next = head->prev = NULL;
88 head->n = 0;
89 head->leaf = 1;
90
91 ksl->head = head;
92 ksl->front = ksl->back = head;
93
94 return 0;
95 }
96
97 #ifdef NOMEMPOOL
98 /*
99 * ksl_free_blk frees |blk| recursively.
100 */
ksl_free_blk(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk)101 static void ksl_free_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
102 size_t i;
103
104 if (!blk->leaf) {
105 for (i = 0; i < blk->n; ++i) {
106 ksl_free_blk(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk);
107 }
108 }
109
110 ksl_blk_objalloc_del(ksl, blk);
111 }
112 #endif /* NOMEMPOOL */
113
ngtcp2_ksl_free(ngtcp2_ksl * ksl)114 void ngtcp2_ksl_free(ngtcp2_ksl *ksl) {
115 if (!ksl || !ksl->head) {
116 return;
117 }
118
119 #ifdef NOMEMPOOL
120 ksl_free_blk(ksl, ksl->head);
121 #endif /* NOMEMPOOL */
122
123 ngtcp2_objalloc_free(&ksl->blkalloc);
124 }
125
126 /*
127 * ksl_split_blk splits |blk| into 2 ngtcp2_ksl_blk objects. The new
128 * ngtcp2_ksl_blk is always the "right" block.
129 *
130 * It returns the pointer to the ngtcp2_ksl_blk created which is the
131 * located at the right of |blk|, or NULL which indicates out of
132 * memory error.
133 */
ksl_split_blk(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk)134 static ngtcp2_ksl_blk *ksl_split_blk(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk) {
135 ngtcp2_ksl_blk *rblk;
136
137 rblk = ksl_blk_objalloc_new(ksl);
138 if (rblk == NULL) {
139 return NULL;
140 }
141
142 rblk->next = blk->next;
143 blk->next = rblk;
144 if (rblk->next) {
145 rblk->next->prev = rblk;
146 } else if (ksl->back == blk) {
147 ksl->back = rblk;
148 }
149 rblk->prev = blk;
150 rblk->leaf = blk->leaf;
151
152 rblk->n = blk->n / 2;
153
154 memcpy(rblk->nodes, blk->nodes + ksl->nodelen * (blk->n - rblk->n),
155 ksl->nodelen * rblk->n);
156
157 blk->n -= rblk->n;
158
159 assert(blk->n >= NGTCP2_KSL_MIN_NBLK);
160 assert(rblk->n >= NGTCP2_KSL_MIN_NBLK);
161
162 return rblk;
163 }
164
165 /*
166 * ksl_split_node splits a node included in |blk| at the position |i|
167 * into 2 adjacent nodes. The new node is always inserted at the
168 * position |i+1|.
169 *
170 * It returns 0 if it succeeds, or one of the following negative error
171 * codes:
172 *
173 * NGTCP2_ERR_NOMEM
174 * Out of memory.
175 */
ksl_split_node(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)176 static int ksl_split_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
177 ngtcp2_ksl_node *node;
178 ngtcp2_ksl_blk *lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk, *rblk;
179
180 rblk = ksl_split_blk(ksl, lblk);
181 if (rblk == NULL) {
182 return NGTCP2_ERR_NOMEM;
183 }
184
185 memmove(blk->nodes + (i + 2) * ksl->nodelen,
186 blk->nodes + (i + 1) * ksl->nodelen,
187 ksl->nodelen * (blk->n - (i + 1)));
188
189 node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
190 node->blk = rblk;
191 ++blk->n;
192 ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
193
194 node = ngtcp2_ksl_nth_node(ksl, blk, i);
195 ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
196
197 return 0;
198 }
199
200 /*
201 * ksl_split_head splits a head (root) block. It increases the height
202 * of skip list by 1.
203 *
204 * It returns 0 if it succeeds, or one of the following negative error
205 * codes:
206 *
207 * NGTCP2_ERR_NOMEM
208 * Out of memory.
209 */
ksl_split_head(ngtcp2_ksl * ksl)210 static int ksl_split_head(ngtcp2_ksl *ksl) {
211 ngtcp2_ksl_blk *rblk = NULL, *lblk, *nhead = NULL;
212 ngtcp2_ksl_node *node;
213
214 rblk = ksl_split_blk(ksl, ksl->head);
215 if (rblk == NULL) {
216 return NGTCP2_ERR_NOMEM;
217 }
218
219 lblk = ksl->head;
220
221 nhead = ksl_blk_objalloc_new(ksl);
222 if (nhead == NULL) {
223 ksl_blk_objalloc_del(ksl, rblk);
224 return NGTCP2_ERR_NOMEM;
225 }
226 nhead->next = nhead->prev = NULL;
227 nhead->n = 2;
228 nhead->leaf = 0;
229
230 node = ngtcp2_ksl_nth_node(ksl, nhead, 0);
231 ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
232 node->blk = lblk;
233
234 node = ngtcp2_ksl_nth_node(ksl, nhead, 1);
235 ksl_node_set_key(ksl, node, ngtcp2_ksl_nth_node(ksl, rblk, rblk->n - 1)->key);
236 node->blk = rblk;
237
238 ksl->head = nhead;
239
240 return 0;
241 }
242
243 /*
244 * insert_node inserts a node whose key is |key| with the associated
245 * |data| at the index of |i|. This function assumes that the number
246 * of nodes contained by |blk| is strictly less than
247 * NGTCP2_KSL_MAX_NBLK.
248 */
ksl_insert_node(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i,const ngtcp2_ksl_key * key,void * data)249 static void ksl_insert_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i,
250 const ngtcp2_ksl_key *key, void *data) {
251 ngtcp2_ksl_node *node;
252
253 assert(blk->n < NGTCP2_KSL_MAX_NBLK);
254
255 memmove(blk->nodes + (i + 1) * ksl->nodelen, blk->nodes + i * ksl->nodelen,
256 ksl->nodelen * (blk->n - i));
257
258 node = ngtcp2_ksl_nth_node(ksl, blk, i);
259 ksl_node_set_key(ksl, node, key);
260 node->data = data;
261
262 ++blk->n;
263 }
264
ksl_bsearch(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,const ngtcp2_ksl_key * key,ngtcp2_ksl_compar compar)265 static size_t ksl_bsearch(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
266 const ngtcp2_ksl_key *key, ngtcp2_ksl_compar compar) {
267 size_t i;
268 ngtcp2_ksl_node *node;
269
270 for (i = 0, node = (ngtcp2_ksl_node *)(void *)blk->nodes;
271 i < blk->n && compar((ngtcp2_ksl_key *)node->key, key);
272 ++i, node = (ngtcp2_ksl_node *)(void *)((uint8_t *)node + ksl->nodelen))
273 ;
274
275 return i;
276 }
277
ngtcp2_ksl_insert(ngtcp2_ksl * ksl,ngtcp2_ksl_it * it,const ngtcp2_ksl_key * key,void * data)278 int ngtcp2_ksl_insert(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
279 const ngtcp2_ksl_key *key, void *data) {
280 ngtcp2_ksl_blk *blk;
281 ngtcp2_ksl_node *node;
282 size_t i;
283 int rv;
284
285 if (!ksl->head) {
286 rv = ksl_head_init(ksl);
287 if (rv != 0) {
288 return rv;
289 }
290 }
291
292 blk = ksl->head;
293
294 if (blk->n == NGTCP2_KSL_MAX_NBLK) {
295 rv = ksl_split_head(ksl);
296 if (rv != 0) {
297 return rv;
298 }
299 blk = ksl->head;
300 }
301
302 for (;;) {
303 i = ksl_bsearch(ksl, blk, key, ksl->compar);
304
305 if (blk->leaf) {
306 if (i < blk->n &&
307 !ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
308 if (it) {
309 *it = ngtcp2_ksl_end(ksl);
310 }
311 return NGTCP2_ERR_INVALID_ARGUMENT;
312 }
313 ksl_insert_node(ksl, blk, i, key, data);
314 ++ksl->n;
315 if (it) {
316 ngtcp2_ksl_it_init(it, ksl, blk, i);
317 }
318 return 0;
319 }
320
321 if (i == blk->n) {
322 /* This insertion extends the largest key in this subtree. */
323 for (; !blk->leaf;) {
324 node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
325 if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
326 rv = ksl_split_node(ksl, blk, blk->n - 1);
327 if (rv != 0) {
328 return rv;
329 }
330 node = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1);
331 }
332 ksl_node_set_key(ksl, node, key);
333 blk = node->blk;
334 }
335 ksl_insert_node(ksl, blk, blk->n, key, data);
336 ++ksl->n;
337 if (it) {
338 ngtcp2_ksl_it_init(it, ksl, blk, blk->n - 1);
339 }
340 return 0;
341 }
342
343 node = ngtcp2_ksl_nth_node(ksl, blk, i);
344
345 if (node->blk->n == NGTCP2_KSL_MAX_NBLK) {
346 rv = ksl_split_node(ksl, blk, i);
347 if (rv != 0) {
348 return rv;
349 }
350 if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
351 node = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
352 if (ksl->compar((ngtcp2_ksl_key *)node->key, key)) {
353 ksl_node_set_key(ksl, node, key);
354 }
355 }
356 }
357
358 blk = node->blk;
359 }
360 }
361
362 /*
363 * ksl_remove_node removes the node included in |blk| at the index of
364 * |i|.
365 */
ksl_remove_node(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)366 static void ksl_remove_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
367 memmove(blk->nodes + i * ksl->nodelen, blk->nodes + (i + 1) * ksl->nodelen,
368 ksl->nodelen * (blk->n - (i + 1)));
369
370 --blk->n;
371 }
372
373 /*
374 * ksl_merge_node merges 2 nodes which are the nodes at the index of
375 * |i| and |i + 1|.
376 *
377 * If |blk| is the direct descendant of head (root) block and the head
378 * block contains just 2 nodes, the merged block becomes head block,
379 * which decreases the height of |ksl| by 1.
380 *
381 * This function returns the pointer to the merged block.
382 */
ksl_merge_node(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)383 static ngtcp2_ksl_blk *ksl_merge_node(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk,
384 size_t i) {
385 ngtcp2_ksl_blk *lblk, *rblk;
386
387 assert(i + 1 < blk->n);
388
389 lblk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
390 rblk = ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk;
391
392 assert(lblk->n + rblk->n < NGTCP2_KSL_MAX_NBLK);
393
394 memcpy(lblk->nodes + ksl->nodelen * lblk->n, rblk->nodes,
395 ksl->nodelen * rblk->n);
396
397 lblk->n += rblk->n;
398 lblk->next = rblk->next;
399 if (lblk->next) {
400 lblk->next->prev = lblk;
401 } else if (ksl->back == rblk) {
402 ksl->back = lblk;
403 }
404
405 ksl_blk_objalloc_del(ksl, rblk);
406
407 if (ksl->head == blk && blk->n == 2) {
408 ksl_blk_objalloc_del(ksl, ksl->head);
409 ksl->head = lblk;
410 } else {
411 ksl_remove_node(ksl, blk, i + 1);
412 ksl_node_set_key(ksl, ngtcp2_ksl_nth_node(ksl, blk, i),
413 ngtcp2_ksl_nth_node(ksl, lblk, lblk->n - 1)->key);
414 }
415
416 return lblk;
417 }
418
419 /*
420 * ksl_shift_left moves the first nodes in blk->nodes[i]->blk->nodes
421 * to blk->nodes[i - 1]->blk->nodes in a manner that they have the
422 * same amount of nodes as much as possible.
423 */
ksl_shift_left(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)424 static void ksl_shift_left(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
425 ngtcp2_ksl_node *lnode, *rnode;
426 size_t n;
427
428 assert(i > 0);
429
430 lnode = ngtcp2_ksl_nth_node(ksl, blk, i - 1);
431 rnode = ngtcp2_ksl_nth_node(ksl, blk, i);
432
433 assert(lnode->blk->n < NGTCP2_KSL_MAX_NBLK);
434 assert(rnode->blk->n > NGTCP2_KSL_MIN_NBLK);
435
436 n = (lnode->blk->n + rnode->blk->n + 1) / 2 - lnode->blk->n;
437
438 assert(n > 0);
439 assert(lnode->blk->n <= NGTCP2_KSL_MAX_NBLK - n);
440 assert(rnode->blk->n >= NGTCP2_KSL_MIN_NBLK + n);
441
442 memcpy(lnode->blk->nodes + ksl->nodelen * lnode->blk->n, rnode->blk->nodes,
443 ksl->nodelen * n);
444
445 lnode->blk->n += (uint32_t)n;
446 rnode->blk->n -= (uint32_t)n;
447
448 ksl_node_set_key(
449 ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
450
451 memmove(rnode->blk->nodes, rnode->blk->nodes + ksl->nodelen * n,
452 ksl->nodelen * rnode->blk->n);
453 }
454
455 /*
456 * ksl_shift_right moves the last nodes in blk->nodes[i]->blk->nodes
457 * to blk->nodes[i + 1]->blk->nodes in a manner that they have the
458 * same amount of nodes as much as possible..
459 */
ksl_shift_right(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)460 static void ksl_shift_right(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t i) {
461 ngtcp2_ksl_node *lnode, *rnode;
462 size_t n;
463
464 assert(i < blk->n - 1);
465
466 lnode = ngtcp2_ksl_nth_node(ksl, blk, i);
467 rnode = ngtcp2_ksl_nth_node(ksl, blk, i + 1);
468
469 assert(lnode->blk->n > NGTCP2_KSL_MIN_NBLK);
470 assert(rnode->blk->n < NGTCP2_KSL_MAX_NBLK);
471
472 n = (lnode->blk->n + rnode->blk->n + 1) / 2 - rnode->blk->n;
473
474 assert(n > 0);
475 assert(lnode->blk->n >= NGTCP2_KSL_MIN_NBLK + n);
476 assert(rnode->blk->n <= NGTCP2_KSL_MAX_NBLK - n);
477
478 memmove(rnode->blk->nodes + ksl->nodelen * n, rnode->blk->nodes,
479 ksl->nodelen * rnode->blk->n);
480
481 rnode->blk->n += (uint32_t)n;
482 lnode->blk->n -= (uint32_t)n;
483
484 memcpy(rnode->blk->nodes, lnode->blk->nodes + ksl->nodelen * lnode->blk->n,
485 ksl->nodelen * n);
486
487 ksl_node_set_key(
488 ksl, lnode, ngtcp2_ksl_nth_node(ksl, lnode->blk, lnode->blk->n - 1)->key);
489 }
490
491 /*
492 * key_equal returns nonzero if |lhs| and |rhs| are equal using the
493 * function |compar|.
494 */
key_equal(ngtcp2_ksl_compar compar,const ngtcp2_ksl_key * lhs,const ngtcp2_ksl_key * rhs)495 static int key_equal(ngtcp2_ksl_compar compar, const ngtcp2_ksl_key *lhs,
496 const ngtcp2_ksl_key *rhs) {
497 return !compar(lhs, rhs) && !compar(rhs, lhs);
498 }
499
ngtcp2_ksl_remove_hint(ngtcp2_ksl * ksl,ngtcp2_ksl_it * it,const ngtcp2_ksl_it * hint,const ngtcp2_ksl_key * key)500 int ngtcp2_ksl_remove_hint(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
501 const ngtcp2_ksl_it *hint,
502 const ngtcp2_ksl_key *key) {
503 ngtcp2_ksl_blk *blk = hint->blk;
504
505 assert(ksl->head);
506
507 if (blk->n <= NGTCP2_KSL_MIN_NBLK) {
508 return ngtcp2_ksl_remove(ksl, it, key);
509 }
510
511 ksl_remove_node(ksl, blk, hint->i);
512
513 --ksl->n;
514
515 if (it) {
516 if (hint->i == blk->n && blk->next) {
517 ngtcp2_ksl_it_init(it, ksl, blk->next, 0);
518 } else {
519 ngtcp2_ksl_it_init(it, ksl, blk, hint->i);
520 }
521 }
522
523 return 0;
524 }
525
ngtcp2_ksl_remove(ngtcp2_ksl * ksl,ngtcp2_ksl_it * it,const ngtcp2_ksl_key * key)526 int ngtcp2_ksl_remove(ngtcp2_ksl *ksl, ngtcp2_ksl_it *it,
527 const ngtcp2_ksl_key *key) {
528 ngtcp2_ksl_blk *blk = ksl->head;
529 ngtcp2_ksl_node *node;
530 size_t i;
531
532 if (!ksl->head) {
533 return NGTCP2_ERR_INVALID_ARGUMENT;
534 }
535
536 if (!blk->leaf && blk->n == 2 &&
537 ngtcp2_ksl_nth_node(ksl, blk, 0)->blk->n == NGTCP2_KSL_MIN_NBLK &&
538 ngtcp2_ksl_nth_node(ksl, blk, 1)->blk->n == NGTCP2_KSL_MIN_NBLK) {
539 blk = ksl_merge_node(ksl, ksl->head, 0);
540 }
541
542 for (;;) {
543 i = ksl_bsearch(ksl, blk, key, ksl->compar);
544
545 if (i == blk->n) {
546 if (it) {
547 *it = ngtcp2_ksl_end(ksl);
548 }
549 return NGTCP2_ERR_INVALID_ARGUMENT;
550 }
551
552 if (blk->leaf) {
553 if (ksl->compar(key, ngtcp2_ksl_nth_node(ksl, blk, i)->key)) {
554 if (it) {
555 *it = ngtcp2_ksl_end(ksl);
556 }
557 return NGTCP2_ERR_INVALID_ARGUMENT;
558 }
559 ksl_remove_node(ksl, blk, i);
560 --ksl->n;
561 if (it) {
562 if (blk->n == i && blk->next) {
563 ngtcp2_ksl_it_init(it, ksl, blk->next, 0);
564 } else {
565 ngtcp2_ksl_it_init(it, ksl, blk, i);
566 }
567 }
568 return 0;
569 }
570
571 node = ngtcp2_ksl_nth_node(ksl, blk, i);
572
573 if (node->blk->n > NGTCP2_KSL_MIN_NBLK) {
574 blk = node->blk;
575 continue;
576 }
577
578 assert(node->blk->n == NGTCP2_KSL_MIN_NBLK);
579
580 if (i + 1 < blk->n &&
581 ngtcp2_ksl_nth_node(ksl, blk, i + 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
582 ksl_shift_left(ksl, blk, i + 1);
583 blk = node->blk;
584 continue;
585 }
586
587 if (i > 0 &&
588 ngtcp2_ksl_nth_node(ksl, blk, i - 1)->blk->n > NGTCP2_KSL_MIN_NBLK) {
589 ksl_shift_right(ksl, blk, i - 1);
590 blk = node->blk;
591 continue;
592 }
593
594 if (i + 1 < blk->n) {
595 blk = ksl_merge_node(ksl, blk, i);
596 continue;
597 }
598
599 assert(i > 0);
600
601 blk = ksl_merge_node(ksl, blk, i - 1);
602 }
603 }
604
ngtcp2_ksl_lower_bound(ngtcp2_ksl * ksl,const ngtcp2_ksl_key * key)605 ngtcp2_ksl_it ngtcp2_ksl_lower_bound(ngtcp2_ksl *ksl,
606 const ngtcp2_ksl_key *key) {
607 ngtcp2_ksl_blk *blk = ksl->head;
608 ngtcp2_ksl_it it;
609 size_t i;
610
611 if (!blk) {
612 ngtcp2_ksl_it_init(&it, ksl, &null_blk, 0);
613 return it;
614 }
615
616 for (;;) {
617 i = ksl_bsearch(ksl, blk, key, ksl->compar);
618
619 if (blk->leaf) {
620 if (i == blk->n && blk->next) {
621 blk = blk->next;
622 i = 0;
623 }
624 ngtcp2_ksl_it_init(&it, ksl, blk, i);
625 return it;
626 }
627
628 if (i == blk->n) {
629 /* This happens if descendant has smaller key. Fast forward to
630 find last node in this subtree. */
631 for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
632 ;
633 if (blk->next) {
634 blk = blk->next;
635 i = 0;
636 } else {
637 i = blk->n;
638 }
639 ngtcp2_ksl_it_init(&it, ksl, blk, i);
640 return it;
641 }
642 blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
643 }
644 }
645
ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl * ksl,const ngtcp2_ksl_key * key,ngtcp2_ksl_compar compar)646 ngtcp2_ksl_it ngtcp2_ksl_lower_bound_compar(ngtcp2_ksl *ksl,
647 const ngtcp2_ksl_key *key,
648 ngtcp2_ksl_compar compar) {
649 ngtcp2_ksl_blk *blk = ksl->head;
650 ngtcp2_ksl_it it;
651 size_t i;
652
653 if (!blk) {
654 ngtcp2_ksl_it_init(&it, ksl, &null_blk, 0);
655 return it;
656 }
657
658 for (;;) {
659 i = ksl_bsearch(ksl, blk, key, compar);
660
661 if (blk->leaf) {
662 if (i == blk->n && blk->next) {
663 blk = blk->next;
664 i = 0;
665 }
666 ngtcp2_ksl_it_init(&it, ksl, blk, i);
667 return it;
668 }
669
670 if (i == blk->n) {
671 /* This happens if descendant has smaller key. Fast forward to
672 find last node in this subtree. */
673 for (; !blk->leaf; blk = ngtcp2_ksl_nth_node(ksl, blk, blk->n - 1)->blk)
674 ;
675 if (blk->next) {
676 blk = blk->next;
677 i = 0;
678 } else {
679 i = blk->n;
680 }
681 ngtcp2_ksl_it_init(&it, ksl, blk, i);
682 return it;
683 }
684 blk = ngtcp2_ksl_nth_node(ksl, blk, i)->blk;
685 }
686 }
687
ngtcp2_ksl_update_key(ngtcp2_ksl * ksl,const ngtcp2_ksl_key * old_key,const ngtcp2_ksl_key * new_key)688 void ngtcp2_ksl_update_key(ngtcp2_ksl *ksl, const ngtcp2_ksl_key *old_key,
689 const ngtcp2_ksl_key *new_key) {
690 ngtcp2_ksl_blk *blk = ksl->head;
691 ngtcp2_ksl_node *node;
692 size_t i;
693
694 assert(ksl->head);
695
696 for (;;) {
697 i = ksl_bsearch(ksl, blk, old_key, ksl->compar);
698
699 assert(i < blk->n);
700 node = ngtcp2_ksl_nth_node(ksl, blk, i);
701
702 if (blk->leaf) {
703 assert(key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key));
704 ksl_node_set_key(ksl, node, new_key);
705 return;
706 }
707
708 if (key_equal(ksl->compar, (ngtcp2_ksl_key *)node->key, old_key) ||
709 ksl->compar((ngtcp2_ksl_key *)node->key, new_key)) {
710 ksl_node_set_key(ksl, node, new_key);
711 }
712
713 blk = node->blk;
714 }
715 }
716
ksl_print(ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t level)717 static void ksl_print(ngtcp2_ksl *ksl, ngtcp2_ksl_blk *blk, size_t level) {
718 size_t i;
719 ngtcp2_ksl_node *node;
720
721 fprintf(stderr, "LV=%zu n=%u\n", level, blk->n);
722
723 if (blk->leaf) {
724 for (i = 0; i < blk->n; ++i) {
725 node = ngtcp2_ksl_nth_node(ksl, blk, i);
726 fprintf(stderr, " %" PRId64, *(int64_t *)(void *)node->key);
727 }
728 fprintf(stderr, "\n");
729 return;
730 }
731
732 for (i = 0; i < blk->n; ++i) {
733 ksl_print(ksl, ngtcp2_ksl_nth_node(ksl, blk, i)->blk, level + 1);
734 }
735 }
736
ngtcp2_ksl_len(ngtcp2_ksl * ksl)737 size_t ngtcp2_ksl_len(ngtcp2_ksl *ksl) { return ksl->n; }
738
ngtcp2_ksl_clear(ngtcp2_ksl * ksl)739 void ngtcp2_ksl_clear(ngtcp2_ksl *ksl) {
740 if (!ksl->head) {
741 return;
742 }
743
744 #ifdef NOMEMPOOL
745 ksl_free_blk(ksl, ksl->head);
746 #endif /* NOMEMPOOL */
747
748 ksl->front = ksl->back = ksl->head = NULL;
749 ksl->n = 0;
750
751 ngtcp2_objalloc_clear(&ksl->blkalloc);
752 }
753
ngtcp2_ksl_print(ngtcp2_ksl * ksl)754 void ngtcp2_ksl_print(ngtcp2_ksl *ksl) {
755 if (!ksl->head) {
756 return;
757 }
758
759 ksl_print(ksl, ksl->head, 0);
760 }
761
ngtcp2_ksl_begin(const ngtcp2_ksl * ksl)762 ngtcp2_ksl_it ngtcp2_ksl_begin(const ngtcp2_ksl *ksl) {
763 ngtcp2_ksl_it it;
764
765 if (ksl->head) {
766 ngtcp2_ksl_it_init(&it, ksl, ksl->front, 0);
767 } else {
768 ngtcp2_ksl_it_init(&it, ksl, &null_blk, 0);
769 }
770
771 return it;
772 }
773
ngtcp2_ksl_end(const ngtcp2_ksl * ksl)774 ngtcp2_ksl_it ngtcp2_ksl_end(const ngtcp2_ksl *ksl) {
775 ngtcp2_ksl_it it;
776
777 if (ksl->head) {
778 ngtcp2_ksl_it_init(&it, ksl, ksl->back, ksl->back->n);
779 } else {
780 ngtcp2_ksl_it_init(&it, ksl, &null_blk, 0);
781 }
782
783 return it;
784 }
785
ngtcp2_ksl_it_init(ngtcp2_ksl_it * it,const ngtcp2_ksl * ksl,ngtcp2_ksl_blk * blk,size_t i)786 void ngtcp2_ksl_it_init(ngtcp2_ksl_it *it, const ngtcp2_ksl *ksl,
787 ngtcp2_ksl_blk *blk, size_t i) {
788 it->ksl = ksl;
789 it->blk = blk;
790 it->i = i;
791 }
792
ngtcp2_ksl_it_prev(ngtcp2_ksl_it * it)793 void ngtcp2_ksl_it_prev(ngtcp2_ksl_it *it) {
794 assert(!ngtcp2_ksl_it_begin(it));
795
796 if (it->i == 0) {
797 it->blk = it->blk->prev;
798 it->i = it->blk->n - 1;
799 } else {
800 --it->i;
801 }
802 }
803
ngtcp2_ksl_it_begin(const ngtcp2_ksl_it * it)804 int ngtcp2_ksl_it_begin(const ngtcp2_ksl_it *it) {
805 return it->i == 0 && it->blk->prev == NULL;
806 }
807
ngtcp2_ksl_range_compar(const ngtcp2_ksl_key * lhs,const ngtcp2_ksl_key * rhs)808 int ngtcp2_ksl_range_compar(const ngtcp2_ksl_key *lhs,
809 const ngtcp2_ksl_key *rhs) {
810 const ngtcp2_range *a = lhs, *b = rhs;
811 return a->begin < b->begin;
812 }
813
ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key * lhs,const ngtcp2_ksl_key * rhs)814 int ngtcp2_ksl_range_exclusive_compar(const ngtcp2_ksl_key *lhs,
815 const ngtcp2_ksl_key *rhs) {
816 const ngtcp2_range *a = lhs, *b = rhs;
817 return a->begin < b->begin &&
818 !(ngtcp2_max(a->begin, b->begin) < ngtcp2_min(a->end, b->end));
819 }
820