@ -785,13 +785,28 @@ class btree_node {
& mutable_child ( start ( ) ) , ( kNodeValues + 1 ) * sizeof ( btree_node * ) ) ;
}
static void deallocate ( const size_type size , btree_node * node ,
allocator_type * alloc ) {
absl : : container_internal : : Deallocate < Alignment ( ) > ( alloc , node , size ) ;
}
// Deletes a node and all of its children.
static void clear_and_delete ( btree_node * node , allocator_type * alloc ) ;
// TODO(ezb): don't use recursion here to avoid potential stack overflows.
static void clear_and_delete ( btree_node * node , allocator_type * alloc ) {
const field_type start = node - > start ( ) ;
const field_type finish = node - > finish ( ) ;
for ( field_type i = start ; i < finish ; + + i ) {
node - > value_destroy ( i , alloc ) ;
}
if ( node - > leaf ( ) ) {
absl : : container_internal : : Deallocate < Alignment ( ) > (
alloc , node , LeafSize ( node - > max_count ( ) ) ) ;
} else {
// If the node is empty, then there are no children so don't try clearing.
if ( start < finish ) {
for ( field_type i = start ; i < = finish ; + + i ) {
clear_and_delete ( node - > child ( i ) , alloc ) ;
}
}
absl : : container_internal : : Deallocate < Alignment ( ) > ( alloc , node ,
InternalSize ( ) ) ;
}
}
public :
// Exposed only for tests.
@ -801,21 +816,14 @@ class btree_node {
private :
template < typename . . . Args >
void value_init ( const field _type i , allocator_type * alloc , Args & & . . . args ) {
void value_init ( const size _type i , allocator_type * alloc , Args & & . . . args ) {
absl : : container_internal : : SanitizerUnpoisonObject ( slot ( i ) ) ;
params_type : : construct ( alloc , slot ( i ) , std : : forward < Args > ( args ) . . . ) ;
}
void value_destroy ( const field _type i , allocator_type * alloc ) {
void value_destroy ( const size _type i , allocator_type * alloc ) {
params_type : : destroy ( alloc , slot ( i ) ) ;
absl : : container_internal : : SanitizerPoisonObject ( slot ( i ) ) ;
}
void value_destroy_n ( const field_type i , const field_type n ,
allocator_type * alloc ) {
for ( slot_type * s = slot ( i ) , * end = slot ( i + n ) ; s ! = end ; + + s ) {
params_type : : destroy ( alloc , s ) ;
absl : : container_internal : : SanitizerPoisonObject ( s ) ;
}
}
// Transfers value from slot `src_i` in `src_node` to slot `dest_i` in `this`.
void transfer ( const size_type dest_i , const size_type src_i ,
@ -1559,9 +1567,11 @@ inline void btree_node<P>::remove_values(const field_type i,
const field_type to_erase ,
allocator_type * alloc ) {
// Transfer values after the removed range into their new places.
value_destroy_n ( i , to_erase , alloc ) ;
const field_type orig_finish = finish ( ) ;
const field_type src_i = i + to_erase ;
for ( field_type j = i ; j < src_i ; + + j ) {
value_destroy ( j , alloc ) ;
}
transfer_n ( orig_finish - src_i , i , src_i , this , alloc ) ;
if ( ! leaf ( ) ) {
@ -1731,49 +1741,6 @@ void btree_node<P>::merge(btree_node *src, allocator_type *alloc) {
parent ( ) - > remove_values ( position ( ) , /*to_erase=*/ 1 , alloc ) ;
}
template < typename P >
void btree_node < P > : : clear_and_delete ( btree_node * node , allocator_type * alloc ) {
if ( node - > leaf ( ) ) {
node - > value_destroy_n ( node - > start ( ) , node - > count ( ) , alloc ) ;
deallocate ( LeafSize ( node - > max_count ( ) ) , node , alloc ) ;
return ;
}
if ( node - > count ( ) = = 0 ) {
deallocate ( InternalSize ( ) , node , alloc ) ;
return ;
}
// The parent of the root of the subtree we are deleting.
btree_node * delete_root_parent = node - > parent ( ) ;
// Navigate to the leftmost leaf under node, and then delete upwards.
while ( ! node - > leaf ( ) ) node = node - > start_child ( ) ;
field_type pos = node - > position ( ) ;
btree_node * parent = node - > parent ( ) ;
do {
// In each iteration of this loop, we delete one leaf node and go right.
for ( ; pos < = parent - > finish ( ) ; + + pos ) {
node = parent - > child ( pos ) ;
if ( ! node - > leaf ( ) ) {
// Navigate to the leftmost leaf under node.
while ( ! node - > leaf ( ) ) node = node - > start_child ( ) ;
pos = node - > position ( ) ;
parent = node - > parent ( ) ;
}
node - > value_destroy_n ( node - > start ( ) , node - > count ( ) , alloc ) ;
deallocate ( LeafSize ( node - > max_count ( ) ) , node , alloc ) ;
}
// If we've deleted all children of parent, then delete parent and go up.
for ( ; parent ! = delete_root_parent & & pos > parent - > finish ( ) ; + + pos ) {
node = parent ;
pos = node - > position ( ) ;
parent = node - > parent ( ) ;
node - > value_destroy_n ( node - > start ( ) , node - > count ( ) , alloc ) ;
deallocate ( InternalSize ( ) , node , alloc ) ;
}
} while ( parent ! = delete_root_parent ) ;
}
////
// btree_iterator methods
template < typename N , typename R , typename P >