LCOV - code coverage report
Current view: top level - tommyds - tommytree.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 127 127 100.0 %
Date: 2026-04-29 15:04:44 Functions: 19 19 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: BSD-2-Clause
       2             : // Copyright (C) 2015 Andrea Mazzoleni
       3             : 
       4             : #include "tommytree.h"
       5             : 
       6             : #include <assert.h> /* for assert */
       7             : 
       8             : /******************************************************************************/
       9             : /* tree */
      10             : 
      11        3701 : TOMMY_API void tommy_tree_init(tommy_tree* tree, tommy_compare_func* cmp)
      12             : {
      13        3701 :         tree->root = 0;
      14        3701 :         tree->count = 0;
      15        3701 :         tree->cmp = cmp;
      16        3701 : }
      17             : 
      18   120764469 : static tommy_ssize_t tommy_tree_delta(tommy_tree_node* root)
      19             : {
      20   120764469 :         tommy_ssize_t left_height = root->prev ? root->prev->index : 0;
      21   120764469 :         tommy_ssize_t right_height = root->next ? root->next->index : 0;
      22             : 
      23   120764469 :         return left_height - right_height;
      24             : }
      25             : 
      26             : /* AVL tree operations */
      27             : static tommy_tree_node* tommy_tree_balance(tommy_tree_node*);
      28             : 
      29     8089193 : static tommy_tree_node* tommy_tree_rotate_left(tommy_tree_node* root)
      30             : {
      31     8089193 :         tommy_tree_node* next = root->next;
      32             : 
      33     8089193 :         root->next = next->prev;
      34             : 
      35     8089193 :         next->prev = tommy_tree_balance(root);
      36             : 
      37     8089193 :         return tommy_tree_balance(next);
      38             : }
      39             : 
      40      195595 : static tommy_tree_node* tommy_tree_rotate_right(tommy_tree_node* root)
      41             : {
      42      195595 :         tommy_tree_node* prev = root->prev;
      43             : 
      44      195595 :         root->prev = prev->next;
      45             : 
      46      195595 :         prev->next = tommy_tree_balance(root);
      47             : 
      48      195595 :         return tommy_tree_balance(prev);
      49             : }
      50             : 
      51      199670 : static tommy_tree_node* tommy_tree_move_right(tommy_tree_node* root, tommy_tree_node* node)
      52             : {
      53      199670 :         if (!root)
      54       84622 :                 return node;
      55             : 
      56      115048 :         root->next = tommy_tree_move_right(root->next, node);
      57             : 
      58      115048 :         return tommy_tree_balance(root);
      59             : }
      60             : 
      61   112656697 : static tommy_tree_node* tommy_tree_balance(tommy_tree_node* root)
      62             : {
      63   112656697 :         tommy_ssize_t delta = tommy_tree_delta(root);
      64             : 
      65   112656697 :         if (delta < -1) {
      66     7962401 :                 if (tommy_tree_delta(root->next) > 0)
      67       50224 :                         root->next = tommy_tree_rotate_right(root->next);
      68     7962401 :                 return tommy_tree_rotate_left(root);
      69             :         }
      70             : 
      71   104694296 :         if (delta > 1) {
      72      145371 :                 if (tommy_tree_delta(root->prev) < 0)
      73      126792 :                         root->prev = tommy_tree_rotate_left(root->prev);
      74      145371 :                 return tommy_tree_rotate_right(root);
      75             :         }
      76             : 
      77             :         /* recompute key */
      78   104548925 :         root->index = 0;
      79             : 
      80   104548925 :         if (root->prev && root->prev->index > root->index)
      81    84475885 :                 root->index = root->prev->index;
      82             : 
      83   104548925 :         if (root->next && root->next->index > root->index)
      84    48112306 :                 root->index = root->next->index;
      85             : 
      86             :         /* count itself */
      87   104548925 :         root->index += 1;
      88             : 
      89   104548925 :         return root;
      90             : }
      91             : 
      92   103293953 : static tommy_tree_node* tommy_tree_insert_node(tommy_compare_func* cmp, tommy_tree_node* root, tommy_tree_node** let)
      93             : {
      94             :         int c;
      95             : 
      96   103293953 :         if (!root)
      97     8065146 :                 return *let;
      98             : 
      99    95228807 :         c = cmp((*let)->data, root->data);
     100             : 
     101    95228807 :         if (c < 0) {
     102     1773421 :                 root->prev = tommy_tree_insert_node(cmp, root->prev, let);
     103     1773421 :                 return tommy_tree_balance(root);
     104             :         }
     105             : 
     106    93455386 :         if (c > 0) {
     107    93455385 :                 root->next = tommy_tree_insert_node(cmp, root->next, let);
     108    93455385 :                 return tommy_tree_balance(root);
     109             :         }
     110             : 
     111             :         /* already present, set the return pointer */
     112           1 :         *let = root;
     113             : 
     114           1 :         return root;
     115             : }
     116             : 
     117     8065147 : TOMMY_API void* tommy_tree_insert(tommy_tree* tree, tommy_tree_node* node, void* data)
     118             : {
     119     8065147 :         tommy_tree_node* insert = node;
     120             : 
     121     8065147 :         insert->data = data;
     122     8065147 :         insert->prev = 0;
     123     8065147 :         insert->next = 0;
     124     8065147 :         insert->index = 0;
     125             : 
     126     8065147 :         tree->root = tommy_tree_insert_node(tree->cmp, tree->root, &insert);
     127             : 
     128     8065147 :         if (insert == node)
     129     8065146 :                 ++tree->count;
     130             : 
     131     8065147 :         return insert->data;
     132             : }
     133             : 
     134      828017 : static tommy_tree_node* tommy_tree_remove_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data, tommy_tree_node** let)
     135             : {
     136             :         int c;
     137             : 
     138      828017 :         if (!root)
     139         128 :                 return 0;
     140             : 
     141      827889 :         c = cmp(data, root->data);
     142             : 
     143      827889 :         if (c < 0) {
     144      336145 :                 root->prev = tommy_tree_remove_node(cmp, root->prev, data, let);
     145      336145 :                 return tommy_tree_balance(root);
     146             :         }
     147             : 
     148      491744 :         if (c > 0) {
     149      407122 :                 root->next = tommy_tree_remove_node(cmp, root->next, data, let);
     150      407122 :                 return tommy_tree_balance(root);
     151             :         }
     152             : 
     153             :         /* found */
     154       84622 :         *let = root;
     155             : 
     156       84622 :         return tommy_tree_move_right(root->prev, root->next);
     157             : }
     158             : 
     159       84750 : TOMMY_API void* tommy_tree_remove(tommy_tree* tree, void* data)
     160             : {
     161       84750 :         tommy_tree_node* node = 0;
     162             : 
     163       84750 :         tree->root = tommy_tree_remove_node(tree->cmp, tree->root, data, &node);
     164             : 
     165       84750 :         if (!node)
     166         128 :                 return 0;
     167             : 
     168       84622 :         --tree->count;
     169             : 
     170       84622 :         return node->data;
     171             : }
     172             : 
     173   195194354 : static tommy_tree_node* tommy_tree_search_node(tommy_compare_func* cmp, tommy_tree_node* root, void* data)
     174             : {
     175             :         int c;
     176             : 
     177   195194354 :         if (!root)
     178     2167732 :                 return 0;
     179             : 
     180   193026622 :         c = cmp(data, root->data);
     181             : 
     182   193026622 :         if (c < 0)
     183    71213608 :                 return tommy_tree_search_node(cmp, root->prev, data);
     184             : 
     185   121813014 :         if (c > 0)
     186   106258181 :                 return tommy_tree_search_node(cmp, root->next, data);
     187             : 
     188    15554833 :         return root;
     189             : }
     190             : 
     191           2 : TOMMY_API void* tommy_tree_search(tommy_tree* tree, void* data)
     192             : {
     193           2 :         tommy_tree_node* node = tommy_tree_search_node(tree->cmp, tree->root, data);
     194             : 
     195           2 :         if (!node)
     196           1 :                 return 0;
     197             : 
     198           1 :         return node->data;
     199             : }
     200             : 
     201    17722563 : TOMMY_API void* tommy_tree_search_compare(tommy_tree* tree, tommy_compare_func* cmp, void* cmp_arg)
     202             : {
     203    17722563 :         tommy_tree_node* node = tommy_tree_search_node(cmp, tree->root, cmp_arg);
     204             : 
     205    17722563 :         if (!node)
     206     2167731 :                 return 0;
     207             : 
     208    15554832 :         return node->data;
     209             : }
     210             : 
     211         128 : TOMMY_API void* tommy_tree_remove_existing(tommy_tree* tree, tommy_tree_node* node)
     212             : {
     213         128 :         void* data = tommy_tree_remove(tree, node->data);
     214             : 
     215         128 :         assert(data != 0);
     216             : 
     217         128 :         return data;
     218             : }
     219             : 
     220     7486367 : static void tommy_tree_foreach_node(tommy_tree_node* root, tommy_foreach_func* func)
     221             : {
     222             :         tommy_tree_node* next;
     223             : 
     224     7486367 :         if (!root)
     225     3744043 :                 return;
     226             : 
     227     3742324 :         tommy_tree_foreach_node(root->prev, func);
     228             : 
     229             :         /* make a copy in case func is free() */
     230     3742324 :         next = root->next;
     231             : 
     232     3742324 :         func(root->data);
     233             : 
     234     3742324 :         tommy_tree_foreach_node(next, func);
     235             : }
     236             : 
     237        1719 : TOMMY_API void tommy_tree_foreach(tommy_tree* tree, tommy_foreach_func* func)
     238             : {
     239        1719 :         tommy_tree_foreach_node(tree->root, func);
     240        1719 : }
     241             : 
     242    28830723 : static void tommy_tree_foreach_arg_node(tommy_tree_node* root, tommy_foreach_arg_func* func, void* arg)
     243             : {
     244             :         tommy_tree_node* next;
     245             : 
     246    28830723 :         if (!root)
     247    14418731 :                 return;
     248             : 
     249    14411992 :         tommy_tree_foreach_arg_node(root->prev, func, arg);
     250             : 
     251             :         /* make a copy in case func is free() */
     252    14411992 :         next = root->next;
     253             : 
     254    14411992 :         func(arg, root->data);
     255             : 
     256    14411992 :         tommy_tree_foreach_arg_node(next, func, arg);
     257             : }
     258             : 
     259        6739 : TOMMY_API void tommy_tree_foreach_arg(tommy_tree* tree, tommy_foreach_arg_func* func, void* arg)
     260             : {
     261        6739 :         tommy_tree_foreach_arg_node(tree->root, func, arg);
     262        6739 : }
     263             : 
     264           1 : TOMMY_API tommy_size_t tommy_tree_memory_usage(tommy_tree* tree)
     265             : {
     266           1 :         return tommy_tree_count(tree) * sizeof(tommy_tree_node);
     267             : }
     268             : 

Generated by: LCOV version 1.0