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:
@@ -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
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user