summaryrefslogblamecommitdiffstats
path: root/private/ole32/dcomss/olescm/scmhash.cxx
blob: efd1e009faa45b9291874b1d063650b7a44e252d (plain) (tree)
















































































































































































































































































































































                                                                               
//+-------------------------------------------------------------------------
//
//  Microsoft Windows
//  Copyright (C) Microsoft Corporation, 1992 - 1993.
//
//  File:       scmhash.cxx
//
//  Contents:   Class definitions used for SCM hash table.
//
//  History:    20-Jan-93 Ricksa    Created from map_kv.cpp
//
//  Notes:      The reason for creating this file rather than using the
//              original class is that the SCM has different memory allocation
//              needs depending on whether it is built for Win95 or NT.
//
//--------------------------------------------------------------------------
#include    <headers.cxx>
#include    <scmhash.hxx>



//+-------------------------------------------------------------------------
//
//  Member:     CScmHashEntry::~CScmHashEntry
//
//  Synopsis:   Clean up hash entry
//
//  History:	16-Feb-96 Ricksa    Created
//
//--------------------------------------------------------------------------
CScmHashEntry::~CScmHashEntry(void)
{
    // Just exists hopefully to save some space
}






//+-------------------------------------------------------------------------
//
//  Member:     CScmHashTable::~CScmHashTable
//
//  Synopsis:   Free resources held by the hash table
//
//  Algorithm:  For each hash bucket, delete all member of the collison
//              list.
//
//  History:	16-Feb-95 Ricksa    Created
//
//--------------------------------------------------------------------------
CScmHashTable::~CScmHashTable(void)
{
    // Free all the objects in the table.

    // Loop through each hash bucket
    for (DWORD i = 0; i < _ndwHashTableSize; i++)
    {
        // For each entry in the hash bucket list delete it.
        CScmHashEntry *pshe = _apsheHashTable[i];

        while (pshe != NULL)
        {
            CScmHashEntry *psheNext = pshe->GetNext();

            delete pshe;

            pshe = psheNext;
        }

    }

    // Free the table itself
    ScmMemFree(_apsheHashTable);
}




//+-------------------------------------------------------------------------
//
//  Member:     CScmHashTable::Lookup
//
//  Synopsis:   Look up entry by hash and key
//
//  Arguments:  [dwHash] - hash value to use
//              [pKey] - key to use
//              [cbKey] - count of bytes in the key
//
//  Returns:    NULL - no matching entry was found
//              Pointer to first matching entry found
//
//  Algorithm:  If there is an entry for the hash bucket, search
//              through the collision entries for the first entry
//              that matches.
//
//  History:    20-Jan-95 Ricksa    Created
//
//--------------------------------------------------------------------------
CScmHashEntry * CScmHashTable::Lookup(
    DWORD dwHash,
    LPVOID pKey,
    UINT cbKey) const
{
    CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::Lookup "
        "( %lx , %p , %lx )\n", this, dwHash, pKey, cbKey));

    CScmHashEntry *psheFound = NULL;

    // Are there any entries for this bucket?
    if (_apsheHashTable[dwHash] != NULL)
    {
        CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];

        // Loop searching for a match
        do
        {
            if (psheToSearch->IsEqual(pKey, cbKey))
            {
                psheFound = psheToSearch;
                break;
            }
        } while ((psheToSearch = psheToSearch->GetNext()) != NULL);
    }

    CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::Lookup ( %p )\n",
        this, psheFound));
    return psheFound;
}



//+-------------------------------------------------------------------------
//
//  Member:     CScmHashTable::SetAt
//
//  Synopsis:   Add a new entry
//
//  Arguments:  [dwHash] - hash value to use
//              [psheToAdd] - hash entry to add
//
//  Algorithm:  If there are no entries for the bucket, make the bucket
//              point to this entry. Otherwise, put this entry on the
//              end of the list of collisions.
//
//  History:    20-Jan-95 Ricksa    Created
//
//--------------------------------------------------------------------------
void CScmHashTable::SetAt(
    DWORD dwHash,
    CScmHashEntry *psheToAdd)
{
    CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::SetAt "
        "( %lx , %p )\n", this, dwHash, psheToAdd));

    // Are there entries that has to this bucket?
    if (_apsheHashTable[dwHash] != NULL)
    {
        // Yes -- then put this one on the end of the list

        CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
        CScmHashEntry *psheLast;

        do
        {

            psheLast = psheToSearch;

        } while ((psheToSearch = psheToSearch->GetNext()) != NULL);

        psheLast->SetNext(psheToAdd);
    }
    else
    {
        // No entries on the list so put this one first
        _apsheHashTable[dwHash] = psheToAdd;
    }

    _ndwCount++;

    CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::SetAt \n", this));
}


//+-------------------------------------------------------------------------
//
//  Member:     CScmHashTable::RemoveEntry
//
//  Synopsis:   Remove an entry from the list
//
//  Arguments:  [dwHash] - hash value to use
//              [psheToRemove] - hash entry to add
//
//  Returns:    TRUE - entry removed.
//              FALSE - no such entry found
//
//  Algorithm:  If bucket is not empty, if this is the first entry replace
//              it with its next. Otherwise, loop through the list searching
//              for the entry and make its previous point to the current
//              one's next.
//
//  History:    20-Jan-95 Ricksa    Created
//
//--------------------------------------------------------------------------
BOOL CScmHashTable::RemoveEntry(
    DWORD dwHash,
    CScmHashEntry *psheToRemove)
{
    CairoleDebugOut((DEB_ROT, "%p _IN CScmHashTable::RemoveEntry "
        "( %lx , %p )\n", this, dwHash, psheToRemove));

    BOOL fFound = FALSE;

    // Are there any entries for this bucket?
    if (_apsheHashTable[dwHash] != NULL)
    {
        CScmHashEntry *psheToSearch = _apsheHashTable[dwHash];
        CScmHashEntry *pshePrev = NULL;

        while (psheToSearch != NULL)
        {
            if (psheToSearch == psheToRemove)
            {
                if (pshePrev == NULL)
                {
                    // First entry matches so update the head of the list
                    _apsheHashTable[dwHash] = psheToSearch->GetNext();
                }
                else
                {
                    // Found entry in the middle of the list so delete
                    // the previous item's next pointer
                    pshePrev->SetNext(psheToSearch->GetNext());
                }

                // Tell the caller we found the item
                fFound = TRUE;
                break;
            }

            pshePrev = psheToSearch;
            psheToSearch = psheToSearch->GetNext();
        }

        if (fFound)
        {
            _ndwCount--;
        }
    }

    CairoleDebugOut((DEB_ROT, "%p OUT CScmHashTable::RemoveEntry ( %lx )\n",
        this, fFound));

    return fFound;
}




//+-------------------------------------------------------------------------
//
//  Member:     CScmHashIter::FindNextBucketWithEntry
//
//  Synopsis:   Find next hash bucket that has an entry
//
//  Returns:    Entry for bucket or NULL if there are none/
//
//  Algorithm:  Beginning with the current bucket loop through the list
//              of buckets till one is not null or there are no more
//              buckets.
//
//  History:    20-Jan-95 Ricksa    Created
//
//--------------------------------------------------------------------------
CScmHashEntry *CScmHashIter::FindNextBucketWithEntry(void)
{
    CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::FindNextBucketWithEntry\n",
        this));

    for (; _dwBucket < _psht->_ndwHashTableSize; _dwBucket++)
    {
        if ((_psheNext =_psht->_apsheHashTable[_dwBucket]) != NULL)
        {
            break;
        }
    }

    // Point to the next bucket
    _dwBucket++;

    CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::FindNextBucketWithEntry "
        "( %p )\n", this, _psheNext));

    return _psheNext;
}




//+-------------------------------------------------------------------------
//
//  Member:     CScmHashIter::GetNext
//
//  Synopsis:   Find next hash bucket that has an entry
//
//  Returns:    Next entry in the iteration
//
//  Algorithm:  Get the next pointer from the object and then update
//              the next pointer if there are still entries to be
//              iterated.
//
//  History:    20-Jan-95 Ricksa    Created
//
//--------------------------------------------------------------------------
CScmHashEntry *CScmHashIter::GetNext(void)
{
    CairoleDebugOut((DEB_ROT, "%p _IN CScmHashIter::GetNext \n", this));

    CScmHashEntry *psheToReturn = _psheNext;

    // Search for the next entry to return
    if (_psheNext != NULL)
    {
        _psheNext = _psheNext->GetNext();

        if (_psheNext == NULL)
        {
            FindNextBucketWithEntry();
        }
    }

    CairoleDebugOut((DEB_ROT, "%p OUT CScmHashIter::GetNext "
        "( %p )\n", this, psheToReturn));

    return psheToReturn;
}