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.
This commit is contained in:
Przemysław Czerpak
2013-12-23 17:11:36 +01:00
parent 8443c9754b
commit e34407ad88
9 changed files with 471 additions and 339 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 );

View File

@@ -125,6 +125,7 @@ PRG_HEADERS := \
hbmemvar.ch \
hboo.ch \
hbpers.ch \
hbserial.ch \
hbsetup.ch \
hbsix.ch \
hbsocket.ch \

View File

@@ -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 );

View File

@@ -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_ )

58
include/hbserial.ch Normal file
View File

@@ -0,0 +1,58 @@
/*
* Harbour Project source code:
* header file for item serialization flags
*
* Copyright 2013 Przemyslaw Czerpak <druzus / at / priv.onet.pl>
* 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_ */

View File

@@ -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;

View File

@@ -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' <BE64:n><str> 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 );
}
}