diff --git a/ChangeLog.txt b/ChangeLog.txt index 18a332f773..5fba67791b 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,48 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2014-08-27 18:19 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbserial.ch + * src/rtl/itemseri.c + + added HB_SERIALIZE_IGNOREREF flag. + This flag fully disables logic used to detect multireferences to the + same complex (sub)items like arrays or hashes. It increses the speed + of serialization but serialized data does not contain any information + about refences, i.e. aVal[ 1 ] and aVal[ 2 ] in code below: + aSub := { 1, 2, 3 } + aVal := { aSub, aSub } + are serialized as separated arrays. Additionally items with cyclic + references like: + aSub[ 2 ] := aSub + cannot be serialized at all with HB_SERIALIZE_IGNOREREF flag because + it will create infinite serialization loop and crash with out of + memory message. + + * src/rtl/itemseri.c + % rewritten algorithm used to detect cyclic and multi references in + serialized items. The original algorithm has very high overhead when + huge arrays were serialized, i.e. serialization of array with 1'000'000 + of subarrays needed about 30 minutes on my i5@3.30GHz. Now it needs + less then a second and this time is only a little bit bigger then + used by serialization with HB_SERIALIZE_IGNOREREF flag. + This modification improve performance also in other code using Harbour + serialization mechanism like I18N files, HBNETIO, GTNET, ... when large + arrays or hashes are saved or transmitted. + + * include/hbapi.h + * include/hbapicls.h + * src/vm/arrays.c + * src/vm/classes.c + * src/vm/hashes.c + * src/vm/itemapi.c + * replaced algorithm used to detect cyclic and multi references in + array and hash clone operations with new one similar to current + item serial code. The speed improvement for very large arrays is + the same as in case of serialization code. + + * src/rtl/gtsln/mousesln.c + ! typo in while loop - synced with Viktor's branch + 2014-08-22 14:41 UTC+0200 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * src/vm/hvm.c * map 0 and 1 byte length strings to the same addresses diff --git a/include/hbapi.h b/include/hbapi.h index 5853a78706..20f6d8fc71 100644 --- a/include/hbapi.h +++ b/include/hbapi.h @@ -459,11 +459,17 @@ typedef struct _HB_EXTREF HB_EXTREF_FUNC0 mark; } HB_EXTREF, * PHB_EXTREF; -typedef struct _HB_NESTED_CLONED +typedef struct { void * value; PHB_ITEM pDest; - struct _HB_NESTED_CLONED * pNext; +} HB_NESTED_REF, * PHB_NESTED_REF; + +typedef struct +{ + HB_SIZE nSize; + HB_SIZE nCount; + PHB_NESTED_REF pRefs; } HB_NESTED_CLONED, * PHB_NESTED_CLONED; #endif /* _HB_API_INTERNAL_ */ @@ -862,8 +868,10 @@ extern HB_EXPORT HB_LONGLONG hb_arrayGetNLL( PHB_ITEM pArray, HB_SIZE nIndex ); /* internal array API not exported */ extern void hb_arrayPushBase( PHB_BASEARRAY pBaseArray ); extern void hb_arraySwap( PHB_ITEM pArray1, PHB_ITEM pArray2 ); -extern void hb_cloneNested( PHB_ITEM pDstItem, PHB_ITEM pSrcItem, PHB_NESTED_CLONED pClonedList ); -extern void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pClonedList ); +extern void hb_nestedCloneInit( PHB_NESTED_CLONED pClonedList, void * pValue, PHB_ITEM pDest ); +extern void hb_nestedCloneFree( PHB_NESTED_CLONED pClonedList ); +extern void hb_nestedCloneDo( PHB_ITEM pDstItem, PHB_ITEM pSrcItem, PHB_NESTED_CLONED pClonedList ); +extern void hb_hashCloneBody( PHB_ITEM pDest, PHB_ITEM pHash, PHB_NESTED_CLONED pClonedList ); #endif diff --git a/include/hbapicls.h b/include/hbapicls.h index fc1c8c6ea0..c1dbdee013 100644 --- a/include/hbapicls.h +++ b/include/hbapicls.h @@ -100,7 +100,8 @@ extern HB_BOOL hb_objGetVarRef( PHB_ITEM pObject, PHB_SYMB pMessage, PHB_STAC extern HB_BOOL hb_objHasOperator( PHB_ITEM pObject, HB_USHORT uiOperator ); extern HB_BOOL hb_objOperatorCall( HB_USHORT uiOperator, PHB_ITEM pResult, PHB_ITEM pObject, PHB_ITEM pMsgArg1, PHB_ITEM pMsgArg2 ); extern void hb_objDestructorCall( PHB_ITEM pObject ); -extern void hb_objCloneTo( PHB_ITEM pDest, PHB_ITEM pSource, PHB_NESTED_CLONED pClonedList ); +extern PHB_ITEM hb_objCloneTo( PHB_ITEM pDest, PHB_ITEM pObject ); +extern void hb_objCloneBody( PHB_ITEM pDest, PHB_ITEM pObject, PHB_NESTED_CLONED pClonedList ); #ifndef HB_NO_PROFILER /* profiler for object management */ diff --git a/include/hbserial.ch b/include/hbserial.ch index 906ef81c36..f1bc4aa1e3 100644 --- a/include/hbserial.ch +++ b/include/hbserial.ch @@ -54,5 +54,6 @@ #define HB_SERIALIZE_NUMSIZE 0x01 #define HB_SERIALIZE_OBJECTSTRUCT 0x02 #define HB_SERIALIZE_COMPRESS 0x04 +#define HB_SERIALIZE_IGNOREREF 0x08 #endif /* HB_SERIAL_CH_ */ diff --git a/src/rtl/gtsln/mousesln.c b/src/rtl/gtsln/mousesln.c index 36d7a0be78..f84e0a2748 100644 --- a/src/rtl/gtsln/mousesln.c +++ b/src/rtl/gtsln/mousesln.c @@ -368,7 +368,7 @@ void hb_gt_sln_mouse_Init( void ) s_bMousePresent = HB_TRUE; - while( GetGpmEvent( &Evt ) ); + while( GetGpmEvent( &Evt ) ) { s_iMouseRow = Evt.y; s_iMouseCol = Evt.x; diff --git a/src/rtl/itemseri.c b/src/rtl/itemseri.c index 8497adb74e..a8b3ccfe4a 100644 --- a/src/rtl/itemseri.c +++ b/src/rtl/itemseri.c @@ -185,74 +185,191 @@ complex ones: #define HB_SERIAL_DUMMYOFFSET ( ( HB_SIZE ) -1 ) -typedef struct _HB_CYCLIC_REF +#define HB_SERIAL_REFLSTINIT 16 + +typedef struct { void * value; HB_SIZE nOffset; int iRefs; int iType; - struct _HB_CYCLIC_REF * pNext; -} HB_CYCLIC_REF, * PHB_CYCLIC_REF; +} HB_REF_ITEM, * PHB_REF_ITEM; + +typedef struct +{ + HB_SIZE nSize; + HB_SIZE nCount; + PHB_REF_ITEM pRefs; +} HB_REF_LIST, * PHB_REF_LIST; static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, const HB_UCHAR * pBuffer, HB_SIZE nOffset, - PHB_CYCLIC_REF pRef ); + PHB_REF_LIST pRefList ); -/* used by hb_itemSerialSize() for HB_IT_ARRAY and HB_IT_HASH */ -static HB_BOOL hb_itemSerialValueRef( PHB_CYCLIC_REF * pRefPtr, void * value, - HB_SIZE nOffset ) +/* +static void hb_itemSerialRefListShow( PHB_REF_LIST pRefList ) { - while( *pRefPtr ) + HB_SIZE nPos; + + printf( "\n================================\n" ); + printf( "pRefList->nSize=%ld, pRefList->nCount=%ld\n", pRefList->nSize, pRefList->nCount ); + + for( nPos = 0; nPos < pRefList->nCount; ++nPos ) { - if( ( *pRefPtr )->value == value ) + printf( "\t%ld] value=0x%p, nOffset=%ld, iRefs=%d, iType=%d\n", nPos, + pRefList->pRefs[ nPos ].value, + pRefList->pRefs[ nPos ].nOffset, + pRefList->pRefs[ nPos ].iRefs, + pRefList->pRefs[ nPos ].iType ); + } + printf( "================================\n" ); fflush( stdout ); +} +*/ + +static void hb_itemSerialRefListInit( PHB_REF_LIST pRefList ) +{ + memset( pRefList, 0, sizeof( HB_REF_LIST ) ); +} + +static void hb_itemSerialRefListFree( PHB_REF_LIST pRefList ) +{ + if( pRefList->nSize ) + hb_xfree( pRefList->pRefs ); +} + +static PHB_REF_ITEM hb_itemSerialValueFind( PHB_REF_LIST pRefList, void * value, + HB_SIZE * pnPos ) +{ + HB_SIZE nFirst, nLast, nMiddle; + + nFirst = 0; + nLast = pRefList->nCount; + nMiddle = ( nFirst + nLast ) >> 1; + + while( nFirst < nLast ) + { + if( ( HB_PTRUINT ) pRefList->pRefs[ nMiddle ].value < ( HB_PTRUINT ) value ) + nFirst = nMiddle + 1; + else if( ( HB_PTRUINT ) pRefList->pRefs[ nMiddle ].value > ( HB_PTRUINT ) value ) + nLast = nMiddle; + else { - ( *pRefPtr )->iRefs = 1; - return HB_TRUE; + * pnPos = nMiddle; + return &pRefList->pRefs[ nMiddle ]; } - pRefPtr = &( *pRefPtr )->pNext; + nMiddle = ( nFirst + nLast ) >> 1; } - *pRefPtr = ( PHB_CYCLIC_REF ) hb_xgrab( sizeof( HB_CYCLIC_REF ) ); - ( *pRefPtr )->value = value; - ( *pRefPtr )->nOffset = nOffset; - ( *pRefPtr )->iRefs = 0; - ( *pRefPtr )->iType = 0; - ( *pRefPtr )->pNext = NULL; + * pnPos = nMiddle; + + return NULL; +} + +static PHB_REF_ITEM hb_itemSerialOffsetFind( PHB_REF_LIST pRefList, HB_SIZE nOffset, + int iType, HB_SIZE * pnPos ) +{ + HB_SIZE nFirst, nLast, nMiddle; + + nFirst = 0; + nLast = pRefList->nCount; + nMiddle = ( nFirst + nLast ) >> 1; + + while( nFirst < nLast ) + { + if( pRefList->pRefs[ nMiddle ].nOffset < nOffset ) + nFirst = nMiddle + 1; + else if( pRefList->pRefs[ nMiddle ].nOffset > nOffset ) + nLast = nMiddle; + else if( pRefList->pRefs[ nMiddle ].iType < iType ) + nFirst = nMiddle + 1; + else if( pRefList->pRefs[ nMiddle ].iType > iType ) + nLast = nMiddle; + else + { + * pnPos = nMiddle; + return &pRefList->pRefs[ nMiddle ]; + } + nMiddle = ( nFirst + nLast ) >> 1; + } + + * pnPos = nMiddle; + + return NULL; +} + +/* used by hb_itemSerialSize() for HB_IT_ARRAY and HB_IT_HASH */ +static HB_BOOL hb_itemSerialValueRef( PHB_REF_LIST pRefList, void * value, + HB_SIZE nOffset ) +{ + PHB_REF_ITEM pRef; + HB_SIZE nPos; + + if( ( pRef = hb_itemSerialValueFind( pRefList, value, &nPos ) ) != NULL ) + { + pRef->iRefs = 1; + return HB_TRUE; + } + + if( pRefList->nCount >= pRefList->nSize ) + { + if( pRefList->nSize == 0 ) + pRefList->nSize = HB_SERIAL_REFLSTINIT; + else + pRefList->nSize += pRefList->nSize >> 1; + pRefList->pRefs = ( PHB_REF_ITEM ) + hb_xrealloc( pRefList->pRefs, + pRefList->nSize * sizeof( HB_REF_ITEM ) ); + } + + pRef = &pRefList->pRefs[ nPos ]; + if( nPos < pRefList->nCount ) + memmove( pRef + 1, pRef, ( pRefList->nCount - nPos ) * sizeof( HB_REF_ITEM ) ); + pRefList->nCount++; + + pRef->value = value; + pRef->nOffset = nOffset; + pRef->iRefs = 0; + pRef->iType = 0; return HB_FALSE; } /* used between hb_itemSerialSize() and hb_serializeItem() */ -static void hb_itemSerialUnRefFree( PHB_CYCLIC_REF * pRefPtr ) +static void hb_itemSerialUnusedFree( PHB_REF_LIST pRefList ) { - PHB_CYCLIC_REF pRef; - - while( *pRefPtr ) + if( pRefList->nSize ) { - pRef = *pRefPtr; - if( pRef->iRefs == 0 ) + HB_SIZE nPos, nCount; + + for( nPos = nCount = 0; nPos < pRefList->nCount; ++nPos ) { - *pRefPtr = pRef->pNext; - hb_xfree( pRef ); + if( pRefList->pRefs[ nPos ].iRefs != 0 ) + { + if( nCount != nPos ) + memcpy( &pRefList->pRefs[ nCount ], &pRefList->pRefs[ nPos ], + sizeof( HB_REF_ITEM ) ); + ++nCount; + } } - else - pRefPtr = &pRef->pNext; + pRefList->nSize = pRefList->nCount = nCount; + pRefList->pRefs = ( PHB_REF_ITEM ) + hb_xrealloc( pRefList->pRefs, + nCount * sizeof( HB_REF_ITEM ) ); } } /* used by hb_serializeItem() for HB_IT_ARRAY and HB_IT_HASH */ -static HB_BOOL hb_itemSerialValueOffset( PHB_CYCLIC_REF pRef, void * value, +static HB_BOOL hb_itemSerialValueOffset( PHB_REF_LIST pRefList, void * value, HB_SIZE nOffset, HB_SIZE * pnRef ) { - while( pRef ) + PHB_REF_ITEM pRef; + HB_SIZE nPos; + + if( ( pRef = hb_itemSerialValueFind( pRefList, value, &nPos ) ) != NULL ) { - if( pRef->value == value ) - { - *pnRef = pRef->nOffset; - return pRef->nOffset < nOffset; - } - pRef = pRef->pNext; + *pnRef = pRef->nOffset; + return pRef->nOffset < nOffset; } *pnRef = HB_SERIAL_DUMMYOFFSET; @@ -261,128 +378,129 @@ static HB_BOOL hb_itemSerialValueOffset( PHB_CYCLIC_REF pRef, void * value, /* used by hb_deserializeTest() for HB_SERIAL_ARRAYREF*, HB_SERIAL_HASHREF*, HB_SERIAL_REF */ -static HB_BOOL hb_itemSerialOffsetRef( PHB_CYCLIC_REF * pRefPtr, HB_SIZE nOffset ) +static HB_BOOL hb_itemSerialOffsetRef( PHB_REF_LIST pRefList, HB_SIZE nOffset ) { - while( *pRefPtr ) + PHB_REF_ITEM pRef; + HB_SIZE nPos; + + if( hb_itemSerialOffsetFind( pRefList, nOffset, 0, &nPos ) != NULL ) + return HB_TRUE; + + if( pRefList->nCount >= pRefList->nSize ) { - if( ( *pRefPtr )->nOffset == nOffset ) - return HB_TRUE; - pRefPtr = &( *pRefPtr )->pNext; + if( pRefList->nSize == 0 ) + pRefList->nSize = HB_SERIAL_REFLSTINIT; + else + pRefList->nSize += pRefList->nSize >> 1; + pRefList->pRefs = ( PHB_REF_ITEM ) + hb_xrealloc( pRefList->pRefs, + pRefList->nSize * sizeof( HB_REF_ITEM ) ); } - *pRefPtr = ( PHB_CYCLIC_REF ) hb_xgrab( sizeof( HB_CYCLIC_REF ) ); - ( *pRefPtr )->value = NULL; - ( *pRefPtr )->nOffset = nOffset; - ( *pRefPtr )->iRefs = 0; - ( *pRefPtr )->iType = 0; - ( *pRefPtr )->pNext = NULL; + pRef = &pRefList->pRefs[ nPos ]; + if( nPos < pRefList->nCount ) + memmove( pRef + 1, pRef, ( pRefList->nCount - nPos ) * sizeof( HB_REF_ITEM ) ); + pRefList->nCount++; + + pRef->value = NULL; + pRef->nOffset = nOffset; + pRef->iRefs = 0; + pRef->iType = 0; return HB_FALSE; } /* used by hb_deserializeTest() for HB_SERIAL_XHB_R */ -static void hb_itemSerialTypedRef( PHB_CYCLIC_REF * pRefPtr, int iType, +static void hb_itemSerialTypedRef( PHB_REF_LIST pRefList, int iType, HB_SIZE nIndex ) { - PHB_CYCLIC_REF pRef; + HB_SIZE nPos; - while( *pRefPtr ) + if( hb_itemSerialOffsetFind( pRefList, nIndex, iType, &nPos ) == NULL ) { - if( ( *pRefPtr )->iType == iType && ( *pRefPtr )->nOffset <= nIndex ) - { - if( ( *pRefPtr )->nOffset == nIndex ) - return; - else - break; - } - pRefPtr = &( *pRefPtr )->pNext; - } + PHB_REF_ITEM pRef; - pRef = ( PHB_CYCLIC_REF ) hb_xgrab( sizeof( HB_CYCLIC_REF ) ); - pRef->value = NULL; - pRef->nOffset = nIndex; - pRef->iRefs = 0; - pRef->iType = iType; - pRef->pNext = *pRefPtr; - *pRefPtr = pRef; + if( pRefList->nCount >= pRefList->nSize ) + { + if( pRefList->nSize == 0 ) + pRefList->nSize = HB_SERIAL_REFLSTINIT; + else + pRefList->nSize += pRefList->nSize >> 1; + pRefList->pRefs = ( PHB_REF_ITEM ) + hb_xrealloc( pRefList->pRefs, + pRefList->nSize * sizeof( HB_REF_ITEM ) ); + } + + pRef = &pRefList->pRefs[ nPos ]; + if( nPos < pRefList->nCount ) + memmove( pRef + 1, pRef, ( pRefList->nCount - nPos ) * sizeof( HB_REF_ITEM ) ); + pRefList->nCount++; + + pRef->value = NULL; + pRef->nOffset = nIndex; + pRef->iRefs = 0; + pRef->iType = iType; + } } /* used by hb_deserializeItem() for HB_SERIAL_ARRAYREF* and HB_SERIAL_HASHREF* */ -static void hb_itemSerialOffsetSet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, +static void hb_itemSerialOffsetSet( PHB_REF_LIST pRefList, PHB_ITEM pItem, HB_SIZE nOffset ) { - while( pRef ) - { - if( pRef->nOffset == nOffset && pRef->iRefs == 0 ) - { - pRef->value = ( void * ) pItem; - break; - } - pRef = pRef->pNext; - } + PHB_REF_ITEM pRef; + HB_SIZE nPos; + + if( ( pRef = hb_itemSerialOffsetFind( pRefList, nOffset, 0, &nPos ) ) != NULL ) + pRef->value = ( void * ) pItem; } /* used by hb_deserializeItem() for HB_SERIAL_REF */ -static void hb_itemSerialOffsetGet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, +static void hb_itemSerialOffsetGet( PHB_REF_LIST pRefList, PHB_ITEM pItem, HB_SIZE nOffset ) { - while( pRef ) - { - if( pRef->nOffset == nOffset && pRef->iRefs == 0 ) - { - hb_itemCopy( pItem, ( PHB_ITEM ) pRef->value ); - break; - } - pRef = pRef->pNext; - } + PHB_REF_ITEM pRef; + HB_SIZE nPos; + + if( ( pRef = hb_itemSerialOffsetFind( pRefList, nOffset, 0, &nPos ) ) != NULL ) + hb_itemCopy( pItem, ( PHB_ITEM ) pRef->value ); } /* used by hb_deserializeItem() for HB_SERIAL_XHB_A, HB_SERIAL_XHB_H, HB_SERIAL_XHB_Q, HB_SERIAL_XHB_O */ -static void hb_itemSerialTypedSet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, int iType ) +static void hb_itemSerialTypedSet( PHB_REF_LIST pRefList, PHB_ITEM pItem, int iType ) { - while( pRef ) + HB_SIZE nPos = pRefList->nCount; + + while( nPos-- ) { + PHB_REF_ITEM pRef = &pRefList->pRefs[ nPos ]; + if( pRef->iType == iType && pRef->value == NULL ) { if( ( HB_SIZE ) ++pRef->iRefs == pRef->nOffset ) pRef->value = ( void * ) pItem; } - pRef = pRef->pNext; } } /* used by hb_deserializeItem() for HB_SERIAL_XHB_R */ -static void hb_itemSerialTypedGet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, +static void hb_itemSerialTypedGet( PHB_REF_LIST pRefList, PHB_ITEM pItem, int iType, HB_SIZE nIndex ) { - while( pRef ) - { - if( pRef->iType == iType && pRef->nOffset == nIndex ) - { - if( pRef->value ) - hb_itemCopy( pItem, ( PHB_ITEM ) pRef->value ); - break; - } - pRef = pRef->pNext; - } -} + PHB_REF_ITEM pRef; + HB_SIZE nPos; -/* free reference list after serialization/deserialization process */ -static void hb_itemSerialRefFree( PHB_CYCLIC_REF pRef ) -{ - while( pRef ) + if( ( pRef = hb_itemSerialOffsetFind( pRefList, nIndex, iType, &nPos ) ) != NULL ) { - PHB_CYCLIC_REF pFree = pRef; - pRef = pRef->pNext; - hb_xfree( pFree ); + if( pRef->value ) + hb_itemCopy( pItem, ( PHB_ITEM ) pRef->value ); } } static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, - PHB_CYCLIC_REF * pRefPtr, HB_SIZE nOffset ) + PHB_REF_LIST pRefList, HB_SIZE nOffset ) { HB_SIZE nSize, nLen, u; HB_MAXINT lVal; @@ -470,7 +588,8 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, if( szClass && szFunc ) nSize += strlen( szClass ) + strlen( szFunc ) + 3; } - if( hb_itemSerialValueRef( pRefPtr, hb_arrayId( pItem ), nOffset + nSize ) ) + if( ( iFlags & HB_SERIALIZE_IGNOREREF ) == 0 && + hb_itemSerialValueRef( pRefList, hb_arrayId( pItem ), nOffset + nSize ) ) { nSize = 5; } @@ -485,12 +604,13 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, nSize += 5; for( u = 1; u <= nLen; u++ ) nSize += hb_itemSerialSize( hb_arrayGetItemPtr( pItem, u ), iFlags, - cdpIn, cdpOut, pRefPtr, nOffset + nSize ); + cdpIn, cdpOut, pRefList, nOffset + nSize ); } break; case HB_IT_HASH: - if( hb_itemSerialValueRef( pRefPtr, hb_hashId( pItem ), nOffset ) ) + if( ( iFlags & HB_SERIALIZE_IGNOREREF ) == 0 && + hb_itemSerialValueRef( pRefList, hb_hashId( pItem ), nOffset ) ) { nSize = 5; } @@ -505,7 +625,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, { nSize++; nSize += hb_itemSerialSize( pDefVal, iFlags, - cdpIn, cdpOut, pRefPtr, nOffset + nSize ); + cdpIn, cdpOut, pRefList, nOffset + nSize ); } nLen = hb_hashLen( pItem ); if( nLen <= 255 ) @@ -517,9 +637,9 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, for( u = 1; u <= nLen; u++ ) { nSize += hb_itemSerialSize( hb_hashGetKeyAt( pItem, u ), iFlags, - cdpIn, cdpOut, pRefPtr, nOffset + nSize ); + cdpIn, cdpOut, pRefList, nOffset + nSize ); nSize += hb_itemSerialSize( hb_hashGetValueAt( pItem, u ), iFlags, - cdpIn, cdpOut, pRefPtr, nOffset + nSize ); + cdpIn, cdpOut, pRefList, nOffset + nSize ); } } break; @@ -535,7 +655,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, HB_UCHAR * pBuffer, HB_SIZE nOffset, - PHB_CYCLIC_REF pRef ) + PHB_REF_LIST pRefList ) { HB_MAXINT lVal; double d; @@ -756,7 +876,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, break; case HB_IT_ARRAY: - if( hb_itemSerialValueOffset( pRef, hb_arrayId( pItem ), nOffset, &nRef ) ) + if( hb_itemSerialValueOffset( pRefList, hb_arrayId( pItem ), nOffset, &nRef ) ) { pBuffer[ nOffset++ ] = HB_SERIAL_REF; HB_PUT_LE_UINT32( &pBuffer[ nOffset ], nRef ); @@ -803,12 +923,12 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, } for( n = 1; n <= nLen; n++ ) nOffset = hb_serializeItem( hb_arrayGetItemPtr( pItem, n ), iFlags, - cdpIn, cdpOut, pBuffer, nOffset, pRef ); + cdpIn, cdpOut, pBuffer, nOffset, pRefList ); } break; case HB_IT_HASH: - if( hb_itemSerialValueOffset( pRef, hb_hashId( pItem ), nOffset, &nRef ) ) + if( hb_itemSerialValueOffset( pRefList, hb_hashId( pItem ), nOffset, &nRef ) ) { pBuffer[ nOffset++ ] = HB_SERIAL_REF; HB_PUT_LE_UINT32( &pBuffer[ nOffset ], nRef ); @@ -829,7 +949,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, { pBuffer[ nOffset++ ] = HB_SERIAL_HASHDEFVAL; nOffset = hb_serializeItem( pDefVal, iHashFlags, - cdpIn, cdpOut, pBuffer, nOffset, pRef ); + cdpIn, cdpOut, pBuffer, nOffset, pRefList ); } nLen = hb_hashLen( pItem ); if( nLen <= 255 ) @@ -855,9 +975,9 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, for( n = 1; n <= nLen; n++ ) { nOffset = hb_serializeItem( hb_hashGetKeyAt( pItem, n ), iFlags, - cdpIn, cdpOut, pBuffer, nOffset, pRef ); + cdpIn, cdpOut, pBuffer, nOffset, pRefList ); nOffset = hb_serializeItem( hb_hashGetValueAt( pItem, n ), iFlags, - cdpIn, cdpOut, pBuffer, nOffset, pRef ); + cdpIn, cdpOut, pBuffer, nOffset, pRefList ); } } break; @@ -872,7 +992,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL iFlags, } static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSize, - HB_SIZE nOffset, PHB_CYCLIC_REF * pRefPtr ) + HB_SIZE nOffset, PHB_REF_LIST pRefList ) { const HB_UCHAR * pBuffer = *pBufferPtr; HB_SIZE nSize = *pnSize, nLen = 0; @@ -939,7 +1059,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize = 9 + ( nSize >= 9 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); break; case HB_SERIAL_ARRAYREF8: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_ARRAY8: if( nSize >= 2 ) @@ -951,7 +1071,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_ARRAYREF16: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_ARRAY16: if( nSize >= 3 ) @@ -963,7 +1083,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_ARRAYREF32: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_ARRAY32: if( nSize >= 5 ) @@ -975,7 +1095,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_HASHREF8: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_HASH8: if( nSize >= 2 ) @@ -987,7 +1107,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_HASHREF16: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_HASH16: if( nSize >= 3 ) @@ -999,7 +1119,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_HASHREF32: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + if( hb_itemSerialOffsetRef( pRefList, nOffset ) ) return HB_FALSE; case HB_SERIAL_HASH32: if( nSize >= 5 ) @@ -1011,7 +1131,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz nSize++; break; case HB_SERIAL_REF: - if( ! hb_itemSerialOffsetRef( pRefPtr, HB_GET_LE_UINT32( pBuffer ) ) ) + if( ! hb_itemSerialOffsetRef( pRefList, HB_GET_LE_UINT32( pBuffer ) ) ) return HB_FALSE; nSize = 5; break; @@ -1115,7 +1235,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz case HB_SERIAL_XHB_A: case HB_SERIAL_XHB_H: case HB_SERIAL_XHB_O: - hb_itemSerialTypedRef( pRefPtr, pBuffer[ 0 ], + hb_itemSerialTypedRef( pRefList, pBuffer[ 0 ], ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ 1 ] ) ); case HB_SERIAL_XHB_B: nSize = 10; @@ -1139,7 +1259,7 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz { nOffset += nSize; nSize = *pnSize; - if( ! hb_deserializeTest( pBufferPtr, pnSize, nOffset, pRefPtr ) ) + if( ! hb_deserializeTest( pBufferPtr, pnSize, nOffset, pRefList ) ) return HB_FALSE; nSize -= *pnSize; --nLen; @@ -1151,11 +1271,9 @@ static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSiz static HB_SIZE hb_deserializeHash( PHB_ITEM pItem, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, const HB_UCHAR * pBuffer, HB_SIZE nOffset, - HB_SIZE nLen, PHB_CYCLIC_REF pRef, int iType ) + HB_SIZE nLen, PHB_REF_LIST pRefList ) { hb_hashNew( pItem ); - if( iType != 0 ) - hb_itemSerialTypedSet( pRef, pItem, iType ); if( nLen ) { @@ -1166,8 +1284,8 @@ static HB_SIZE hb_deserializeHash( PHB_ITEM pItem, hb_hashPreallocate( pItem, nLen ); while( nLen-- ) { - nOffset = hb_deserializeItem( pKey, cdpIn, cdpOut, pBuffer, nOffset, pRef ); - nOffset = hb_deserializeItem( pVal, cdpIn, cdpOut, pBuffer, nOffset, pRef ); + nOffset = hb_deserializeItem( pKey, cdpIn, cdpOut, pBuffer, nOffset, pRefList ); + nOffset = hb_deserializeItem( pVal, cdpIn, cdpOut, pBuffer, nOffset, pRefList ); hb_hashAdd( pItem, pKey, pVal ); } hb_itemRelease( pKey ); @@ -1181,8 +1299,8 @@ static HB_SIZE hb_deserializeHash( PHB_ITEM pItem, { if( hb_hashAllocNewPair( pItem, &pKey, &pVal ) ) { - nOffset = hb_deserializeItem( pKey, cdpIn, cdpOut, pBuffer, nOffset, pRef ); - nOffset = hb_deserializeItem( pVal, cdpIn, cdpOut, pBuffer, nOffset, pRef ); + nOffset = hb_deserializeItem( pKey, cdpIn, cdpOut, pBuffer, nOffset, pRefList ); + nOffset = hb_deserializeItem( pVal, cdpIn, cdpOut, pBuffer, nOffset, pRefList ); } } #endif @@ -1194,16 +1312,15 @@ static HB_SIZE hb_deserializeHash( PHB_ITEM pItem, static HB_SIZE hb_deserializeArray( PHB_ITEM pItem, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, const HB_UCHAR * pBuffer, HB_SIZE nOffset, - HB_SIZE nLen, PHB_CYCLIC_REF pRef, int iType ) + HB_SIZE nLen, PHB_REF_LIST pRefList ) { HB_SIZE u; hb_arrayNew( pItem, nLen ); - if( iType != 0 ) - hb_itemSerialTypedSet( pRef, pItem, iType ); + for( u = 1; u <= nLen; u++ ) nOffset = hb_deserializeItem( hb_arrayGetItemPtr( pItem, u ), - cdpIn, cdpOut, pBuffer, nOffset, pRef ); + cdpIn, cdpOut, pBuffer, nOffset, pRefList ); return nOffset; } @@ -1211,7 +1328,7 @@ static HB_SIZE hb_deserializeArray( PHB_ITEM pItem, static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, const HB_UCHAR * pBuffer, HB_SIZE nOffset, - PHB_CYCLIC_REF pRef ) + PHB_REF_LIST pRefList ) { HB_SIZE nLen, nPad, nSize; char * szVal; @@ -1386,45 +1503,45 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, break; case HB_SERIAL_ARRAYREF8: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_ARRAY8: nLen = pBuffer[ nOffset++ ]; - nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset, nLen, pRef, 0 ); + nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset, nLen, pRefList ); break; case HB_SERIAL_ARRAYREF16: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_ARRAY16: nLen = HB_GET_LE_UINT16( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset + 2, nLen, pRef, 0 ); + nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset + 2, nLen, pRefList ); break; case HB_SERIAL_ARRAYREF32: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_ARRAY32: nLen = HB_GET_LE_UINT32( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset + 4, nLen, pRef, 0 ); + nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset + 4, nLen, pRefList ); break; case HB_SERIAL_HASHREF8: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_HASH8: nLen = pBuffer[ nOffset++ ]; - nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset, nLen, pRef, 0 ); + nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset, nLen, pRefList ); break; case HB_SERIAL_HASHREF16: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_HASH16: nLen = HB_GET_LE_UINT16( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset + 2, nLen, pRef, 0 ); + nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset + 2, nLen, pRefList ); break; case HB_SERIAL_HASHREF32: - hb_itemSerialOffsetSet( pRef, pItem, nOffset - 1 ); + hb_itemSerialOffsetSet( pRefList, pItem, nOffset - 1 ); case HB_SERIAL_HASH32: nLen = HB_GET_LE_UINT32( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset + 4, nLen, pRef, 0 ); + nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset + 4, nLen, pRefList ); break; case HB_SERIAL_REF: - hb_itemSerialOffsetGet( pRef, pItem, + hb_itemSerialOffsetGet( pRefList, pItem, HB_GET_LE_UINT32( &pBuffer[ nOffset ] ) ); nOffset += 4; break; @@ -1436,7 +1553,7 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, nLen = strlen( szClass ); szFunc = szClass + nLen + 1; nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset + nLen + strlen( szFunc ) + 2, pRef ); + nOffset + nLen + strlen( szFunc ) + 2, pRefList ); hb_objSetClass( pItem, szClass, szFunc ); break; } @@ -1445,7 +1562,7 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, { int iHashFlags = HB_GET_LE_UINT16( &pBuffer[ nOffset ] ); nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset + 2, pRef ); + nOffset + 2, pRefList ); hb_hashClearFlags( pItem, HB_HASH_FLAG_MASK ); if( ( iHashFlags & ( HB_HASH_KEEPORDER | HB_HASH_BINARY ) ) != HB_HASH_BINARY ) iHashFlags |= HB_HASH_RESORT; @@ -1457,9 +1574,9 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, { PHB_ITEM pDefVal = hb_itemNew( NULL ); nOffset = hb_deserializeItem( pDefVal, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); hb_hashSetDefault( pItem, pDefVal ); hb_itemRelease( pDefVal ); break; @@ -1476,13 +1593,15 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, { case HB_ZLIB_RES_OK: { - PHB_CYCLIC_REF pRefZ = NULL; + HB_REF_LIST refListZ; + + hb_itemSerialRefListInit( &refListZ ); pBuffer = ( const HB_UCHAR * ) szVal; - if( hb_deserializeTest( &pBuffer, &nLen, 0, &pRefZ ) ) - hb_deserializeItem( pItem, cdpIn, cdpOut, ( const HB_UCHAR * ) szVal, 0, pRefZ ); + if( hb_deserializeTest( &pBuffer, &nLen, 0, &refListZ ) ) + hb_deserializeItem( pItem, cdpIn, cdpOut, ( const HB_UCHAR * ) szVal, 0, &refListZ ); else hb_itemClear( pItem ); - hb_itemSerialRefFree( pRefZ ); + hb_itemSerialRefListFree( &refListZ ); break; } case HB_ZLIB_RES_UNSUPPORTED: @@ -1551,20 +1670,20 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, break; case HB_SERIAL_XHB_A: nLen = ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, - nOffset + 8, nLen, pRef, HB_SERIAL_XHB_A ); + hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_A ); + nOffset = hb_deserializeArray( pItem, cdpIn, cdpOut, pBuffer, nOffset + 8, nLen, pRefList ); break; case HB_SERIAL_XHB_B: nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); /* we do not support codeblock deserialization: HB_RestoreBlock( pItem ) */ - /* hb_itemSerialTypedSet( pRef, pItem, HB_SERIAL_XHB_O ); */ + /* hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_B ); */ hb_itemClear( pItem ); break; case HB_SERIAL_XHB_H: nLen = ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset ] ); - nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, - nOffset + 8, nLen, pRef, HB_SERIAL_XHB_H ); + hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_H ); + nOffset = hb_deserializeHash( pItem, cdpIn, cdpOut, pBuffer, nOffset + 8, nLen, pRefList ); hb_hashSetFlags( pItem, HB_HASH_KEEPORDER | HB_HASH_RESORT ); break; case HB_SERIAL_XHB_O: @@ -1574,7 +1693,7 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, nLen = ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset ] ); /* deserialize :className */ nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset + 8, pRef ); + nOffset + 8, pRefList ); /* find class handle */ uiClass = hb_clsFindClass( hb_itemGetCPtr( pItem ), NULL ); if( uiClass && hb_vmRequestReenter() ) @@ -1584,14 +1703,14 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, hb_clsAssociate( uiClass ); hb_itemMove( pItem, hb_stackReturnItem() ); - hb_itemSerialTypedSet( pRef, pItem, HB_SERIAL_XHB_O ); + hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_O ); while( nLen-- ) { nOffset = hb_deserializeItem( pMsg, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); nOffset = hb_deserializeItem( pVal, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); if( hb_vmRequestQuery() == 0 ) { char szMsg[ HB_SYMBOL_NAME_LEN ]; @@ -1605,13 +1724,13 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, } else { - hb_itemSerialTypedSet( pRef, pItem, HB_SERIAL_XHB_O ); + hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_O ); while( nLen-- ) { nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset, pRef ); + nOffset, pRefList ); } hb_itemClear( pItem ); } @@ -1624,7 +1743,7 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, nPad = ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset ] ) + nOffset + 8; /* deserialize :className */ nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, - nOffset + 8, pRef ); + nOffset + 8, pRefList ); nLen = nPad - nOffset; /* get serialized HBPERSISTENT text */ szVal = hb_cdpnDup( ( const char * ) &pBuffer[ nOffset ], &nLen, @@ -1646,11 +1765,11 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, } else hb_itemClear( pItem ); - hb_itemSerialTypedSet( pRef, pItem, HB_SERIAL_XHB_O ); + hb_itemSerialTypedSet( pRefList, pItem, HB_SERIAL_XHB_O ); break; } case HB_SERIAL_XHB_R: - hb_itemSerialTypedGet( pRef, pItem, pBuffer[ nOffset ], + hb_itemSerialTypedGet( pRefList, pItem, pBuffer[ nOffset ], ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset + 1 ] ) ); nOffset += 9; break; @@ -1670,13 +1789,16 @@ char * hb_itemSerializeCP( PHB_ITEM pItem, int iFlags, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, HB_SIZE * pnSize ) { - PHB_CYCLIC_REF pRef = NULL; - HB_SIZE nSize = hb_itemSerialSize( pItem, iFlags, cdpIn, cdpOut, &pRef, 0 ); - HB_UCHAR * pBuffer = ( HB_UCHAR * ) hb_xgrab( nSize + 1 ); + HB_REF_LIST refList; + HB_UCHAR * pBuffer; + HB_SIZE nSize; - hb_itemSerialUnRefFree( &pRef ); - hb_serializeItem( pItem, iFlags, cdpIn, cdpOut, pBuffer, 0, pRef ); - hb_itemSerialRefFree( pRef ); + hb_itemSerialRefListInit( &refList ); + nSize = hb_itemSerialSize( pItem, iFlags, cdpIn, cdpOut, &refList, 0 ); + pBuffer = ( HB_UCHAR * ) hb_xgrab( nSize + 1 ); + hb_itemSerialUnusedFree( &refList ); + hb_serializeItem( pItem, iFlags, cdpIn, cdpOut, pBuffer, 0, &refList ); + hb_itemSerialRefListFree( &refList ); if( ( iFlags & HB_SERIALIZE_COMPRESS ) != 0 && nSize > 20 ) { @@ -1713,16 +1835,17 @@ char * hb_itemSerialize( PHB_ITEM pItem, int iFlags, HB_SIZE *pnSize ) PHB_ITEM hb_itemDeserializeCP( const char ** pBufferPtr, HB_SIZE * pnSize, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut ) { - PHB_CYCLIC_REF pRef = NULL; const HB_UCHAR * pBuffer = ( const HB_UCHAR * ) *pBufferPtr; PHB_ITEM pItem = NULL; + HB_REF_LIST refList; - if( ! pnSize || hb_deserializeTest( ( const HB_UCHAR ** ) pBufferPtr, pnSize, 0, &pRef ) ) + hb_itemSerialRefListInit( &refList ); + if( ! pnSize || hb_deserializeTest( ( const HB_UCHAR ** ) pBufferPtr, pnSize, 0, &refList ) ) { pItem = hb_itemNew( NULL ); - hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, 0, pRef ); + hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, 0, &refList ); } - hb_itemSerialRefFree( pRef ); + hb_itemSerialRefListFree( &refList ); return pItem; } diff --git a/src/vm/arrays.c b/src/vm/arrays.c index cbeab24267..7c243648dc 100644 --- a/src/vm/arrays.c +++ b/src/vm/arrays.c @@ -1467,112 +1467,117 @@ HB_BOOL hb_arrayCopy( PHB_ITEM pSrcArray, PHB_ITEM pDstArray, HB_SIZE * pnStart, return HB_FALSE; } -static void hb_arrayCloneBody( PHB_BASEARRAY pSrcBaseArray, PHB_BASEARRAY pDstBaseArray, PHB_NESTED_CLONED pClonedList ) +static void hb_arrayCloneBody( PHB_ITEM pDest, PHB_ITEM pArray, PHB_NESTED_CLONED pClonedList ) { PHB_ITEM pSrcItem, pDstItem; HB_SIZE nLen; - HB_TRACE( HB_TR_DEBUG, ( "hb_arrayCloneBody(%p, %p, %p)", pSrcBaseArray, pDstBaseArray, pClonedList ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_arrayCloneBody(%p, %p, %p)", pDest, pArray, pClonedList ) ); - pSrcItem = pSrcBaseArray->pItems; - pDstItem = pDstBaseArray->pItems; + nLen = pArray->item.asArray.value->nLen; + hb_arrayNew( pDest, nLen ); + pDest->item.asArray.value->uiClass = pArray->item.asArray.value->uiClass; + pSrcItem = pArray->item.asArray.value->pItems; + pDstItem = pDest->item.asArray.value->pItems; - pDstBaseArray->uiClass = pSrcBaseArray->uiClass; - - for( nLen = pSrcBaseArray->nLen; nLen; --nLen, ++pSrcItem, ++pDstItem ) - hb_cloneNested( pDstItem, pSrcItem, pClonedList ); + while( nLen-- ) + hb_nestedCloneDo( pDstItem++, pSrcItem++, pClonedList ); } -void hb_cloneNested( PHB_ITEM pDstItem, PHB_ITEM pSrcItem, PHB_NESTED_CLONED pClonedList ) +void hb_nestedCloneInit( PHB_NESTED_CLONED pClonedList, void * pValue, PHB_ITEM pDest ) +{ + pClonedList->nSize = 16; + pClonedList->nCount = 1; + pClonedList->pRefs = ( PHB_NESTED_REF ) + hb_xgrab( pClonedList->nSize * sizeof( HB_NESTED_REF ) ); + pClonedList->pRefs[ 0 ].value = pValue; + pClonedList->pRefs[ 0 ].pDest = pDest; +} + +void hb_nestedCloneFree( PHB_NESTED_CLONED pClonedList ) +{ + hb_xfree( pClonedList->pRefs ); +} + +static HB_BOOL hb_nestedCloneFind( PHB_NESTED_CLONED pClonedList, void * pValue, PHB_ITEM pDest ) +{ + HB_SIZE nFirst, nLast, nMiddle; + PHB_NESTED_REF pRef; + + nFirst = 0; + nLast = pClonedList->nCount; + nMiddle = ( nFirst + nLast ) >> 1; + pRef = pClonedList->pRefs; + + while( nFirst < nLast ) + { + if( ( HB_PTRUINT ) pRef[ nMiddle ].value < ( HB_PTRUINT ) pValue ) + nFirst = nMiddle + 1; + else if( ( HB_PTRUINT ) pRef[ nMiddle ].value > ( HB_PTRUINT ) pValue ) + nLast = nMiddle; + else + { + hb_itemCopy( pDest, pRef[ nMiddle ].pDest ); + return HB_TRUE; + } + nMiddle = ( nFirst + nLast ) >> 1; + } + + if( pClonedList->nCount >= pClonedList->nSize ) + { + pClonedList->nSize += pClonedList->nSize >> 1; + pClonedList->pRefs = ( PHB_NESTED_REF ) + hb_xrealloc( pClonedList->pRefs, + pClonedList->nSize * sizeof( HB_NESTED_REF ) ); + } + + pRef = &pClonedList->pRefs[ nMiddle ]; + if( nMiddle < pClonedList->nCount ) + memmove( pRef + 1, pRef, + ( pClonedList->nCount - nMiddle ) * sizeof( HB_NESTED_REF ) ); + pClonedList->nCount++; + + pRef->value = pValue; + pRef->pDest = pDest; + + return HB_FALSE; +} + +void hb_nestedCloneDo( PHB_ITEM pDstItem, PHB_ITEM pSrcItem, PHB_NESTED_CLONED pClonedList ) { /* Clipper clones nested array ONLY if NOT an Object!!! */ if( HB_IS_ARRAY( pSrcItem ) ) { - PHB_NESTED_CLONED pCloned = pClonedList; - PHB_BASEARRAY pBaseArray = pSrcItem->item.asArray.value; - - do + if( ! hb_nestedCloneFind( pClonedList, ( void * ) pSrcItem->item.asArray.value, pDstItem ) ) { - if( pCloned->value == ( void * ) pBaseArray ) - break; - pCloned = pCloned->pNext; - } - while( pCloned ); - - if( pCloned ) - hb_itemCopy( pDstItem, pCloned->pDest ); - else if( pSrcItem->item.asArray.value->uiClass != 0 ) - hb_objCloneTo( pDstItem, pSrcItem, pClonedList ); - else - { - hb_arrayNew( pDstItem, pBaseArray->nLen ); - - pCloned = ( PHB_NESTED_CLONED ) hb_xgrab( sizeof( HB_NESTED_CLONED ) ); - pCloned->value = ( void * ) pBaseArray; - pCloned->pDest = pDstItem; - pCloned->pNext = pClonedList->pNext; - pClonedList->pNext = pCloned; - - hb_arrayCloneBody( pBaseArray, pDstItem->item.asArray.value, pClonedList ); + if( pSrcItem->item.asArray.value->uiClass != 0 ) + hb_objCloneBody( pDstItem, pSrcItem, pClonedList ); + else + hb_arrayCloneBody( pDstItem, pSrcItem, pClonedList ); } } else if( HB_IS_HASH( pSrcItem ) ) { - PHB_NESTED_CLONED pCloned = pClonedList; - PHB_BASEHASH pBaseHash = pSrcItem->item.asHash.value; - - do - { - if( pCloned->value == ( void * ) pBaseHash ) - break; - pCloned = pCloned->pNext; - } - while( pCloned ); - - if( pCloned ) - hb_itemCopy( pDstItem, pCloned->pDest ); - else - { - pCloned = ( PHB_NESTED_CLONED ) hb_xgrab( sizeof( HB_NESTED_CLONED ) ); - pCloned->value = ( void * ) pBaseHash; - pCloned->pDest = pDstItem; - pCloned->pNext = pClonedList->pNext; - pClonedList->pNext = pCloned; - - hb_hashCloneBody( pSrcItem, pDstItem, pClonedList ); - } + if( ! hb_nestedCloneFind( pClonedList, ( void * ) pSrcItem->item.asHash.value, pDstItem ) ) + hb_hashCloneBody( pDstItem, pSrcItem, pClonedList ); } else hb_itemCopy( pDstItem, pSrcItem ); } -PHB_ITEM hb_arrayCloneTo( PHB_ITEM pDstArray, PHB_ITEM pSrcArray ) +PHB_ITEM hb_arrayCloneTo( PHB_ITEM pDest, PHB_ITEM pArray ) { - HB_TRACE( HB_TR_DEBUG, ( "hb_arrayCloneTo(%p,%p)", pDstArray, pSrcArray ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_arrayCloneTo(%p,%p)", pDest, pArray ) ); - if( HB_IS_ARRAY( pSrcArray ) ) + if( HB_IS_ARRAY( pArray ) ) { - PHB_NESTED_CLONED pClonedList, pCloned; - PHB_BASEARRAY pSrcBaseArray = pSrcArray->item.asArray.value; - HB_SIZE nSrcLen = pSrcBaseArray->nLen; + HB_NESTED_CLONED clonedList; - hb_arrayNew( pDstArray, nSrcLen ); - pClonedList = ( PHB_NESTED_CLONED ) hb_xgrab( sizeof( HB_NESTED_CLONED ) ); - pClonedList->value = ( void * ) pSrcBaseArray; - pClonedList->pDest = pDstArray; - pClonedList->pNext = NULL; - - hb_arrayCloneBody( pSrcBaseArray, pDstArray->item.asArray.value, pClonedList ); - - do - { - pCloned = pClonedList; - pClonedList = pClonedList->pNext; - hb_xfree( pCloned ); - } - while( pClonedList ); + hb_nestedCloneInit( &clonedList, ( void * ) pArray->item.asArray.value, pDest ); + hb_arrayCloneBody( pDest, pArray, &clonedList ); + hb_nestedCloneFree( &clonedList ); } - return pDstArray; + return pDest; } PHB_ITEM hb_arrayClone( PHB_ITEM pArray ) diff --git a/src/vm/classes.c b/src/vm/classes.c index 0996e390d6..6d3e11f838 100644 --- a/src/vm/classes.c +++ b/src/vm/classes.c @@ -2689,15 +2689,25 @@ static PHB_SYMB hb_objGetFuncSym( PHB_ITEM pItem ) } /* clone object if user defined clone method or copy it */ -void hb_objCloneTo( PHB_ITEM pDest, PHB_ITEM pSource, PHB_NESTED_CLONED pClonedList ) +void hb_objCloneBody( PHB_ITEM pDest, PHB_ITEM pObject, PHB_NESTED_CLONED pClonedList ) { - HB_TRACE( HB_TR_DEBUG, ( "hb_objCloneTo(%p,%p,%p)", pDest, pSource, pClonedList ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_objCloneBody(%p,%p,%p)", pDest, pObject, pClonedList ) ); HB_SYMBOL_UNUSED( pClonedList ); /* TODO: add support for user defined clone operation */ - hb_itemCopy( pDest, pSource ); + hb_itemCopy( pDest, pObject ); +} + +/* clone object if user defined clone method or copy it */ +PHB_ITEM hb_objCloneTo( PHB_ITEM pDest, PHB_ITEM pObject ) +{ + HB_TRACE( HB_TR_DEBUG, ( "hb_objCloneTo(%p,%p)", pDest, pObject ) ); + + hb_objCloneBody( pDest, pObject, NULL ); + + return pDest; } /* send message which allows to set execution context for debugger */ diff --git a/src/vm/hashes.c b/src/vm/hashes.c index 76b8e949ec..de0cc7be8e 100644 --- a/src/vm/hashes.c +++ b/src/vm/hashes.c @@ -949,11 +949,11 @@ void * hb_hashId( PHB_ITEM pHash ) return NULL; } -void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pClonedList ) +void hb_hashCloneBody( PHB_ITEM pDest, PHB_ITEM pHash, PHB_NESTED_CLONED pClonedList ) { HB_SIZE nPos; - HB_TRACE( HB_TR_DEBUG, ( "hb_hashCloneBody(%p,%p,%p)", pHash, pDest, pClonedList ) ); + HB_TRACE( HB_TR_DEBUG, ( "hb_hashCloneBody(%p,%p,%p)", pDest, pHash, pClonedList ) ); hb_hashNew( pDest ); pDest->item.asHash.value->iFlags = pHash->item.asHash.value->iFlags; @@ -976,7 +976,7 @@ void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pCloned hb_itemCopy( &pDest->item.asHash.value->pPairs[ nPos ].key, &pHash->item.asHash.value->pPairs[ nPos ].key ); pDest->item.asHash.value->nLen++; - hb_cloneNested( &pDest->item.asHash.value->pPairs[ nPos ].value, pValue, pClonedList ); + hb_nestedCloneDo( &pDest->item.asHash.value->pPairs[ nPos ].value, pValue, pClonedList ); } } @@ -986,22 +986,11 @@ PHB_ITEM hb_hashCloneTo( PHB_ITEM pDest, PHB_ITEM pHash ) if( HB_IS_HASH( pHash ) ) { - PHB_NESTED_CLONED pClonedList, pCloned; + HB_NESTED_CLONED clonedList; - pClonedList = ( PHB_NESTED_CLONED ) hb_xgrab( sizeof( HB_NESTED_CLONED ) ); - pClonedList->value = ( void * ) pHash->item.asHash.value; - pClonedList->pDest = pDest; - pClonedList->pNext = NULL; - - hb_hashCloneBody( pHash, pDest, pClonedList ); - - do - { - pCloned = pClonedList; - pClonedList = pClonedList->pNext; - hb_xfree( pCloned ); - } - while( pClonedList ); + hb_nestedCloneInit( &clonedList, ( void * ) pHash->item.asHash.value, pDest ); + hb_hashCloneBody( pDest, pHash, &clonedList ); + hb_nestedCloneFree( &clonedList ); } return pDest; diff --git a/src/vm/itemapi.c b/src/vm/itemapi.c index cce4749921..a053e041e1 100644 --- a/src/vm/itemapi.c +++ b/src/vm/itemapi.c @@ -2144,12 +2144,7 @@ PHB_ITEM hb_itemClone( PHB_ITEM pItem ) if( HB_IS_ARRAY( pItem ) ) { if( HB_IS_OBJECT( pItem ) ) - { - PHB_ITEM pResult = hb_itemNew( NULL ); - - hb_objCloneTo( pResult, pItem, NULL ); - return pResult; - } + return hb_objCloneTo( hb_itemNew( NULL ), pItem ); else return hb_arrayClone( pItem ); } @@ -2166,7 +2161,7 @@ void hb_itemCloneTo( PHB_ITEM pDest, PHB_ITEM pSource ) if( HB_IS_ARRAY( pSource ) ) { if( HB_IS_OBJECT( pSource ) ) - hb_objCloneTo( pDest, pSource, NULL ); + hb_objCloneTo( pDest, pSource ); else hb_arrayCloneTo( pDest, pSource ); }