diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 49c2ba3401..58e321e1a2 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -8,6 +8,24 @@ 2002-12-01 13:30 UTC+0100 Foo Bar */ +2007-04-16 21:30 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/include/hbcompat.ch + * always translate hash H*() function to HB_H*() ones even if + HB_COMPAT_XHB is set. Code which uses HB_H*() functions can + be linked with any Harbour builds + + * harbour/include/hbapi.h + * harbour/source/vm/hashes.c + + added hb_hashId() + + * harbour/source/pp/ppcore.c + + added #ytranslate, #ycommand, #yuntranslate, #yuncommand + case sensitive version of corresponding #x* directives + + * harbour/source/rtl/itemseri.c + + added support for serialization arrays and/or hashes with cyclic + references + 2007-04-16 21:25 UTC+0200 Lorenzo Fiorini (lorenzo.fiorini/at/gmail.com) * harbour/source/rtl/tget.prg * harbour/source/rtl/tgetlist.prg diff --git a/harbour/include/hbapi.h b/harbour/include/hbapi.h index 9b6bba6e82..e346cce7ad 100644 --- a/harbour/include/hbapi.h +++ b/harbour/include/hbapi.h @@ -75,8 +75,8 @@ HB_EXTERN_BEGIN #define HB_IT_NIL ( ( HB_TYPE ) 0x00000 ) #define HB_IT_POINTER ( ( HB_TYPE ) 0x00001 ) #define HB_IT_INTEGER ( ( HB_TYPE ) 0x00002 ) -#define HB_IT_LONG ( ( HB_TYPE ) 0x00008 ) #define HB_IT_HASH ( ( HB_TYPE ) 0x00004 ) +#define HB_IT_LONG ( ( HB_TYPE ) 0x00008 ) #define HB_IT_DOUBLE ( ( HB_TYPE ) 0x00010 ) #define HB_IT_DATE ( ( HB_TYPE ) 0x00020 ) #define HB_IT_LOGICAL ( ( HB_TYPE ) 0x00080 ) @@ -94,7 +94,7 @@ HB_EXTERN_BEGIN #define HB_IT_NUMERIC ( ( HB_TYPE ) ( HB_IT_INTEGER | HB_IT_LONG | HB_IT_DOUBLE ) ) #define HB_IT_NUMINT ( ( HB_TYPE ) ( HB_IT_INTEGER | HB_IT_LONG ) ) #define HB_IT_ANY ( ( HB_TYPE ) 0xFFFFFFFF ) -#define HB_IT_COMPLEX ( ( HB_TYPE ) ( HB_IT_BLOCK | HB_IT_ARRAY | HB_IT_HASH | HB_IT_POINTER | HB_IT_MEMVAR | HB_IT_ENUM | HB_IT_BYREF | HB_IT_STRING ) ) +#define HB_IT_COMPLEX ( ( HB_TYPE ) ( HB_IT_BLOCK | HB_IT_ARRAY | HB_IT_HASH | HB_IT_POINTER | /* HB_IT_MEMVAR | HB_IT_ENUM |*/ HB_IT_BYREF | HB_IT_STRING ) ) #define HB_IT_GCITEM ( ( HB_TYPE ) ( HB_IT_BLOCK | HB_IT_ARRAY | HB_IT_HASH | HB_IT_POINTER | HB_IT_BYREF ) ) #define HB_IT_HASHKEY ( ( HB_TYPE ) ( HB_IT_INTEGER | HB_IT_LONG | HB_IT_DOUBLE | HB_IT_DATE | HB_IT_STRING ) ) @@ -714,6 +714,7 @@ extern HB_EXPORT PHB_ITEM hb_hashGetDefault( PHB_ITEM pHash ); extern HB_EXPORT void hb_hashSetFlags( PHB_ITEM pHash, int iFlags ); extern HB_EXPORT void hb_hashClearFlags( PHB_ITEM pHash, int iFlags ); extern HB_EXPORT int hb_hashGetFlags( PHB_ITEM pHash ); +extern HB_EXPORT void * hb_hashId( PHB_ITEM pHash ); /* retrieves the hash unique ID */ extern HB_EXPORT PHB_ITEM hb_hashGetItemPtr( PHB_ITEM pHash, PHB_ITEM pKey ); extern HB_EXPORT PHB_ITEM hb_hashGetItemRefPtr( PHB_ITEM pHash, PHB_ITEM pKey ); diff --git a/harbour/include/hbcompat.ch b/harbour/include/hbcompat.ch index a0a250e806..51fd965429 100644 --- a/harbour/include/hbcompat.ch +++ b/harbour/include/hbcompat.ch @@ -62,10 +62,13 @@ #ifdef __XHARBOUR__ + #xtranslate hb_gtSys => gtSys #xtranslate hb_gtInfo([]) => gtInfo([]) #xtranslate hb_gtVersion([]) => hb_gt_Version([]) + #else + #xtranslate gtSys => hb_gtSys #xtranslate gtInfo([]) => hb_gtInfo([]) #xtranslate hb_gt_Version([]) => hb_gtVersion([]) @@ -75,13 +78,9 @@ #xtranslate gtPasteClipBoard([]) => hb_gtInfo( GTI_CLIPBOARDPAST ) #xtranslate gfxPrimitive([])=> hb_gfxPrimitive([]) #xtranslate gfxText([]) => hb_gfxText([]) -#endif -#ifndef __XHARBOUR__ + /* SWITCH ... ; case ... ; DEFAULT ; ... ; END */ #xcommand DEFAULT => OTHERWISE -#endif - -#if !defined( HB_COMPAT_XHB ) #xtranslate HASH([]) => HB_HASH([]) #xtranslate HHASKEY([]) => HB_HHASKEY([]) diff --git a/harbour/source/pp/ppcore.c b/harbour/source/pp/ppcore.c index 4fb3173614..ca0b76222c 100644 --- a/harbour/source/pp/ppcore.c +++ b/harbour/source/pp/ppcore.c @@ -4521,6 +4521,12 @@ static void hb_pp_preprocesToken( PHB_PP_STATE pState ) { hb_pp_directiveNew( pState, pToken, HB_PP_CMP_STD, FALSE, fDirect, FALSE ); } +#ifndef HB_C52_STRICT + else if( hb_pp_tokenValueCmp( pToken, "YTRANSLATE", HB_PP_CMP_DBASE ) ) + { + hb_pp_directiveNew( pState, pToken, HB_PP_CMP_CASE, FALSE, fDirect, FALSE ); + } +#endif else if( hb_pp_tokenValueCmp( pToken, "COMMAND", HB_PP_CMP_DBASE ) ) { hb_pp_directiveNew( pState, pToken, HB_PP_CMP_DBASE, TRUE, fDirect, FALSE ); @@ -4530,6 +4536,10 @@ static void hb_pp_preprocesToken( PHB_PP_STATE pState ) hb_pp_directiveNew( pState, pToken, HB_PP_CMP_STD, TRUE, fDirect, FALSE ); } #ifndef HB_C52_STRICT + else if( hb_pp_tokenValueCmp( pToken, "YCOMMAND", HB_PP_CMP_DBASE ) ) + { + hb_pp_directiveNew( pState, pToken, HB_PP_CMP_CASE, TRUE, fDirect, FALSE ); + } /* xHarbour PP extensions */ else if( hb_pp_tokenValueCmp( pToken, "UNTRANSLATE", HB_PP_CMP_DBASE ) ) { @@ -4539,6 +4549,10 @@ static void hb_pp_preprocesToken( PHB_PP_STATE pState ) { hb_pp_directiveNew( pState, pToken, HB_PP_CMP_STD, FALSE, fDirect, TRUE ); } + else if( hb_pp_tokenValueCmp( pToken, "YUNTRANSLATE", HB_PP_CMP_DBASE ) ) + { + hb_pp_directiveNew( pState, pToken, HB_PP_CMP_CASE, FALSE, fDirect, TRUE ); + } else if( hb_pp_tokenValueCmp( pToken, "UNCOMMAND", HB_PP_CMP_DBASE ) ) { hb_pp_directiveNew( pState, pToken, HB_PP_CMP_DBASE, TRUE, fDirect, TRUE ); @@ -4547,6 +4561,10 @@ static void hb_pp_preprocesToken( PHB_PP_STATE pState ) { hb_pp_directiveNew( pState, pToken, HB_PP_CMP_STD, TRUE, fDirect, TRUE ); } + else if( hb_pp_tokenValueCmp( pToken, "YUNCOMMAND", HB_PP_CMP_DBASE ) ) + { + hb_pp_directiveNew( pState, pToken, HB_PP_CMP_CASE, TRUE, fDirect, TRUE ); + } /* Clipper PP does not accept #line and generate error */ else if( hb_pp_tokenValueCmp( pToken, "LINE", HB_PP_CMP_DBASE ) ) { diff --git a/harbour/source/rtl/itemseri.c b/harbour/source/rtl/itemseri.c index 86adfbdb13..624a2d6fbc 100644 --- a/harbour/source/rtl/itemseri.c +++ b/harbour/source/rtl/itemseri.c @@ -50,13 +50,16 @@ * */ +#include "hbapi.h" +#include "hbapiitm.h" + /* -TODO: 1. add cyclic reference detection - 2. extended number format with size and decimals - 3. extended hash format with default value and hash flags - +TODO: 1. extended number format with size and decimals + 2. extended hash format with default value and hash flags +*/ +/* UCHAR [ 1 ] - item type 0. NIL 0 1. TRUE 0 @@ -66,20 +69,26 @@ UCHAR [ 1 ] - item type 5. INT16 2 6. INT24 3 7. INT32 4 - 8. INT64 5 - 9. DOUBLE IEE754 LE 8+1+1 - 10. DATE 4 + 8. INT64 8 + 9. DOUBLE IEE754 LE 8 + 10. DATE 3 11. STRING8 1+n 12. STRING16 2+n 13. STRING32 4+n 14. ARRAY8 1+n 15. ARRAY16 2+n 16. ARRAY32 4+n - 17. HASH8 1+n - 18. HASH16 2+n - 19. HASH32 4+n - 20. CYCLIC REFERENCE 4 - 21. SYMBOL 1+n + 17. ARRAYREF8 1+n + 18. ARRAYREF16 2+n + 19. ARRAYREF32 4+n + 20. HASH8 1+n + 21. HASH16 2+n + 22. HASH32 4+n + 23. HASHREF8 1+n + 24. HASHREF16 2+n + 25. HASHREF32 4+n + 26. SYMBOL 1+n + 27. CYCLIC REFERENCE 4 */ #define HB_SERIAL_NIL 0 @@ -99,18 +108,145 @@ UCHAR [ 1 ] - item type #define HB_SERIAL_ARRAY8 14 #define HB_SERIAL_ARRAY16 15 #define HB_SERIAL_ARRAY32 16 -#define HB_SERIAL_HASH8 17 -#define HB_SERIAL_HASH16 18 -#define HB_SERIAL_HASH32 19 -#define HB_SERIAL_REF 20 -#define HB_SERIAL_SYMBOL 21 +#define HB_SERIAL_ARRAYREF8 17 +#define HB_SERIAL_ARRAYREF16 18 +#define HB_SERIAL_ARRAYREF32 19 +#define HB_SERIAL_HASH8 20 +#define HB_SERIAL_HASH16 21 +#define HB_SERIAL_HASH32 22 +#define HB_SERIAL_HASHREF8 23 +#define HB_SERIAL_HASHREF16 24 +#define HB_SERIAL_HASHREF32 25 +#define HB_SERIAL_SYMBOL 26 +#define HB_SERIAL_REF 27 -#include "hbapi.h" -#include "hbapiitm.h" +#define HB_SERIAL_DUMMYOFFSET ( ( ULONG ) -1 ) -static UCHAR * hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer ); +typedef struct _HB_CYCLIC_REF +{ + void * value; + ULONG ulOffset; + BOOL fRef; + struct _HB_CYCLIC_REF * pNext; +} HB_CYCLIC_REF, * PHB_CYCLIC_REF; -static ULONG hb_itemSerialSize( PHB_ITEM pItem ) +static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer, + ULONG ulOffset, PHB_CYCLIC_REF pRef ); + +static BOOL hb_itemSerialValueRef( PHB_CYCLIC_REF * pRefPtr, void * value, + ULONG ulOffset ) +{ + while( * pRefPtr ) + { + if( ( * pRefPtr )->value == value ) + { + ( * pRefPtr )->fRef = TRUE; + return TRUE; + } + pRefPtr = &( * pRefPtr )->pNext; + } + + * pRefPtr = ( PHB_CYCLIC_REF ) hb_xgrab( sizeof( HB_CYCLIC_REF ) ); + ( * pRefPtr )->value = value; + ( * pRefPtr )->ulOffset = ulOffset; + ( * pRefPtr )->fRef = FALSE; + ( * pRefPtr )->pNext = NULL; + + return FALSE; +} + +static void hb_itemSerialUnRefFree( PHB_CYCLIC_REF * pRefPtr ) +{ + PHB_CYCLIC_REF pRef; + + while( * pRefPtr ) + { + pRef = * pRefPtr; + if( ! pRef->fRef ) + { + * pRefPtr =pRef->pNext; + hb_xfree( pRef ); + } + else + pRefPtr = &pRef->pNext; + } +} + +static BOOL hb_itemSerialValueOffset( PHB_CYCLIC_REF pRef, void * value, + ULONG ulOffset, ULONG * pulRef ) +{ + while( pRef ) + { + if( pRef->value == value ) + { + * pulRef = pRef->ulOffset; + return pRef->ulOffset < ulOffset; + } + pRef = pRef->pNext; + } + + * pulRef = HB_SERIAL_DUMMYOFFSET; + return FALSE; +} + +static BOOL hb_itemSerialOffsetRef( PHB_CYCLIC_REF * pRefPtr, void * value, + ULONG ulOffset ) +{ + while( * pRefPtr ) + { + if( ( * pRefPtr )->ulOffset == ulOffset ) + return TRUE; + pRefPtr = &( * pRefPtr )->pNext; + } + + * pRefPtr = ( PHB_CYCLIC_REF ) hb_xgrab( sizeof( HB_CYCLIC_REF ) ); + ( * pRefPtr )->value = value; + ( * pRefPtr )->ulOffset = ulOffset; + ( * pRefPtr )->fRef = FALSE; + ( * pRefPtr )->pNext = NULL; + + return FALSE; +} + +static void hb_itemSerialOffsetSet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, + ULONG ulOffset ) +{ + while( pRef ) + { + if( pRef->ulOffset == ulOffset ) + { + pRef->value = ( void * ) pItem; + break; + } + pRef = pRef->pNext; + } +} + +static void hb_itemSerialOffsetGet( PHB_CYCLIC_REF pRef, PHB_ITEM pItem, + ULONG ulOffset ) +{ + while( pRef ) + { + if( pRef->ulOffset == ulOffset ) + { + hb_itemCopy( pItem, ( PHB_ITEM ) pRef->value ); + break; + } + pRef = pRef->pNext; + } +} + +static void hb_itemSerialRefFree( PHB_CYCLIC_REF pRef ) +{ + while( pRef ) + { + PHB_CYCLIC_REF pNext = pRef->pNext; + hb_xfree( pRef ); + pRef = pNext; + } +} + +static ULONG hb_itemSerialSize( PHB_ITEM pItem, PHB_CYCLIC_REF * pRefPtr, ULONG ulOffset ) { ULONG ulSize, ulLen, u; HB_LONG lVal; @@ -168,29 +304,46 @@ static ULONG hb_itemSerialSize( PHB_ITEM pItem ) break; case HB_IT_ARRAY: - ulLen = hb_arrayLen( pItem ); - if( ulLen <= 255 ) - ulSize = 2; - else if( ulLen <= UINT16_MAX ) - ulSize = 3; - else + if( hb_itemSerialValueRef( pRefPtr, hb_arrayId( pItem ), ulOffset ) ) + { ulSize = 5; - for( u = 1; u <= ulLen; u++ ) - ulSize += hb_itemSerialSize( hb_arrayGetItemPtr( pItem, u ) ); + } + else + { + ulLen = hb_arrayLen( pItem ); + if( ulLen <= 255 ) + ulSize = 2; + else if( ulLen <= UINT16_MAX ) + ulSize = 3; + else + ulSize = 5; + for( u = 1; u <= ulLen; u++ ) + ulSize += hb_itemSerialSize( hb_arrayGetItemPtr( pItem, u ), + pRefPtr, ulOffset + ulSize ); + } break; case HB_IT_HASH: - ulLen = hb_hashLen( pItem ); - if( ulLen <= 255 ) - ulSize = 2; - else if( ulLen <= UINT16_MAX ) - ulSize = 3; - else - ulSize = 5; - for( u = 1; u <= ulLen; u++ ) + if( hb_itemSerialValueRef( pRefPtr, hb_hashId( pItem ), ulOffset ) ) { - ulSize += hb_itemSerialSize( hb_hashGetKeyAt( pItem, u ) ); - ulSize += hb_itemSerialSize( hb_hashGetValueAt( pItem, u ) ); + ulSize = 5; + } + else + { + ulLen = hb_hashLen( pItem ); + if( ulLen <= 255 ) + ulSize = 2; + else if( ulLen <= UINT16_MAX ) + ulSize = 3; + else + ulSize = 5; + for( u = 1; u <= ulLen; u++ ) + { + ulSize += hb_itemSerialSize( hb_hashGetKeyAt( pItem, u ), + pRefPtr, ulOffset + ulSize ); + ulSize += hb_itemSerialSize( hb_hashGetValueAt( pItem, u ), + pRefPtr, ulOffset + ulSize ); + } } break; @@ -202,10 +355,11 @@ static ULONG hb_itemSerialSize( PHB_ITEM pItem ) return ulSize; } -static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) +static ULONG hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer, + ULONG ulOffset, PHB_CYCLIC_REF pRef ) { HB_LONG lVal; - ULONG ulLen, u; + ULONG ulRef, ulLen, u; LONG l; double d; char * szVal; @@ -213,18 +367,18 @@ static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) switch( hb_itemType( pItem ) ) { case HB_IT_NIL: - *pBuffer++ = HB_SERIAL_NIL; + pBuffer[ ulOffset++ ] = HB_SERIAL_NIL; break; case HB_IT_LOGICAL: - *pBuffer++ = hb_itemGetL( pItem ) ? HB_SERIAL_TRUE : HB_SERIAL_FALSE; + pBuffer[ ulOffset++ ] = hb_itemGetL( pItem ) ? HB_SERIAL_TRUE : HB_SERIAL_FALSE; break; case HB_IT_DATE: - *pBuffer++ = HB_SERIAL_DATE; + pBuffer[ ulOffset++ ] = HB_SERIAL_DATE; l = hb_itemGetDL( pItem ); - HB_PUT_LE_UINT24( pBuffer, l ); - pBuffer += 3; + HB_PUT_LE_UINT24( &pBuffer[ ulOffset ], l ); + ulOffset += 3; break; case HB_IT_INTEGER: @@ -232,36 +386,36 @@ static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) lVal = hb_itemGetNInt( pItem ); if( lVal == 0 ) { - *pBuffer++ = HB_SERIAL_ZERO; + pBuffer[ ulOffset++ ] = HB_SERIAL_ZERO; } else if( HB_LIM_INT8( lVal ) ) { - *pBuffer++ = HB_SERIAL_INT8; - *pBuffer++ = ( UCHAR ) lVal; + pBuffer[ ulOffset++ ] = HB_SERIAL_INT8; + pBuffer[ ulOffset++ ] = ( UCHAR ) lVal; } else if( HB_LIM_INT16( lVal ) ) { - *pBuffer++ = HB_SERIAL_INT16; - HB_PUT_LE_UINT16( pBuffer, lVal ); - pBuffer += 2; + pBuffer[ ulOffset++ ] = HB_SERIAL_INT16; + HB_PUT_LE_UINT16( &pBuffer[ ulOffset ], lVal ); + ulOffset += 2; } else if( HB_LIM_INT24( lVal ) ) { - *pBuffer++ = HB_SERIAL_INT24; - HB_PUT_LE_UINT24( pBuffer, lVal ); - pBuffer += 3; + pBuffer[ ulOffset++ ] = HB_SERIAL_INT24; + HB_PUT_LE_UINT24( &pBuffer[ ulOffset ], lVal ); + ulOffset += 3; } else if( HB_LIM_INT32( lVal ) ) { - *pBuffer++ = HB_SERIAL_INT32; - HB_PUT_LE_UINT32( pBuffer, lVal ); - pBuffer += 4; + pBuffer[ ulOffset++ ] = HB_SERIAL_INT32; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], lVal ); + ulOffset += 4; } else { - *pBuffer++ = HB_SERIAL_INT64; - HB_PUT_LE_UINT64( pBuffer, lVal ); - pBuffer += 8; + pBuffer[ ulOffset++ ] = HB_SERIAL_INT64; + HB_PUT_LE_UINT64( &pBuffer[ ulOffset ], lVal ); + ulOffset += 8; } break; @@ -269,13 +423,13 @@ static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) d = hb_itemGetND( pItem ); if( d == 0.0 ) { - *pBuffer++ = HB_SERIAL_ZERO; + pBuffer[ ulOffset++ ] = HB_SERIAL_ZERO; } else { - *pBuffer++ = HB_SERIAL_DOUBLE; - HB_PUT_LE_DOUBLE( pBuffer, d ); - pBuffer += 8; + pBuffer[ ulOffset++ ] = HB_SERIAL_DOUBLE; + HB_PUT_LE_DOUBLE( &pBuffer[ ulOffset ], d ); + ulOffset += 8; } break; @@ -284,10 +438,10 @@ static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) ulLen = strlen( szVal ); if( ulLen > 0xFF ) ulLen = 0xFF; - *pBuffer++ = HB_SERIAL_SYMBOL; - *pBuffer++ = ( UCHAR ) ulLen; - memcpy( pBuffer, szVal, ulLen ); - pBuffer += ulLen; + pBuffer[ ulOffset++ ] = HB_SERIAL_SYMBOL; + pBuffer[ ulOffset++ ] = ( UCHAR ) ulLen; + memcpy( &pBuffer[ ulOffset ], szVal, ulLen ); + ulOffset += ulLen; break; case HB_IT_STRING: @@ -295,84 +449,109 @@ static UCHAR * hb_serializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) ulLen = hb_itemGetCLen( pItem ); if( ulLen <= 255 ) { - *pBuffer++ = HB_SERIAL_STRING8; - *pBuffer++ = ( UCHAR ) ulLen; + pBuffer[ ulOffset++ ] = HB_SERIAL_STRING8; + pBuffer[ ulOffset++ ] = ( UCHAR ) ulLen; } else if( ulLen <= UINT16_MAX ) { - *pBuffer++ = HB_SERIAL_STRING16; - HB_PUT_LE_UINT16( pBuffer, ulLen ); - pBuffer += 2; + pBuffer[ ulOffset++ ] = HB_SERIAL_STRING16; + HB_PUT_LE_UINT16( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 2; } else { - *pBuffer++ = HB_SERIAL_STRING32; - HB_PUT_LE_UINT32( pBuffer, ulLen ); - pBuffer += 4; + pBuffer[ ulOffset++ ] = HB_SERIAL_STRING32; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 4; } - memcpy( pBuffer, hb_itemGetCPtr( pItem ), ulLen ); - pBuffer += ulLen; + memcpy( &pBuffer[ ulOffset ], hb_itemGetCPtr( pItem ), ulLen ); + ulOffset += ulLen; break; case HB_IT_ARRAY: - ulLen = hb_arrayLen( pItem ); - if( ulLen <= 255 ) + if( hb_itemSerialValueOffset( pRef, hb_arrayId( pItem ), ulOffset, &ulRef ) ) { - *pBuffer++ = HB_SERIAL_ARRAY8; - *pBuffer++ = ( UCHAR ) ulLen; - } - else if( ulLen <= UINT16_MAX ) - { - *pBuffer++ = HB_SERIAL_ARRAY16; - HB_PUT_LE_UINT16( pBuffer, ulLen ); - pBuffer += 2; + pBuffer[ ulOffset++ ] = HB_SERIAL_REF; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], ulRef ); + ulOffset += 4; } else { - *pBuffer++ = HB_SERIAL_ARRAY32; - HB_PUT_LE_UINT32( pBuffer, ulLen ); - pBuffer += 4; + ulLen = hb_arrayLen( pItem ); + if( ulLen <= 255 ) + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_ARRAY8 : HB_SERIAL_ARRAYREF8; + pBuffer[ ulOffset++ ] = ( UCHAR ) ulLen; + } + else if( ulLen <= UINT16_MAX ) + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_ARRAY16 : HB_SERIAL_ARRAYREF16; + HB_PUT_LE_UINT16( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 2; + } + else + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_ARRAY32 : HB_SERIAL_ARRAYREF32; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 4; + } + for( u = 1; u <= ulLen; u++ ) + ulOffset = hb_serializeItem( hb_arrayGetItemPtr( pItem, u ), pBuffer, ulOffset, pRef ); } - for( u = 1; u <= ulLen; u++ ) - pBuffer = hb_serializeItem( hb_arrayGetItemPtr( pItem, u ), pBuffer ); break; case HB_IT_HASH: - ulLen = hb_hashLen( pItem ); - if( ulLen <= 255 ) + if( hb_itemSerialValueOffset( pRef, hb_hashId( pItem ), ulOffset, &ulRef ) ) { - *pBuffer++ = HB_SERIAL_HASH8; - *pBuffer++ = ( UCHAR ) ulLen; - } - else if( ulLen <= UINT16_MAX ) - { - *pBuffer++ = HB_SERIAL_HASH16; - HB_PUT_LE_UINT16( pBuffer, ulLen ); - pBuffer += 2; + pBuffer[ ulOffset++ ] = HB_SERIAL_REF; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], ulRef ); + ulOffset += 4; } else { - *pBuffer++ = HB_SERIAL_HASH32; - HB_PUT_LE_UINT32( pBuffer, ulLen ); - pBuffer += 4; - } - for( u = 1; u <= ulLen; u++ ) - { - pBuffer = hb_serializeItem( hb_hashGetKeyAt( pItem, u ), pBuffer ); - pBuffer = hb_serializeItem( hb_hashGetValueAt( pItem, u ), pBuffer ); + ulLen = hb_hashLen( pItem ); + if( ulLen <= 255 ) + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_HASH8 : HB_SERIAL_HASHREF8; + pBuffer[ ulOffset++ ] = ( UCHAR ) ulLen; + } + else if( ulLen <= UINT16_MAX ) + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_HASH16 : HB_SERIAL_HASHREF16; + HB_PUT_LE_UINT16( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 2; + } + else + { + pBuffer[ ulOffset++ ] = ulRef == HB_SERIAL_DUMMYOFFSET ? + HB_SERIAL_HASH32 : HB_SERIAL_HASHREF32; + HB_PUT_LE_UINT32( &pBuffer[ ulOffset ], ulLen ); + ulOffset += 4; + } + for( u = 1; u <= ulLen; u++ ) + { + ulOffset = hb_serializeItem( hb_hashGetKeyAt( pItem, u ), pBuffer, ulOffset, pRef ); + ulOffset = hb_serializeItem( hb_hashGetValueAt( pItem, u ), pBuffer, ulOffset, pRef ); + } } break; default: /* map to NIL */ - *pBuffer++ = HB_SERIAL_NIL; + pBuffer[ ulOffset++ ] = HB_SERIAL_NIL; break; } - return pBuffer; + return ulOffset; } -static UCHAR * hb_deserializeHash( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulLen ) +static ULONG hb_deserializeHash( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffset, + ULONG ulLen, PHB_CYCLIC_REF pRef ) { hb_hashNew( pItem ); @@ -384,34 +563,37 @@ static UCHAR * hb_deserializeHash( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulLen hb_hashPreallocate( pItem, ulLen ); while( ulLen-- ) { - pBuffer = hb_deserializeItem( pKey, pBuffer ); - pBuffer = hb_deserializeItem( pVal, pBuffer ); + ulOffset = hb_deserializeItem( pKey, pBuffer, ulOffset, pRef ); + ulOffset = hb_deserializeItem( pVal, pBuffer, ulOffset, pRef ); hb_hashAdd( pItem, pKey, pVal ); } hb_itemRelease( pKey ); hb_itemRelease( pVal ); } - return pBuffer; + return ulOffset; } -static UCHAR * hb_deserializeArray( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulLen ) +static ULONG hb_deserializeArray( PHB_ITEM pItem, UCHAR * pBuffer, ULONG ulOffset, + ULONG ulLen, PHB_CYCLIC_REF pRef ) { ULONG u; hb_arrayNew( pItem, ulLen ); for( u = 1; u <= ulLen; u++ ) - pBuffer = hb_deserializeItem( hb_arrayGetItemPtr( pItem, u ), pBuffer ); + ulOffset = hb_deserializeItem( hb_arrayGetItemPtr( pItem, u ), + pBuffer, ulOffset, pRef ); - return pBuffer; + return ulOffset; } -static UCHAR * hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) +static ULONG hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer, + ULONG ulOffset, PHB_CYCLIC_REF pRef ) { ULONG ulLen; char * szVal; - switch( *pBuffer++ ) + switch( pBuffer[ ulOffset++ ] ) { case HB_SERIAL_NIL: hb_itemClear( pItem ); @@ -430,93 +612,107 @@ static UCHAR * hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) break; case HB_SERIAL_INT8: - hb_itemPutNI( pItem, *pBuffer++ ); + hb_itemPutNI( pItem, pBuffer[ ulOffset++ ] ); break; case HB_SERIAL_INT16: - hb_itemPutNI( pItem, HB_GET_LE_INT16( pBuffer ) ); - pBuffer += 2; + hb_itemPutNI( pItem, HB_GET_LE_INT16( &pBuffer[ ulOffset ] ) ); + ulOffset += 2; break; case HB_SERIAL_INT24: - hb_itemPutNInt( pItem, HB_GET_LE_INT24( pBuffer ) ); - pBuffer += 3; + hb_itemPutNInt( pItem, HB_GET_LE_INT24( &pBuffer[ ulOffset ] ) ); + ulOffset += 3; break; case HB_SERIAL_INT32: - hb_itemPutNInt( pItem, HB_GET_LE_INT32( pBuffer ) ); - pBuffer += 4; + hb_itemPutNInt( pItem, HB_GET_LE_INT32( &pBuffer[ ulOffset ] ) ); + ulOffset += 4; break; case HB_SERIAL_INT64: - hb_itemPutNInt( pItem, HB_GET_LE_INT64( pBuffer ) ); - pBuffer += 8; + hb_itemPutNInt( pItem, HB_GET_LE_INT64( &pBuffer[ ulOffset ] ) ); + ulOffset += 8; break; case HB_SERIAL_DOUBLE: - hb_itemPutND( pItem, HB_GET_LE_DOUBLE( pBuffer ) ); - pBuffer += 8; + hb_itemPutND( pItem, HB_GET_LE_DOUBLE( &pBuffer[ ulOffset ] ) ); + ulOffset += 8; break; case HB_SERIAL_DATE: - hb_itemPutDL( pItem, HB_GET_LE_UINT24( pBuffer ) ); - pBuffer += 3; + hb_itemPutDL( pItem, HB_GET_LE_UINT24( &pBuffer[ ulOffset ] ) ); + ulOffset += 3; break; case HB_SERIAL_SYMBOL: - ulLen = *pBuffer++; - szVal = hb_strndup( ( char * ) pBuffer, ulLen ); + ulLen = pBuffer[ ulOffset++ ]; + szVal = hb_strndup( ( char * ) &pBuffer[ ulOffset ], ulLen ); hb_itemPutSymbol( pItem, hb_dynsymGetSymbol( szVal ) ); hb_xfree( szVal ); - pBuffer += ulLen; + ulOffset += ulLen; break; case HB_SERIAL_STRING8: - ulLen = *pBuffer++; - hb_itemPutCL( pItem, ( char * ) pBuffer, ulLen ); - pBuffer += ulLen; + ulLen = pBuffer[ ulOffset++ ]; + hb_itemPutCL( pItem, ( char * ) &pBuffer[ ulOffset ], ulLen ); + ulOffset += ulLen; break; case HB_SERIAL_STRING16: - ulLen = HB_GET_LE_UINT16( pBuffer ); - pBuffer += 2; - hb_itemPutCL( pItem, ( char * ) pBuffer, ulLen ); - pBuffer += ulLen; + ulLen = HB_GET_LE_UINT16( &pBuffer[ ulOffset ] ); + ulOffset += 2; + hb_itemPutCL( pItem, ( char * ) &pBuffer[ ulOffset ], ulLen ); + ulOffset += ulLen; break; case HB_SERIAL_STRING32: - ulLen = HB_GET_LE_UINT32( pBuffer ); - pBuffer += 4; - hb_itemPutCL( pItem, ( char * ) pBuffer, ulLen ); - pBuffer += ulLen; + ulLen = HB_GET_LE_UINT32( &pBuffer[ ulOffset ] ); + ulOffset += 4; + hb_itemPutCL( pItem, ( char * ) &pBuffer[ ulOffset ], ulLen ); + ulOffset += ulLen; break; + case HB_SERIAL_ARRAYREF8: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_ARRAY8: - ulLen = *pBuffer++; - pBuffer = hb_deserializeArray( pItem, pBuffer, ulLen ); + ulLen = pBuffer[ ulOffset++ ]; + ulOffset = hb_deserializeArray( pItem, pBuffer, ulOffset, ulLen, pRef ); break; + case HB_SERIAL_ARRAYREF16: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_ARRAY16: - ulLen = HB_GET_LE_UINT16( pBuffer ); - pBuffer += 2; - pBuffer = hb_deserializeArray( pItem, pBuffer, ulLen ); + ulLen = HB_GET_LE_UINT16( &pBuffer[ ulOffset ] ); + ulOffset = hb_deserializeArray( pItem, pBuffer, ulOffset + 2, ulLen, pRef ); break; + case HB_SERIAL_ARRAYREF32: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_ARRAY32: - ulLen = HB_GET_LE_UINT32( pBuffer ); - pBuffer += 4; - pBuffer = hb_deserializeArray( pItem, pBuffer, ulLen ); + ulLen = HB_GET_LE_UINT32( &pBuffer[ ulOffset ] ); + ulOffset = hb_deserializeArray( pItem, pBuffer, ulOffset + 4, ulLen, pRef ); break; + case HB_SERIAL_HASHREF8: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_HASH8: - ulLen = *pBuffer++; - pBuffer = hb_deserializeHash( pItem, pBuffer, ulLen ); + ulLen = pBuffer[ ulOffset++ ]; + ulOffset = hb_deserializeHash( pItem, pBuffer, ulOffset, ulLen, pRef ); break; + case HB_SERIAL_HASHREF16: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_HASH16: - ulLen = HB_GET_LE_UINT16( pBuffer ); - pBuffer += 2; - pBuffer = hb_deserializeHash( pItem, pBuffer, ulLen ); + ulLen = HB_GET_LE_UINT16( &pBuffer[ ulOffset ] ); + ulOffset = hb_deserializeHash( pItem, pBuffer, ulOffset + 2, ulLen, pRef ); break; + case HB_SERIAL_HASHREF32: + hb_itemSerialOffsetSet( pRef, pItem, ulOffset - 1 ); case HB_SERIAL_HASH32: - ulLen = HB_GET_LE_UINT32( pBuffer ); - pBuffer += 4; - pBuffer = hb_deserializeHash( pItem, pBuffer, ulLen ); + ulLen = HB_GET_LE_UINT32( &pBuffer[ ulOffset ] ); + ulOffset = hb_deserializeHash( pItem, pBuffer, ulOffset + 4, ulLen, pRef ); + break; + + case HB_SERIAL_REF: + hb_itemSerialOffsetGet( pRef, pItem, + HB_GET_LE_UINT32( &pBuffer[ ulOffset ] ) ); + ulOffset += 4; break; default: @@ -524,10 +720,11 @@ static UCHAR * hb_deserializeItem( PHB_ITEM pItem, UCHAR * pBuffer ) break; } - return pBuffer; + return ulOffset; } -static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) +static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize, + ULONG ulOffset, PHB_CYCLIC_REF * pRefPtr ) { UCHAR * pBuffer = * pBufferPtr; ULONG ulSize = * pulSize, ulLen = 0; @@ -567,6 +764,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) case HB_SERIAL_STRING32: ulSize = 1 + ( ulSize >= 5 ? HB_GET_LE_UINT32( pBuffer ) : ulSize ); break; + case HB_SERIAL_ARRAYREF8: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_ARRAY8: if( ulSize >= 2 ) { @@ -576,6 +776,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_ARRAYREF16: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_ARRAY16: if( ulSize >= 3 ) { @@ -585,6 +788,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_ARRAYREF32: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_ARRAY32: if( ulSize >= 5 ) { @@ -594,6 +800,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_HASHREF8: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_HASH8: if( ulSize >= 2 ) { @@ -603,6 +812,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_HASHREF16: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_HASH16: if( ulSize >= 3 ) { @@ -612,6 +824,9 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_HASHREF32: + if( hb_itemSerialOffsetRef( pRefPtr, NULL, ulOffset ) ) + return FALSE; case HB_SERIAL_HASH32: if( ulSize >= 5 ) { @@ -621,6 +836,11 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) else ulSize++; break; + case HB_SERIAL_REF: + if( !hb_itemSerialOffsetRef( pRefPtr, NULL, HB_GET_LE_UINT32( pBuffer ) ) ) + return FALSE; + ulSize = 5; + break; default: ulSize = 1; break; @@ -634,8 +854,11 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) while( ulLen ) { - if( !hb_deserializeTest( pBufferPtr, pulSize ) ) + ulOffset += ulSize; + ulSize = * pulSize; + if( !hb_deserializeTest( pBufferPtr, pulSize, ulOffset, pRefPtr ) ) return FALSE; + ulOffset += ulSize - * pulSize; --ulLen; } @@ -647,14 +870,18 @@ static BOOL hb_deserializeTest( UCHAR ** pBufferPtr, ULONG * pulSize ) */ static char * hb_itemSerial( PHB_ITEM pItem, ULONG *pulSize ) { - ULONG ulSize = hb_itemSerialSize( pItem ); + PHB_CYCLIC_REF pRef = NULL; + ULONG ulSize = hb_itemSerialSize( pItem, &pRef, 0 ); UCHAR * pBuffer = ( UCHAR * ) hb_xgrab( ulSize + 1 ); - hb_serializeItem( pItem, pBuffer ); + hb_itemSerialUnRefFree( &pRef ); + hb_serializeItem( pItem, pBuffer, 0, pRef ); pBuffer[ ulSize ] = '\0'; if( pulSize ) *pulSize = ulSize; + hb_itemSerialRefFree( pRef ); + return ( char * ) pBuffer; } @@ -663,14 +890,16 @@ static char * hb_itemSerial( PHB_ITEM pItem, ULONG *pulSize ) */ static PHB_ITEM hb_itemDeSerial( char ** pBufferPtr, ULONG * pulSize ) { + PHB_CYCLIC_REF pRef = NULL; UCHAR * pBuffer = ( UCHAR * ) *pBufferPtr; PHB_ITEM pItem = NULL; - if( !pulSize || hb_deserializeTest( ( UCHAR ** ) pBufferPtr, pulSize ) ) + if( !pulSize || hb_deserializeTest( ( UCHAR ** ) pBufferPtr, pulSize, 0, &pRef ) ) { pItem = hb_itemNew( NULL ); - hb_deserializeItem( pItem, pBuffer ); + hb_deserializeItem( pItem, pBuffer, 0, pRef ); } + hb_itemSerialRefFree( pRef ); return pItem; } @@ -703,7 +932,7 @@ HB_FUNC( HB_DESERIALIZE ) if( pParam ) { hb_itemPutCL( pItem, pBuffer, ulSize ); - hb_itemCopy( pParam, pItem ); + hb_itemMove( pParam, pItem ); } hb_itemRelease( pItem ); } diff --git a/harbour/source/vm/hashes.c b/harbour/source/vm/hashes.c index 2a7b54aea3..d68bb63bec 100644 --- a/harbour/source/vm/hashes.c +++ b/harbour/source/vm/hashes.c @@ -580,6 +580,17 @@ HB_EXPORT BOOL hb_hashDelAt( PHB_ITEM pHash, ULONG ulPos ) return FALSE; } +/* retrives the hash unique ID */ +HB_EXPORT void * hb_hashId( PHB_ITEM pHash ) +{ + HB_TRACE(HB_TR_DEBUG, ("hb_hashId(%p)", pHash)); + + if( HB_IS_HASH( pHash ) ) + return ( void * ) pHash->item.asHash.value; + else + return NULL; +} + void hb_hashCloneBody( PHB_ITEM pHash, PHB_ITEM pDest, PHB_NESTED_CLONED pClonedList ) { ULONG ulPos;