diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 6f779fe998..f5c24f9eae 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,14 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-04-03 14:10 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbapi.h + * harbour/source/vm/arrays.c + + added hb_arrayRevScan() + + * harbour/source/vm/arrayshb.c + + added RASCAN() covered by HB_COMPAT_XHB macro + 2007-04-03 13:00 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/source/compiler/harbour.y * harbour/source/compiler/harbour.yyc diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 8028c09110..ee17444ad9 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -677,6 +677,7 @@ extern HB_EXPORT long hb_arrayGetDL( PHB_ITEM pArray, ULONG ulIndex ); /* r extern HB_EXPORT HB_TYPE hb_arrayGetType( PHB_ITEM pArray, ULONG ulIndex ); /* retrieves the type of an array item */ extern HB_EXPORT BOOL hb_arrayFill( PHB_ITEM pArray, PHB_ITEM pValue, ULONG * pulStart, ULONG * pulCount ); /* fill an array with a given item */ extern HB_EXPORT ULONG hb_arrayScan( PHB_ITEM pArray, PHB_ITEM pValue, ULONG * pulStart, ULONG * pulCount, BOOL fExact ); /* scan an array for a given item, or until code-block item returns TRUE */ +extern HB_EXPORT ULONG hb_arrayRevScan( PHB_ITEM pArray, PHB_ITEM pValue, ULONG * pulStart, ULONG * pulCount, BOOL fExact ); /* scan an array for a given item, or until code-block item returns TRUE in reverted order */ extern HB_EXPORT BOOL hb_arrayEval( PHB_ITEM pArray, PHB_ITEM bBlock, ULONG * pulStart, ULONG * pulCount ); /* execute a code-block for every element of an array item */ extern HB_EXPORT BOOL hb_arrayCopy( PHB_ITEM pSrcArray, PHB_ITEM pDstArray, ULONG * pulStart, ULONG * pulCount, ULONG * pulTarget ); /* copy items from one array to another */ extern HB_EXPORT PHB_ITEM hb_arrayClone( PHB_ITEM pArray ); /* returns a duplicate of an existing array, including all nested items */ diff --git a/harbour/source/vm/arrays.c b/harbour/source/vm/arrays.c index b3fd3415ed..6d5d491b69 100644 --- a/harbour/source/vm/arrays.c +++ b/harbour/source/vm/arrays.c @@ -799,6 +799,154 @@ ULONG hb_arrayScan( PHB_ITEM pArray, PHB_ITEM pValue, ULONG * pulStart, ULONG * return 0; } +ULONG hb_arrayRevScan( PHB_ITEM pArray, PHB_ITEM pValue, ULONG * pulStart, ULONG * pulCount, BOOL fExact ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_arrayRevScan(%p, %p, %p, %p, %d)", pArray, pValue, pulStart, pulCount, (int) fExact)); + + if( HB_IS_ARRAY( pArray ) ) + { + PHB_BASEARRAY pBaseArray = pArray->item.asArray.value; + ULONG ulLen = pBaseArray->ulLen; + ULONG ulStart; + ULONG ulCount; + + if( pulStart && *pulStart ) + ulStart = *pulStart - 1; + else + ulStart = ulLen - 1; + + if( ulStart < ulLen ) + { + ulCount = ulStart + 1; + if( pulCount && *pulCount < ulCount ) + ulCount = *pulCount; + + if( ulCount > 0 ) + { + /* Make separate search loops for different types to find, so that + the loop can be faster. */ + + if( HB_IS_BLOCK( pValue ) ) + { + do + { + hb_vmPushSymbol( &hb_symEval ); + hb_vmPush( pValue ); + hb_vmPush( pBaseArray->pItems + ulStart ); + hb_vmPushLong( ulStart + 1 ); + hb_vmDo( 2 ); + + if( HB_IS_LOGICAL( hb_stackReturnItem() ) && hb_stackReturnItem()->item.asLogical.value ) + return ulStart; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_STRING( pValue ) ) + { + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + /* NOTE: The order of the pItem and pValue parameters passed to + hb_itemStrCmp() is significant, please don't change it. [vszakats] */ + if( HB_IS_STRING( pItem ) && hb_itemStrCmp( pItem, pValue, fExact ) == 0 ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_NUMERIC( pValue ) ) + { + double dValue = hb_itemGetND( pValue ); + + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_NUMERIC( pItem ) && hb_itemGetND( pItem ) == dValue ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_DATE( pValue ) ) + { + long lValue = hb_itemGetDL( pValue ); /* NOTE: This is correct: Get the date as a long value. [vszakats] */ + + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_DATE( pItem ) && hb_itemGetDL( pItem ) == lValue ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_LOGICAL( pValue ) ) + { + BOOL bValue = hb_itemGetL( pValue ); + + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_LOGICAL( pItem ) && hb_itemGetL( pItem ) == bValue ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_NIL( pValue ) ) + { + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_NIL( pItem ) ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( HB_IS_POINTER( pValue ) ) + { + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_POINTER( pItem ) && + pItem->item.asPointer.value == pValue->item.asPointer.value ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( fExact && HB_IS_ARRAY( pValue ) ) + { + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_ARRAY( pItem ) && + pItem->item.asArray.value == pValue->item.asArray.value ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + else if( fExact && HB_IS_HASH( pValue ) ) + { + do + { + PHB_ITEM pItem = pBaseArray->pItems + ulStart; + + if( HB_IS_HASH( pItem ) && + pItem->item.asHash.value == pValue->item.asHash.value ) + return ulStart + 1; + } + while( --ulCount && ulStart-- ); + } + } + } + } + + return 0; +} + BOOL hb_arrayEval( PHB_ITEM pArray, PHB_ITEM bBlock, ULONG * pulStart, ULONG * pulCount ) { HB_TRACE(HB_TR_DEBUG, ("hb_arrayEval(%p, %p, %p, %p)", pArray, bBlock, pulStart, pulCount)); diff --git a/harbour/source/vm/arrayshb.c b/harbour/source/vm/arrayshb.c index ac29be45b0..c3a983573b 100644 --- a/harbour/source/vm/arrayshb.c +++ b/harbour/source/vm/arrayshb.c @@ -286,21 +286,41 @@ HB_FUNC( ASCAN ) ULONG ulCount = hb_parnl( 4 ); #if defined( HB_COMPAT_XHB ) - hb_retnl( hb_arrayScan( pArray, pValue, - ISNUM( 3 ) ? &ulStart : NULL, - ISNUM( 4 ) ? &ulCount : NULL, - hb_parl( 5 ) ) ); + hb_retnint( hb_arrayScan( pArray, pValue, + ISNUM( 3 ) ? &ulStart : NULL, + ISNUM( 4 ) ? &ulCount : NULL, + hb_parl( 5 ) ) ); #else - hb_retnl( hb_arrayScan( pArray, pValue, - ISNUM( 3 ) ? &ulStart : NULL, - ISNUM( 4 ) ? &ulCount : NULL, - FALSE ) ); + hb_retnint( hb_arrayScan( pArray, pValue, + ISNUM( 3 ) ? &ulStart : NULL, + ISNUM( 4 ) ? &ulCount : NULL, + FALSE ) ); #endif } else - hb_retnl( 0 ); + hb_retni( 0 ); } +#if defined( HB_COMPAT_XHB ) +HB_FUNC( RASCAN ) +{ + PHB_ITEM pArray = hb_param( 1, HB_IT_ARRAY ); + PHB_ITEM pValue = hb_param( 2, HB_IT_ANY ); + + if( pArray && pValue ) + { + ULONG ulStart = hb_parnl( 3 ); + ULONG ulCount = hb_parnl( 4 ); + hb_retnint( hb_arrayRevScan( pArray, pValue, + ISNUM( 3 ) ? &ulStart : NULL, + ISNUM( 4 ) ? &ulCount : NULL, + hb_parl( 5 ) ) ); + } + else + hb_retni( 0 ); +} +#endif + /* TODO: In Xbase++ fifth parameter determines whether array elements are passed by reference to the code block. [vszakats] */