2015-11-30 14:56 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
* include/hbjson.h
* src/rtl/hbjson.c
+ added new C function:
char * hb_jsonEncodeCP( PHB_ITEM pValue, HB_SIZE * pnLen,
HB_BOOL fHuman, PHB_CODEPAGE cdp );
It allows to pass explicitly codepage in which strings inside pValue
are encoded. If cdp parameter is not NULL then it's used to extract
unicode character values from passed strings and this values is used
to encode to encode non ASCII characters as "\uXXXX" where XXXX is
unicode character value. Data serialized in such way is 7bit clean.
If this parameter is NULL then strings are encoded in raw form just
like in hb_jsonEncode().
+ added new C function:
HB_SIZE hb_jsonDecodeCP( const char * szSource, PHB_ITEM pValue,
PHB_CODEPAGE cdp );
It allows to pass explicitly codepage used for strings decoded from
JSON data. If this parameter is NULL then strings are decoded in raw
form and unicode character with code over 255 are converted to '?'
char.
+ added optional 3-rd parameter with codepage ID to PRG functions
hb_jsonEncode() and hb_jsonDecode(). If this parameter is not given
then above functions works like before this modification:
hb_jsonEncode() uses raw string encoding and hb_jsonDecode() uses
current HVM CP to decode characters encoded as \uXXXX.
+ modified PRG function hb_jsonDecode() to return decoded data
instead of length of decoded data when second parameter is not
passed by reference.
This commit is contained in:
@@ -10,6 +10,35 @@
|
||||
* Change, ! Fix, % Optimization, + Addition, - Removal, ; Comment
|
||||
*/
|
||||
|
||||
2015-11-30 14:56 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* include/hbjson.h
|
||||
* src/rtl/hbjson.c
|
||||
+ added new C function:
|
||||
char * hb_jsonEncodeCP( PHB_ITEM pValue, HB_SIZE * pnLen,
|
||||
HB_BOOL fHuman, PHB_CODEPAGE cdp );
|
||||
It allows to pass explicitly codepage in which strings inside pValue
|
||||
are encoded. If cdp parameter is not NULL then it's used to extract
|
||||
unicode character values from passed strings and this values is used
|
||||
to encode to encode non ASCII characters as "\uXXXX" where XXXX is
|
||||
unicode character value. Data serialized in such way is 7bit clean.
|
||||
If this parameter is NULL then strings are encoded in raw form just
|
||||
like in hb_jsonEncode().
|
||||
+ added new C function:
|
||||
HB_SIZE hb_jsonDecodeCP( const char * szSource, PHB_ITEM pValue,
|
||||
PHB_CODEPAGE cdp );
|
||||
It allows to pass explicitly codepage used for strings decoded from
|
||||
JSON data. If this parameter is NULL then strings are decoded in raw
|
||||
form and unicode character with code over 255 are converted to '?'
|
||||
char.
|
||||
+ added optional 3-rd parameter with codepage ID to PRG functions
|
||||
hb_jsonEncode() and hb_jsonDecode(). If this parameter is not given
|
||||
then above functions works like before this modification:
|
||||
hb_jsonEncode() uses raw string encoding and hb_jsonDecode() uses
|
||||
current HVM CP to decode characters encoded as \uXXXX.
|
||||
+ modified PRG function hb_jsonDecode() to return decoded data
|
||||
instead of length of decoded data when second parameter is not
|
||||
passed by reference.
|
||||
|
||||
2015-11-25 15:06 UTC+0100 Przemyslaw Czerpak (druzus/at/poczta.onet.pl)
|
||||
* include/harbour.hbx
|
||||
* src/rtl/dateshb.c
|
||||
|
||||
@@ -50,11 +50,14 @@
|
||||
#define HB_JSON_H_
|
||||
|
||||
#include "hbapi.h"
|
||||
#include "hbapicdp.h"
|
||||
|
||||
HB_EXTERN_BEGIN
|
||||
|
||||
extern HB_EXPORT char * hb_jsonEncode( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman );
|
||||
extern HB_EXPORT char * hb_jsonEncodeCP( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman, PHB_CODEPAGE cdp );
|
||||
extern HB_EXPORT HB_SIZE hb_jsonDecode( const char * szSource, PHB_ITEM pValue );
|
||||
extern HB_EXPORT HB_SIZE hb_jsonDecodeCP( const char * szSource, PHB_ITEM pValue, PHB_CODEPAGE cdp );
|
||||
|
||||
HB_EXTERN_END
|
||||
|
||||
|
||||
203
src/rtl/hbjson.c
203
src/rtl/hbjson.c
@@ -142,7 +142,7 @@ static void _hb_jsonCtxAddIndent( PHB_JSON_ENCODE_CTX pCtx, HB_SIZE nCount )
|
||||
}
|
||||
|
||||
static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx,
|
||||
HB_SIZE nLevel, HB_BOOL fEOL )
|
||||
HB_SIZE nLevel, HB_BOOL fEOL, PHB_CODEPAGE cdp )
|
||||
{
|
||||
/* Protection against recursive structures */
|
||||
if( ( HB_IS_ARRAY( pValue ) || HB_IS_HASH( pValue ) ) && hb_itemSize( pValue ) > 0 )
|
||||
@@ -176,57 +176,102 @@ static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx,
|
||||
|
||||
if( HB_IS_STRING( pValue ) )
|
||||
{
|
||||
const char * szString = hb_itemGetCPtr( pValue );
|
||||
HB_SIZE nPos, nPos2, nLen = hb_itemGetCLen( pValue );
|
||||
const char * szString = hb_itemGetCPtr( pValue );
|
||||
char buf[ 8 ];
|
||||
|
||||
_hb_jsonCtxAdd( pCtx, "\"", 1 );
|
||||
|
||||
nPos = 0;
|
||||
while( nPos < nLen )
|
||||
if( cdp )
|
||||
{
|
||||
nPos2 = nPos;
|
||||
while( *( ( const unsigned char * ) szString + nPos2 ) >= ' ' &&
|
||||
szString[ nPos2 ] != '\\' && szString[ nPos2 ] != '\"' )
|
||||
nPos2++;
|
||||
if( nPos2 > nPos )
|
||||
{
|
||||
_hb_jsonCtxAdd( pCtx, szString + nPos, nPos2 - nPos );
|
||||
nPos = nPos2;
|
||||
continue;
|
||||
}
|
||||
HB_WCHAR wc;
|
||||
|
||||
switch( szString[ nPos ] )
|
||||
nPos = 0;
|
||||
while( HB_CDPCHAR_GET( cdp, szString, nLen, &nPos, &wc ) )
|
||||
{
|
||||
case '\\':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\\", 2 );
|
||||
break;
|
||||
case '\"':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\"", 2 );
|
||||
break;
|
||||
case '\b':
|
||||
_hb_jsonCtxAdd( pCtx, "\\b", 2 );
|
||||
break;
|
||||
case '\f':
|
||||
_hb_jsonCtxAdd( pCtx, "\\f", 2 );
|
||||
break;
|
||||
case '\n':
|
||||
_hb_jsonCtxAdd( pCtx, "\\n", 2 );
|
||||
break;
|
||||
case '\r':
|
||||
_hb_jsonCtxAdd( pCtx, "\\r", 2 );
|
||||
break;
|
||||
case '\t':
|
||||
_hb_jsonCtxAdd( pCtx, "\\t", 2 );
|
||||
break;
|
||||
default:
|
||||
if( wc >= ' ' && wc < 0x7F && wc != '\\' && wc != '\"' )
|
||||
{
|
||||
char buf[ 8 ];
|
||||
hb_snprintf( buf, sizeof( buf ), "\\u00%02X", ( unsigned char ) szString[ nPos ] );
|
||||
_hb_jsonCtxAdd( pCtx, buf, 6 );
|
||||
break;
|
||||
buf[ 0 ] = ( char ) wc;
|
||||
_hb_jsonCtxAdd( pCtx, buf, 1 );
|
||||
continue;
|
||||
}
|
||||
switch( wc )
|
||||
{
|
||||
case '\\':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\\", 2 );
|
||||
break;
|
||||
case '\"':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\"", 2 );
|
||||
break;
|
||||
case '\b':
|
||||
_hb_jsonCtxAdd( pCtx, "\\b", 2 );
|
||||
break;
|
||||
case '\f':
|
||||
_hb_jsonCtxAdd( pCtx, "\\f", 2 );
|
||||
break;
|
||||
case '\n':
|
||||
_hb_jsonCtxAdd( pCtx, "\\n", 2 );
|
||||
break;
|
||||
case '\r':
|
||||
_hb_jsonCtxAdd( pCtx, "\\r", 2 );
|
||||
break;
|
||||
case '\t':
|
||||
_hb_jsonCtxAdd( pCtx, "\\t", 2 );
|
||||
break;
|
||||
default:
|
||||
hb_snprintf( buf, sizeof( buf ), "\\u%04X", wc );
|
||||
_hb_jsonCtxAdd( pCtx, buf, 6 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
nPos++;
|
||||
}
|
||||
else
|
||||
{
|
||||
nPos = 0;
|
||||
while( nPos < nLen )
|
||||
{
|
||||
unsigned char uch = szString[ nPos ];
|
||||
nPos2 = nPos;
|
||||
while( uch >= ' ' && uch != '\\' && uch != '\"' )
|
||||
uch = szString[ ++nPos2 ];
|
||||
if( nPos2 > nPos )
|
||||
{
|
||||
_hb_jsonCtxAdd( pCtx, szString + nPos, nPos2 - nPos );
|
||||
if( nPos2 >= nLen )
|
||||
break;
|
||||
nPos = nPos2;
|
||||
}
|
||||
|
||||
switch( uch )
|
||||
{
|
||||
case '\\':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\\", 2 );
|
||||
break;
|
||||
case '\"':
|
||||
_hb_jsonCtxAdd( pCtx, "\\\"", 2 );
|
||||
break;
|
||||
case '\b':
|
||||
_hb_jsonCtxAdd( pCtx, "\\b", 2 );
|
||||
break;
|
||||
case '\f':
|
||||
_hb_jsonCtxAdd( pCtx, "\\f", 2 );
|
||||
break;
|
||||
case '\n':
|
||||
_hb_jsonCtxAdd( pCtx, "\\n", 2 );
|
||||
break;
|
||||
case '\r':
|
||||
_hb_jsonCtxAdd( pCtx, "\\r", 2 );
|
||||
break;
|
||||
case '\t':
|
||||
_hb_jsonCtxAdd( pCtx, "\\t", 2 );
|
||||
break;
|
||||
default:
|
||||
hb_snprintf( buf, sizeof( buf ), "\\u00%02X", uch );
|
||||
_hb_jsonCtxAdd( pCtx, buf, 6 );
|
||||
break;
|
||||
}
|
||||
nPos++;
|
||||
}
|
||||
}
|
||||
_hb_jsonCtxAdd( pCtx, "\"", 1 );
|
||||
}
|
||||
@@ -312,7 +357,7 @@ static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx,
|
||||
hb_itemSize( pItem ) > 0 ) )
|
||||
_hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE );
|
||||
|
||||
_hb_jsonEncode( pItem, pCtx, nLevel + 1, HB_FALSE );
|
||||
_hb_jsonEncode( pItem, pCtx, nLevel + 1, HB_FALSE, cdp );
|
||||
}
|
||||
if( pCtx->fHuman )
|
||||
{
|
||||
@@ -353,7 +398,7 @@ static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx,
|
||||
_hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen );
|
||||
_hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE );
|
||||
}
|
||||
_hb_jsonEncode( pKey, pCtx, nLevel + 1, HB_FALSE );
|
||||
_hb_jsonEncode( pKey, pCtx, nLevel + 1, HB_FALSE, cdp );
|
||||
|
||||
if( pCtx->fHuman )
|
||||
{
|
||||
@@ -366,7 +411,7 @@ static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx,
|
||||
fEOL = HB_FALSE;
|
||||
}
|
||||
|
||||
_hb_jsonEncode( pItem, pCtx, nLevel + 1, fEOL );
|
||||
_hb_jsonEncode( pItem, pCtx, nLevel + 1, fEOL, cdp );
|
||||
}
|
||||
}
|
||||
if( pCtx->fHuman )
|
||||
@@ -394,7 +439,7 @@ static const char * _skipws( const char * szSource )
|
||||
return szSource;
|
||||
}
|
||||
|
||||
static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue, PHB_CODEPAGE cdp )
|
||||
{
|
||||
if( *szSource == '\"' )
|
||||
{
|
||||
@@ -462,9 +507,14 @@ static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
szHead += hb_cdpU16ToStr( hb_vmCDP(), HB_CDP_ENDIAN_NATIVE,
|
||||
&wc, 1,
|
||||
szHead, szDest + nAlloc - szHead );
|
||||
if( cdp )
|
||||
szHead += hb_cdpU16ToStr( cdp, HB_CDP_ENDIAN_NATIVE,
|
||||
&wc, 1,
|
||||
szHead, szDest + nAlloc - szHead );
|
||||
else if( wc <= 0xFF )
|
||||
*szHead++ = ( char ) wc;
|
||||
else
|
||||
*szHead++ = '?';
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -574,7 +624,7 @@ static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
|
||||
for( ;; )
|
||||
{
|
||||
szSource = _hb_jsonDecode( szSource, pItem );
|
||||
szSource = _hb_jsonDecode( szSource, pItem, cdp );
|
||||
if( ! szSource )
|
||||
{
|
||||
hb_itemRelease( pItem );
|
||||
@@ -612,10 +662,10 @@ static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
for( ;; )
|
||||
{
|
||||
/* Do we need to check if key does not exist yet? */
|
||||
if( ( szSource = _hb_jsonDecode( szSource, pItemKey ) ) == NULL ||
|
||||
if( ( szSource = _hb_jsonDecode( szSource, pItemKey, cdp ) ) == NULL ||
|
||||
! HB_IS_STRING( pItemKey ) ||
|
||||
* ( szSource = _skipws( szSource ) ) != ':' ||
|
||||
( szSource = _hb_jsonDecode( _skipws( szSource + 1 ), pItemValue ) ) == NULL)
|
||||
( szSource = _hb_jsonDecode( _skipws( szSource + 1 ), pItemValue, cdp ) ) == NULL)
|
||||
{
|
||||
hb_itemRelease( pItemKey );
|
||||
hb_itemRelease( pItemValue );
|
||||
@@ -648,7 +698,7 @@ static const char * _hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
|
||||
/* C level API functions */
|
||||
|
||||
char * hb_jsonEncode( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman )
|
||||
char * hb_jsonEncodeCP( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman, PHB_CODEPAGE cdp )
|
||||
{
|
||||
PHB_JSON_ENCODE_CTX pCtx;
|
||||
char * szRet;
|
||||
@@ -665,7 +715,7 @@ char * hb_jsonEncode( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman )
|
||||
pCtx->szEol = hb_conNewLine();
|
||||
pCtx->iEolLen = ( int ) strlen( pCtx->szEol );
|
||||
|
||||
_hb_jsonEncode( pValue, pCtx, 0, HB_FALSE );
|
||||
_hb_jsonEncode( pValue, pCtx, 0, HB_FALSE, cdp );
|
||||
if( fHuman )
|
||||
_hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen );
|
||||
|
||||
@@ -679,12 +729,17 @@ char * hb_jsonEncode( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman )
|
||||
return szRet;
|
||||
}
|
||||
|
||||
HB_SIZE hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
char * hb_jsonEncode( PHB_ITEM pValue, HB_SIZE * pnLen, HB_BOOL fHuman )
|
||||
{
|
||||
return hb_jsonEncodeCP( pValue, pnLen, fHuman, NULL );
|
||||
}
|
||||
|
||||
HB_SIZE hb_jsonDecodeCP( const char * szSource, PHB_ITEM pValue, PHB_CODEPAGE cdp )
|
||||
{
|
||||
PHB_ITEM pItem = pValue ? pValue : hb_itemNew( NULL );
|
||||
const char * sz;
|
||||
|
||||
sz = szSource ? _hb_jsonDecode( _skipws( szSource ), pItem ) : NULL;
|
||||
sz = szSource ? _hb_jsonDecode( _skipws( szSource ), pItem, cdp ) : NULL;
|
||||
if( ! pValue )
|
||||
hb_itemRelease( pItem );
|
||||
if( sz )
|
||||
@@ -692,9 +747,28 @@ HB_SIZE hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
return 0;
|
||||
}
|
||||
|
||||
HB_SIZE hb_jsonDecode( const char * szSource, PHB_ITEM pValue )
|
||||
{
|
||||
return hb_jsonDecodeCP( szSource, pValue, hb_vmCDP() );
|
||||
}
|
||||
|
||||
/* Harbour level API functions */
|
||||
|
||||
static PHB_CODEPAGE _hb_jsonCdpPar( int iParam, HB_BOOL lVmCp )
|
||||
{
|
||||
if( hb_pcount() >= iParam )
|
||||
{
|
||||
const char * szCdp = hb_parc( iParam );
|
||||
|
||||
if( szCdp )
|
||||
return hb_cdpFindExt( szCdp );
|
||||
}
|
||||
else if( lVmCp )
|
||||
return hb_vmCDP();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HB_FUNC( HB_JSONENCODE )
|
||||
{
|
||||
PHB_ITEM pItem = hb_param( 1, HB_IT_ANY );
|
||||
@@ -702,8 +776,10 @@ HB_FUNC( HB_JSONENCODE )
|
||||
if( pItem )
|
||||
{
|
||||
HB_SIZE nLen;
|
||||
char * szRet;
|
||||
|
||||
char * szRet = hb_jsonEncode( pItem, &nLen, hb_parl( 2 ) );
|
||||
szRet = hb_jsonEncodeCP( pItem, &nLen, hb_parl( 2 ),
|
||||
_hb_jsonCdpPar( 3, HB_FALSE ) );
|
||||
hb_retclen_buffer( szRet, nLen );
|
||||
}
|
||||
}
|
||||
@@ -711,8 +787,15 @@ HB_FUNC( HB_JSONENCODE )
|
||||
HB_FUNC( HB_JSONDECODE )
|
||||
{
|
||||
PHB_ITEM pItem = hb_itemNew( NULL );
|
||||
HB_SIZE nSize = hb_jsonDecodeCP( hb_parc( 1 ), pItem,
|
||||
_hb_jsonCdpPar( 3, HB_TRUE ) );
|
||||
|
||||
hb_retns( ( HB_ISIZ ) hb_jsonDecode( hb_parc( 1 ), pItem ) );
|
||||
hb_itemParamStoreForward( 2, pItem );
|
||||
hb_itemRelease( pItem );
|
||||
if( HB_ISBYREF( 2 ) )
|
||||
{
|
||||
hb_retns( ( HB_ISIZ ) nSize );
|
||||
hb_itemParamStoreForward( 2, pItem );
|
||||
hb_itemRelease( pItem );
|
||||
}
|
||||
else
|
||||
hb_itemReturnRelease( pItem );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user