@@ -161,6 +161,19 @@ static inline bool cavl2_is_inserted(const CAVL2_T* const root, const CAVL2_T* c
161161 return out ;
162162}
163163
164+ /// Remove the specified node if it is inserted in the tree; otherwise, do nothing.
165+ /// This is a convenience wrapper that combines cavl2_is_inserted() and cavl2_remove().
166+ /// Returns true if the node was inserted and has been removed, false otherwise.
167+ static inline bool cavl2_remove_if (CAVL2_T * * const root , CAVL2_T * const node )
168+ {
169+ bool removed = false;
170+ if ((root != NULL ) && cavl2_is_inserted (* root , node )) {
171+ cavl2_remove (root , node );
172+ removed = true;
173+ }
174+ return removed ;
175+ }
176+
164177/// Return the min-/max-valued node stored in the tree, depending on the flag. This is an extremely fast query.
165178/// Returns NULL iff the argument is NULL (i.e., the tree is empty). The worst-case complexity is O(log n).
166179static inline CAVL2_T * cavl2_extremum (CAVL2_T * const root , const bool maximum )
@@ -310,20 +323,20 @@ static inline CAVL2_T* cavl2_trivial_factory(void* const user)
310323/// struct cavl2_t* tree_node_b = cavl2_find(...); // whatever
311324/// if (tree_node_b == NULL) { ... } // do something else
312325/// struct my_type_t* my_struct = CAVL2_TO_OWNER(tree_node_b, struct my_type_t, tree_b);
313- #define CAVL2_TO_OWNER (tree_node_ptr , owner_type , owner_tree_node_field ) \
314- ((owner_type*)_cavl2_to_owner_helper ((tree_node_ptr), offsetof(owner_type, owner_tree_node_field))) // NOLINT
326+ #define CAVL2_TO_OWNER (tree_node_ptr , owner_type , owner_tree_node_field ) \
327+ ((owner_type*)cavl2_impl_to_owner_helper ((tree_node_ptr), offsetof(owner_type, owner_tree_node_field))) // NOLINT
315328
316329// ---------------------------------------- END OF PUBLIC API SECTION ----------------------------------------
317330// ---------------------------------------- POLICE LINE DO NOT CROSS ----------------------------------------
318331
319332/// INTERNAL USE ONLY.
320- static inline void * _cavl2_to_owner_helper (const void * const tree_node_ptr , const size_t offset )
333+ static inline void * cavl2_impl_to_owner_helper (const void * const tree_node_ptr , const size_t offset )
321334{
322335 return (tree_node_ptr == NULL ) ? NULL : (void * )((char * )tree_node_ptr - offset );
323336}
324337
325338/// INTERNAL USE ONLY. Makes the '!r' child of node 'x' its parent; i.e., rotates 'x' toward 'r'.
326- static inline void _cavl2_rotate (CAVL2_T * const x , const bool r )
339+ static inline void cavl2_impl_rotate (CAVL2_T * const x , const bool r )
327340{
328341 CAVL2_ASSERT ((x != NULL ) && (x -> lr [!r ] != NULL ) && ((x -> bf >= -1 ) && (x -> bf <= +1 )));
329342 CAVL2_T * const z = x -> lr [!r ];
@@ -342,7 +355,7 @@ static inline void _cavl2_rotate(CAVL2_T* const x, const bool r)
342355/// INTERNAL USE ONLY.
343356/// Accepts a node and how its balance factor needs to be changed -- either +1 or -1.
344357/// Returns the new node to replace the old one if tree rotation took place, same node otherwise.
345- static inline CAVL2_T * _cavl2_adjust_balance (CAVL2_T * const x , const bool increment )
358+ static inline CAVL2_T * cavl2_impl_adjust_balance (CAVL2_T * const x , const bool increment )
346359{
347360 CAVL2_ASSERT ((x != NULL ) && ((x -> bf >= -1 ) && (x -> bf <= +1 )));
348361 CAVL2_T * out = x ;
@@ -354,7 +367,7 @@ static inline CAVL2_T* _cavl2_adjust_balance(CAVL2_T* const x, const bool increm
354367 CAVL2_ASSERT (z != NULL ); // Heavy side cannot be empty. NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
355368 if ((z -> bf * sign ) <= 0 ) { // Parent and child are heavy on the same side or the child is balanced.
356369 out = z ;
357- _cavl2_rotate (x , r );
370+ cavl2_impl_rotate (x , r );
358371 if (0 == z -> bf ) {
359372 x -> bf = (int_fast8_t )(- sign );
360373 z -> bf = (int_fast8_t )(+ sign );
@@ -366,8 +379,8 @@ static inline CAVL2_T* _cavl2_adjust_balance(CAVL2_T* const x, const bool increm
366379 CAVL2_T * const y = z -> lr [r ];
367380 CAVL2_ASSERT (y != NULL ); // Heavy side cannot be empty.
368381 out = y ;
369- _cavl2_rotate (z , !r );
370- _cavl2_rotate (x , r );
382+ cavl2_impl_rotate (z , !r );
383+ cavl2_impl_rotate (x , r );
371384 if ((y -> bf * sign ) < 0 ) {
372385 x -> bf = (int_fast8_t )(+ sign );
373386 y -> bf = 0 ;
@@ -390,19 +403,18 @@ static inline CAVL2_T* _cavl2_adjust_balance(CAVL2_T* const x, const bool increm
390403/// INTERNAL USE ONLY.
391404/// Takes the culprit node (the one that is added); returns NULL or the root of the tree (possibly new one).
392405/// When adding a new node, set its balance factor to zero and call this function to propagate the changes upward.
393- static inline CAVL2_T * _cavl2_retrace_on_growth (CAVL2_T * const added )
406+ static inline CAVL2_T * cavl2_impl_retrace_on_growth (CAVL2_T * const added )
394407{
395408 CAVL2_ASSERT ((added != NULL ) && (0 == added -> bf ));
396409 CAVL2_T * c = added ; // Child
397410 CAVL2_T * p = added -> up ; // Parent
398411 while (p != NULL ) {
399412 const bool r = p -> lr [1 ] == c ; // c is the right child of parent
400413 CAVL2_ASSERT (p -> lr [r ] == c );
401- c = _cavl2_adjust_balance (p , r );
414+ c = cavl2_impl_adjust_balance (p , r );
402415 p = c -> up ;
403- if (0 ==
404- c -> bf ) { // The height change of the subtree made this parent perfectly balanced (as all things should be),
405- break ; // hence, the height of the outer subtree is unchanged, so upper balance factors are unchanged.
416+ if (0 == c -> bf ) { // The height change of the subtree made this parent balanced (as all things should be),
417+ break ; // hence, the height of the outer subtree is unchanged, so upper balance factors are unchanged.
406418 }
407419 }
408420 CAVL2_ASSERT (c != NULL );
@@ -437,7 +449,7 @@ static inline CAVL2_T* cavl2_find_or_insert(CAVL2_T** const root,
437449 out -> lr [1 ] = NULL ;
438450 out -> up = up ;
439451 out -> bf = 0 ;
440- CAVL2_T * const rt = _cavl2_retrace_on_growth (out );
452+ CAVL2_T * const rt = cavl2_impl_retrace_on_growth (out );
441453 if (rt != NULL ) {
442454 * root = rt ;
443455 }
@@ -472,8 +484,7 @@ static inline void cavl2_remove(CAVL2_T** const root, CAVL2_T* const node)
472484 re -> lr [1 ] = node -> lr [1 ];
473485 re -> lr [1 ]-> up = re ;
474486 r = false;
475- } else // In this case, we are reducing the height of the right subtree, so r=1.
476- {
487+ } else { // In this case, we are reducing the height of the right subtree, so r=1.
477488 p = re ; // Retracing starts with the replacement node itself as we are deleting its parent.
478489 r = true; // The right child of the replacement node remains the same so we don't bother relinking it.
479490 }
@@ -506,7 +517,7 @@ static inline void cavl2_remove(CAVL2_T** const root, CAVL2_T* const node)
506517 if (p != NULL ) {
507518 CAVL2_T * c = NULL ;
508519 for (;;) {
509- c = _cavl2_adjust_balance (p , !r );
520+ c = cavl2_impl_adjust_balance (p , !r );
510521 p = c -> up ;
511522 if ((c -> bf != 0 ) || (NULL == p )) { // Reached the root or the height difference is absorbed by c.
512523 break ;
0 commit comments