Added a custom tag (void*) to the Node object and a callback before freeing a Node. This to aid in resource management for a scripting language with auto-garbage collection.

This commit is contained in:
Thijs Schreijer 2012-05-06 23:10:07 +02:00
parent e570b7943d
commit 2b4c5f8168
6 changed files with 103 additions and 3 deletions

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug Lib|Win32">
@ -158,7 +158,7 @@
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\ixml\inc;..\..\ixml\src\inc;..\inc;..\..\upnp\inc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>DEBUG;WIN32;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL;_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_AFX_SECURE_NO_WARNINGS;_AFX_SECURE_NO_DEPRECATE;_SECURE_ATL;_ATL_NO_COM_SUPPORT;_ATL_SECURE_NO_WARNINGS;_ATL_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>DEBUG;WIN32;_USRDLL;LIBUPNP_EXPORTS;UPNP_USE_MSVCPP;SCRIPTSUPPORT;_CRT_NONSTDC_NO_WARNINGS;_CRT_NONSTDC_NO_DEPRECATE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;_SECURE_SCL;_SCL_SECURE_NO_WARNINGS;_SCL_SECURE_NO_DEPRECATE;_AFX_SECURE_NO_WARNINGS;_AFX_SECURE_NO_DEPRECATE;_SECURE_ATL;_ATL_NO_COM_SUPPORT;_ATL_SECURE_NO_WARNINGS;_ATL_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>

View File

@ -158,6 +158,13 @@ typedef struct _IXML_Document *Docptr;
typedef struct _IXML_Node *Nodeptr;
#ifdef SCRIPTSUPPORT
/*!
* \brief Signature for GC support method, called before a node is freed.
*/
typedef void (*IXML_BeforeFreeNode_t) (Nodeptr obj);
#endif
/*!
* \brief Data structure common to all types of nodes.
@ -178,6 +185,9 @@ typedef struct _IXML_Node
Nodeptr nextSibling;
Nodeptr firstAttr;
Docptr ownerDocument;
#ifdef SCRIPTSUPPORT
void* ctag; // custom tag
#endif
} IXML_Node;
@ -625,9 +635,29 @@ EXPORT_SPEC BOOL ixmlNode_hasAttributes(
* \brief Frees a \b Node and all \b Nodes in its subtree.
*/
EXPORT_SPEC void ixmlNode_free(
/*! [in] The \b Node tree to free. */
/*! [in] The \b Node tree to free. Before it is freed, the handler
* set by \b ixmlSetBeforeFree will be called, the order will be
* top-down.
*/
IXML_Node *nodeptr);
#ifdef SCRIPTSUPPORT
/*!
* \brief Sets the custom tag for the node.
*/
EXPORT_SPEC void ixmlNode_setCTag(
/*! [in] The \b Node to which to attach the tag. */
IXML_Node *nodeptr,
/*! [in] The \b tag to attach. */
void *ctag);
/*!
* \brief Gets the custom tag for the node.
*/
EXPORT_SPEC void* ixmlNode_getCTag(
/*! [in] The \b Node from which to get the tag. */
IXML_Node *nodeptr);
#endif
/* @} Interface Node */
@ -1737,6 +1767,18 @@ EXPORT_SPEC void ixmlRelaxParser(
*/
char errorChar);
#ifdef SCRIPTSUPPORT
/*!
* \brief Sets the handler to call before a node is freed.
*/
EXPORT_SPEC void ixmlSetBeforeFree(
/*! [in] If \b hndlr is set to a function, it will be called before any
* node is freed, with the node as its parameter. This allows scripting
* languages to do their garbage collection, without maintaining their
* own tree structure.
*/
IXML_BeforeFreeNode_t hndlr);
#endif
/*!
* \brief Parses an XML text buffer converting it into an IXML DOM representation.

View File

@ -120,6 +120,25 @@ void Parser_setErrorChar(
/*! [in] The character to become the error character. */
char c);
#ifdef SCRIPTSUPPORT
/*!
* \brief Sets the handler to call before a node is freed.
*
* If \b hndlr is set to a function, it will be called before any
* node is freed, with the node as its parameter. This allows scripting
* languages to do their garbage collection, without maintaining their
* own tree structure.
*/
void Parser_setBeforeFree(
/*! [in] The handler callback to call before each node to be freed. */
IXML_BeforeFreeNode_t hndlr);
/*!
* \brief Gets the handler to call before a node is freed.
*/
IXML_BeforeFreeNode_t Parser_getBeforeFree();
#endif
/*!
* \brief Fees a node contents.

View File

@ -417,6 +417,13 @@ void ixmlRelaxParser(char errorChar)
Parser_setErrorChar(errorChar);
}
#ifdef SCRIPTSUPPORT
void ixmlSetBeforeFree(IXML_BeforeFreeNode_t hndlr)
{
Parser_setBeforeFree(hndlr);
}
#endif
int ixmlParseBufferEx(const char *buffer, IXML_Document **retDoc)
{

View File

@ -55,6 +55,9 @@
static char g_error_char = '\0';
#ifdef SCRIPTSUPPORT
static IXML_BeforeFreeNode_t Before_Free_callback;
#endif
static const char LESSTHAN = '<';
@ -2498,6 +2501,17 @@ void Parser_setErrorChar(char c)
g_error_char = c;
}
#ifdef SCRIPTSUPPORT
void Parser_setBeforeFree(IXML_BeforeFreeNode_t hndlr)
{
Before_Free_callback = hndlr;
}
IXML_BeforeFreeNode_t Parser_getBeforeFree()
{
return Before_Free_callback;
}
#endif
/*!
* \brief Initializes a xml parser.

View File

@ -107,6 +107,10 @@ static void ixmlNode_freeSingleNode(
void ixmlNode_free(IXML_Node *nodeptr)
{
if (nodeptr != NULL) {
#ifdef SCRIPTSUPPORT
IXML_BeforeFreeNode_t hndlr = Parser_getBeforeFree();
if (hndlr != NULL) hndlr(nodeptr);
#endif
ixmlNode_free(nodeptr->firstChild);
ixmlNode_free(nodeptr->nextSibling);
ixmlNode_free(nodeptr->firstAttr);
@ -1377,3 +1381,17 @@ ErrorHandler:
return IXML_INSUFFICIENT_MEMORY;
}
#ifdef SCRIPTSUPPORT
void ixmlNode_setCTag(IXML_Node *nodeptr, void *ctag)
{
if (nodeptr != NULL) nodeptr->ctag = ctag;
}
void* ixmlNode_getCTag(IXML_Node *nodeptr)
{
if (nodeptr != NULL)
return nodeptr->ctag;
else
return NULL;
}
#endif