2011-01-15 13:47 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/contrib/hbmxml/hbmxml.c
    ! fixed using released strings
    ! added missing callback item clearing
    ! release previous callback items in MXMLSETERRORCALLBACK() and
      MXMLSETCUSTOMHANDLERS() - it fixes memory leak in repeated calls
      and allows to free all items used by codeblock callbacks before
      application/thread exit.
    ; small note about TSD functions:
         hb_stackGetTSD() always returns non NULL pointer, on first call
         it allocates and initialize new structure. It's not necessary to
         check if return value is not NULL.
         hb_stackTestTSD() return NULL if TSD structure is not allocated
         yet by current thread, otherwise it returns this structure.
         Newly allocated TSD structures are cleared so it's not necessary
         to clear their members inside init functions. In such case init
         functions can be ignored (set to NULL in HB_TSD_NEW().
         I know that on some platforms NULL can be represented as non
         0 value anyhow current Harbour code is not ready to work with
         such platforms and needs a lot of modifications to adopt it
         to such condition. I do not expect that anyone will try to
         make such port in the future.
    ; QUESTION: why custom_save_cb() uses hb_parc() instead of 
                hb_parstr_utf8()?
    ; QUESTION2: what TODO in MXMLDELETE() means?
This commit is contained in:
Przemyslaw Czerpak
2011-01-15 12:48:01 +00:00
parent 82df9ab45a
commit 2b7384befc
2 changed files with 102 additions and 33 deletions

View File

@@ -16,6 +16,32 @@
The license applies to all entries newer than 2009-04-28.
*/
2011-01-15 13:47 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/hbmxml/hbmxml.c
! fixed using released strings
! added missing callback item clearing
! release previous callback items in MXMLSETERRORCALLBACK() and
MXMLSETCUSTOMHANDLERS() - it fixes memory leak in repeated calls
and allows to free all items used by codeblock callbacks before
application/thread exit.
; small note about TSD functions:
hb_stackGetTSD() always returns non NULL pointer, on first call
it allocates and initialize new structure. It's not necessary to
check if return value is not NULL.
hb_stackTestTSD() return NULL if TSD structure is not allocated
yet by current thread, otherwise it returns this structure.
Newly allocated TSD structures are cleared so it's not necessary
to clear their members inside init functions. In such case init
functions can be ignored (set to NULL in HB_TSD_NEW().
I know that on some platforms NULL can be represented as non
0 value anyhow current Harbour code is not ready to work with
such platforms and needs a lot of modifications to adopt it
to such condition. I do not expect that anyone will try to
make such port in the future.
; QUESTION: why custom_save_cb() uses hb_parc() instead of
hb_parstr_utf8()?
; QUESTION2: what TODO in MXMLDELETE() means?
2011-01-15 12:07 UTC+0100 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/include/hbapi.h
* harbour/include/hbwmain.c

View File

@@ -78,6 +78,7 @@ typedef struct
PHB_ITEM type_cb;
PHB_ITEM save_cb;
PHB_ITEM sax_cb;
void * hText;
} HB_CBS_VAR;
typedef struct
@@ -749,7 +750,7 @@ HB_FUNC( MXMLINDEXRESET )
static mxml_type_t type_cb( mxml_node_t * node )
{
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackGetTSD( &s_cbs_var );
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackTestTSD( &s_cbs_var );
if( pCbs != NULL )
{
@@ -1153,7 +1154,7 @@ HB_FUNC( MXMLRETAIN )
static void sax_cb( mxml_node_t * node, mxml_sax_event_t event, void * data )
{
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackGetTSD( &s_cbs_var );
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackTestTSD( &s_cbs_var );
if( node != NULL && pCbs != NULL )
{
@@ -1338,17 +1339,21 @@ HB_FUNC( MXMLSAXLOADSTRING )
static const char * save_cb( mxml_node_t * node, int where )
{
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackGetTSD( &s_cbs_var );
HB_CBS_VAR * pCbs = ( HB_CBS_VAR * ) hb_stackTestTSD( &s_cbs_var );
if( node != NULL && pCbs != NULL )
{
PHB_ITEM pCallback = pCbs->save_cb;
if( pCbs->hText )
{
hb_strfree( pCbs->hText );
pCbs->hText = NULL;
}
if( pCallback && hb_vmRequestReenter() )
{
PHB_ITEM pNode = hb_itemNew( NULL );
PHB_ITEM pResult;
const char * pszResult;
hbmxml_node_ItemPut( pNode, node, 0 );
@@ -1359,24 +1364,7 @@ static const char * save_cb( mxml_node_t * node, int where )
hb_vmPushInteger( where );
hb_vmSend( 2 );
pResult = hb_param( -1, HB_IT_ANY );
if( hb_itemType( pResult ) == HB_IT_STRING )
{
void * hText;
HB_SIZE nText;
const char * pszText = hb_itemGetStrUTF8( pResult, &hText, &nText );
int TOFIX;
/* TOFIX: This will free pszText pointer, so the returned string buffer will
be invalid. [vszakats] */
hb_strfree( hText );
pszResult = pszText;
}
else
pszResult = NULL;
pszResult = hb_itemGetStrUTF8( hb_param( -1, HB_IT_ANY ), &pCbs->hText, NULL );
hb_itemRelease( pNode );
hb_vmRequestRestore();
@@ -1408,6 +1396,11 @@ HB_FUNC( MXMLSAVEALLOCSTRING )
bytes = mxmlSaveString( node, buffer, BUFFER_SIZE, cb );
pCbs->save_cb = NULL;
if( pCbs->hText )
{
hb_strfree( pCbs->hText );
pCbs->hText = NULL;
}
if( bytes <= 0 )
hb_retc_null();
@@ -1455,6 +1448,11 @@ HB_FUNC( MXMLSAVEFILE )
}
pCbs->save_cb = NULL;
if( pCbs->hText )
{
hb_strfree( pCbs->hText );
pCbs->hText = NULL;
}
hb_strfree( hFree );
}
else
@@ -1487,7 +1485,6 @@ HB_FUNC( MXMLSAVESTRING )
if( hb_itemGetWriteCL( pBuffer, &buffer, &buffer_size ) )
{
int bytes = mxmlSaveString( node, buffer, ( int ) buffer_size, cb );
pCbs->save_cb = NULL;
if( bytes <= 0 )
hb_retni( -1 );
@@ -1501,6 +1498,13 @@ HB_FUNC( MXMLSAVESTRING )
}
else
hb_retni( -2 );
pCbs->save_cb = NULL;
if( pCbs->hText )
{
hb_strfree( pCbs->hText );
pCbs->hText = NULL;
}
}
else
hb_retni( -3 );
@@ -1549,7 +1553,7 @@ HB_FUNC( MXMLSETELEMENT )
static void error_cb( const char * pszErrorMsg )
{
HB_ERROR_CB_VAR * pError_cb = ( HB_ERROR_CB_VAR * ) hb_stackGetTSD( &s_error_cb_var );
HB_ERROR_CB_VAR * pError_cb = ( HB_ERROR_CB_VAR * ) hb_stackTestTSD( &s_error_cb_var );
if( pError_cb != NULL )
{
@@ -1569,16 +1573,30 @@ static void error_cb( const char * pszErrorMsg )
HB_FUNC( MXMLSETERRORCALLBACK )
{
if( HB_ISBLOCK( 1 ) || HB_ISSYMBOL( 1 ) )
PHB_ITEM pError = hb_param( 1, HB_IT_BLOCK | HB_IT_SYMBOL );
if( pError )
{
HB_ERROR_CB_VAR * pError_cb = ( HB_ERROR_CB_VAR * ) hb_stackGetTSD( &s_error_cb_var );
pError_cb->error_cb = hb_itemNew( hb_param( 1, HB_IT_BLOCK | HB_IT_SYMBOL ) );
if( pError_cb->error_cb )
hb_itemRelease( pError_cb->error_cb );
pError_cb->error_cb = hb_itemNew( pError );
mxmlSetErrorCallback( error_cb );
}
else
{
HB_ERROR_CB_VAR * pError_cb = ( HB_ERROR_CB_VAR * ) hb_stackTestTSD( &s_error_cb_var );
if( pError_cb && pError_cb->error_cb )
{
hb_itemRelease( pError_cb->error_cb );
pError_cb->error_cb = NULL;
}
mxmlSetErrorCallback( NULL );
}
}
/* int mxmlSetInteger( mxml_node_t * node, int integer ) */
@@ -1804,7 +1822,7 @@ HB_FUNC( MXMLSETCUSTOM )
static int custom_load_cb( mxml_node_t * node, const char * data )
{
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackGetTSD( &s_custom_cbs_var );
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackTestTSD( &s_custom_cbs_var );
if( node != NULL && pCCbs != NULL && data != NULL )
{
@@ -1839,7 +1857,7 @@ static int custom_load_cb( mxml_node_t * node, const char * data )
static char * custom_save_cb( mxml_node_t * node )
{
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackGetTSD( &s_custom_cbs_var );
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackTestTSD( &s_custom_cbs_var );
if( node != NULL && pCCbs != NULL )
{
@@ -1873,16 +1891,41 @@ static char * custom_save_cb( mxml_node_t * node )
HB_FUNC( MXMLSETCUSTOMHANDLERS )
{
if( ( HB_ISBLOCK( 1 ) || HB_ISSYMBOL( 1 ) ) &&
( HB_ISBLOCK( 2 ) || HB_ISSYMBOL( 2 ) ) )
PHB_ITEM pLoad = hb_param( 1, HB_IT_BLOCK | HB_IT_SYMBOL ),
pSave = hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL );
if( pLoad && pSave )
{
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackGetTSD( &s_custom_cbs_var );
pCCbs->load_cb = hb_itemNew( hb_param( 1, HB_IT_BLOCK | HB_IT_SYMBOL ) );
pCCbs->save_cb = hb_itemNew( hb_param( 2, HB_IT_BLOCK | HB_IT_SYMBOL ) );
if( pCCbs->load_cb )
hb_itemRelease( pCCbs->load_cb );
pCCbs->load_cb = hb_itemNew( pLoad );
if( pCCbs->save_cb )
hb_itemRelease( pCCbs->save_cb );
pCCbs->save_cb = hb_itemNew( pSave );
mxmlSetCustomHandlers( custom_load_cb, custom_save_cb );
}
else
{
HB_CUSTOM_CBS_VAR * pCCbs = ( HB_CUSTOM_CBS_VAR * ) hb_stackTestTSD( &s_custom_cbs_var );
if( pCCbs )
{
if( pCCbs->load_cb )
{
hb_itemRelease( pCCbs->load_cb );
pCCbs->load_cb = NULL;
}
if( pCCbs->save_cb )
{
hb_itemRelease( pCCbs->save_cb );
pCCbs->save_cb = NULL;
}
}
mxmlSetCustomHandlers( NULL, NULL );
}
}