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