hashtbl.cpp

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C++ 代码 · 共 347 行

CPP
347
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include "wpch.hpp"
#include "hashtbl.hpp"

static Pool LListBase::Block::blockPool( LListBlockPool, sizeof(LListBase::Block), 64 );


HashTableBase::HashTableBase(int num_buckets)
/*******************************************/
    : _numBuckets( num_buckets )
{
    _table = new Hashable *[num_buckets];
    memset( _table, 0, num_buckets*sizeof(Hashable *));
    _numEntries = 0;
}


HashTableBase::~HashTableBase()
/*****************************/
{
    Hashable *  prev;
    Hashable *  curr;
    int         i;

    for( i=0; i<_numBuckets; i++ ){
        curr = _table[i];
        while( curr != NULL ){
            prev = curr;
            curr = curr->next;
            delete prev;
        }
    }
    delete[] _table;
}


void HashTableBase::Clear()
/*************************/
{
    memset( _table, 0, _numBuckets*sizeof(Hashable *) );
    _numEntries = 0;
}


void HashTableBase::ClearAndDelete()
/**********************************/
{
    Hashable *  prev;
    Hashable *  curr;
    int         i;

    for( i=0; i<_numBuckets; i++ ){
        curr = _table[i];
        while( curr != NULL ){
            prev = curr;
            curr = curr->next;
            delete prev;
        }
        _table[i] = NULL;
    }
    _numEntries = 0;
}


int HashTableBase::Hash( uint_32 id )
/***********************************/
{
    //return ((int) (id << 8)) % _numBuckets;

    uint_32 s = id;
    uint_32 c;
    uint_32 g;
    uint_32 h;

    h = 0x4;
    c = 0x4;
    c += s;
    h = ( h << 4 ) + c;
    g = h & ~0x0ffffff;
    h ^= g;
    h ^= g >> (4+4+4+4+4);
    g = h & ~0x0fff;
    h ^= g;
    h ^= g >> (4+4+4);
    h ^= h >> (2+4);
    WAssert( ( h & ~0x0fff ) == 0 );
    return( (int) (h%_numBuckets) );
}


void HashTableBase::Insert( Hashable *hashdata )
/************************************************/
{
    Hashable *  current;
    Hashable *  prev;
    int         bucket;

    bucket = Hash( hashdata->index );
    current = _table[ bucket ];
    prev = NULL;
    while( current != NULL && current->index < hashdata->index ){
        prev = current;
        current = current->next;
    }
    if( current != NULL ){
        hashdata->next = current;
    } else {
        hashdata->next = NULL;
    }
    if( prev != NULL ){
        prev->next = hashdata;
    } else {
        _table[ bucket ] = hashdata;
    }
    _numEntries++;
}


Hashable * HashTableBase::Lookup( uint_32 id )
/**********************************************/
{
    Hashable *  result;
    Hashable *  current;

    current = _table[ Hash( id ) ];
    result = NULL;
    for( ;; ){
        if( current == NULL ){
            break;
        } else if( current->index > id ){
            break;
        } else if( current->index == id ){
            result = current;
            break;
        }
        current = current->next;
    }
    return result;
}


Hashable * HashTableBase::Remove( uint_32 id )
/**********************************************/
{
    Hashable            *current;
    Hashable            *prev;
    int                 index;

    prev = NULL;
    index = Hash( id );
    current = _table[ index ];
    for( ;; ){
        if( current == NULL ){
            break;
        } else if( current->index > id ){
            break;
        } else if( current->index == id ){
            if( prev != NULL ){
                prev->next = current->next;
            } else {
                _table[index] = current->next;
            }
            break;
        }
        prev = current;
        current = current->next;
    }
    return current;
}


LListBase::LListBase()
/********************/
{
    _tail = _current = 32-1;
    _headBlock = _tailBlock = _currentBlock = NULL;
    _numEntries = 0;
}


LListBase::~LListBase()
/*********************/
{
    Block *     prev;
    Block *     curr;

    curr = _headBlock;
    while( curr != NULL ){
        prev = curr;
        curr = curr->next;
        delete prev;
    }
}


void LListBase::Append( void *data )
/**********************************/
{
    Block       *block;
    int         tail;

    tail = _tail+1;
    if( tail == 32 ){
        block = new Block;
        block->data[0] = data;
        block->next = NULL;
        block->prev = _tailBlock;
        if( _headBlock == NULL ){
            _headBlock = block;
        } else {
            _tailBlock->next = block;
        }
        _tailBlock = block;
        _tail = 0;
    } else {
        _tail = tail;
        _tailBlock->data[tail] = data;
    }
    _numEntries++;
}


void *LListBase::Pop()
/********************/
{
    void        *result;
    Block       *topBlock;
    int         top;

    topBlock = _tailBlock;
    if( topBlock == NULL ){
        return NULL;
    }
    top = _tail;
    result = topBlock->data[top];
    top--;
    if( top == -1 ){
        _tailBlock = topBlock->prev;
        if( _tailBlock == NULL ){
            _headBlock = NULL;
        }
        _tail = 32-1;
        delete topBlock;
    } else {
        _tail = top;
    }
    _numEntries--;
    return result;
}


void * LListBase::First()
/***********************/
{
    _current = 0;
    _currentBlock = _headBlock;
    return (_currentBlock!=NULL)?_currentBlock->data[0]:NULL;
}


void * LListBase::Next()
/**********************/
{
    Block       *currentBlock;
    int         current;

    currentBlock = _currentBlock;
    if( currentBlock == NULL ){
        return NULL;
    } else {
        current = _current+1;
        if( currentBlock == _tailBlock ){
            if( current > _tail ){
                _currentBlock = NULL;
                return NULL;
            } else {
                _current = current;
                return currentBlock->data[current];
            }
        } else {
            if( current < 32 ){
                _current = current;
                return currentBlock->data[current];
            } else {
                _current = 0;
                WAssert( currentBlock->next != NULL );
                _currentBlock = currentBlock->next;
                return _currentBlock->data[0];
            }
        }
    }
}


void LListBase::Clear()
/*********************/
{
    Block *     prev;
    Block *     curr;

    curr = _headBlock;
    while( curr != NULL ){
        prev = curr;
        curr = curr->next;
        delete prev;
    }
    _headBlock = NULL;
    _tailBlock = NULL;
    _currentBlock = NULL;
    _tail = 32-1;
    _current = 32-1;
    _numEntries = 0;

    Block::blockPool.CleanUp( Pool::Medium );
}

⌨️ 快捷键说明

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