Hola!
A continuación lo realizado respecto a la clase THbHash de Manu con algunas colaboraciones aportadas acá y de este servidor. A mi parecer, la clase ya cumple con lo necesario.
La Clase:
Code: Select all | Expand
//-----------------------------------------------------------------------------
// Gestion de hash como objetos
//-----------------------------------------------------------------------------
#include "hbapiitm.h"
#include "hbvm.h"
#include "hbstack.h"
#include "hbapicls.h"
#include "hboo.ch"
#include "hbinit.h"
#define _GETHASH0() hb_arrayGetPtr( hb_stackSelfItem(), 1 )
#define _GETHASH1( pSelf ) hb_arrayGetPtr( (pSelf), 1 )
//-----------------------------------------------------------------------------
// Constructor
static void THBHASH_NEW( void )
{
PHB_ITEM pSelf = hb_stackSelfItem();
PHB_ITEM hTable;
PHB_ITEM hTablePar = hb_param( 1, HB_IT_HASH );
if( hTablePar )
{
hTable = hb_itemNew( NULL );
hb_itemMove( hTable, hTablePar );
}
else
{
hTable = hb_hashNew( NULL );
}
hb_hashClearFlags( hTable, HB_HASH_BINARY );
hb_hashSetFlags( hTable, HB_HASH_IGNORECASE | HB_HASH_RESORT );
hb_arraySetPtr( pSelf, 1, hTable );
hb_itemReturn( pSelf );
}
//-----------------------------------------------------------------------------
// Asigna un nuevo hash para gestionarlo desde el objeto
static void THBHASH_SETHASH( void )
{
PHB_ITEM pSelf = hb_stackSelfItem();
PHB_ITEM hTablePar = hb_param( 1, HB_IT_HASH );
PHB_ITEM hTableOld = _GETHASH1( pSelf );
if( hTableOld )
{
hTableOld = hb_hashNew( hTableOld );
}
if( hTablePar )
{
PHB_ITEM hTable = hb_itemNew( NULL );
hb_itemMove( hTable, hTablePar );
hb_hashClearFlags( hTable, HB_HASH_BINARY );
hb_hashSetFlags( hTable, HB_HASH_IGNORECASE | HB_HASH_RESORT );
hb_arraySetPtr( pSelf, 1, hTable );
}
hb_itemReturnRelease( hTableOld );
}
//-----------------------------------------------------------------------------
// Obtiene el hash gestionado desde el objeto
static void THBHASH_GETHASH( void )
{
PHB_ITEM pSelf = hb_stackSelfItem();
hb_itemReturn( hb_arrayGetPtr( pSelf, 1 ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_LEN( void )
{
hb_retnint( hb_hashLen( _GETHASH0() ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_DEL( void )
{
PHB_ITEM pKey = hb_param( 1, HB_IT_HASHKEY );
if( pKey )
{
hb_retl( hb_hashDel( _GETHASH0(), pKey ) );
}
else
{
hb_retl( HB_FALSE );
}
}
//-----------------------------------------------------------------------------
static void THBHASH_SET( void )
{
PHB_ITEM pKey = hb_param( 1, HB_IT_HASHKEY );
if( pKey )
{
hb_retl( hb_hashAdd( _GETHASH0(), pKey, hb_param( 2, HB_IT_ANY ) ) );
}
else
{
hb_retl( HB_FALSE );
}
}
//-----------------------------------------------------------------------------
static void THBHASH_CLEAR( void )
{
hb_retl( hb_hashClear( _GETHASH0() ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_SORT( void )
{
hb_hashSort( _GETHASH0() );
}
//-----------------------------------------------------------------------------
static void THBHASH_SCAN( void )
{
HB_SIZE nPos = 0;
PHB_ITEM pKey = hb_param( 1, HB_IT_HASHKEY );
if( pKey )
{
hb_hashScan( _GETHASH0(), pKey, &nPos );
}
hb_retnint( nPos );
}
//-----------------------------------------------------------------------------
static void THBHASH_KEYS( void )
{
hb_itemReturnRelease( hb_hashGetKeys( _GETHASH0() ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_VALUES( void )
{
hb_itemReturnRelease( hb_hashGetValues( _GETHASH0() ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_GET( void )
{
PHB_ITEM pKey = hb_param( 1, HB_IT_HASHKEY );
if( pKey )
{
PHB_ITEM pValue = hb_hashGetItemPtr( _GETHASH0(), pKey, HB_HASH_AUTOADD_ACCESS );
if( pValue )
{
hb_itemReturn( pValue );
return;
}
}
hb_ret();
}
//-----------------------------------------------------------------------------
static void THBHASH_VALUEAT( void )
{
PHB_ITEM pPos = hb_param( 1, HB_IT_NUMERIC );
if( pPos )
{
PHB_ITEM pValue = hb_hashGetValueAt( _GETHASH0(), hb_itemGetNS( pPos ) );
if( pValue )
{
hb_itemReturn( pValue );
return;
}
}
hb_ret();
}
//-----------------------------------------------------------------------------
static void THBHASH_KEYAT( void )
{
PHB_ITEM pPos = hb_param( 1, HB_IT_NUMERIC );
if( pPos )
{
PHB_ITEM pKey = hb_hashGetKeyAt( _GETHASH0(), hb_itemGetNS( pPos ) );
if( pKey )
{
hb_itemReturn( pKey );
return;
}
}
hb_ret();
}
//-----------------------------------------------------------------------------
static void THBHASH_DELAT( void )
{
PHB_ITEM pPos = hb_param( 1, HB_IT_NUMERIC );
if( pPos )
{
if( hb_hashDelAt( _GETHASH0(), hb_itemGetNS( pPos ) ) )
{
hb_retl( HB_TRUE );
return;
}
}
hb_retl( HB_FALSE );
}
//-----------------------------------------------------------------------------
static void THBHASH_HASKEY( void )
{
PHB_ITEM pKey = hb_param( 1, HB_IT_HASHKEY );
if( pKey )
{
HB_SIZE nPos;
hb_retl( hb_hashScanSoft( _GETHASH0(), pKey, &nPos ) );
hb_storns( nPos, 3 );
}
hb_ret();
}
//-----------------------------------------------------------------------------
static void THBHASH_SETFLAGS( void )
{
PHB_ITEM nFlags = hb_param( 1, HB_IT_INTEGER );
if( nFlags )
{
hb_hashSetFlags( _GETHASH0(), hb_itemGetNI( nFlags ) );
}
}
//-----------------------------------------------------------------------------
static void THBHASH_GETFLAGS( void )
{
hb_retni( hb_hashGetFlags( _GETHASH0() ) );
}
//-----------------------------------------------------------------------------
static void THBHASH_CLEARFLAGS( void )
{
PHB_ITEM nFlags = hb_param( 1, HB_IT_INTEGER );
if( nFlags )
{
hb_hashClearFlags( _GETHASH0(), hb_itemGetNI( nFlags ) );
}
}
//-----------------------------------------------------------------------------
static void THBHASH_END( void )
{
hb_itemRelease( _GETHASH0() );
}
//-----------------------------------------------------------------------------
HB_FUNC_STATIC( THBHASH_ONERROR )
{
PHB_ITEM pKey;
char *szKey;
PHB_ITEM hTable = _GETHASH0();
hb_vmPushSymbol( hb_dynsymSymbol( hb_dynsymFindName( "__GETMESSAGE" ) ) );
hb_vmPushNil();
hb_vmProc( 0 );
pKey = hb_stackReturnItem();
szKey = hb_itemGetC( pKey );
if( szKey [ 0 ] == '_' ) // SET
{
hb_itemPutC( pKey, szKey + 1 );
hb_hashAdd( hTable, pKey, hb_param( 1, HB_IT_ANY ) );
}
else // GET
{
HB_SIZE nPos;
if( hb_hashScan( hTable, pKey, &nPos ) )
{
hb_itemReturn( hb_hashGetValueAt( hTable, nPos ) );
}
}
hb_xfree( szKey );
}
//-----------------------------------------------------------------------------
// Añade los metodos de la clase
static void addMethods( HB_USHORT usClassH )
{
static HB_SYMB symOnError = { "ONERROR", { HB_FS_STATIC }, { HB_FUNCNAME( THBHASH_ONERROR ) }, NULL };
// Data hash
hb_clsAdd( usClassH, "_HASH", THBHASH_SETHASH );
hb_clsAdd( usClassH, "HASH", THBHASH_GETHASH );
// Data flags
hb_clsAdd( usClassH, "_FLAGS", THBHASH_SETFLAGS );
hb_clsAdd( usClassH, "FLAGS", THBHASH_GETFLAGS );
// Metodos
hb_clsAdd( usClassH, "NEW", THBHASH_NEW );
hb_clsAdd( usClassH, "SETHASH", THBHASH_SETHASH );
hb_clsAdd( usClassH, "GETHASH", THBHASH_GETHASH );
hb_clsAdd( usClassH, "LEN", THBHASH_LEN );
hb_clsAdd( usClassH, "DEL", THBHASH_DEL );
hb_clsAdd( usClassH, "ADD", THBHASH_SET );
hb_clsAdd( usClassH, "SET", THBHASH_SET );
hb_clsAdd( usClassH, "GET", THBHASH_GET );
hb_clsAdd( usClassH, "CLEAR", THBHASH_CLEAR );
hb_clsAdd( usClassH, "SORT", THBHASH_SORT );
hb_clsAdd( usClassH, "SCAN", THBHASH_SCAN );
hb_clsAdd( usClassH, "KEYS", THBHASH_KEYS );
hb_clsAdd( usClassH, "VALUES", THBHASH_VALUES );
hb_clsAdd( usClassH, "VALUEAT", THBHASH_VALUEAT );
hb_clsAdd( usClassH, "KEYAT", THBHASH_KEYAT );
hb_clsAdd( usClassH, "DELAT", THBHASH_DELAT );
hb_clsAdd( usClassH, "HASKEY", THBHASH_HASKEY );
hb_clsAdd( usClassH, "SETFLAGS", THBHASH_SETFLAGS );
hb_clsAdd( usClassH, "GETFLAGS", THBHASH_GETFLAGS );
hb_clsAdd( usClassH, "CLEARFLAGS", THBHASH_CLEARFLAGS );
hb_clsAdd( usClassH, "END", THBHASH_END );
// Añade el metodo ONERROR como gestor de errores de la clase
hb_vmPushSymbol( hb_dynsymFindSymbol( "__CLSADDMSG" ) );
hb_vmPushNil();
hb_vmPushInteger( usClassH );
hb_vmPushString( "ONERROR", strlen( "ONERROR" ) );
hb_vmPushSymbol( &symOnError );
hb_vmPushInteger( HB_OO_MSG_ONERROR );
hb_vmProc( 4 );
}
//-----------------------------------------------------------------------------
// Funcion de clase para usar desde Harbour
//-----------------------------------------------------------------------------
HB_FUNC( THBHASH )
{
static HB_USHORT usClassH = 0;
if( usClassH == 0 )
{
usClassH = hb_clsCreate( 1, "THBHASH" );
addMethods( usClassH );
}
// Instancia un objeto de la clase THBARRAY y lo mete en la pila
hb_clsAssociate( usClassH );
// Asigna el objeto C++ a la data del objeto de xBase
hb_arraySetPtr( hb_stackReturnItem(), 1, NULL );
}
//=============================================================================
// Inicializa los simbolos de las clase en la tabla de simbolos de harbour.
//=============================================================================
HB_INIT_SYMBOLS_BEGIN( THBHASH__InitSymbols )
{ "THBHASH", { HB_FS_PUBLIC | HB_FS_LOCAL }, { HB_FUNCNAME( THBHASH ) }, NULL }
HB_INIT_SYMBOLS_END( THBPGPP__InitSymbols )
#if defined( HB_PRAGMA_STARTUP )
#pragma startup THBHASH__InitSymbols
#elif defined( HB_DATASEG_STARTUP )
#define HB_DATASEG_BODY HB_DATASEG_FUNC( THBHASH__InitSymbols )
#include "hbiniseg.h"
#endif
//-----------------------------------------------------------------------------
test00.prg
Code: Select all | Expand
//-----------------------------------------------------------------------------
// Ejemplo uso de THbHash
//-----------------------------------------------------------------------------
procedure main
local h := THbHash():new()
local i, c, n
alert( valtype( h ) )
alert( valtype( h:getHash() ) )
for i := 1 to 10
c := hb_ntos( i )
h:set( "key" + c, "value" + c )
next
? "Numero de elementos:", n:= h:len()
? "------------------------------------------------------"
for i := 1 to n
? "Clave:", c := "key" + hb_ntos( i ), "Valor:", h:get( c )
next
? h:key1, h:get( "key1" )
h:autor := "Manu Exposito"
? h:autor, h:get( "autor" )
? "------------------------------------------------------"
? "Keys:"
? hb_valtoexp( h:keys() )
? "Values:"
? hb_valtoexp( h:values() )
h:end()
alert( "Fin" )
return
test01.prg
Code: Select all | Expand
//-----------------------------------------------------------------------------
// Ejemplo uso de THbHash
//-----------------------------------------------------------------------------
procedure main
local hash := { "key1" => "valor1", "key2" => "valor2", "key3" => "valor3"}
local h := THbHash():new( hash )
? "Numero de elementos:", h:len(), len( hash )
h:autor := "Manu Exposito"
? h:autor, h:get( "autor" )
hash[ "prueba" ] = "prueba desde fuera"
? "------------------------------------------------------"
? "Keys:"
? hb_valtoexp( h:keys() )
? "Values:"
? hb_valtoexp( h:values() )
? "Todo:"
? hb_valtoexp( hash )
h:end()
? "Todo despues del end:"
? hb_valtoexp( hash )
alert( "Fin" )
return
test02.prg
Code: Select all | Expand
//-----------------------------------------------------------------------------
// Ejemplo uso de THbHash
//-----------------------------------------------------------------------------
procedure main
local hash := { "key1" => "valor1", "key2" => "valor2", "key3" => "valor3"}
local h := THbHash():new()
? "Numero de elementos:", h:len(), len( hash )
h:setHash( hash )
? "Numero de elementos:", h:len(), len( hash )
h:autor := "Manu Exposito"
? h:autor, h:get( "autor" )
hash[ "prueba" ] = "prueba desde fuera"
? "------------------------------------------------------"
? "Keys:"
? hb_valtoexp( h:keys() )
? "Values:"
? hb_valtoexp( h:values() )
? "Todo:"
? hb_valtoexp( hash )
h:end()
? "Todo despues del end:"
? hb_valtoexp( hash )
alert( "Fin" )
return
test03.prg
Code: Select all | Expand
//-----------------------------------------------------------------------------
// Ejemplo usu de THbHash
//-----------------------------------------------------------------------------
procedure main
local h := THbHash():new()
local i, c, cKey
CLS
h:cAuthor := "Manu Exposito"
? "Author: ", h:cAuthor, "Key con mayusculas y minusculas:", h:cAuThOr
h:cAuthor := "YO Exposito"
? "valtype( h ) => ", valtype( h ) , " | "
?? "valtype( h:getHash() ) => ", valtype( h:getHash() )
? "------------------------------------------------------"
? "List of Methods:"
? hb_valtoexp( __objGetMethodList( h ) )
for i := 1 to 10
c := hb_ntos( i )
h:set( "key" + c, "value" + c )
next
h:key1 := { 1, 2, 3, 4 }
h:add( "key11", {|| alert("Fin!") } )
? "------------------------------------------------------"
? "Delete key10. => h:del('key10') => ", h:del( "key10" )
? "Scan the key5 => h:scan('key5') => ", hb_valtoexp( h:scan( "key5" ) ), " ( Return value in key5 ) "
? "Value in position 6 => h:valueAt( 6 ) => ", hb_valtoexp( h:valueAt( 6 ) )
? "Is defined 'key8'? => h:hasKey('key8') => ", h:hasKey( "key8" )
? "------------------------------------------------------"
? "Number of elements:", hb_ntos( h:len() )
? "Keys:"
? hb_valtoexp( h:keys() )
? "Values:"
? hb_valtoexp( h:values() )
? "------------------------------------------------------"
FOR EACH cKey IN h:Keys()
? cKey, "=>" , hb_valtoexp( h:get(cKey) )
if hb_isBlock( h:get(cKey) ) ; EVAL( h:get(cKey) ) ; endif
NEXT
h:end()
return
Saludos cordiales.