diff --git a/ChangeLog.txt b/ChangeLog.txt index 135bbb3996..9fde8a1f04 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -10,6 +10,38 @@ * Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment */ +2013-12-23 17:11 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) + * include/hbapicdp.h + * include/hbapiitm.h + * src/rtl/itemseri.c + * changed 2-nd parameter in hb_itemSerialize() and hb_itemSerializeCP() + from HB_BOOL fNumSize parameter to int iFlags. + Previous fNumSize is replaced by HB_SERIALIZE_NUMSIZE flag. + Warning: declaration is not backward compatible though existing code + using these functions is binary compatible so it will work + without recompilation. + + added support for optional compression of serialized values. + It can be enabled in C code by HB_SERIALIZE_COMPRESS flag. + + added support for serialization flags passed in 2-nd parameter to + hb_Serialize() PRG function. + ; Info: support for compression and decompression exists only in + programs which are linked with ZLIB library. Programmers + which want to use it and so far the haven't used ZLIB functions + should add to their code REQUEST HB_ZCOMPRESS + + * include/Makefile + + include/hbserial.ch + + added header file with Harbour serialization flags. + Now the following flags are supported: + HB_SERIALIZE_NUMSIZE + HB_SERIALIZE_COMPRESS + I'll add support for HB_SERIALIZE_OBJECTSTRUCT soon. + + * src/rtl/hbi18n1.c + * contrib/hbnetio/netiocli.c + * contrib/hbnetio/netiosrv.c + * updated to use new Harbour serialization flags. + 2013-12-20 00:24 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl) * include/hbexpra.c ! fixed silly copy and past typo diff --git a/contrib/hbnetio/netiocli.c b/contrib/hbnetio/netiocli.c index 7705a76587..ad937bf128 100644 --- a/contrib/hbnetio/netiocli.c +++ b/contrib/hbnetio/netiocli.c @@ -88,6 +88,7 @@ #include "hbstack.h" #include "hbthread.h" #include "netio.h" +#include "hbserial.ch" /* * client code @@ -1127,7 +1128,7 @@ static const char * s_netio_params( int iParam, int iMsg, const char * pszName, while( ++iParam <= iPCount ) { - itmData = hb_itemSerialize( hb_param( iParam, HB_IT_ANY ), HB_TRUE, &itmSize ); + itmData = hb_itemSerialize( hb_param( iParam, HB_IT_ANY ), HB_SERIALIZE_NUMSIZE, &itmSize ); if( data == NULL ) data = ( char * ) memcpy( hb_xgrab( size + itmSize ), pszName, size ); else diff --git a/contrib/hbnetio/netiosrv.c b/contrib/hbnetio/netiosrv.c index 8dfaaf0281..888792bb14 100644 --- a/contrib/hbnetio/netiosrv.c +++ b/contrib/hbnetio/netiosrv.c @@ -84,6 +84,7 @@ #include "hbthread.h" #include "hbdate.h" #include "netio.h" +#include "hbserial.ch" /* @@ -1241,7 +1242,7 @@ HB_FUNC( NETIO_SERVER ) { HB_SIZE itmSize; PHB_ITEM pResult = hb_stackReturnItem(); - char * itmData = hb_itemSerialize( pResult, HB_TRUE, &itmSize ); + char * itmData = hb_itemSerialize( pResult, HB_SERIALIZE_NUMSIZE, &itmSize ); if( itmSize <= sizeof( buffer ) - NETIO_MSGLEN ) msg = buffer; else if( ! ptr || itmSize > ( HB_SIZE ) size - NETIO_MSGLEN ) @@ -1339,7 +1340,7 @@ HB_FUNC( NETIO_SRVSENDITEM ) HB_SIZE nLen; long lLen; - itmData = hb_itemSerialize( pItem, HB_TRUE, &nLen ); + itmData = hb_itemSerialize( pItem, HB_SERIALIZE_NUMSIZE, &nLen ); lLen = ( long ) nLen; msg = ( char * ) hb_xgrab( lLen + NETIO_MSGLEN ); HB_PUT_LE_UINT32( &msg[ 0 ], NETIO_SRVITEM ); diff --git a/include/Makefile b/include/Makefile index 9e1e538b35..6c3b8369f3 100644 --- a/include/Makefile +++ b/include/Makefile @@ -125,6 +125,7 @@ PRG_HEADERS := \ hbmemvar.ch \ hboo.ch \ hbpers.ch \ + hbserial.ch \ hbsetup.ch \ hbsix.ch \ hbsocket.ch \ diff --git a/include/hbapicdp.h b/include/hbapicdp.h index b4763c157e..00047ac41c 100644 --- a/include/hbapicdp.h +++ b/include/hbapicdp.h @@ -497,7 +497,7 @@ extern HB_EXPORT HB_BOOL hb_cdpUTF8ToU16NextChar( HB_UCHAR ucChar, int * n, extern HB_EXPORT PHB_ITEM hb_itemDeserializeCP( const char ** pBufferPtr, HB_SIZE * pnSize, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut ); -extern HB_EXPORT char * hb_itemSerializeCP( PHB_ITEM pItem, HB_BOOL fNumSize, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, HB_SIZE * pnSize ); +extern HB_EXPORT char * hb_itemSerializeCP( PHB_ITEM pItem, int iFlags, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, HB_SIZE * pnSize ); extern HB_EXPORT HB_WCHAR hb_cdpUpperWC( PHB_CODEPAGE cdp, HB_WCHAR wc ); diff --git a/include/hbapiitm.h b/include/hbapiitm.h index bea091b76a..5bc176a1d4 100644 --- a/include/hbapiitm.h +++ b/include/hbapiitm.h @@ -180,7 +180,7 @@ extern HB_EXPORT PHB_ITEM hb_itemValToStr ( PHB_ITEM pItem ); /* Convert an extern HB_EXPORT char * hb_itemPadConv ( PHB_ITEM pItem, HB_SIZE * pnSize, HB_BOOL * bFreeReq ); extern HB_EXPORT void hb_itemSwap ( PHB_ITEM pItem1, PHB_ITEM pItem2 ); -extern HB_EXPORT char * hb_itemSerialize( PHB_ITEM pItem, HB_BOOL fNumSize, HB_SIZE * pnSize ); +extern HB_EXPORT char * hb_itemSerialize( PHB_ITEM pItem, int iFlags, HB_SIZE * pnSize ); extern HB_EXPORT PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, HB_SIZE * pnSize ); #if defined( _HB_API_INTERNAL_ ) diff --git a/include/hbserial.ch b/include/hbserial.ch new file mode 100644 index 0000000000..906ef81c36 --- /dev/null +++ b/include/hbserial.ch @@ -0,0 +1,58 @@ +/* + * Harbour Project source code: + * header file for item serialization flags + * + * Copyright 2013 Przemyslaw Czerpak + * www - http://harbour-project.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; see the file COPYING.txt. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). + * + * As a special exception, the Harbour Project gives permission for + * additional uses of the text contained in its release of Harbour. + * + * The exception is that, if you link the Harbour libraries with other + * files to produce an executable, this does not by itself cause the + * resulting executable to be covered by the GNU General Public License. + * Your use of that executable is in no way restricted on account of + * linking the Harbour library code into it. + * + * This exception does not however invalidate any other reasons why + * the executable file might be covered by the GNU General Public License. + * + * This exception applies only to the code released by the Harbour + * Project under the name Harbour. If you copy code from other + * Harbour Project or Free Software Foundation releases into a copy of + * Harbour, as the General Public License permits, the exception does + * not apply to the code that you add in this way. To avoid misleading + * anyone as to the status of such modified files, you must delete + * this exception notice from them. + * + * If you write modifications of your own for Harbour, it is your choice + * whether to permit this exception to apply to your modifications. + * If you do not wish that, delete this exception notice. + * + */ + +/* NOTE: This file is also used by C code. */ + +#ifndef HB_SERIAL_CH_ +#define HB_SERIAL_CH_ + +#define HB_SERIALIZE_NUMSIZE 0x01 +#define HB_SERIALIZE_OBJECTSTRUCT 0x02 +#define HB_SERIALIZE_COMPRESS 0x04 + +#endif /* HB_SERIAL_CH_ */ diff --git a/src/rtl/hbi18n1.c b/src/rtl/hbi18n1.c index 0bf1c83147..f442327d72 100644 --- a/src/rtl/hbi18n1.c +++ b/src/rtl/hbi18n1.c @@ -443,7 +443,7 @@ static PHB_ITEM hb_i18n_serialize( PHB_I18N_TRANS pI18N ) { HB_SIZE nSize; HB_U32 ulCRC; - char * pBuffer = hb_itemSerialize( pI18N->table, HB_FALSE, &nSize ); + char * pBuffer = hb_itemSerialize( pI18N->table, 0, &nSize ); char * pI18Nbuffer; PHB_ITEM pKey, pValue; diff --git a/src/rtl/itemseri.c b/src/rtl/itemseri.c index abf256e2fc..bdd7f0839d 100644 --- a/src/rtl/itemseri.c +++ b/src/rtl/itemseri.c @@ -50,9 +50,11 @@ #include "hbapiitm.h" #include "hbapicls.h" #include "hbapicdp.h" - +#include "hbapierr.h" +#include "hbzlib.h" #include "hbvm.h" #include "hbstack.h" +#include "hbserial.ch" /* @@ -99,6 +101,7 @@ HB_UCHAR [ 1 ] - item type 39. TIMESTAMP 8 40. HASHFLAGS 2 41. HASHDEFAULT VALUE 0 + 42. ZCOMPRESS 4+4+n xHarbour types HB_SERIAL_XHB_*: 67. 'C' 8+n @@ -164,6 +167,7 @@ complex ones: #define HB_SERIAL_TIMESTAMP 39 #define HB_SERIAL_HASHFLAGS 40 #define HB_SERIAL_HASHDEFVAL 41 +#define HB_SERIAL_ZCOMPRESS 42 /* xHarbour types */ #define HB_SERIAL_XHB_A 65 #define HB_SERIAL_XHB_B 66 @@ -376,7 +380,7 @@ static void hb_itemSerialRefFree( PHB_CYCLIC_REF pRef ) } } -static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, +static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, int iFlags, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, PHB_CYCLIC_REF * pRefPtr, HB_SIZE nOffset ) { @@ -408,7 +412,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, case HB_IT_LONG: lVal = hb_itemGetNInt( pItem ); if( lVal == 0 ) - nSize = fNumSize ? 2 : 1; + nSize = ( iFlags & HB_SERIALIZE_NUMSIZE ) ? 2 : 1; else if( HB_LIM_INT8( lVal ) ) nSize = 2; else if( HB_LIM_INT16( lVal ) ) @@ -419,12 +423,12 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, nSize = 5; else nSize = 9; - if( fNumSize ) + if( iFlags & HB_SERIALIZE_NUMSIZE ) nSize++; break; case HB_IT_DOUBLE: - if( fNumSize ) + if( iFlags & HB_SERIALIZE_NUMSIZE ) nSize = 11; else nSize = ( hb_itemGetND( pItem ) == 0.0 ) ? 1 : 9; @@ -480,7 +484,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, else nSize += 5; for( u = 1; u <= nLen; u++ ) - nSize += hb_itemSerialSize( hb_arrayGetItemPtr( pItem, u ), fNumSize, + nSize += hb_itemSerialSize( hb_arrayGetItemPtr( pItem, u ), iFlags, cdpIn, cdpOut, pRefPtr, nOffset + nSize ); } break; @@ -500,7 +504,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, if( pDefVal ) { nSize++; - nSize += hb_itemSerialSize( pDefVal, fNumSize, + nSize += hb_itemSerialSize( pDefVal, iFlags, cdpIn, cdpOut, pRefPtr, nOffset + nSize ); } nLen = hb_hashLen( pItem ); @@ -512,9 +516,9 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, nSize += 5; for( u = 1; u <= nLen; u++ ) { - nSize += hb_itemSerialSize( hb_hashGetKeyAt( pItem, u ), fNumSize, + nSize += hb_itemSerialSize( hb_hashGetKeyAt( pItem, u ), iFlags, cdpIn, cdpOut, pRefPtr, nOffset + nSize ); - nSize += hb_itemSerialSize( hb_hashGetValueAt( pItem, u ), fNumSize, + nSize += hb_itemSerialSize( hb_hashGetValueAt( pItem, u ), iFlags, cdpIn, cdpOut, pRefPtr, nOffset + nSize ); } } @@ -528,7 +532,7 @@ static HB_SIZE hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, return nSize; } -static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, +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 ) @@ -572,7 +576,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, case HB_IT_INTEGER: case HB_IT_LONG: lVal = hb_itemGetNInt( pItem ); - if( fNumSize ) + if( iFlags & HB_SERIALIZE_NUMSIZE ) { hb_itemGetNLen( pItem, &iWidth, NULL ); if( HB_LIM_INT8( lVal ) ) @@ -643,7 +647,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, case HB_IT_DOUBLE: d = hb_itemGetND( pItem ); - if( fNumSize ) + if( iFlags & HB_SERIALIZE_NUMSIZE ) { hb_itemGetNLen( pItem, &iWidth, &iDecimal ); pBuffer[ nOffset++ ] = HB_SERIAL_DBLNUM; @@ -798,7 +802,7 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, nOffset += 4; } for( n = 1; n <= nLen; n++ ) - nOffset = hb_serializeItem( hb_arrayGetItemPtr( pItem, n ), fNumSize, + nOffset = hb_serializeItem( hb_arrayGetItemPtr( pItem, n ), iFlags, cdpIn, cdpOut, pBuffer, nOffset, pRef ); } break; @@ -812,19 +816,19 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, } else { - int iFlags = hb_hashGetFlags( pItem ); + int iHashFlags = hb_hashGetFlags( pItem ); PHB_ITEM pDefVal = hb_hashGetDefault( pItem ); - if( ( iFlags & ~HB_HASH_RESORT ) != HB_HASH_FLAG_DEFAULT ) + if( ( iHashFlags & ~HB_HASH_RESORT ) != HB_HASH_FLAG_DEFAULT ) { pBuffer[ nOffset++ ] = HB_SERIAL_HASHFLAGS; - HB_PUT_LE_UINT16( &pBuffer[ nOffset ], iFlags ); + HB_PUT_LE_UINT16( &pBuffer[ nOffset ], iHashFlags ); nOffset += 2; } if( pDefVal ) { pBuffer[ nOffset++ ] = HB_SERIAL_HASHDEFVAL; - nOffset = hb_serializeItem( pDefVal, fNumSize, + nOffset = hb_serializeItem( pDefVal, iHashFlags, cdpIn, cdpOut, pBuffer, nOffset, pRef ); } nLen = hb_hashLen( pItem ); @@ -850,9 +854,9 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, } for( n = 1; n <= nLen; n++ ) { - nOffset = hb_serializeItem( hb_hashGetKeyAt( pItem, n ), fNumSize, + nOffset = hb_serializeItem( hb_hashGetKeyAt( pItem, n ), iFlags, cdpIn, cdpOut, pBuffer, nOffset, pRef ); - nOffset = hb_serializeItem( hb_hashGetValueAt( pItem, n ), fNumSize, + nOffset = hb_serializeItem( hb_hashGetValueAt( pItem, n ), iFlags, cdpIn, cdpOut, pBuffer, nOffset, pRef ); } } @@ -867,6 +871,283 @@ static HB_SIZE hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, return nOffset; } +static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSize, + HB_SIZE nOffset, PHB_CYCLIC_REF * pRefPtr ) +{ + const HB_UCHAR * pBuffer = *pBufferPtr; + HB_SIZE nSize = *pnSize, nLen = 0; + + if( nSize == 0 ) + return HB_FALSE; + + switch( *pBuffer++ ) + { + case HB_SERIAL_NIL: + case HB_SERIAL_TRUE: + case HB_SERIAL_FALSE: + case HB_SERIAL_ZERO: + case HB_SERIAL_STRNUL: + nSize = 1; + break; + case HB_SERIAL_INT8: + nSize = 2; + break; + case HB_SERIAL_INT8NUM: + case HB_SERIAL_INT16: + nSize = 3; + break; + case HB_SERIAL_INT16NUM: + case HB_SERIAL_INT24: + case HB_SERIAL_DATE: + nSize = 4; + break; + case HB_SERIAL_INT24NUM: + case HB_SERIAL_INT32: + nSize = 5; + break; + case HB_SERIAL_INT32NUM: + nSize = 6; + break; + case HB_SERIAL_INT64: + case HB_SERIAL_DOUBLE: + case HB_SERIAL_TIMESTAMP: + nSize = 9; + break; + case HB_SERIAL_INT64NUM: + nSize = 10; + break; + case HB_SERIAL_DBLNUM: + nSize = 11; + break; + case HB_SERIAL_SYMBOL: + case HB_SERIAL_STRING8: + nSize = 2 + ( nSize >= 2 ? *pBuffer : nSize ); + break; + case HB_SERIAL_STRING16: + nSize = 3 + ( nSize >= 3 ? HB_GET_LE_UINT16( pBuffer ) : nSize ); + break; + case HB_SERIAL_STRING32: + nSize = 5 + ( nSize >= 5 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); + break; + case HB_SERIAL_STRPAD8: + nSize = 3 + ( nSize >= 3 ? *pBuffer : nSize ); + break; + case HB_SERIAL_STRPAD16: + nSize = 5 + ( nSize >= 5 ? HB_GET_LE_UINT16( pBuffer ) : nSize ); + break; + case HB_SERIAL_STRPAD32: + nSize = 9 + ( nSize >= 9 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); + break; + case HB_SERIAL_ARRAYREF8: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_ARRAY8: + if( nSize >= 2 ) + { + nSize = 2; + nLen = *pBuffer; + } + else + nSize++; + break; + case HB_SERIAL_ARRAYREF16: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_ARRAY16: + if( nSize >= 3 ) + { + nSize = 3; + nLen = HB_GET_LE_UINT16( pBuffer ); + } + else + nSize++; + break; + case HB_SERIAL_ARRAYREF32: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_ARRAY32: + if( nSize >= 5 ) + { + nSize = 5; + nLen = HB_GET_LE_UINT32( pBuffer ); + } + else + nSize++; + break; + case HB_SERIAL_HASHREF8: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_HASH8: + if( nSize >= 2 ) + { + nSize = 2; + nLen = *pBuffer << 1; + } + else + nSize++; + break; + case HB_SERIAL_HASHREF16: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_HASH16: + if( nSize >= 3 ) + { + nSize = 3; + nLen = HB_GET_LE_UINT16( pBuffer ) << 1; + } + else + nSize++; + break; + case HB_SERIAL_HASHREF32: + if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) + return HB_FALSE; + case HB_SERIAL_HASH32: + if( nSize >= 5 ) + { + nSize = 5; + nLen = HB_GET_LE_UINT32( pBuffer ) << 1; + } + else + nSize++; + break; + case HB_SERIAL_REF: + if( ! hb_itemSerialOffsetRef( pRefPtr, HB_GET_LE_UINT32( pBuffer ) ) ) + return HB_FALSE; + nSize = 5; + break; + case HB_SERIAL_OBJ: + nLen = hb_strnlen( ( const char * ) pBuffer, nSize - 1 ) + 1; + if( nLen >= nSize ) + nSize++; + else + { + nLen += hb_strnlen( ( const char * ) pBuffer + nLen, nSize - nLen - 1 ) + 2; + if( nLen >= nSize ) + nSize++; + else + nSize = nLen; + } + nLen = 1; + break; + case HB_SERIAL_HASHFLAGS: + nSize = 3; + nLen = 1; + break; + case HB_SERIAL_HASHDEFVAL: + nSize = 1; + nLen = 2; + break; + case HB_SERIAL_ZCOMPRESS: + nSize = 9 + ( nSize >= 9 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); + break; + + /* xHarbour types */ + case HB_SERIAL_XHB_C: + nSize = 9 + ( nSize >= 9 ? ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) : nSize ); + break; + case HB_SERIAL_XHB_L: + nSize = 2; + break; + case HB_SERIAL_XHB_N: + if( nSize >= 2 && *pBuffer == 'X' ) + /* this is workaround for bug in xHarbour serialization code */ + nSize = 20; + else + nSize = 10; + break; + case HB_SERIAL_XHB_D: + case HB_SERIAL_XHB_T: + nSize = 9; + break; + case HB_SERIAL_XHB_Z: + nSize = 1; + break; + case HB_SERIAL_XHB_A: + if( nSize >= 9 ) + { + nSize = 9; + nLen = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ); + } + else + nSize++; + break; + case HB_SERIAL_XHB_B: + nSize = 1; + nLen = 1; + break; + case HB_SERIAL_XHB_H: + if( nSize >= 9 ) + { + nSize = 9; + nLen = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) << 1; + } + else + nSize++; + break; + case HB_SERIAL_XHB_O: + if( nSize >= 9 ) + { + nSize = 9; + nLen = ( ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) << 1 ) + 1; + } + else + nSize++; + break; + case HB_SERIAL_XHB_Q: + if( nSize >= 18 && pBuffer[ 8 ] == HB_SERIAL_XHB_C ) + { + HB_SIZE nData = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ); + if( nData >= 9 && nData - 9 >= + ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ 9 ] ) ) + nSize = 9 + nData; + else + nSize++; + } + else + nSize++; + nSize = 9 + ( nSize >= 9 ? ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) : nSize ); + break; + case HB_SERIAL_XHB_R: + if( nSize++ >= 10 ) + { + switch( pBuffer[ 0 ] ) + { + case HB_SERIAL_XHB_A: + case HB_SERIAL_XHB_H: + case HB_SERIAL_XHB_O: + hb_itemSerialTypedRef( pRefPtr, pBuffer[ 0 ], + ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ 1 ] ) ); + case HB_SERIAL_XHB_B: + nSize = 10; + break; + } + } + break; + + default: + nSize = 1; + break; + } + + if( nSize > *pnSize ) + return HB_FALSE; + + *pnSize -= nSize; + *pBufferPtr += nSize; + + while( nLen ) + { + nOffset += nSize; + nSize = *pnSize; + if( ! hb_deserializeTest( pBufferPtr, pnSize, nOffset, pRefPtr ) ) + return HB_FALSE; + nSize -= *pnSize; + --nLen; + } + + return HB_TRUE; +} + static HB_SIZE hb_deserializeHash( PHB_ITEM pItem, PHB_CODEPAGE cdpIn, PHB_CODEPAGE cdpOut, const HB_UCHAR * pBuffer, HB_SIZE nOffset, @@ -1162,13 +1443,13 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, case HB_SERIAL_HASHFLAGS: { - int iFlags = HB_GET_LE_UINT16( &pBuffer[ nOffset ] ); + int iHashFlags = HB_GET_LE_UINT16( &pBuffer[ nOffset ] ); nOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, nOffset + 2, pRef ); hb_hashClearFlags( pItem, HB_HASH_FLAG_MASK ); - if( ( iFlags & ( HB_HASH_KEEPORDER | HB_HASH_BINARY ) ) != HB_HASH_BINARY ) - iFlags |= HB_HASH_RESORT; - hb_hashSetFlags( pItem, iFlags ); + if( ( iHashFlags & ( HB_HASH_KEEPORDER | HB_HASH_BINARY ) ) != HB_HASH_BINARY ) + iHashFlags |= HB_HASH_RESORT; + hb_hashSetFlags( pItem, iHashFlags ); break; } @@ -1184,6 +1465,35 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, break; } + case HB_SERIAL_ZCOMPRESS: + nSize = HB_GET_LE_UINT32( &pBuffer[ nOffset ] ); + nOffset += 4; + nLen = HB_GET_LE_UINT32( &pBuffer[ nOffset ] ); + nOffset += 4; + szVal = ( char * ) hb_xgrab( nLen + 1 ); + if( hb_zlibUncompress( szVal, &nLen, ( const char * ) &pBuffer[ nOffset ], + nSize ) == HB_ZLIB_RES_OK ) + { + PHB_CYCLIC_REF pRefZ = NULL; + pBuffer = ( const HB_UCHAR * ) szVal; + if( hb_deserializeTest( &pBuffer, &nLen, 0, &pRefZ ) ) + hb_deserializeItem( pItem, cdpIn, cdpOut, ( const HB_UCHAR * ) szVal, 0, pRefZ ); + else + hb_itemClear( pItem ); + hb_itemSerialRefFree( pRefZ ); + } + else if( hb_vmRequestQuery() == 0 ) + { + hb_itemPutCLPtr( pItem, szVal, nLen ); + hb_errRT_BASE_Ext1( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, 0, EF_CANDEFAULT, 1, pItem ); + hb_itemClear( pItem ); + szVal = NULL; + } + if( szVal ) + hb_xfree( szVal ); + nOffset += nSize; + break; + /* xHarbour types */ case HB_SERIAL_XHB_C: nSize = nLen = ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ nOffset ] ); @@ -1344,333 +1654,51 @@ static HB_SIZE hb_deserializeItem( PHB_ITEM pItem, return nOffset; } -static HB_BOOL hb_deserializeTest( const HB_UCHAR ** pBufferPtr, HB_SIZE * pnSize, - HB_SIZE nOffset, PHB_CYCLIC_REF * pRefPtr ) -{ - const HB_UCHAR * pBuffer = *pBufferPtr; - HB_SIZE nSize = *pnSize, nLen = 0; - - if( nSize == 0 ) - return HB_FALSE; - - switch( *pBuffer++ ) - { - case HB_SERIAL_NIL: - case HB_SERIAL_TRUE: - case HB_SERIAL_FALSE: - case HB_SERIAL_ZERO: - case HB_SERIAL_STRNUL: - nSize = 1; - break; - case HB_SERIAL_INT8: - nSize = 2; - break; - case HB_SERIAL_INT8NUM: - case HB_SERIAL_INT16: - nSize = 3; - break; - case HB_SERIAL_INT16NUM: - case HB_SERIAL_INT24: - case HB_SERIAL_DATE: - nSize = 4; - break; - case HB_SERIAL_INT24NUM: - case HB_SERIAL_INT32: - nSize = 5; - break; - case HB_SERIAL_INT32NUM: - nSize = 6; - break; - case HB_SERIAL_INT64: - case HB_SERIAL_DOUBLE: - case HB_SERIAL_TIMESTAMP: - nSize = 9; - break; - case HB_SERIAL_INT64NUM: - nSize = 10; - break; - case HB_SERIAL_DBLNUM: - nSize = 11; - break; - case HB_SERIAL_SYMBOL: - case HB_SERIAL_STRING8: - nSize = 2 + ( nSize >= 2 ? *pBuffer : nSize ); - break; - case HB_SERIAL_STRING16: - nSize = 3 + ( nSize >= 3 ? HB_GET_LE_UINT16( pBuffer ) : nSize ); - break; - case HB_SERIAL_STRING32: - nSize = 5 + ( nSize >= 5 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); - break; - case HB_SERIAL_STRPAD8: - nSize = 3 + ( nSize >= 3 ? *pBuffer : nSize ); - break; - case HB_SERIAL_STRPAD16: - nSize = 5 + ( nSize >= 5 ? HB_GET_LE_UINT16( pBuffer ) : nSize ); - break; - case HB_SERIAL_STRPAD32: - nSize = 9 + ( nSize >= 9 ? HB_GET_LE_UINT32( pBuffer ) : nSize ); - break; - case HB_SERIAL_ARRAYREF8: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_ARRAY8: - if( nSize >= 2 ) - { - nSize = 2; - nLen = *pBuffer; - } - else - nSize++; - break; - case HB_SERIAL_ARRAYREF16: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_ARRAY16: - if( nSize >= 3 ) - { - nSize = 3; - nLen = HB_GET_LE_UINT16( pBuffer ); - } - else - nSize++; - break; - case HB_SERIAL_ARRAYREF32: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_ARRAY32: - if( nSize >= 5 ) - { - nSize = 5; - nLen = HB_GET_LE_UINT32( pBuffer ); - } - else - nSize++; - break; - case HB_SERIAL_HASHREF8: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_HASH8: - if( nSize >= 2 ) - { - nSize = 2; - nLen = *pBuffer << 1; - } - else - nSize++; - break; - case HB_SERIAL_HASHREF16: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_HASH16: - if( nSize >= 3 ) - { - nSize = 3; - nLen = HB_GET_LE_UINT16( pBuffer ) << 1; - } - else - nSize++; - break; - case HB_SERIAL_HASHREF32: - if( hb_itemSerialOffsetRef( pRefPtr, nOffset ) ) - return HB_FALSE; - case HB_SERIAL_HASH32: - if( nSize >= 5 ) - { - nSize = 5; - nLen = HB_GET_LE_UINT32( pBuffer ) << 1; - } - else - nSize++; - break; - case HB_SERIAL_REF: - if( ! hb_itemSerialOffsetRef( pRefPtr, HB_GET_LE_UINT32( pBuffer ) ) ) - return HB_FALSE; - nSize = 5; - break; - case HB_SERIAL_OBJ: - nLen = hb_strnlen( ( const char * ) pBuffer, nSize - 1 ) + 1; - if( nLen >= nSize ) - nSize++; - else - { - nLen += hb_strnlen( ( const char * ) pBuffer + nLen, nSize - nLen - 1 ) + 2; - if( nLen >= nSize ) - nSize++; - else - nSize = nLen; - } - nLen = 1; - break; - case HB_SERIAL_HASHFLAGS: - nSize = 3; - nLen = 1; - break; - case HB_SERIAL_HASHDEFVAL: - nSize = 1; - nLen = 2; - break; - - /* xHarbour types */ - case HB_SERIAL_XHB_C: - nSize = 9 + ( nSize >= 9 ? ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) : nSize ); - break; - case HB_SERIAL_XHB_L: - nSize = 2; - break; - case HB_SERIAL_XHB_N: - if( nSize >= 2 && *pBuffer == 'X' ) - /* this is workaround for bug in xHarbour serialization code */ - nSize = 20; - else - nSize = 10; - break; - case HB_SERIAL_XHB_D: - case HB_SERIAL_XHB_T: - nSize = 9; - break; - case HB_SERIAL_XHB_Z: - nSize = 1; - break; - case HB_SERIAL_XHB_A: - if( nSize >= 9 ) - { - nSize = 9; - nLen = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ); - } - else - nSize++; - break; - case HB_SERIAL_XHB_B: - nSize = 1; - nLen = 1; - break; - case HB_SERIAL_XHB_H: - if( nSize >= 9 ) - { - nSize = 9; - nLen = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) << 1; - } - else - nSize++; - break; - case HB_SERIAL_XHB_O: - if( nSize >= 9 ) - { - nSize = 9; - nLen = ( ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) << 1 ) + 1; - } - else - nSize++; - break; - case HB_SERIAL_XHB_Q: - if( nSize >= 18 && pBuffer[ 8 ] == HB_SERIAL_XHB_C ) - { - HB_SIZE nData = ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ); - if( nData >= 9 && nData - 9 >= - ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ 9 ] ) ) - nSize = 9 + nData; - else - nSize++; - } - else - nSize++; - nSize = 9 + ( nSize >= 9 ? ( HB_SIZE ) HB_GET_BE_UINT64( pBuffer ) : nSize ); - break; - case HB_SERIAL_XHB_R: - if( nSize++ >= 10 ) - { - switch( pBuffer[ 0 ] ) - { - case HB_SERIAL_XHB_A: - case HB_SERIAL_XHB_H: - case HB_SERIAL_XHB_O: - hb_itemSerialTypedRef( pRefPtr, pBuffer[ 0 ], - ( HB_SIZE ) HB_GET_BE_UINT64( &pBuffer[ 1 ] ) ); - case HB_SERIAL_XHB_B: - nSize = 10; - break; - } - } - break; - - default: - nSize = 1; - break; - } - - if( nSize > *pnSize ) - return HB_FALSE; - - *pnSize -= nSize; - *pBufferPtr += nSize; - - while( nLen ) - { - nOffset += nSize; - nSize = *pnSize; - if( ! hb_deserializeTest( pBufferPtr, pnSize, nOffset, pRefPtr ) ) - return HB_FALSE; - nSize -= *pnSize; - --nLen; - } - - return HB_TRUE; -} - /* * public API functions */ -char * hb_itemSerialize( PHB_ITEM pItem, HB_BOOL fNumSize, HB_SIZE *pnSize ) -{ - PHB_CYCLIC_REF pRef = NULL; - HB_SIZE nSize = hb_itemSerialSize( pItem, fNumSize, NULL, NULL, &pRef, 0 ); - HB_UCHAR * pBuffer = ( HB_UCHAR * ) hb_xgrab( nSize + 1 ); - - hb_itemSerialUnRefFree( &pRef ); - hb_serializeItem( pItem, fNumSize, NULL, NULL, pBuffer, 0, pRef ); - pBuffer[ nSize ] = '\0'; - if( pnSize ) - *pnSize = nSize; - - hb_itemSerialRefFree( pRef ); - - return ( char * ) pBuffer; -} - -char * hb_itemSerializeCP( PHB_ITEM pItem, HB_BOOL fNumSize, +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, fNumSize, cdpIn, cdpOut, &pRef, 0 ); + HB_SIZE nSize = hb_itemSerialSize( pItem, iFlags, cdpIn, cdpOut, &pRef, 0 ); HB_UCHAR * pBuffer = ( HB_UCHAR * ) hb_xgrab( nSize + 1 ); hb_itemSerialUnRefFree( &pRef ); - hb_serializeItem( pItem, fNumSize, cdpIn, cdpOut, pBuffer, 0, pRef ); + hb_serializeItem( pItem, iFlags, cdpIn, cdpOut, pBuffer, 0, pRef ); + hb_itemSerialRefFree( pRef ); + + if( ( iFlags & HB_SERIALIZE_COMPRESS ) != 0 && nSize > 20 ) + { + HB_SIZE nDest = hb_zlibCompressBound( nSize ); + char * pDest = hb_xgrab( nDest ); + if( hb_zlibCompress( pDest, &nDest, ( const char * ) pBuffer, nSize, + HB_ZLIB_COMPRESSION_DEFAULT ) == HB_ZLIB_RES_OK ) + { + if( nDest + 9 < nSize ) + { + pBuffer[ 0 ] = HB_SERIAL_ZCOMPRESS; + HB_PUT_LE_UINT32( &pBuffer[ 1 ], nDest ); + HB_PUT_LE_UINT32( &pBuffer[ 5 ], nSize ); + memcpy( &pBuffer[ 9 ], pDest, nDest ); + nSize = nDest + 9; + pBuffer = ( HB_UCHAR * ) hb_xrealloc( pBuffer, nSize + 1 ); + } + } + hb_xfree( pDest ); + } + pBuffer[ nSize ] = '\0'; if( pnSize ) *pnSize = nSize; - hb_itemSerialRefFree( pRef ); - return ( char * ) pBuffer; } -PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, HB_SIZE * pnSize ) +char * hb_itemSerialize( PHB_ITEM pItem, int iFlags, HB_SIZE *pnSize ) { - PHB_CYCLIC_REF pRef = NULL; - const HB_UCHAR * pBuffer = ( const HB_UCHAR * ) *pBufferPtr; - PHB_ITEM pItem = NULL; - - if( ! pnSize || hb_deserializeTest( ( const HB_UCHAR ** ) pBufferPtr, pnSize, 0, &pRef ) ) - { - pItem = hb_itemNew( NULL ); - hb_deserializeItem( pItem, NULL, NULL, pBuffer, 0, pRef ); - } - hb_itemSerialRefFree( pRef ); - - return pItem; + return hb_itemSerializeCP( pItem, iFlags, NULL, NULL, pnSize ); } PHB_ITEM hb_itemDeserializeCP( const char ** pBufferPtr, HB_SIZE * pnSize, @@ -1690,6 +1718,11 @@ PHB_ITEM hb_itemDeserializeCP( const char ** pBufferPtr, HB_SIZE * pnSize, return pItem; } +PHB_ITEM hb_itemDeserialize( const char ** pBufferPtr, HB_SIZE * pnSize ) +{ + return hb_itemDeserializeCP( pBufferPtr, pnSize, NULL, NULL ); +} + HB_FUNC( HB_SERIALIZE ) { PHB_ITEM pItem = hb_param( 1, HB_IT_ANY ); @@ -1700,6 +1733,7 @@ HB_FUNC( HB_SERIALIZE ) const char * pszCdpIn, * pszCdpOut; char * pBuffer; HB_SIZE nSize; + int iFlags; pszCdpIn = hb_parc( 3 ); pszCdpOut = hb_parc( 4 ); @@ -1707,7 +1741,12 @@ HB_FUNC( HB_SERIALIZE ) cdpIn = pszCdpIn ? hb_cdpFindExt( pszCdpIn ) : hb_vmCDP(); cdpOut = pszCdpOut ? hb_cdpFindExt( pszCdpOut ) : hb_vmCDP(); - pBuffer = hb_itemSerializeCP( pItem, hb_parl( 2 ), cdpIn, cdpOut, &nSize ); + if( HB_ISNUM( 2 ) ) + iFlags = hb_parni( 2 ); + else + iFlags = hb_parl( 2 ) ? HB_SERIALIZE_NUMSIZE : 0; + + pBuffer = hb_itemSerializeCP( pItem, iFlags, cdpIn, cdpOut, &nSize ); hb_retclen_buffer( pBuffer, nSize ); } }