2019-05-30 02:57:21 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2012-07-31 08:31:32 +04:00
/*
* Based on strlist . c by :
* ( c ) 2009 Arnaldo Carvalho de Melo < acme @ redhat . com >
*/
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include "rblist.h"
int rblist__add_node ( struct rblist * rblist , const void * new_entry )
{
2018-12-06 22:18:16 +03:00
struct rb_node * * p = & rblist - > entries . rb_root . rb_node ;
2012-07-31 08:31:32 +04:00
struct rb_node * parent = NULL , * new_node ;
2018-12-06 22:18:16 +03:00
bool leftmost = true ;
2012-07-31 08:31:32 +04:00
while ( * p ! = NULL ) {
int rc ;
parent = * p ;
rc = rblist - > node_cmp ( parent , new_entry ) ;
if ( rc > 0 )
p = & ( * p ) - > rb_left ;
2018-12-06 22:18:16 +03:00
else if ( rc < 0 ) {
2012-07-31 08:31:32 +04:00
p = & ( * p ) - > rb_right ;
2018-12-06 22:18:16 +03:00
leftmost = false ;
}
2012-07-31 08:31:32 +04:00
else
return - EEXIST ;
}
new_node = rblist - > node_new ( rblist , new_entry ) ;
if ( new_node = = NULL )
return - ENOMEM ;
rb_link_node ( new_node , parent , p ) ;
2018-12-06 22:18:16 +03:00
rb_insert_color_cached ( new_node , & rblist - > entries , leftmost ) ;
2012-07-31 08:31:32 +04:00
+ + rblist - > nr_entries ;
return 0 ;
}
void rblist__remove_node ( struct rblist * rblist , struct rb_node * rb_node )
{
2018-12-06 22:18:16 +03:00
rb_erase_cached ( rb_node , & rblist - > entries ) ;
2012-08-31 11:09:18 +04:00
- - rblist - > nr_entries ;
2012-07-31 08:31:32 +04:00
rblist - > node_delete ( rblist , rb_node ) ;
}
2013-10-09 07:26:52 +04:00
static struct rb_node * __rblist__findnew ( struct rblist * rblist ,
const void * entry ,
bool create )
2012-07-31 08:31:32 +04:00
{
2018-12-06 22:18:16 +03:00
struct rb_node * * p = & rblist - > entries . rb_root . rb_node ;
2013-10-09 07:26:52 +04:00
struct rb_node * parent = NULL , * new_node = NULL ;
2018-12-06 22:18:16 +03:00
bool leftmost = true ;
2012-07-31 08:31:32 +04:00
while ( * p ! = NULL ) {
int rc ;
parent = * p ;
rc = rblist - > node_cmp ( parent , entry ) ;
if ( rc > 0 )
p = & ( * p ) - > rb_left ;
2018-12-06 22:18:16 +03:00
else if ( rc < 0 ) {
2012-07-31 08:31:32 +04:00
p = & ( * p ) - > rb_right ;
2018-12-06 22:18:16 +03:00
leftmost = false ;
}
2012-07-31 08:31:32 +04:00
else
return parent ;
}
2013-10-09 07:26:52 +04:00
if ( create ) {
new_node = rblist - > node_new ( rblist , entry ) ;
if ( new_node ) {
rb_link_node ( new_node , parent , p ) ;
2018-12-06 22:18:16 +03:00
rb_insert_color_cached ( new_node ,
& rblist - > entries , leftmost ) ;
2013-10-09 07:26:52 +04:00
+ + rblist - > nr_entries ;
}
}
return new_node ;
}
struct rb_node * rblist__find ( struct rblist * rblist , const void * entry )
{
return __rblist__findnew ( rblist , entry , false ) ;
}
struct rb_node * rblist__findnew ( struct rblist * rblist , const void * entry )
{
return __rblist__findnew ( rblist , entry , true ) ;
2012-07-31 08:31:32 +04:00
}
void rblist__init ( struct rblist * rblist )
{
if ( rblist ! = NULL ) {
2018-12-06 22:18:16 +03:00
rblist - > entries = RB_ROOT_CACHED ;
2012-07-31 08:31:32 +04:00
rblist - > nr_entries = 0 ;
}
return ;
}
2017-12-01 13:57:25 +03:00
void rblist__exit ( struct rblist * rblist )
{
2018-12-06 22:18:16 +03:00
struct rb_node * pos , * next = rb_first_cached ( & rblist - > entries ) ;
2017-12-01 13:57:25 +03:00
while ( next ) {
pos = next ;
next = rb_next ( pos ) ;
rblist__remove_node ( rblist , pos ) ;
}
}
2012-07-31 08:31:32 +04:00
void rblist__delete ( struct rblist * rblist )
{
if ( rblist ! = NULL ) {
2017-12-01 13:57:25 +03:00
rblist__exit ( rblist ) ;
2012-07-31 08:31:32 +04:00
free ( rblist ) ;
}
}
struct rb_node * rblist__entry ( const struct rblist * rblist , unsigned int idx )
{
struct rb_node * node ;
2018-12-06 22:18:16 +03:00
for ( node = rb_first_cached ( & rblist - > entries ) ; node ;
node = rb_next ( node ) ) {
2012-07-31 08:31:32 +04:00
if ( ! idx - - )
return node ;
}
return NULL ;
}