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