From d248d8e892d42c2f54b6eaef728305ea369d6653 Mon Sep 17 00:00:00 2001 From: Przemyslaw Czerpak Date: Thu, 21 Jan 2010 00:10:08 +0000 Subject: [PATCH] 2010-01-21 01:09 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) * harbour/contrib/hbnetio/netiocli.c * harbour/contrib/hbnetio/readme.txt + added new client side function: NETIO_DECODE( [@], [@], [@], [@], ; [@], [@], [@] ) -> Decode connection parameters from and default settings. Return .T. if contains any connection settings. should not contain "net:" prefix. * harbour/src/rtl/itemseri.c + added support for hash array flags and default value serialization Warning: before this modification hash arrays were always restored with binary sorting with default auto assign setting and without any default value and resorted if necessary. Now only non binary hash arrays are resorted what may cause problems for hash arrays not using binary sorting serialized by old code and restored by the current one. In such case it's necessary to restore original flags manually using hb_h*() functions to force resorting. - removed my TODO note: "extended hash format with default value and hash flags" --- harbour/ChangeLog | 24 +++ harbour/contrib/hbnetio/netiocli.c | 255 +++++++++++++++++++---------- harbour/contrib/hbnetio/readme.txt | 11 +- harbour/src/rtl/itemseri.c | 79 +++++++-- 4 files changed, 269 insertions(+), 100 deletions(-) diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 569bdf10c0..7ce029d188 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -17,6 +17,30 @@ past entries belonging to author(s): Viktor Szakats. */ +2010-01-21 01:09 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl) + * harbour/contrib/hbnetio/netiocli.c + * harbour/contrib/hbnetio/readme.txt + + added new client side function: + NETIO_DECODE( [@], [@], [@], [@], ; + [@], [@], [@] ) + -> + Decode connection parameters from and default settings. + Return .T. if contains any connection settings. + should not contain "net:" prefix. + + * harbour/src/rtl/itemseri.c + + added support for hash array flags and default value serialization + Warning: before this modification hash arrays were always restored + with binary sorting with default auto assign setting and + without any default value and resorted if necessary. Now + only non binary hash arrays are resorted what may cause + problems for hash arrays not using binary sorting serialized + by old code and restored by the current one. In such case + it's necessary to restore original flags manually using + hb_h*() functions to force resorting. + - removed my TODO note: + "extended hash format with default value and hash flags" + 2010-01-21 00:52 UTC+0100 Viktor Szakats (harbour.01 syenar.hu) * INSTALL + Added new item to TROUBLESHOOTING section describing diff --git a/harbour/contrib/hbnetio/netiocli.c b/harbour/contrib/hbnetio/netiocli.c index 3a962f4283..9fbbc0c9b5 100644 --- a/harbour/contrib/hbnetio/netiocli.c +++ b/harbour/contrib/hbnetio/netiocli.c @@ -8,14 +8,17 @@ * very simple TCP/IP file server with RPC support * All files which names starts 'net:' are redirected to this API. * This is client code with - * NETIO_CONNECT( [], [], [], + * NETIO_CONNECT( [], [], [], * [], [], [] ) * -> * function which register alternative RDD IO API, sets server * address and port and connection timeout parameter. * Then it tries to connect to the server and returns .T. on success. * This code also provides the following .prg functions: - * NETIO_DISCONNECT( [], [] ) -> + * NETIO_DISCONNECT( [], [] ) -> + * NETIO_DECODE( [@], [@], [@], [@], + * [@], [@], [@] ) + * -> * NETIO_PROCEXISTS( ) -> * NETIO_PROCEXEC( [, ] ) -> * NETIO_PROCEXECW( [, ] ) -> @@ -399,7 +402,114 @@ static void s_fileGetConnParam( const char ** pszServer, int * piPort, int * piT } } -static PHB_CONCLI s_fileConnect( const char ** pszFilename, +static const char * s_fileDecode( const char * pszFilename, + char * buffer, const char ** pServer, + int * piPort, int * piTimeOut, + const char ** pPasswd, int * piPassLen, + int * piLevel, int * piStrategy ) +{ + HB_SYMBOL_UNUSED( piTimeOut ); + HB_SYMBOL_UNUSED( piLevel ); + HB_SYMBOL_UNUSED( piStrategy ); + + if( pszFilename ) + { + /* decode server address and port if given as part of file name + * in format like: + * "192.168.0.1:2941:path/to/file" + * or: + * "192.168.0.1:2941:passwd:path/to/file" + * or: + * "//192.168.0.1:2941/path/to/file" + */ + const char * psz, * pth = NULL; + + if( ( pszFilename[ 0 ] == '/' || pszFilename[ 0 ] == '\\' ) && + pszFilename[ 0 ] == pszFilename[ 1 ] ) + { + pszFilename += 2; + pth = strchr( pszFilename, '/' ); + psz = strchr( pszFilename, '\\' ); + if( !pth || ( psz && psz < pth ) ) + { + pth = psz; + if( !pth ) + pth = pszFilename + strlen( pszFilename ); + } + } + + psz = strchr( pszFilename, ':' ); + if( pth && ( !psz || pth < psz ) ) + psz = pth; + + if( psz ) + { + int iLen = ( int ) ( psz - pszFilename ); + + if( pth || iLen == 0 || iLen > 1 ) + { + char port_buf[ 10 ], c; + + if( iLen >= NETIO_SERVERNAME_MAX ) + iLen = NETIO_SERVERNAME_MAX - 1; + if( iLen > 0 ) + { + hb_strncpy( buffer, pszFilename, iLen ); + *pServer = buffer; + } + pszFilename = psz + 1; + if( !pth || psz < pth ) + { + iLen = 0; + while( HB_ISDIGIT( pszFilename[ iLen ] ) && + iLen < ( int ) sizeof( port_buf ) - 1 ) + { + port_buf[ iLen ] = pszFilename[ iLen ]; + ++iLen; + } + c = pszFilename[ iLen ]; + if( c == ':' || c == '/' || c == '\\' ) + { + if( iLen > 0 ) + { + int iOverflow; + HB_LONG llPort; + + port_buf[ iLen ] = '\0'; + llPort = hb_strValInt( port_buf, &iOverflow ); + + if( !iOverflow && llPort > 0 && llPort < 0x10000 ) + { + pszFilename += iLen; + *piPort = ( int ) llPort; + } + } + if( c == ':' ) + { + ++pszFilename; + iLen = 0; + while( pszFilename[ iLen ] && + pszFilename[ iLen ] != ':' ) + ++iLen; + if( pszFilename[ iLen ] == ':' ) + { + *pPasswd = pszFilename; + pszFilename += iLen + 1; + if( iLen > NETIO_PASSWD_MAX ) + iLen = NETIO_PASSWD_MAX; + *piPassLen = iLen; + } + } + } + } + } + } + } + + return pszFilename; +} + +static PHB_CONCLI s_fileConnect( const char ** pFilename, const char * pszServer, int iPort, int iTimeOut, const char * pszPasswd, int iPassLen, @@ -412,89 +522,10 @@ static PHB_CONCLI s_fileConnect( const char ** pszFilename, s_fileGetConnParam( &pszServer, &iPort, &iTimeOut, &pszPasswd, &iPassLen ); - if( pszFilename ) - { - /* decode server address and port if given as part of file name - * in format like: - * "192.168.0.1:2941:path/to/file" - * or: - * "192.168.0.1:2941:passwd:path/to/file" - * or: - * "//192.168.0.1:2941/path/to/file" - */ - const char * psz, * tmp; - - if( ( ( *pszFilename )[ 0 ] == '/' || ( *pszFilename )[ 0 ] == '\\' ) && - ( *pszFilename )[ 0 ] == ( *pszFilename )[ 1 ] ) - { - *pszFilename += 2; - psz = strchr( *pszFilename, '/' ); - tmp = strchr( *pszFilename, '\\' ); - if( tmp < psz ) - psz = tmp; - } - else - psz = strchr( *pszFilename, ':' ); - - if( psz ) - { - int iLen = ( int ) ( psz - *pszFilename ); - - if( iLen == 0 || iLen > 1 ) - { - char port_buf[ 10 ], c; - if( iLen >= ( int ) sizeof( server ) ) - iLen = ( int ) sizeof( server ) - 1; - if( iLen > 0 ) - { - hb_strncpy( server, *pszFilename, iLen ); - pszServer = server; - } - *pszFilename = psz + 1; - iLen = 0; - while( HB_ISDIGIT( ( *pszFilename )[ iLen ] ) && - iLen < ( int ) sizeof( port_buf ) - 1 ) - { - port_buf[ iLen ] = ( *pszFilename )[ iLen ]; - ++iLen; - } - c = ( *pszFilename )[ iLen ]; - if( c == ':' || c == '/' || c == '\\' ) - { - if( iLen > 0 ) - { - int iOverflow; - HB_LONG llPort; - - port_buf[ iLen ] = '\0'; - llPort = hb_strValInt( port_buf, &iOverflow ); - - if( !iOverflow && llPort > 0 && llPort < 0x10000 ) - { - *pszFilename += iLen; - iPort = ( int ) llPort; - } - } - if( c == ':' ) - { - ++( *pszFilename ); - iLen = 0; - while( ( *pszFilename )[ iLen ] && - ( *pszFilename )[ iLen ] != ':' ) - ++iLen; - if( ( *pszFilename )[ iLen ] == ':' ) - { - pszPasswd = *pszFilename; - *pszFilename += iLen + 1; - iPassLen = iLen; - if( iPassLen > NETIO_PASSWD_MAX ) - iPassLen = NETIO_PASSWD_MAX; - } - } - } - } - } - } + if( pFilename ) + *pFilename = s_fileDecode( *pFilename, server, + &pszServer, &iPort, &iTimeOut, + &pszPasswd, &iPassLen, &iLevel, &iStrategy ); if( iLevel == HB_ZLIB_COMPRESSION_DISABLE && iPassLen ) iLevel = HB_ZLIB_COMPRESSION_DEFAULT; @@ -618,7 +649,55 @@ static void s_netio_init( void * cargo ) } } -/* NETIO_CONNECT( [], [], [], ; +/* NETIO_DECODE( [@], [@], [@], [@], ; + * [@], [@], [@] ) -> + */ +HB_FUNC( NETIO_DECODE ) +{ + char server[ NETIO_SERVERNAME_MAX ]; + const char * pszFullName = hb_parc( 1 ); + const char * pszServer, * pszPasswd, * pszFile; + int iPort, iTimeOut, iPassLen, iLevel, iStrategy; + HB_BOOL fResult = FALSE; + + pszServer = NULL; + pszPasswd = NULL; + iPort = iTimeOut = iPassLen = 0; + iLevel = HB_ZLIB_COMPRESSION_DISABLE; + iStrategy = HB_ZLIB_STRATEGY_DEFAULT; + + s_fileGetConnParam( &pszServer, &iPort, &iTimeOut, &pszPasswd, &iPassLen ); + + pszFile = s_fileDecode( pszFullName, server, + &pszServer, &iPort, &iTimeOut, + &pszPasswd, &iPassLen, &iLevel, &iStrategy ); + + if( iLevel == HB_ZLIB_COMPRESSION_DISABLE && iPassLen ) + iLevel = HB_ZLIB_COMPRESSION_DEFAULT; + + hb_storc( pszServer, 2 ); + hb_storni( iPort, 3 ); + hb_storni( iTimeOut, 4 ); + hb_storclen( pszPasswd, iPassLen, 5 ); + hb_storni( iLevel, 6 ); + hb_storni( iStrategy, 7 ); + + fResult = pszFile != pszFullName; + if( fResult && HB_ISBYREF( 1 ) ) + { + if( * pszFile ) + { + char * pszFileName = hb_strdup( pszFile ); + if( !hb_storclen_buffer( pszFileName, strlen( pszFileName ), 1 ) ) + hb_xfree( pszFileName ); + } + else + hb_storc( NULL, 1 ); + } + hb_retl( fResult ); +} + +/* NETIO_CONNECT( [], [], [], ; * [], [], [] ) -> */ HB_FUNC( NETIO_CONNECT ) @@ -658,7 +737,7 @@ HB_FUNC( NETIO_CONNECT ) hb_retl( conn != NULL ); } -/* NETIO_DISCONNECT( [], [] ) -> +/* NETIO_DISCONNECT( [], [] ) -> */ HB_FUNC( NETIO_DISCONNECT ) { diff --git a/harbour/contrib/hbnetio/readme.txt b/harbour/contrib/hbnetio/readme.txt index 8dc14a00ff..2f0cb36fcc 100644 --- a/harbour/contrib/hbnetio/readme.txt +++ b/harbour/contrib/hbnetio/readme.txt @@ -14,7 +14,7 @@ RDDs with name starting with "net:" are redirected to the hbnetio server. Client side functions: ====================== - NETIO_CONNECT( [], [], [], ; + NETIO_CONNECT( [], [], [], ; [], [], [] ) -> Register HBNETIO as alternative RDD IO API redirecting all files @@ -59,10 +59,17 @@ Client side functions: given then default connection is chosen. - NETIO_DISCONNECT( [], [] ) -> + NETIO_DISCONNECT( [], [] ) -> Close the connection created by NETIO_CONNECT() + NETIO_DECODE( [@], [@], [@], [@], ; + [@], [@], [@] ) + -> + Decode connection parameters from and default settings. + Return .T. if contains any connection settings. + should not contain "net:" prefix. + NETIO_PROCEXISTS( ) -> Check if function or procedure exists on the server side. diff --git a/harbour/src/rtl/itemseri.c b/harbour/src/rtl/itemseri.c index aceaaae762..e935c2c7c2 100644 --- a/harbour/src/rtl/itemseri.c +++ b/harbour/src/rtl/itemseri.c @@ -56,10 +56,6 @@ #include "hbapicdp.h" -/* -TODO: extended hash format with default value and hash flags -*/ - /* UCHAR [ 1 ] - item type 0. NIL 0 @@ -102,6 +98,8 @@ UCHAR [ 1 ] - item type 37. INT64NUM 8+1 38. DBLNUM 8+1+1 39. TIMESTAMP 8 + 40. HASHFLAGS 2 + 41. HASHDEFAULT VALUE 0 */ #define HB_SERIAL_NIL 0 @@ -144,6 +142,8 @@ UCHAR [ 1 ] - item type #define HB_SERIAL_INT64NUM 37 #define HB_SERIAL_DBLNUM 38 #define HB_SERIAL_TIMESTAMP 39 +#define HB_SERIAL_HASHFLAGS 40 +#define HB_SERIAL_HASHDEFVAL 41 #define HB_SERIAL_DUMMYOFFSET ( ( ULONG ) -1 ) @@ -280,6 +280,7 @@ static ULONG hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, ULONG ulSize, ulLen, u; HB_LONG lVal; USHORT uiClass; + PHB_ITEM pDefVal; const char * szVal; if( HB_IS_BYREF( pItem ) ) @@ -388,13 +389,24 @@ static ULONG hb_itemSerialSize( PHB_ITEM pItem, HB_BOOL fNumSize, } else { - ulLen = hb_hashLen( pItem ); - if( ulLen <= 255 ) - ulSize = 2; - else if( ulLen <= UINT16_MAX ) + if( hb_hashGetFlags( pItem ) != HB_HASH_FLAG_DEFAULT ) ulSize = 3; else - ulSize = 5; + ulSize = 0; + pDefVal = hb_hashGetDefault( pItem ); + if( pDefVal ) + { + ulSize++; + ulSize += hb_itemSerialSize( pDefVal, fNumSize, + cdpIn, cdpOut, pRefPtr, ulOffset + ulSize ); + } + 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 ), fNumSize, @@ -697,6 +709,21 @@ static ULONG hb_serializeItem( PHB_ITEM pItem, HB_BOOL fNumSize, } else { + int iFlags = hb_hashGetFlags( pItem ); + PHB_ITEM pDefVal = hb_hashGetDefault( pItem ); + + if( iFlags != HB_HASH_FLAG_DEFAULT ) + { + pBuffer[ ulOffset++ ] = HB_SERIAL_HASHFLAGS; + HB_PUT_LE_UINT16( &pBuffer[ ulOffset ], iFlags ); + ulOffset += 2; + } + if( pDefVal ) + { + pBuffer[ ulOffset++ ] = HB_SERIAL_HASHDEFVAL; + ulOffset = hb_serializeItem( pDefVal, fNumSize, + cdpIn, cdpOut, pBuffer, ulOffset, pRef ); + } ulLen = hb_hashLen( pItem ); if( ulLen <= 255 ) { @@ -762,7 +789,7 @@ static ULONG hb_deserializeHash( PHB_ITEM pItem, #else PHB_ITEM pKey, pVal; - hb_hashSetFlags( pItem, HB_HASH_BINARY | HB_HASH_RESORT ); + hb_hashSetFlags( pItem, HB_HASH_BINARY /* | HB_HASH_RESORT */ ); hb_hashPreallocate( pItem, ulLen ); while( ulLen-- ) { @@ -1026,6 +1053,30 @@ static ULONG hb_deserializeItem( PHB_ITEM pItem, break; } + case HB_SERIAL_HASHFLAGS: + { + int iFlags = HB_GET_LE_UINT16( &pBuffer[ ulOffset ] ); + ulOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, + ulOffset + 2, pRef ); + hb_hashClearFlags( pItem, HB_HASH_FLAG_MASK ); + if( ( iFlags & HB_HASH_BINARY ) == 0 ) + iFlags |= HB_HASH_RESORT; + hb_hashSetFlags( pItem, iFlags ); + break; + } + + case HB_SERIAL_HASHDEFVAL: + { + PHB_ITEM pDefVal = hb_itemNew( NULL ); + ulOffset = hb_deserializeItem( pDefVal, cdpIn, cdpOut, pBuffer, + ulOffset, pRef ); + ulOffset = hb_deserializeItem( pItem, cdpIn, cdpOut, pBuffer, + ulOffset, pRef ); + hb_hashSetDefault( pItem, pDefVal ); + hb_itemRelease( pDefVal ); + break; + } + default: hb_itemClear( pItem ); break; @@ -1192,6 +1243,14 @@ static HB_BOOL hb_deserializeTest( const UCHAR ** pBufferPtr, ULONG * pulSize, } ulLen = 1; break; + case HB_SERIAL_HASHFLAGS: + ulSize = 3; + ulLen = 1; + break; + case HB_SERIAL_HASHDEFVAL: + ulSize = 1; + ulLen = 2; + break; default: ulSize = 1; break;