Files
harbour-core/harbour/source/common/hbhash.c
Przemyslaw Czerpak 0ef0f1aab9 2007-03-13 19:40 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapi.h
  * harbour/include/hbapiitm.h
  * harbour/source/vm/garbage.c
  * harbour/source/vm/extend.c
  * harbour/source/vm/itemapi.c
    + added hb_gcFunc(), hb_parptrGC(), hb_itemGetPtrGC()
      hb_parptrGC() and hb_itemGetPtrGC() uses GC cleanup function address
      to validate if pointer item points to expected memory block type

  * harbour/source/common/hbhash.c
  * harbour/source/compiler/hbident.c
    * formatting and minor modifications

  * harbour/source/pp/pplib.c
  * harbour/source/pp/pplib2.c
    * use hb_parptrGC() to be sure that given pointer item points
      to PP structure

  + harbour/include/hbregex.h
  + harbour/source/rtl/hbregex.c
  * harbour/source/rtl/Makefile
  * harbour/common.mak
    + added support for regular expressions. Now it's enabled by default
      only in *nixes (POSIX regex) and BCC 5.5 (PCRE regex). Setting
      HB_PCRE_REGEX macro enables Perl-Compatible Regular Expressions
      and HB_POSIX_REGEX - POSIX regular expressions. In xHarbour regex
      support is enabled for all builds because PCRE source code is stored
      in CVS. If you will want we can make the same.
    + the following C functions are available:
      hb_regexCompile(), hb_regexGet(), hb_regexFree(), hb_regexMatch()
    + the following PGR functions are available:
      HB_REGEXCOMP(), HB_ISREGEX(), HB_ATX(), HB_REGEX(), HB_REGEXMATCH(),
      HB_REGEXSPLIT(), HB_REGEXATX(), HB_REGEXALL()
      They are working in similar way to the ones in xHarbour with the
      exception to some bug fixes and form of compiled regular expression.
      In Harbour it's pointer item for which HB_ISREGEX() returns TRUE when
      in xHarbour it's binary string.

  * harbour/source/rdd/dbfcdx/dbfcdx1.c
  * harbour/source/rdd/dbfntx/dbfntx1.c
    * enabled code to seek in index using regular expressions
      (DBOI_SKIPREGEX[BACK])
2007-03-13 18:40:56 +00:00

280 lines
8.0 KiB
C

/*
* $Id$
*/
/*
* Harbour Project source code:
* Harbour simple hash table implementation
*
* Copyright 1999-2002 Ryszard Glab <rglab@imid.med.pl>
* www - http://www.harbour-project.org
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this software; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/).
*
* As a special exception, the Harbour Project gives permission for
* additional uses of the text contained in its release of Harbour.
*
* The exception is that, if you link the Harbour libraries with other
* files to produce an executable, this does not by itself cause the
* resulting executable to be covered by the GNU General Public License.
* Your use of that executable is in no way restricted on account of
* linking the Harbour library code into it.
*
* This exception does not however invalidate any other reasons why
* the executable file might be covered by the GNU General Public License.
*
* This exception applies only to the code released by the Harbour
* Project under the name Harbour. If you copy code from other
* Harbour Project or Free Software Foundation releases into a copy of
* Harbour, as the General Public License permits, the exception does
* not apply to the code that you add in this way. To avoid misleading
* anyone as to the status of such modified files, you must delete
* this exception notice from them.
*
* If you write modifications of your own for Harbour, it is your choice
* whether to permit this exception to apply to your modifications.
* If you do not wish that, delete this exception notice.
*
*/
#include "hbhash.h"
static HB_HASH_ITEM_PTR hb_hashItemNew( ULONG ulKey, void *pKey, void * pValue )
{
HB_HASH_ITEM_PTR pItem = (HB_HASH_ITEM_PTR) hb_xgrab( sizeof( HB_HASH_ITEM ) );
pItem->key = ulKey;
pItem->KeyPtr = pKey;
pItem->ValPtr = pValue;
pItem->next = NULL;
return pItem;
}
static void hb_hashItemDelete( HB_HASH_TABLE_PTR pTable, HB_HASH_ITEM_PTR pItem )
{
if( pTable->pDeleteItemFunc )
( pTable->pDeleteItemFunc )( pTable, pItem->KeyPtr, pItem->ValPtr );
hb_xfree( (void *) pItem );
}
/* create a new hash table
* ulSize = initial numer of items in the table
* pHashTable = a function that calculates a hash key value
* (first parameter is a value to add)
* pDelete = a function that clears item's value before item's releasing
* (first parameter is a value to clear)
* pComp = a function for comparing a values
* (first and second are values to compare, function have to return
* zero if values match or nonzero if they don't match)
*/
HB_HASH_TABLE_PTR hb_hashTableCreate( ULONG ulSize,
HB_HASH_FUNC_PTR pHashFunc,
HB_HASH_FUNC_PTR pDelete,
HB_HASH_FUNC_PTR pComp )
{
HB_HASH_TABLE_PTR pTable = ( HB_HASH_TABLE_PTR ) hb_xgrab( sizeof( HB_HASH_TABLE ) );
pTable->ulTableSize = ulSize;
pTable->pKeyFunc = pHashFunc;
pTable->pDeleteItemFunc = pDelete;
pTable->pCompFunc = pComp;
pTable->ulCount = pTable->ulUsed = 0;
pTable->pItems = ( HB_HASH_ITEM_PTR * ) hb_xgrab( sizeof( HB_HASH_ITEM_PTR ) * ulSize );
memset( pTable->pItems, 0, sizeof( HB_HASH_ITEM_PTR ) * ulSize );
return pTable;
}
/* Delete all items in the hash table and next delete the table
*/
void hb_hashTableKill( HB_HASH_TABLE_PTR pTable )
{
ULONG ulSize = 0;
while( ulSize < pTable->ulTableSize )
{
if( pTable->pItems[ ulSize ] )
{
HB_HASH_ITEM_PTR pItem, pFree;
pItem = pTable->pItems[ ulSize ];
while( pItem )
{
pFree = pItem;
pItem = pItem->next;
hb_hashItemDelete( pTable, pFree );
}
}
++ulSize;
}
hb_xfree( ( void * ) pTable->pItems );
hb_xfree( ( void * ) pTable );
}
/* resize table */
HB_HASH_TABLE_PTR hb_hashTableResize( HB_HASH_TABLE_PTR pTable, ULONG ulNewSize )
{
HB_HASH_TABLE_PTR pNew;
ULONG ulSize = 0;
if( ulNewSize == 0 )
ulNewSize = 2 * pTable->ulTableSize + 1;
pNew = hb_hashTableCreate( ulNewSize,
pTable->pKeyFunc,
pTable->pDeleteItemFunc,
pTable->pCompFunc );
while( ulSize < pTable->ulTableSize )
{
if( pTable->pItems[ ulSize ] )
{
HB_HASH_ITEM_PTR pItem;
pItem = pTable->pItems[ ulSize ];
while( pItem )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pNewItem, pNext;
pNext = pItem->next;
ulKey = ( pTable->pKeyFunc )( pNew, pItem->KeyPtr, pItem->ValPtr );
pNewItem = pNew->pItems[ ulKey ];
if( pNewItem )
{
while( pNewItem->next )
pNewItem = pNewItem->next;
pNewItem->next = pItem;
}
else
{
pNew->pItems[ ulKey ] = pItem;
++pNew->ulUsed;
}
pItem->key = ulKey;
pItem->next = NULL;
++pNew->ulCount;
pItem = pNext;
}
}
++ulSize;
}
hb_xfree( ( void * ) pTable->pItems );
hb_xfree( ( void * ) pTable );
return pNew;
}
/* add a new value into th ehash table */
BOOL hb_hashTableAdd( HB_HASH_TABLE_PTR pTable, void *pKey, void *pValue )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
ulKey = ( pTable->pKeyFunc )( pTable, pKey, pValue );
pItem = pTable->pItems[ ulKey ];
if( pItem )
{
while( pItem->next )
pItem = pItem->next;
pItem->next = hb_hashItemNew( ulKey, pKey, pValue );
}
else
{
pTable->pItems[ ulKey ] = hb_hashItemNew( ulKey, pKey, pValue );
++pTable->ulUsed;
}
++pTable->ulCount;
return TRUE;
}
/* return the pointer to item's value or NULL if not found
*/
void * hb_hashTableFind( HB_HASH_TABLE_PTR pTable, void *pKey )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
void * pFound = NULL;
ulKey = ( pTable->pKeyFunc )( pTable, pKey, NULL );
pItem = pTable->pItems[ ulKey ];
if( pItem )
{
while( pItem && (( pTable->pCompFunc )( pTable, pItem->KeyPtr, pKey ) != 0) )
pItem = pItem->next;
if( pItem )
pFound = pItem->ValPtr;
}
return pFound;
}
/* Delete an item from the table
* Returns TRUE if item was found and returns FALSE when passed item
* is not stored in the table
*/
BOOL hb_hashTableDel( HB_HASH_TABLE_PTR pTable, void *pKey )
{
ULONG ulKey;
HB_HASH_ITEM_PTR pItem;
HB_HASH_ITEM_PTR pPrev = NULL;
BOOL bFound = FALSE;
ulKey = ( pTable->pKeyFunc )( pTable, pKey, NULL );
if( ulKey > pTable->ulTableSize )
return FALSE;
pItem = pTable->pItems[ ulKey ];
while( pItem && !bFound )
{
if( ( pTable->pCompFunc )( pTable, pItem->KeyPtr, pKey ) == 0 )
{
if( pPrev )
{
pPrev->next = pItem->next;
}
else
{
pTable->pItems[ ulKey ] = pItem->next;
if( !pItem->next )
{
--pTable->ulUsed;
pTable->pItems[ ulKey ] = NULL;
}
}
--pTable->ulCount;
hb_hashItemDelete( pTable, pItem );
bFound = TRUE;
}
else
{
pPrev = pItem;
pItem = pItem->next;
}
}
return bFound;
}
/* return the hash table size */
ULONG hb_hashTableSize( HB_HASH_TABLE_PTR pTable )
{
return pTable->ulTableSize;
}