static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx, HB_SIZE nLevel, HB_BOOL fEOL ) { /* Protection against recursive structures */ if( ( HB_IS_ARRAY( pValue ) || HB_IS_HASH( pValue ) ) && hb_itemSize( pValue ) > 0 ) { void * id = HB_IS_HASH( pValue ) ? hb_hashId( pValue ) : hb_arrayId( pValue ); HB_SIZE nIndex; for( nIndex = 0; nIndex < nLevel; nIndex++ ) { if( pCtx->pId[ nIndex ] == id ) { if( ! fEOL && pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "null", 4 ); return; } } if( nLevel >= pCtx->nAllocId ) { pCtx->nAllocId += 8; pCtx->pId = ( void ** ) hb_xrealloc( pCtx->pId, sizeof( void * ) * pCtx->nAllocId ); } pCtx->pId[ nLevel ] = id; } if( fEOL ) { --pCtx->pHead; _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); } if( HB_IS_STRING( pValue ) ) { const char * szString = hb_itemGetCPtr( pValue ); HB_SIZE nPos, nPos2, nLen = hb_itemGetCLen( pValue ); _hb_jsonCtxAdd( pCtx, "\"", 1 ); nPos = 0; while( nPos < nLen ) { 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; } switch( szString[ nPos ] ) { 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: { char buf[ 8 ]; hb_snprintf( buf, sizeof( buf ), "\\u00%02X", ( unsigned char ) szString[ nPos ] ); _hb_jsonCtxAdd( pCtx, buf, 6 ); break; } } nPos++; } _hb_jsonCtxAdd( pCtx, "\"", 1 ); } else if( HB_IS_NUMINT( pValue ) ) { char buf[ 32 ]; hb_snprintf( buf, sizeof( buf ), "%" PFHL "d", hb_itemGetNInt( pValue ) ); _hb_jsonCtxAdd( pCtx, buf, strlen( buf ) ); } else if( HB_IS_NUMERIC( pValue ) ) { char buf[ 64 ]; int iDec; double dblValue = hb_itemGetNDDec( pValue, &iDec ); hb_snprintf( buf, sizeof( buf ), "%.*f", iDec, dblValue ); _hb_jsonCtxAdd( pCtx, buf, strlen( buf ) ); } else if( HB_IS_NIL( pValue ) ) { _hb_jsonCtxAdd( pCtx, "null", 4 ); } else if( HB_IS_LOGICAL( pValue ) ) { if( hb_itemGetL( pValue ) ) _hb_jsonCtxAdd( pCtx, "true", 4 ); else _hb_jsonCtxAdd( pCtx, "false", 5 ); } else if( HB_IS_DATE( pValue ) ) { char szBuffer[ 10 ]; hb_itemGetDS( pValue, szBuffer + 1 ); szBuffer[ 0 ] = '\"'; szBuffer[ 9 ] = '\"'; _hb_jsonCtxAdd( pCtx, szBuffer, 10 ); } else if( HB_IS_TIMESTAMP( pValue ) ) { char szBuffer[ 19 ]; hb_itemGetTS( pValue, szBuffer + 1 ); szBuffer[ 0 ] = '\"'; szBuffer[ 18 ] = '\"'; _hb_jsonCtxAdd( pCtx, szBuffer, 19 ); } else if( HB_IS_ARRAY( pValue ) ) { HB_SIZE nLen = hb_itemSize( pValue ); if( nLen ) { HB_SIZE nIndex; if( pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "[", 1 ); for( nIndex = 1; nIndex <= nLen; nIndex++ ) { PHB_ITEM pItem = hb_arrayGetItemPtr( pValue, nIndex ); if( nIndex > 1 ) _hb_jsonCtxAdd( pCtx, ",", 1 ); if( pCtx->fHuman ) _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); if( pCtx->fHuman && ! ( ( HB_IS_ARRAY( pItem ) || HB_IS_HASH( pItem ) ) && hb_itemSize( pItem ) > 0 ) ) _hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE ); _hb_jsonEncode( pItem, pCtx, nLevel + 1, HB_FALSE ); } if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); } _hb_jsonCtxAdd( pCtx, "]", 1 ); } else _hb_jsonCtxAdd( pCtx, "[]", 2 ); } else if( HB_IS_HASH( pValue ) ) { HB_SIZE nLen = hb_hashLen( pValue ); if( nLen ) { HB_SIZE nIndex; if( pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "{", 1 ); for( nIndex = 1; nIndex <= nLen; nIndex++ ) { PHB_ITEM pKey = hb_hashGetKeyAt( pValue, nIndex ); if( HB_IS_STRING( pKey ) ) { PHB_ITEM pItem = hb_hashGetValueAt( pValue, nIndex ); HB_BOOL fEOL = HB_FALSE; if( nIndex > 1 ) _hb_jsonCtxAdd( pCtx, ",", 1 ); if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE ); } _hb_jsonEncode( pKey, pCtx, nLevel + 1, HB_FALSE ); if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, ": ", 2 ); fEOL = ( HB_IS_ARRAY( pItem ) || HB_IS_HASH( pItem ) ) && hb_itemSize( pItem ) > 0; } else _hb_jsonCtxAdd( pCtx, ":", 1 ); _hb_jsonEncode( pItem, pCtx, nLevel + 1, fEOL ); } } if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); } _hb_jsonCtxAdd( pCtx, "}", 1 ); } else _hb_jsonCtxAdd( pCtx, "{}", 2 ); } else { /* All unsupported types are replacd by null */ _hb_jsonCtxAdd( pCtx, "null", 4 ); } }
static void _hb_jsonEncode( PHB_ITEM pValue, PHB_JSON_ENCODE_CTX pCtx, 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 ) { void * id = HB_IS_HASH( pValue ) ? hb_hashId( pValue ) : hb_arrayId( pValue ); HB_SIZE nIndex; for( nIndex = 0; nIndex < nLevel; nIndex++ ) { if( pCtx->pId[ nIndex ] == id ) { if( ! fEOL && pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "null", 4 ); return; } } if( nLevel >= pCtx->nAllocId ) { pCtx->nAllocId += 8; pCtx->pId = ( void ** ) hb_xrealloc( pCtx->pId, sizeof( void * ) * pCtx->nAllocId ); } pCtx->pId[ nLevel ] = id; } if( fEOL ) { --pCtx->pHead; _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); } if( HB_IS_STRING( pValue ) ) { HB_SIZE nPos, nLen = hb_itemGetCLen( pValue ); const char * szString = hb_itemGetCPtr( pValue ); char buf[ 8 ]; _hb_jsonCtxAdd( pCtx, "\"", 1 ); if( cdp ) { HB_WCHAR wc; nPos = 0; while( HB_CDPCHAR_GET( cdp, szString, nLen, &nPos, &wc ) ) { if( wc >= ' ' && wc < 0x7F && wc != '\\' && wc != '\"' ) { 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; } } } else { nPos = 0; while( nPos < nLen ) { unsigned char uch = szString[ nPos ]; HB_SIZE 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 ); } else if( HB_IS_NUMINT( pValue ) ) { char buf[ 24 ]; HB_MAXINT nVal = hb_itemGetNInt( pValue ); HB_BOOL fNeg = nVal < 0; int i = 0; if( fNeg ) nVal = -nVal; do buf[ sizeof( buf ) - ++i ] = ( nVal % 10 ) + '0'; while( ( nVal /= 10 ) != 0 ); if( fNeg ) buf[ sizeof( buf ) - ++i ] = '-'; _hb_jsonCtxAdd( pCtx, &buf[ sizeof( buf ) - i ], i ); } else if( HB_IS_NUMERIC( pValue ) ) { char buf[ 64 ]; int iDec; double dblValue = hb_itemGetNDDec( pValue, &iDec ); hb_snprintf( buf, sizeof( buf ), "%.*f", iDec, dblValue ); _hb_jsonCtxAdd( pCtx, buf, strlen( buf ) ); } else if( HB_IS_NIL( pValue ) ) { _hb_jsonCtxAdd( pCtx, "null", 4 ); } else if( HB_IS_LOGICAL( pValue ) ) { if( hb_itemGetL( pValue ) ) _hb_jsonCtxAdd( pCtx, "true", 4 ); else _hb_jsonCtxAdd( pCtx, "false", 5 ); } else if( HB_IS_DATE( pValue ) ) { char szBuffer[ 10 ]; hb_itemGetDS( pValue, szBuffer + 1 ); szBuffer[ 0 ] = '\"'; szBuffer[ 9 ] = '\"'; _hb_jsonCtxAdd( pCtx, szBuffer, 10 ); } else if( HB_IS_TIMESTAMP( pValue ) ) { char szBuffer[ 19 ]; hb_itemGetTS( pValue, szBuffer + 1 ); szBuffer[ 0 ] = '\"'; szBuffer[ 18 ] = '\"'; _hb_jsonCtxAdd( pCtx, szBuffer, 19 ); } else if( HB_IS_ARRAY( pValue ) ) { HB_SIZE nLen = hb_itemSize( pValue ); if( nLen ) { HB_SIZE nIndex; if( pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "[", 1 ); for( nIndex = 1; nIndex <= nLen; nIndex++ ) { PHB_ITEM pItem = hb_arrayGetItemPtr( pValue, nIndex ); if( nIndex > 1 ) _hb_jsonCtxAdd( pCtx, ",", 1 ); if( pCtx->fHuman ) _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); if( pCtx->fHuman && ! ( ( HB_IS_ARRAY( pItem ) || HB_IS_HASH( pItem ) ) && hb_itemSize( pItem ) > 0 ) ) _hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE ); _hb_jsonEncode( pItem, pCtx, nLevel + 1, HB_FALSE, cdp ); } if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); } _hb_jsonCtxAdd( pCtx, "]", 1 ); } else _hb_jsonCtxAdd( pCtx, "[]", 2 ); } else if( HB_IS_HASH( pValue ) ) { HB_SIZE nLen = hb_hashLen( pValue ); if( nLen ) { HB_SIZE nIndex; if( pCtx->fHuman ) _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); _hb_jsonCtxAdd( pCtx, "{", 1 ); for( nIndex = 1; nIndex <= nLen; nIndex++ ) { PHB_ITEM pKey = hb_hashGetKeyAt( pValue, nIndex ); if( HB_IS_STRING( pKey ) ) { PHB_ITEM pItem = hb_hashGetValueAt( pValue, nIndex ); if( nIndex > 1 ) _hb_jsonCtxAdd( pCtx, ",", 1 ); if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, ( nLevel + 1 ) * INDENT_SIZE ); } _hb_jsonEncode( pKey, pCtx, nLevel + 1, HB_FALSE, cdp ); if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, ": ", 2 ); fEOL = ( HB_IS_ARRAY( pItem ) || HB_IS_HASH( pItem ) ) && hb_itemSize( pItem ) > 0; } else { _hb_jsonCtxAdd( pCtx, ":", 1 ); fEOL = HB_FALSE; } _hb_jsonEncode( pItem, pCtx, nLevel + 1, fEOL, cdp ); } } if( pCtx->fHuman ) { _hb_jsonCtxAdd( pCtx, pCtx->szEol, pCtx->iEolLen ); _hb_jsonCtxAddIndent( pCtx, nLevel * INDENT_SIZE ); } _hb_jsonCtxAdd( pCtx, "}", 1 ); } else _hb_jsonCtxAdd( pCtx, "{}", 2 ); } else { /* All unsupported types are replacd by null */ _hb_jsonCtxAdd( pCtx, "null", 4 ); } }