diff --git a/harbour/ChangeLog.txt b/harbour/ChangeLog.txt index b52527921d..71ccf0f6bf 100644 --- a/harbour/ChangeLog.txt +++ b/harbour/ChangeLog.txt @@ -10,6 +10,35 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2013-02-15 12:14 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * harbour/src/rtl/strxchg.c + + added support for using hash arrays as replace pairs in second + argument of hb_strXChg() - hash arrays are accepted if 3-rd parameter + is ommitted or is NIL. Now this alternative syntax: + hb_strXChg( , ) -> + is also supported, i.e.: + cData := hb_strXChg( cSource, { "{LI}" => cLIValue, ; + "{FI}" => cFIValue } ) + Please remember that single hash layer is much lighter data type + then array of subarrays because it needs only one GC item when + each subarray is new GC item. + + * harbour/include/hbtypes.h + * renamed HB_EXTISARRAY to HB_EXTISPARAM, old type is covered by + HB_LEGACY_LEVEL4 macro. + + * harbour/include/hbapi.h + * harbour/src/vm/extend.c + + added new public C function: + HB_BOOL hb_extIsNil( int iParam ); + % use hb_extIsNil(n) in HB_ISNIL(n) macro. It eliminates double + function call and also double (n) usage so it improves the + performance and allows to use complex expressions as HB_ISNIL() + argument. + + * harbour/src/vm/maindllp/dllext.c + + added wrappers for hb_extIsNil() abd hb_extIsObject() + 2013-02-15 03:09 UTC+0100 Viktor Szakats (harbour syenar.net) * src/rtl/tget.prg % use HB_STRXCHG() diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 907b82f348..95f35d3a84 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -228,7 +228,7 @@ HB_EXTERN_BEGIN #endif -#define HB_ISNIL( n ) ( hb_param( n, HB_IT_ANY ) == NULL || HB_IS_NIL( hb_param( n, HB_IT_ANY ) ) ) /* NOTE: Intentionally using a different method */ +#define HB_ISNIL( n ) ( hb_extIsNil( n ) ) /* NOTE: Intentionally using a different method */ #define HB_ISCHAR( n ) ( hb_param( n, HB_IT_STRING ) != NULL ) #define HB_ISNUM( n ) ( hb_param( n, HB_IT_NUMERIC ) != NULL ) #define HB_ISLOG( n ) ( hb_param( n, HB_IT_LOGICAL ) != NULL ) @@ -628,6 +628,7 @@ extern HB_EXPORT HB_ULONG hb_parinfo( int iParam ); /* Determine the param c extern HB_EXPORT HB_SIZE hb_parinfa( int iParamNum, HB_SIZE nArrayIndex ); /* retrieve length or element type of an array parameter */ extern HB_EXPORT PHB_ITEM hb_param( int iParam, long lMask ); /* retrieve a generic parameter */ extern HB_EXPORT PHB_ITEM hb_paramError( int iParam ); /* Returns either the generic parameter or a NIL item if param not provided */ +extern HB_EXPORT HB_BOOL hb_extIsNil( int iParam ); extern HB_EXPORT HB_BOOL hb_extIsArray( int iParam ); extern HB_EXPORT HB_BOOL hb_extIsObject( int iParam ); diff --git a/harbour/include/hbtypes.h b/harbour/include/hbtypes.h index 3df420fdb5..722c72b8f6 100644 --- a/harbour/include/hbtypes.h +++ b/harbour/include/hbtypes.h @@ -66,7 +66,10 @@ typedef HB_ULONG ( * HB_PARINFO )( int iParam ); typedef HB_SIZE ( * HB_PARINFA )( int iParam, HB_SIZE nArrayIndex ); typedef PHB_ITEM ( * HB_PARAM )( int iParam, long lMask ); typedef PHB_ITEM ( * HB_PARAMERROR )( int iParam ); -typedef HB_BOOL ( * HB_EXTISARRAY ) ( int iParam ); +typedef HB_BOOL ( * HB_EXTISPARAM ) ( int iParam ); +#if defined( HB_LEGACY_LEVEL4 ) +# define HB_EXTISARRAY HB_EXTISPARAM +#endif typedef void ( * HB_RET )( void ); typedef void ( * HB_RETC )( const char * szText ); diff --git a/harbour/src/rtl/strxchg.c b/harbour/src/rtl/strxchg.c index fe92339f99..55ff2540c4 100644 --- a/harbour/src/rtl/strxchg.c +++ b/harbour/src/rtl/strxchg.c @@ -60,50 +60,61 @@ HB_FUNC( HB_STRXCHG ) { PHB_ITEM pText = hb_param( 1, HB_IT_STRING ); - PHB_ITEM pSrc = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY ); + PHB_ITEM pSrc = hb_param( 2, HB_IT_STRING | HB_IT_ARRAY | + ( HB_ISNIL( 3 ) ? HB_IT_HASH : 0 ) ); if( pText && pSrc ) { - const char * pszSrc = HB_IS_STRING( pSrc ) ? hb_itemGetCPtr( pSrc ) : NULL; + const char * pszSrc = HB_IS_STRING( pSrc ) ? + hb_itemGetCPtr( pSrc ) : NULL; HB_SIZE nText = hb_itemGetCLen( pText ), - nSrc = pszSrc ? hb_itemGetCLen( pSrc ) : hb_arrayLen( pSrc ); + nSrc = hb_itemSize( pSrc ); if( nText > 0 && nSrc > 0 ) { PHB_ITEM pDst = hb_param( 3, HB_IT_STRING | HB_IT_ARRAY ); - const char * pszDst = pDst && HB_IS_STRING( pDst ) ? hb_itemGetCPtr( pDst ) : NULL; + const char * pszDst = pDst && HB_IS_STRING( pDst ) ? + hb_itemGetCPtr( pDst ) : NULL; const char * pszText = hb_itemGetCPtr( pText ); const char * ptr; char * pszResult = NULL; HB_SIZE nDst, nSize, nPos, nAt, nSkip, nTmp; - nDst = pszDst ? hb_itemGetCLen( pDst ) : - ( pDst ? hb_arrayLen( pDst ) : 0 ); - - nSize = nPos = 0; + nDst = hb_itemSize( HB_IS_HASH( pSrc ) ? pSrc : pDst ); + nSize = nPos = nSkip = 0; while( nPos < nText ) { if( pszSrc ) { - ptr = ( const char * ) memchr( pszSrc, ( HB_UCHAR ) pszText[ nPos ], nSrc ); + ptr = ( const char * ) + memchr( pszSrc, ( HB_UCHAR ) pszText[ nPos ], nSrc ); nAt = ptr ? ptr - pszSrc + 1 : 0; nSkip = 1; } else { - nSkip = nAt = 0; - for( nTmp = 1; nTmp <= nDst; ++nTmp ) + for( nAt = 1; nAt <= nSrc; ++nAt ) { - nSkip = hb_arrayGetCLen( pSrc, nTmp ); - if( nSkip > 0 && nSkip <= nText - nPos && - memcmp( pszText + nPos, hb_arrayGetCPtr( pSrc, nTmp ), nSkip ) == 0 ) + if( HB_IS_HASH( pSrc ) ) { - nAt = nTmp; - break; + pDst = hb_hashGetKeyAt( pSrc, nAt ); + nSkip = hb_itemGetCLen( pDst ); + ptr = hb_itemGetCPtr( pDst ); } + else + { + nSkip = hb_arrayGetCLen( pSrc, nAt ); + ptr = hb_arrayGetCPtr( pSrc, nAt ); + } + if( nSkip > 0 && nSkip <= nText - nPos && + memcmp( pszText + nPos, ptr , nSkip ) == 0 ) + break; } - if( nAt == 0 ) + if( nAt > nSrc ) + { + nAt = 0; nSkip = 1; + } } if( pszResult ) @@ -116,8 +127,18 @@ HB_FUNC( HB_STRXCHG ) pszResult[ nSize++ ] = pszDst[ nAt - 1 ]; else { - nTmp = hb_arrayGetCLen( pDst, nAt ); - memcpy( &pszResult[ nSize ], hb_arrayGetCPtr( pDst, nAt ), nTmp ); + if( HB_IS_HASH( pSrc ) ) + { + pDst = hb_hashGetValueAt( pSrc, nAt ); + nTmp = hb_itemGetCLen( pDst ); + ptr = hb_itemGetCPtr( pDst ); + } + else + { + nTmp = hb_arrayGetCLen( pDst, nAt ); + ptr = hb_arrayGetCPtr( pDst, nAt ); + } + memcpy( &pszResult[ nSize ], ptr, nTmp ); nSize += nTmp; } } @@ -134,6 +155,8 @@ HB_FUNC( HB_STRXCHG ) { if( pszDst ) nSize++; + else if( HB_IS_HASH( pSrc ) ) + nSize += hb_itemGetCLen( hb_hashGetValueAt( pSrc, nAt ) ); else nSize += hb_arrayGetCLen( pDst, nAt ); } diff --git a/harbour/src/vm/extend.c b/harbour/src/vm/extend.c index 2afe5a4b3a..b9d5706e78 100644 --- a/harbour/src/vm/extend.c +++ b/harbour/src/vm/extend.c @@ -164,6 +164,27 @@ HB_SIZE hb_parinfa( int iParamNum, HB_SIZE nArrayIndex ) return 0; } +HB_BOOL hb_extIsNil( int iParam ) +{ + HB_STACK_TLS_PRELOAD + PHB_ITEM pItem; + + HB_TRACE( HB_TR_DEBUG, ( "hb_extIsNil(%d)", iParam ) ); + + if( iParam == -1 ) + pItem = hb_stackReturnItem(); + else if( iParam >= 0 && iParam <= hb_pcount() ) + pItem = hb_stackItemFromBase( iParam ); + else + return HB_TRUE; + + if( HB_IS_BYREF( pItem ) ) + pItem = hb_itemUnRef( pItem ); + + return HB_IS_NIL( pItem ); +} + + /* function to be called from pcode DLLs to detect if the extend system * is going to use an array item */ diff --git a/harbour/src/vm/maindllp/dllext.c b/harbour/src/vm/maindllp/dllext.c index e5debef71e..be816e9349 100644 --- a/harbour/src/vm/maindllp/dllext.c +++ b/harbour/src/vm/maindllp/dllext.c @@ -141,13 +141,27 @@ PHB_ITEM hb_paramError( int iParam ) return s_paramError ? s_paramError( iParam ) : NULL; } +HB_BOOL hb_extIsNil( int iParam ) +{ + static HB_EXTISPARAM s_extIsNil = NULL; + + if( ! s_extIsNil ) + { + s_extIsNil = ( HB_EXTISPARAM ) hb_dllGetProcAddress( "hb_extIsNil" ); + if( ! s_extIsNil ) + HB_DLL_MSG_NO_FUNC( "hb_extIsNil" ); + } + + return s_extIsNil ? s_extIsNil( iParam ) : FALSE; +} + HB_BOOL hb_extIsArray( int iParam ) { - static HB_EXTISARRAY s_extIsArray = NULL; + static HB_EXTISPARAM s_extIsArray = NULL; if( ! s_extIsArray ) { - s_extIsArray = ( HB_EXTISARRAY ) hb_dllGetProcAddress( "hb_extIsArray" ); + s_extIsArray = ( HB_EXTISPARAM ) hb_dllGetProcAddress( "hb_extIsArray" ); if( ! s_extIsArray ) HB_DLL_MSG_NO_FUNC( "hb_extIsArray" ); } @@ -155,6 +169,20 @@ HB_BOOL hb_extIsArray( int iParam ) return s_extIsArray ? s_extIsArray( iParam ) : FALSE; } +HB_BOOL hb_extIsObject( int iParam ) +{ + static HB_EXTISPARAM s_extIsObject = NULL; + + if( ! s_extIsObject ) + { + s_extIsObject = ( HB_EXTISPARAM ) hb_dllGetProcAddress( "hb_extIsObject" ); + if( ! s_extIsObject ) + HB_DLL_MSG_NO_FUNC( "hb_extIsObject" ); + } + + return s_extIsObject ? s_extIsObject( iParam ) : FALSE; +} + void hb_ret( void ) {