From 91cf12d405183bd21603d26fecac2d1f5ae0aa7a Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Tue, 25 May 2010 11:20:34 +0000 Subject: [PATCH] 2010-05-25 13:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/include/hbapi.h * harbour/src/vm/hashes.c * harbour/src/vm/hashfunc.c + added support for keeping strict assign order in hash arrays. It's enabled optionally by setting HB_HASH_KEEPORDER hash array flag. It gives the same functionality as associative arrays in xHarbour (enabled by HSETAACOMPATIBILITY()) but this implementation is internally completely different. It does not introduce linear scan in add operation so enabling it should not reduce the performance in this operation. It can even improve it on some hardware reducing number of memory bytes which have to be moved. Only delete operation will force linear index scan. The most important in this implementation is that it does not need any additional functions like HAA*() in xHarbour. Just simply all existing functions operating on position indexes like HB_HPOS(), HB_HKEYAT(), HB_HVALUEAT(), HB_HPAIRAT(), HB_HDELAT(), HB_HSCAN() use as index natural order in which items were added to hash array. Also HB_HKEYS(), HB_HVALUES() and FOR EACH iterations respect it. + added new PRG functions HB_HKEEPORDER( [, ] ) -> HB_HSETORDER( [, ] ) -> which cam be used to enable/disable strict order in hash array. Enabling strict order for non empty hash arrays accept the order created after sorting existing item not the original assign order. Disabling strict order for non empty hash arrays may change the items order. ; TODO: add translation for xHarbour's HAA*() functions to hbcompat.ch and/or xhb library. * harbour/contrib/hbnetio/netiocli.c * harbour/contrib/hbnetio/netiosrv.c % reenabled TCP_NODELAY on client and server side I had to be really tired when I was making tests and I mixed hb_socketSetNoDelay() with hb_socketSetBlockingIO(). Thanks to Aleksander Czajczynski who noticed the delay in his tests. * harbour/contrib/hbwin/olecore.c * minor cleanup --- harbour/ChangeLog | 41 ++++++++ harbour/contrib/hbnetio/netiocli.c | 2 +- harbour/contrib/hbnetio/netiosrv.c | 2 +- harbour/contrib/hbwin/olecore.c | 2 +- harbour/include/hbapi.h | 1 + harbour/src/vm/hashes.c | 153 ++++++++++++++++++++++++++--- harbour/src/vm/hashfunc.c | 28 ++++++ 7 files changed, 211 insertions(+), 18 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index aba55065b6..dcd46fafd5 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,47 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-05-25 13:20 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapi.h + * harbour/src/vm/hashes.c + * harbour/src/vm/hashfunc.c + + added support for keeping strict assign order in hash arrays. It's + enabled optionally by setting HB_HASH_KEEPORDER hash array flag. + It gives the same functionality as associative arrays in xHarbour + (enabled by HSETAACOMPATIBILITY()) but this implementation is + internally completely different. It does not introduce linear + scan in add operation so enabling it should not reduce the + performance in this operation. It can even improve it on some + hardware reducing number of memory bytes which have to be moved. + Only delete operation will force linear index scan. The most + important in this implementation is that it does not need any + additional functions like HAA*() in xHarbour. Just simply all + existing functions operating on position indexes like HB_HPOS(), + HB_HKEYAT(), HB_HVALUEAT(), HB_HPAIRAT(), HB_HDELAT(), HB_HSCAN() + use as index natural order in which items were added to hash array. + Also HB_HKEYS(), HB_HVALUES() and FOR EACH iterations respect it. + + added new PRG functions + HB_HKEEPORDER( [, ] ) -> + HB_HSETORDER( [, ] ) -> + which cam be used to enable/disable strict order in hash array. + Enabling strict order for non empty hash arrays accept the order + created after sorting existing item not the original assign order. + Disabling strict order for non empty hash arrays may change the + items order. + ; TODO: add translation for xHarbour's HAA*() functions to hbcompat.ch + and/or xhb library. + + * harbour/contrib/hbnetio/netiocli.c + * harbour/contrib/hbnetio/netiosrv.c + % reenabled TCP_NODELAY on client and server side + I had to be really tired when I was making tests and I mixed + hb_socketSetNoDelay() with hb_socketSetBlockingIO(). + Thanks to Aleksander Czajczynski who noticed the delay in his + tests. + + * harbour/contrib/hbwin/olecore.c + * minor cleanup + 2010-05-25 09:21 UTC+0200 Viktor Szakats (harbour.01 syenar.hu) * contrib/hbct/ctrand.prg * contrib/hbct/getsecrt.prg diff --git a/harbour/contrib/hbnetio/netiocli.c b/harbour/contrib/hbnetio/netiocli.c index 22e48a769a..5f8b60977e 100644 --- a/harbour/contrib/hbnetio/netiocli.c +++ b/harbour/contrib/hbnetio/netiocli.c @@ -860,7 +860,7 @@ static PHB_CONCLI s_fileConnect( const char ** pFilename, HB_PUT_LE_UINT16( &msgbuf[ 4 ], len ); memset( msgbuf + 6, '\0', sizeof( msgbuf ) - 6 ); - hb_socketSetNoDelay( sd, HB_FALSE ); + hb_socketSetNoDelay( sd, HB_TRUE ); conn = s_fileConNew( sd, pszIpAddres, iPort, iTimeOut, pszPasswd, iPassLen, iLevel, iStrategy ); sd = HB_NO_SOCKET; diff --git a/harbour/contrib/hbnetio/netiosrv.c b/harbour/contrib/hbnetio/netiosrv.c index ff614ad530..2fc66f875f 100644 --- a/harbour/contrib/hbnetio/netiosrv.c +++ b/harbour/contrib/hbnetio/netiosrv.c @@ -618,7 +618,7 @@ HB_FUNC( NETIO_ACCEPT ) if( connsd != HB_NO_SOCKET ) { hb_socketSetKeepAlive( connsd, HB_TRUE ); - hb_socketSetNoDelay( connsd, HB_FALSE ); + hb_socketSetNoDelay( connsd, HB_TRUE ); conn = s_consrvNew( connsd, lsd->rootPath, lsd->rpc ); diff --git a/harbour/contrib/hbwin/olecore.c b/harbour/contrib/hbwin/olecore.c index 6baae1ff4e..a8bbf0307e 100644 --- a/harbour/contrib/hbwin/olecore.c +++ b/harbour/contrib/hbwin/olecore.c @@ -1460,7 +1460,7 @@ HB_FUNC( WIN_OLEAUTO___ONERROR ) /* Try property put */ - if( szMethod[ 0 ] == '_' && hb_pcount() > 0 ) + if( szMethod[ 0 ] == '_' && hb_pcount() == 1 ) { pMemberArray = &szMethodWide[ 1 ]; lOleError = HB_VTBL( pDisp )->GetIDsOfNames( HB_THIS_( pDisp ) HB_ID_REF( IID_NULL ), &pMemberArray, diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 7ffc4c8d59..692bf44d0c 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -891,6 +891,7 @@ extern HB_EXPORT HB_BOOL hb_hashDelAt( PHB_ITEM pHash, HB_SIZE ulPos ); #define HB_HASH_IGNORECASE 0x10 #define HB_HASH_BINARY 0x20 +#define HB_HASH_KEEPORDER 0x40 #define HB_HASH_FLAG_MASK 0xFFFF #define HB_HASH_FLAG_DEFAULT ( HB_HASH_AUTOADD_ASSIGN | HB_HASH_BINARY ) diff --git a/harbour/src/vm/hashes.c b/harbour/src/vm/hashes.c index 7503dbc1d9..49e9057e2f 100644 --- a/harbour/src/vm/hashes.c +++ b/harbour/src/vm/hashes.c @@ -76,6 +76,7 @@ typedef struct _HB_BASEHASH { PHB_HASHPAIR pPairs; /* pointer to the array of key/value pairs */ PHB_ITEM pDefault; /* default autoadd value */ + HB_SIZE * pulPos; /* the sort order for HB_HASH_KEEPORDER */ HB_SIZE ulSize; /* size of allocated pair array */ HB_SIZE ulLen; /* number of used items in pair array */ int iFlags; /* hash item flags */ @@ -102,6 +103,12 @@ static HB_GARBAGE_FUNC( hb_hashGarbageRelease ) pBaseHash->pPairs = NULL; pBaseHash->ulLen = 0; + if( pBaseHash->pulPos ) + { + hb_xfree( pBaseHash->pulPos ); + pBaseHash->pulPos = NULL; + } + while( ulLen-- ) { if( HB_IS_COMPLEX( &pPairs[ ulLen ].key ) ) @@ -212,18 +219,38 @@ static void hb_hashResort( PHB_BASEHASH pBaseHash ) /* The hash array is probably quite well sorted so this trivial * algorithm is the most efficient one [druzus] */ - for( ulFrom = 1; ulFrom < pBaseHash->ulLen; ++ulFrom ) + + if( pBaseHash->pulPos ) { - ulPos = ulFrom; - while( ulPos > 0 && hb_hashItemCmp( &pBaseHash->pPairs[ ulPos - 1 ].key, - &pBaseHash->pPairs[ ulPos ].key, - iFlags ) > 0 ) + for( ulFrom = 1; ulFrom < pBaseHash->ulLen; ++ulFrom ) { - HB_HASHPAIR pair; - memcpy( &pair, pBaseHash->pPairs + ulPos - 1, sizeof( HB_HASHPAIR ) ); - memcpy( pBaseHash->pPairs + ulPos - 1, pBaseHash->pPairs + ulPos, sizeof( HB_HASHPAIR ) ); - memcpy( pBaseHash->pPairs + ulPos, &pair, sizeof( HB_HASHPAIR ) ); - --ulPos; + ulPos = ulFrom; + while( ulPos > 0 && hb_hashItemCmp( &pBaseHash->pPairs[ pBaseHash->pulPos[ ulPos - 1 ] ].key, + &pBaseHash->pPairs[ pBaseHash->pulPos[ ulPos ] ].key, + iFlags ) > 0 ) + { + HB_SIZE ulTemp = pBaseHash->pulPos[ ulPos - 1 ]; + pBaseHash->pulPos[ ulPos - 1 ] = pBaseHash->pulPos[ ulPos ]; + pBaseHash->pulPos[ ulPos ] = ulTemp; + --ulPos; + } + } + } + else + { + for( ulFrom = 1; ulFrom < pBaseHash->ulLen; ++ulFrom ) + { + ulPos = ulFrom; + while( ulPos > 0 && hb_hashItemCmp( &pBaseHash->pPairs[ ulPos - 1 ].key, + &pBaseHash->pPairs[ ulPos ].key, + iFlags ) > 0 ) + { + HB_HASHPAIR pair; + memcpy( &pair, pBaseHash->pPairs + ulPos - 1, sizeof( HB_HASHPAIR ) ); + memcpy( pBaseHash->pPairs + ulPos - 1, pBaseHash->pPairs + ulPos, sizeof( HB_HASHPAIR ) ); + memcpy( pBaseHash->pPairs + ulPos, &pair, sizeof( HB_HASHPAIR ) ); + --ulPos; + } } } @@ -245,11 +272,13 @@ static HB_BOOL hb_hashFind( PHB_BASEHASH pBaseHash, PHB_ITEM pKey, HB_SIZE * pul while( ulLeft < ulRight ) { ulMiddle = ( ulLeft + ulRight ) >> 1; - i = hb_hashItemCmp( &pBaseHash->pPairs[ ulMiddle ].key, pKey, iFlags ); + i = hb_hashItemCmp( &pBaseHash->pPairs[ pBaseHash->pulPos ? + pBaseHash->pulPos[ ulMiddle ] : ulMiddle ].key, + pKey, iFlags ); if( i == 0 ) { if( pulPos ) - *pulPos = ulMiddle; + *pulPos = pBaseHash->pulPos ? pBaseHash->pulPos[ ulMiddle ] : ulMiddle; return HB_TRUE; } else if( i < 0 ) @@ -268,10 +297,19 @@ static void hb_hashResize( PHB_BASEHASH pBaseHash, HB_SIZE ulNewSize ) if( pBaseHash->ulSize < ulNewSize ) { if( pBaseHash->ulSize ) + { pBaseHash->pPairs = ( PHB_HASHPAIR ) hb_xrealloc( pBaseHash->pPairs, ulNewSize * sizeof( HB_HASHPAIR ) ); + if( pBaseHash->pulPos ) + pBaseHash->pulPos = ( HB_SIZE * ) hb_xrealloc( pBaseHash->pulPos, + ulNewSize * sizeof( HB_SIZE ) ); + } else + { pBaseHash->pPairs = ( PHB_HASHPAIR ) hb_xgrab( ulNewSize * sizeof( HB_HASHPAIR ) ); + if( pBaseHash->iFlags & HB_HASH_KEEPORDER ) + pBaseHash->pulPos = ( HB_SIZE * ) hb_xgrab( ulNewSize * sizeof( HB_SIZE ) ); + } do { @@ -284,12 +322,22 @@ static void hb_hashResize( PHB_BASEHASH pBaseHash, HB_SIZE ulNewSize ) { pBaseHash->ulSize = ulNewSize; if( ulNewSize ) + { pBaseHash->pPairs = ( PHB_HASHPAIR ) hb_xrealloc( pBaseHash->pPairs, ulNewSize * sizeof( HB_HASHPAIR ) ); + if( pBaseHash->pulPos ) + pBaseHash->pulPos = ( HB_SIZE * ) hb_xrealloc( pBaseHash->pulPos, + ulNewSize * sizeof( HB_SIZE ) ); + } else { hb_xfree( pBaseHash->pPairs ); pBaseHash->pPairs = NULL; + if( pBaseHash->pulPos ) + { + hb_xfree( pBaseHash->pulPos ); + pBaseHash->pulPos = NULL; + } } } } @@ -306,7 +354,13 @@ static PHB_ITEM hb_hashValuePtr( PHB_BASEHASH pBaseHash, PHB_ITEM pKey, HB_BOOL if( pBaseHash->ulSize == pBaseHash->ulLen ) hb_hashResize( pBaseHash, pBaseHash->ulSize + HB_HASH_ITEM_ALLOC ); - if( ulPos < pBaseHash->ulLen ) + if( pBaseHash->pulPos ) + { + memmove( pBaseHash->pulPos + ulPos + 1, pBaseHash->pulPos + ulPos, + ( pBaseHash->ulLen - ulPos ) * sizeof( HB_SIZE ) ); + ulPos = ( pBaseHash->pulPos[ ulPos ] = pBaseHash->ulLen ); + } + else if( ulPos < pBaseHash->ulLen ) { memmove( pBaseHash->pPairs + ulPos + 1, pBaseHash->pPairs + ulPos, ( pBaseHash->ulLen - ulPos ) * sizeof( HB_HASHPAIR ) ); @@ -331,7 +385,13 @@ static HB_BOOL hb_hashNewValue( PHB_BASEHASH pBaseHash, PHB_ITEM pKey, PHB_ITEM if( pBaseHash->ulSize == pBaseHash->ulLen ) hb_hashResize( pBaseHash, pBaseHash->ulSize + HB_HASH_ITEM_ALLOC ); - if( ulPos < pBaseHash->ulLen ) + if( pBaseHash->pulPos ) + { + memmove( pBaseHash->pulPos + ulPos + 1, pBaseHash->pulPos + ulPos, + ( pBaseHash->ulLen - ulPos ) * sizeof( HB_SIZE ) ); + ulPos = ( pBaseHash->pulPos[ ulPos ] = pBaseHash->ulLen ); + } + else if( ulPos < pBaseHash->ulLen ) { memmove( pBaseHash->pPairs + ulPos + 1, pBaseHash->pPairs + ulPos, ( pBaseHash->ulLen - ulPos ) * sizeof( HB_HASHPAIR ) ); @@ -354,8 +414,12 @@ static void hb_hashNewPair( PHB_BASEHASH pBaseHash, PHB_ITEM * pKeyPtr, PHB_ITEM if( pBaseHash->ulSize == pBaseHash->ulLen ) hb_hashResize( pBaseHash, pBaseHash->ulSize + HB_HASH_ITEM_ALLOC ); + if( pBaseHash->pulPos ) + pBaseHash->pulPos[ pBaseHash->ulLen ] = pBaseHash->ulLen; + * pKeyPtr = &pBaseHash->pPairs[ pBaseHash->ulLen ].key; * pValPtr = &pBaseHash->pPairs[ pBaseHash->ulLen ].value; + pBaseHash->ulLen++; } @@ -366,6 +430,11 @@ static void hb_hashDelPair( PHB_BASEHASH pBaseHash, HB_SIZE ulPos ) PHB_HASHPAIR pPairs = pBaseHash->pPairs; pBaseHash->pPairs = NULL; pBaseHash->ulSize = 0; + if( pBaseHash->pulPos ) + { + hb_xfree( pBaseHash->pulPos ); + pBaseHash->pulPos = NULL; + } if( HB_IS_COMPLEX( &pPairs->key ) ) hb_itemClear( &pPairs->key ); if( HB_IS_COMPLEX( &pPairs->value ) ) @@ -374,6 +443,21 @@ static void hb_hashDelPair( PHB_BASEHASH pBaseHash, HB_SIZE ulPos ) } else { + if( pBaseHash->pulPos ) + { + HB_SIZE ul = 0; + while( ul < pBaseHash->ulLen ) + { + if( pBaseHash->pulPos[ ul ] > ulPos ) + pBaseHash->pulPos[ ul++ ]--; + else if( pBaseHash->pulPos[ ul ] == ulPos ) + memmove( &pBaseHash->pulPos[ ul ], &pBaseHash->pulPos[ ul + 1 ], + ( pBaseHash->ulLen - ul ) * sizeof( HB_SIZE ) ); + else + ++ul; + } + } + if( ulPos != pBaseHash->ulLen ) { HB_HASHPAIR pair; @@ -383,6 +467,7 @@ static void hb_hashDelPair( PHB_BASEHASH pBaseHash, HB_SIZE ulPos ) ulPos = pBaseHash->ulLen; memcpy( pBaseHash->pPairs + ulPos, &pair, sizeof( HB_HASHPAIR ) ); } + hb_itemSetNil( &pBaseHash->pPairs[ ulPos ].key ); hb_itemSetNil( &pBaseHash->pPairs[ ulPos ].value ); if( pBaseHash->ulSize - pBaseHash->ulLen > ( HB_HASH_ITEM_ALLOC << 1 ) ) @@ -390,6 +475,9 @@ static void hb_hashDelPair( PHB_BASEHASH pBaseHash, HB_SIZE ulPos ) pBaseHash->ulSize -= HB_HASH_ITEM_ALLOC; pBaseHash->pPairs = ( PHB_HASHPAIR ) hb_xrealloc( pBaseHash->pPairs, pBaseHash->ulSize * sizeof( HB_HASHPAIR ) ); + if( pBaseHash->pulPos ) + pBaseHash->pulPos = ( HB_SIZE * ) hb_xrealloc( pBaseHash->pulPos, + pBaseHash->ulSize * sizeof( HB_SIZE ) ); } } } @@ -407,6 +495,7 @@ PHB_ITEM hb_hashNew( PHB_ITEM pItem ) pBaseHash = ( PHB_BASEHASH ) hb_gcAllocRaw( sizeof( HB_BASEHASH ), &s_gcHashFuncs ); pBaseHash->pPairs = NULL; + pBaseHash->pulPos = NULL; pBaseHash->ulSize = 0; pBaseHash->ulLen = 0; pBaseHash->iFlags = HB_HASH_FLAG_DEFAULT; @@ -620,6 +709,11 @@ static HB_BOOL hb_hashClear( PHB_ITEM pHash ) hb_xfree( pHash->item.asHash.value->pPairs ); pHash->item.asHash.value->pPairs = NULL; pHash->item.asHash.value->ulSize = 0; + if( pHash->item.asHash.value->pulPos ) + { + hb_xfree( pHash->item.asHash.value->pulPos ); + pHash->item.asHash.value->pulPos = NULL; + } } } return HB_TRUE; @@ -768,14 +862,18 @@ void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pCloned HB_TRACE(HB_TR_DEBUG, ("hb_hashCloneBody(%p,%p,%p)", pHash, pDest, pClonedList)); hb_hashNew( pDest ); - hb_hashResize( pDest->item.asHash.value, pHash->item.asHash.value->ulLen ); pDest->item.asHash.value->iFlags = pHash->item.asHash.value->iFlags; + hb_hashResize( pDest->item.asHash.value, pHash->item.asHash.value->ulLen ); if( pHash->item.asHash.value->pDefault ) { pDest->item.asHash.value->pDefault = hb_itemNew( pHash->item.asHash.value->pDefault ); hb_gcUnlock( pDest->item.asHash.value->pDefault ); } + if( pHash->item.asHash.value->pulPos ) + memcpy( pDest->item.asHash.value->pulPos, + pHash->item.asHash.value->pulPos, + pHash->item.asHash.value->ulLen * sizeof( HB_SIZE ) ); for( ulPos = 0; ulPos < pHash->item.asHash.value->ulLen; ++ulPos ) { PHB_ITEM pValue = &pHash->item.asHash.value->pPairs[ ulPos ].value; @@ -962,7 +1060,24 @@ void hb_hashSetFlags( PHB_ITEM pHash, int iFlags ) HB_TRACE(HB_TR_DEBUG, ("hb_hashSetFlags(%p,%d)", pHash, iFlags)); if( HB_IS_HASH( pHash ) ) + { pHash->item.asHash.value->iFlags |= iFlags; + if( pHash->item.asHash.value->pulPos == NULL && + pHash->item.asHash.value->ulSize && + ( pHash->item.asHash.value->iFlags & HB_HASH_KEEPORDER ) != 0 ) + { + HB_SIZE ul = pHash->item.asHash.value->ulSize; + + pHash->item.asHash.value->pulPos = ( HB_SIZE * ) + hb_xgrab( pHash->item.asHash.value->ulSize * sizeof( HB_SIZE ) ); + do + { + --ul; + pHash->item.asHash.value->pulPos[ ul ] = ul; + } + while( ul ); + } + } } void hb_hashClearFlags( PHB_ITEM pHash, int iFlags ) @@ -970,7 +1085,15 @@ void hb_hashClearFlags( PHB_ITEM pHash, int iFlags ) HB_TRACE(HB_TR_DEBUG, ("hb_hashClearFlags(%p,%d)", pHash, iFlags)); if( HB_IS_HASH( pHash ) ) + { pHash->item.asHash.value->iFlags &= ~iFlags; + if( pHash->item.asHash.value->pulPos != NULL && + ( pHash->item.asHash.value->iFlags & HB_HASH_KEEPORDER ) == 0 ) + { + hb_xfree( pHash->item.asHash.value->pulPos ); + pHash->item.asHash.value->pulPos = NULL; + } + } } int hb_hashGetFlags( PHB_ITEM pHash ) diff --git a/harbour/src/vm/hashfunc.c b/harbour/src/vm/hashfunc.c index 3eb618f95a..afe132220e 100644 --- a/harbour/src/vm/hashfunc.c +++ b/harbour/src/vm/hashfunc.c @@ -736,6 +736,33 @@ HB_FUNC( HB_HAUTOADD ) hb_errRT_BASE( EG_ARG, 2017, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); } +HB_FUNC( HB_HKEEPORDER ) +{ + PHB_ITEM pHash = hb_param( 1, HB_IT_HASH ); + PHB_ITEM pValue = hb_param( 2, HB_IT_LOGICAL ); + + if( pHash ) + { + int iFlags = hb_hashGetFlags( pHash ); + hb_retl( ( iFlags & HB_HASH_KEEPORDER ) != 0 ); + if( pValue ) + { + if( hb_itemGetL( pValue ) ) + { + if( ( iFlags & HB_HASH_KEEPORDER ) == 0 ) + hb_hashSetFlags( pHash, HB_HASH_KEEPORDER ); + } + else if( ( iFlags & HB_HASH_KEEPORDER ) != 0 ) + { + hb_hashClearFlags( pHash, HB_HASH_KEEPORDER ); + hb_hashSetFlags( pHash, HB_HASH_RESORT ); + } + } + } + else + hb_errRT_BASE( EG_ARG, 2017, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS ); +} + HB_FUNC( HB_HALLOCATE ) { PHB_ITEM pHash = hb_param( 1, HB_IT_HASH ); @@ -768,3 +795,4 @@ HB_FUNC( HB_HDEFAULT ) HB_FUNC( HB_HSETAUTOADD ) { HB_FUNC_EXEC( HB_HAUTOADD ); hb_itemReturn( hb_param( 1, HB_IT_HASH ) ); } HB_FUNC( HB_HSETCASEMATCH ) { HB_FUNC_EXEC( HB_HCASEMATCH ); hb_itemReturn( hb_param( 1, HB_IT_HASH ) ); } HB_FUNC( HB_HSETBINARY ) { HB_FUNC_EXEC( HB_HBINARY ); hb_itemReturn( hb_param( 1, HB_IT_HASH ) ); } +HB_FUNC( HB_HSETORDER ) { HB_FUNC_EXEC( HB_HKEEPORDER ); hb_itemReturn( hb_param( 1, HB_IT_HASH ) ); }