• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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