2017-11-05 13:31:29 +01:00
/*
* Elastic Binary Trees - macros and structures for operations on 32 bit nodes .
* Version 6.0 .6 with backports from v7 - dev
* ( C ) 2002 - 2017 - Willy Tarreau < w @ 1 wt . eu >
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation , version 2.1
* exclusively .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Lesser General Public License for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA 02110 - 1301 USA
*/
# ifndef _EB32SCTREE_H
# define _EB32SCTREE_H
# include "ebtree.h"
/* Return the structure of type <type> whose member <member> points to <ptr> */
# define eb32sc_entry(ptr, type, member) container_of(ptr, type, member)
/* These types may sometimes already be defined */
2017-11-20 21:11:12 +01:00
# ifndef _EB32TREE_H
2017-11-05 13:31:29 +01:00
typedef unsigned int u32 ;
typedef signed int s32 ;
2017-11-20 21:11:12 +01:00
# endif
2017-11-05 13:31:29 +01:00
/* This structure carries a node, a leaf, a scope, and a key. It must start
* with the eb_node so that it can be cast into an eb_node . We could also
* have put some sort of transparent union here to reduce the indirection
* level , but the fact is , the end user is not meant to manipulate internals ,
* so this is pointless .
*/
struct eb32sc_node {
struct eb_node node ; /* the tree node, must be at the beginning */
2018-10-21 06:52:11 +02:00
u32 key ;
2017-11-05 13:31:29 +01:00
unsigned long node_s ; /* visibility of this node's branches */
unsigned long leaf_s ; /* visibility of this node's leaf */
} ;
/*
* Exported functions and macros .
* Many of them are always inlined because they are extremely small , and
* are generally called at most once or twice in a program .
*/
/*
* The following functions are not inlined by default . They are declared
* in eb32sctree . c , which simply relies on their inline version .
*/
REGPRM2 struct eb32sc_node * eb32sc_lookup_ge ( struct eb_root * root , u32 x , unsigned long scope ) ;
2017-11-05 21:23:21 +01:00
REGPRM2 struct eb32sc_node * eb32sc_lookup_ge_or_first ( struct eb_root * root , u32 x , unsigned long scope ) ;
2017-11-05 13:31:29 +01:00
REGPRM2 struct eb32sc_node * eb32sc_insert ( struct eb_root * root , struct eb32sc_node * new , unsigned long scope ) ;
void eb32sc_delete ( struct eb32sc_node * node ) ;
2017-11-05 14:33:01 +01:00
/* Walks down left starting at root pointer <start>, and follow the leftmost
* branch whose scope matches < scope > . It either returns the node hosting the
* first leaf on that side , or NULL if no leaf is found . < start > may either be
* NULL or a branch pointer . The pointer to the leaf ( or NULL ) is returned .
2017-11-05 13:31:29 +01:00
*/
2017-11-05 14:33:01 +01:00
static inline struct eb32sc_node * eb32sc_walk_down_left ( eb_troot_t * start , unsigned long scope )
2017-11-05 13:31:29 +01:00
{
2017-11-05 14:33:01 +01:00
struct eb_root * root ;
struct eb_node * node ;
2017-11-13 18:55:44 +01:00
struct eb32sc_node * eb32 ;
2017-11-05 14:33:01 +01:00
if ( unlikely ( ! start ) )
return NULL ;
2017-11-13 18:55:44 +01:00
while ( 1 ) {
if ( eb_gettag ( start ) = = EB_NODE ) {
root = eb_untag ( start , EB_NODE ) ;
node = eb_root_to_node ( root ) ;
eb32 = container_of ( node , struct eb32sc_node , node ) ;
if ( eb32 - > node_s & scope ) {
start = node - > branches . b [ EB_LEFT ] ;
continue ;
}
start = node - > node_p ;
}
else {
root = eb_untag ( start , EB_LEAF ) ;
node = eb_root_to_node ( root ) ;
eb32 = container_of ( node , struct eb32sc_node , node ) ;
if ( eb32 - > leaf_s & scope )
return eb32 ;
start = node - > leaf_p ;
}
/* here we're on a node that doesn't match the scope. We have
* to walk to the closest right location .
*/
while ( eb_gettag ( start ) ! = EB_LEFT )
/* Walking up from right branch, so we cannot be below root */
start = ( eb_root_to_node ( eb_untag ( start , EB_RGHT ) ) ) - > node_p ;
2017-11-05 14:33:01 +01:00
2017-11-13 18:55:44 +01:00
/* Note that <start> cannot be NULL at this stage */
root = eb_untag ( start , EB_LEFT ) ;
start = root - > b [ EB_RGHT ] ;
if ( eb_clrtag ( start ) = = NULL )
return NULL ;
2017-11-05 14:33:01 +01:00
}
2017-11-05 13:31:29 +01:00
}
2017-11-13 19:13:06 +01:00
/* Return next node in the tree, starting with tagged parent <start>, or NULL if none */
static inline struct eb32sc_node * eb32sc_next_with_parent ( eb_troot_t * start , unsigned long scope )
2017-11-05 13:31:29 +01:00
{
2017-11-13 19:13:06 +01:00
while ( eb_gettag ( start ) ! = EB_LEFT )
2017-11-13 18:55:44 +01:00
/* Walking up from right branch, so we cannot be below root */
2017-11-13 19:13:06 +01:00
start = ( eb_root_to_node ( eb_untag ( start , EB_RGHT ) ) ) - > node_p ;
2017-11-05 13:31:29 +01:00
2017-11-13 18:55:44 +01:00
/* Note that <t> cannot be NULL at this stage */
2017-11-13 19:13:06 +01:00
start = ( eb_untag ( start , EB_LEFT ) ) - > b [ EB_RGHT ] ;
if ( eb_clrtag ( start ) = = NULL )
2017-11-13 18:55:44 +01:00
return NULL ;
2017-11-05 13:31:29 +01:00
2017-11-13 19:13:06 +01:00
return eb32sc_walk_down_left ( start , scope ) ;
}
/* Return next node in the tree, or NULL if none */
static inline struct eb32sc_node * eb32sc_next ( struct eb32sc_node * eb32 , unsigned long scope )
{
return eb32sc_next_with_parent ( eb32 - > node . leaf_p , scope ) ;
2017-11-05 13:31:29 +01:00
}
/* Return leftmost node in the tree, or NULL if none */
static inline struct eb32sc_node * eb32sc_first ( struct eb_root * root , unsigned long scope )
{
2017-11-05 14:33:01 +01:00
return eb32sc_walk_down_left ( root - > b [ 0 ] , scope ) ;
2017-11-05 13:31:29 +01:00
}
# endif /* _EB32SC_TREE_H */