btreend.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 690 行 · 第 1/2 页

CPP
690
字号
}


template < class Key_T, class Obj_T >
BTreeNodeBase< Key_T, Obj_T > * BTreeSearchNode<Key_T,Obj_T>::
nextNode( int_16 & idx)
//---------------------------------------------------------------
{
    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "SearchNode %p, idx = %d, _degree = %d, return = %p\n",
                                    this, idx + 1, _degree, (idx + 1 < _degree) ? _nodes[ idx + 1 ]._child : NULL );
    #endif

    idx += 1;
    if( idx >= _degree ) return NULL;

    return _nodes[ idx ]._child;
}

template < class Key_T, class Obj_T >
Obj_T * BTreeSearchNode<Key_T,Obj_T>::
nextObj( int_16 & )
//------------------------------------
{
    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "SearchNode nextObj == NULL\n" );
    #endif

    return NULL;    // no objects in search node
}


/*--------------------- BTreeBucketNode -----------------------------*/

template < class Key_T, class Obj_T >
static uint BTreeBucketNode<Key_T,Obj_T>::
_objOrder( -1 );

const int BTreeBucketNodePoolSize = 1024;
template < class Key_T, class Obj_T >
static MemoryPool BTreeBucketNode<Key_T,Obj_T>::
_pool( sizeof( BTreeBucketNode ), "BTreeBucketNode", BTreeBucketNodePoolSize );

const int BTreeBucketNodeNodePoolSize = 1024;
template < class Key_T, class Obj_T >
static MemoryPool BTreeBucketNode<Key_T,Obj_T>::
_nodePool( "BTreeBucketNodeNode" );

template < class Key_T, class Obj_T >
BTreeBucketNode<Key_T,Obj_T>::
BTreeBucketNode()
    : _degree(0)
//---------------------------------------------------------------
{
    _nodes = (ObjPtr *) _nodePool.alloc();
}

template < class Key_T, class Obj_T >
BTreeBucketNode<Key_T,Obj_T>::
BTreeBucketNode( Obj_T * obj )
    : _degree( 1 )
//---------------------------------------------------------------
{
    _nodes = (ObjPtr *) _nodePool.alloc();
    _nodes[ 0 ] = obj;
}

template < class Key_T, class Obj_T >
BTreeBucketNode<Key_T,Obj_T>::
~BTreeBucketNode()
{
    // WARNING -- this destructor is not guaranteed to be called
    //            since the elements are pooled and freed using
    //            the pool's ragnarok
}

template < class Key_T, class Obj_T >
static void BTreeBucketNode<Key_T,Obj_T>::
ragnarok()
//----------------------------------------
{
    _pool.ragnarok();
    _nodePool.ragnarok();
}

template < class Key_T, class Obj_T >
static void BTreeBucketNode<Key_T,Obj_T>::
setObjOrder( uint objOrder )
//-------------------------------------------
{
    _objOrder = objOrder;
    _nodePool.setSize( sizeof( ObjPtr ) * 2 * objOrder + sizeof( ObjPtr ),
                       BTreeBucketNodeNodePoolSize );
}

#if INSTRUMENTS
template < class Key_T, class Obj_T >
void BTreeBucketNode<Key_T,Obj_T>::
print( int indent )
//----------------------------------
{
    int i;

    if( _degree == 0 ) {
        Log.printf( "%*c<empty bucket>\n", indent, ' ' );
    }

    for( i = 0; i < _degree; i += 1 ) {
        Log.printf( "%*c%s\n", indent, ' ',
                                        (const char *)(*_nodes[ i ]) );
    }
}
#endif


template < class Key_T, class Obj_T >
uint BTreeBucketNode<Key_T,Obj_T>::
privSearch( const Key_T & key, uint lower, uint upper )
//-----------------------------------------------------------------
// using a binary search, return the first element greater than key
{
    int middle;

    while( lower != upper ) {
        middle = (lower + upper) / 2;

        if( key.operator== ( (const Key_T&)(*_nodes[ middle ])) ) {
            return middle;
        } else {
            if( key.operator< ( (const Key_T&)(*_nodes[ middle ])) ) {
                upper = middle;
            } else {
                lower = middle + 1;
            }
        }
    }

    return lower;
}


template < class Key_T, class Obj_T >
Obj_T * BTreeBucketNode<Key_T,Obj_T>::
find( const Key_T & key )
//------------------------------------
{
    uint    idx;

    idx = privSearch( key, 0, _degree );

    if( idx < _degree && key.operator== ( (const Key_T&)(*_nodes[idx]) )) {
        return _nodes[ idx ];
    } else {
        return NULL;    // not found
    }
}

template < class Key_T, class Obj_T >
void BTreeBucketNode<Key_T,Obj_T>::
remove( const Key_T & key )
//-----------------------------------
// remove an element from the bucket
{
    int idx;

    idx = privSearch( key, 0, _degree );

    if( idx < _degree &&
         key.operator== ( (const Key_T&)(*_nodes[idx]) ) ) {

        for( int j = idx; j < _degree; j += 1 ) {
            _nodes[ j ] = _nodes[ j + 1 ];
        }

        _degree -= 1;
    } else {
        #if INSTRUMENTS
        Log.printf( "NOT FOUND FOR REMOVE!\n", key.getString() );
        print( 0 );
        #endif

        BTreeExcept a( "Element Not Found for Remove",
                        BTreeExcept::NotFoundForRemove );
        throw( a );
    }
}

template < class Key_T, class Obj_T >
Obj_T * BTreeBucketNode<Key_T,Obj_T>::
insert( Obj_T * obj, bool & needsSplit, Key_T & key,
        BTreeNodeBase *& newNode )
//--------------------------------------------------
// attempt to insert object 'obj' into this bucket.  If the
// bucket is full, split it and return the new key and node
// in 'key' and 'newNode' respectively
{
    if( _degree == 2 * _objOrder + 1 ) {
        needsSplit = TRUE;              // we split
        return split( key, obj, newNode );
    } else {
        needsSplit = FALSE;             // we did not split
        return privInsert( obj );
    }
}

template < class Key_T, class Obj_T >
Obj_T * BTreeBucketNode<Key_T,Obj_T>::
privInsert( Obj_T * obj )
//------------------------------------
// insert the element -- there must be room for it!
{
    int idx;

    InternalAssert( _degree < _objOrder * 2 + 1 );

    idx = privSearch( (const Key_T&)(*obj), 0, _degree );

    if( idx < _degree &&
         ((const Key_T&)(*obj)).operator== ( (const Key_T&)(*_nodes[idx]) ) ) {

        if( obj == _nodes[ idx ] ) {
            return obj;
        }

        #if INSTRUMENTS
        Log.printf( "DUPLICATE! %s = \n", (const char *) (*obj) );
        Log.printf( "           %s\n", (const char *) (*_nodes[ idx ]) );
        print( 0 );
        #endif

        BTreeExcept a( "Duplicate", BTreeExcept::Duplicate );
        throw( a );
    }

    if( idx < _degree ) {
        for( int j = _degree; j > idx; j -= 1 ) {
            _nodes[ j ] = _nodes[ j - 1 ];
        }
    }
    _nodes[ idx ] = obj;

    _degree += 1;

    return _nodes[ idx ];
}

template < class Key_T, class Obj_T >
Obj_T * BTreeBucketNode<Key_T,Obj_T>::
split( Key_T & key, Obj_T * obj, BTreeNodeBase *& newNode )
//---------------------------------------------------------
{
    BTreeBucketNode *   right;
    Obj_T *             ret;

    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "splitting bucketnode -- obj %s\n", (const char *)(*obj) );
    #endif

    right = new BTreeBucketNode();

    try {
        if( ((const Key_T &)(*obj)).operator< ( (const Key_T &)(*_nodes[ _objOrder ]) ) ) {

            for( int i = 0; i < _objOrder + 1; i += 1 ) {
                right->_nodes[ i ] = _nodes[ _objOrder + i ];
            }

            right->_degree = _objOrder + 1;
            _degree = _objOrder;
            ret = privInsert( obj );
        } else {
            if( ((const Key_T &)(*obj)).operator== (
                                (const Key_T &)(*_nodes[ _objOrder ]) ) ) {

                #if INSTRUMENTS
                Log.printf( "DUPLICATE! %s =\n", (const char *) (*obj) );
                Log.printf( "           %s\n", (const char *) (*_nodes[ _objOrder ] ) );
                print( 0 );
                #endif

                BTreeExcept a( "Duplicate", BTreeExcept::Duplicate );
                throw( a );
            } else {
                for( int i = 0; i < _objOrder; i += 1 ) {
                    right->_nodes[ i ] = _nodes[ _objOrder + i + 1 ];
                }
                right->_degree = _objOrder;
                _degree = _objOrder + 1;
                ret = right->privInsert( obj );
            }
        }
    } catch( BTreeExcept( oops ) ) {
        // privInsert may throw a duplicate (or other) exception -- try
        // to clean up as best as possible

        delete right;
        right = NULL;
        newNode = NULL;
        _degree = _objOrder * 2 + 1;
        throw;  // re-throw oops
    }

    if( right ) {
        key.operator= ( (const Key_T &) (*right->_nodes[ 0 ]) );
    }
    newNode = right;

    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "split bucketnode -- key, %s, oldnode, newnode\n", key.getString() );
    print(0);
    newNode->print(0);
    #endif

    return ret;
}

template < class Key_T, class Obj_T >
BTreeNodeBase< Key_T, Obj_T > *
BTreeBucketNode<Key_T,Obj_T>::
nextNode( int_16 & )
//-----------------------------------
{
    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "BucketNode nextNode == NULL\n" );
    #endif

    return NULL;    // no nodes in buckets
}

template < class Key_T, class Obj_T >
Obj_T * BTreeBucketNode<Key_T,Obj_T>::
nextObj( int_16 & idx)
//------------------------------------
{
    #if ( INSTRUMENTS == INSTRUMENTS_FULL_LOGGING )
    Log.printf( "BucketNode %p, idx = %d, _degree = %d, return = %p\n",
                                    this, idx + 1, _degree, (idx +1 < _degree) ? _nodes[ idx + 1 ] : NULL );
    #endif

    idx += 1;
    if( idx >= _degree ) return NULL;

    return _nodes[ idx ];
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?