mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-10-31 18:39:57 +00:00
Add alternate string management support.
This commit is contained in:
parent
1dfe8e7ac9
commit
9e22b3ef64
@ -9,6 +9,8 @@
|
||||
`MXML_TYPE_DIRECTIVE` node types (Issue #250)
|
||||
- Added `mxmlLoadFilename` and `mxmlSaveFilename` functions (Issue #291)
|
||||
- Added AFL fuzzing support (Issue #306)
|
||||
- Added string copy/free callbacks to support alternate memory management of
|
||||
strings.
|
||||
- Renamed `mxml_type_t` enumerations to `MXML_TYPE_xxx` (Issue #251)
|
||||
- Updated APIs to use bool type instead of an int representing a boolean value.
|
||||
- Updated the SAX callback to return a `bool` value to control processing
|
||||
|
16
mxml-attr.c
16
mxml-attr.c
@ -45,8 +45,8 @@ mxmlElementDeleteAttr(mxml_node_t *node,// I - Element
|
||||
if (!strcmp(attr->name, name))
|
||||
{
|
||||
// Delete this attribute...
|
||||
free(attr->name);
|
||||
free(attr->value);
|
||||
_mxml_strfree(attr->name);
|
||||
_mxml_strfree(attr->value);
|
||||
|
||||
i --;
|
||||
if (i > 0)
|
||||
@ -165,7 +165,7 @@ mxmlElementSetAttr(mxml_node_t *node, // I - Element node
|
||||
|
||||
if (value)
|
||||
{
|
||||
if ((valuec = strdup(value)) == NULL)
|
||||
if ((valuec = _mxml_strcopy(value)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
return;
|
||||
@ -177,7 +177,7 @@ mxmlElementSetAttr(mxml_node_t *node, // I - Element node
|
||||
}
|
||||
|
||||
if (!mxml_set_attr(node, name, valuec))
|
||||
free(valuec);
|
||||
_mxml_strfree(valuec);
|
||||
}
|
||||
|
||||
|
||||
@ -212,10 +212,10 @@ mxmlElementSetAttrf(mxml_node_t *node, // I - Element node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((value = strdup(buffer)) == NULL)
|
||||
if ((value = _mxml_strcopy(buffer)) == NULL)
|
||||
_mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
else if (!mxml_set_attr(node, name, value))
|
||||
free(value);
|
||||
_mxml_strfree(value);
|
||||
}
|
||||
|
||||
|
||||
@ -238,7 +238,7 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
if (!strcmp(attr->name, name))
|
||||
{
|
||||
// Free the old value as needed...
|
||||
free(attr->value);
|
||||
_mxml_strfree(attr->value);
|
||||
attr->value = value;
|
||||
|
||||
return (true);
|
||||
@ -255,7 +255,7 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
node->value.element.attrs = attr;
|
||||
attr += node->value.element.num_attrs;
|
||||
|
||||
if ((attr->name = strdup(name)) == NULL)
|
||||
if ((attr->name = _mxml_strcopy(name)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
return (false);
|
||||
|
44
mxml-file.c
44
mxml-file.c
@ -527,50 +527,6 @@ mxmlSaveString(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetCustomHandlers()' - Set the handling functions for custom data.
|
||||
//
|
||||
// The load function accepts a node pointer and a data string and must
|
||||
// return 0 on success and non-zero on error.
|
||||
//
|
||||
// The save function accepts a node pointer and must return a malloc'd
|
||||
// string on success and `NULL` on error.
|
||||
//
|
||||
|
||||
void
|
||||
mxmlSetCustomCallbacks(
|
||||
mxml_custom_load_cb_t load_cb, // I - Load callback function
|
||||
mxml_custom_save_cb_t save_cb, // I - Save callback function
|
||||
void *cbdata) // I - Callback data
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
global->custom_load_cb = load_cb;
|
||||
global->custom_save_cb = save_cb;
|
||||
global->custom_cbdata = cbdata;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetErrorCallback()' - Set the error message callback.
|
||||
//
|
||||
|
||||
void
|
||||
mxmlSetErrorCallback(
|
||||
mxml_error_cb_t cb, // I - Error callback function
|
||||
void *cbdata) // I - Error callback data
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
global->error_cb = cb;
|
||||
global->error_cbdata = cbdata;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetWrapMargin()' - Set the wrap margin when saving XML data.
|
||||
//
|
||||
|
@ -33,7 +33,7 @@ mxmlIndexDelete(mxml_index_t *ind) // I - Index to delete
|
||||
return;
|
||||
|
||||
// Free memory...
|
||||
free(ind->attr);
|
||||
_mxml_strfree(ind->attr);
|
||||
free(ind->nodes);
|
||||
free(ind);
|
||||
}
|
||||
@ -228,7 +228,7 @@ mxmlIndexNew(mxml_node_t *node, // I - XML node tree
|
||||
|
||||
if (attr)
|
||||
{
|
||||
if ((ind->attr = strdup(attr)) == NULL)
|
||||
if ((ind->attr = _mxml_strcopy(attr)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for index attribute.");
|
||||
free(ind);
|
||||
|
44
mxml-node.c
44
mxml-node.c
@ -207,7 +207,7 @@ mxmlNewCDATA(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_CDATA)) != NULL)
|
||||
{
|
||||
if ((node->value.cdata = strdup(data)) == NULL)
|
||||
if ((node->value.cdata = _mxml_strcopy(data)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA.");
|
||||
mxmlDelete(node);
|
||||
@ -251,7 +251,7 @@ mxmlNewCDATAf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.cdata = strdup(buffer);
|
||||
node->value.cdata = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -283,7 +283,7 @@ mxmlNewComment(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_COMMENT)) != NULL)
|
||||
{
|
||||
if ((node->value.comment = strdup(comment)) == NULL)
|
||||
if ((node->value.comment = _mxml_strcopy(comment)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment.");
|
||||
mxmlDelete(node);
|
||||
@ -327,7 +327,7 @@ mxmlNewCommentf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.comment = strdup(buffer);
|
||||
node->value.comment = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -391,7 +391,7 @@ mxmlNewDeclaration(
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DECLARATION)) != NULL)
|
||||
{
|
||||
if ((node->value.declaration = strdup(declaration)) == NULL)
|
||||
if ((node->value.declaration = _mxml_strcopy(declaration)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration.");
|
||||
mxmlDelete(node);
|
||||
@ -436,7 +436,7 @@ mxmlNewDeclarationf(
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.declaration = strdup(buffer);
|
||||
node->value.declaration = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -468,7 +468,7 @@ mxmlNewDirective(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DIRECTIVE)) != NULL)
|
||||
{
|
||||
if ((node->value.directive = strdup(directive)) == NULL)
|
||||
if ((node->value.directive = _mxml_strcopy(directive)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for processing instruction.");
|
||||
mxmlDelete(node);
|
||||
@ -512,7 +512,7 @@ mxmlNewDirectivef(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.directive = strdup(buffer);
|
||||
node->value.directive = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -542,7 +542,7 @@ mxmlNewElement(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
|
||||
// Create the node and set the element name...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_ELEMENT)) != NULL)
|
||||
node->value.element.name = strdup(name);
|
||||
node->value.element.name = _mxml_strcopy(name);
|
||||
|
||||
return (node);
|
||||
}
|
||||
@ -597,7 +597,7 @@ mxmlNewOpaque(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
|
||||
// Create the node and set the element name...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_OPAQUE)) != NULL)
|
||||
node->value.opaque = strdup(opaque);
|
||||
node->value.opaque = _mxml_strcopy(opaque);
|
||||
|
||||
return (node);
|
||||
}
|
||||
@ -635,7 +635,7 @@ mxmlNewOpaquef(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.opaque = strdup(buffer);
|
||||
node->value.opaque = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -695,7 +695,7 @@ mxmlNewText(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
if ((node = mxml_new(parent, MXML_TYPE_TEXT)) != NULL)
|
||||
{
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = strdup(string);
|
||||
node->value.text.string = _mxml_strcopy(string);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -737,7 +737,7 @@ mxmlNewTextf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
va_end(ap);
|
||||
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = strdup(buffer);
|
||||
node->value.text.string = _mxml_strcopy(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -854,26 +854,26 @@ mxml_free(mxml_node_t *node) // I - Node
|
||||
switch (node->type)
|
||||
{
|
||||
case MXML_TYPE_CDATA :
|
||||
free(node->value.cdata);
|
||||
_mxml_strfree(node->value.cdata);
|
||||
break;
|
||||
case MXML_TYPE_COMMENT :
|
||||
free(node->value.comment);
|
||||
_mxml_strfree(node->value.comment);
|
||||
break;
|
||||
case MXML_TYPE_DECLARATION :
|
||||
free(node->value.declaration);
|
||||
_mxml_strfree(node->value.declaration);
|
||||
break;
|
||||
case MXML_TYPE_DIRECTIVE :
|
||||
free(node->value.directive);
|
||||
_mxml_strfree(node->value.directive);
|
||||
break;
|
||||
case MXML_TYPE_ELEMENT :
|
||||
free(node->value.element.name);
|
||||
_mxml_strfree(node->value.element.name);
|
||||
|
||||
if (node->value.element.num_attrs)
|
||||
{
|
||||
for (i = 0; i < node->value.element.num_attrs; i ++)
|
||||
{
|
||||
free(node->value.element.attrs[i].name);
|
||||
free(node->value.element.attrs[i].value);
|
||||
_mxml_strfree(node->value.element.attrs[i].name);
|
||||
_mxml_strfree(node->value.element.attrs[i].value);
|
||||
}
|
||||
|
||||
free(node->value.element.attrs);
|
||||
@ -883,13 +883,13 @@ mxml_free(mxml_node_t *node) // I - Node
|
||||
// Nothing to do
|
||||
break;
|
||||
case MXML_TYPE_OPAQUE :
|
||||
free(node->value.opaque);
|
||||
_mxml_strfree(node->value.opaque);
|
||||
break;
|
||||
case MXML_TYPE_REAL :
|
||||
// Nothing to do
|
||||
break;
|
||||
case MXML_TYPE_TEXT :
|
||||
free(node->value.text.string);
|
||||
_mxml_strfree(node->value.text.string);
|
||||
break;
|
||||
case MXML_TYPE_CUSTOM :
|
||||
if (node->value.custom.data && node->value.custom.destroy)
|
||||
|
220
mxml-private.c
220
mxml-private.c
@ -39,6 +39,184 @@
|
||||
#endif // __sun
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetCustomHandlers()' - Set the custom data callbacks.
|
||||
//
|
||||
// This function sets the callbacks that are used for loading and saving custom
|
||||
// data types. The load callback `load_cb` accepts the callback data pointer
|
||||
// `cbdata`, a node pointer, and a data string and returns `true` on success and
|
||||
// `false` on error, for example:
|
||||
//
|
||||
// ```c
|
||||
// typedef struct
|
||||
// {
|
||||
// unsigned year, /* Year */
|
||||
// month, /* Month */
|
||||
// day, /* Day */
|
||||
// hour, /* Hour */
|
||||
// minute, /* Minute */
|
||||
// second; /* Second */
|
||||
// time_t unix; /* UNIX time */
|
||||
// } iso_date_time_t;
|
||||
//
|
||||
// bool
|
||||
// my_custom_load_cb(void *cbdata, mxml_node_t *node, const char *data)
|
||||
// {
|
||||
// iso_date_time_t *dt;
|
||||
// struct tm tmdata;
|
||||
//
|
||||
// /* Allocate custom data structure ... */
|
||||
// dt = calloc(1, sizeof(iso_date_time_t));
|
||||
//
|
||||
// /* Parse the data string... */
|
||||
// if (sscanf(data, "%u-%u-%uT%u:%u:%uZ", &(dt->year), &(dt->month),
|
||||
// &(dt->day), &(dt->hour), &(dt->minute), &(dt->second)) != 6)
|
||||
// {
|
||||
// /* Unable to parse date and time numbers... */
|
||||
// free(dt);
|
||||
// return (false);
|
||||
// }
|
||||
//
|
||||
// /* Range check values... */
|
||||
// if (dt->month < 1 || dt->month > 12 || dt->day < 1 || dt->day > 31 ||
|
||||
// dt->hour < 0 || dt->hour > 23 || dt->minute < 0 || dt->minute > 59 ||
|
||||
// dt->second < 0 || dt->second > 60)
|
||||
// {
|
||||
// /* Date information is out of range... */
|
||||
// free(dt);
|
||||
// return (false);
|
||||
// }
|
||||
//
|
||||
// /* Convert ISO time to UNIX time in seconds... */
|
||||
// tmdata.tm_year = dt->year - 1900;
|
||||
// tmdata.tm_mon = dt->month - 1;
|
||||
// tmdata.tm_day = dt->day;
|
||||
// tmdata.tm_hour = dt->hour;
|
||||
// tmdata.tm_min = dt->minute;
|
||||
// tmdata.tm_sec = dt->second;
|
||||
//
|
||||
// dt->unix = gmtime(&tmdata);
|
||||
//
|
||||
// /* Set custom data and free function... */
|
||||
// mxmlSetCustom(node, data, free);
|
||||
//
|
||||
// /* Return with no errors... */
|
||||
// return (true);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// The save callback `save_cb` accepts the callback data pointer `cbdata` and a
|
||||
// node pointer and returns a malloc'd string on success and `NULL` on error,
|
||||
// for example:
|
||||
//
|
||||
// ```c
|
||||
// char *
|
||||
// my_custom_save_cb(void *cbdata, mxml_node_t *node)
|
||||
// {
|
||||
// char data[255];
|
||||
// iso_date_time_t *dt;
|
||||
//
|
||||
// /* Get the custom data structure */
|
||||
// dt = (iso_date_time_t *)mxmlGetCustom(node);
|
||||
//
|
||||
// /* Generate string version of the date/time... */
|
||||
// snprintf(data, sizeof(data), "%04u-%02u-%02uT%02u:%02u:%02uZ",
|
||||
// dt->year, dt->month, dt->day, dt->hour, dt->minute, dt->second);
|
||||
//
|
||||
// /* Duplicate the string and return... */
|
||||
// return (strdup(data));
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
|
||||
|
||||
void
|
||||
mxmlSetCustomCallbacks(
|
||||
mxml_custom_load_cb_t load_cb, // I - Load callback function
|
||||
mxml_custom_save_cb_t save_cb, // I - Save callback function
|
||||
void *cbdata) // I - Callback data
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
global->custom_load_cb = load_cb;
|
||||
global->custom_save_cb = save_cb;
|
||||
global->custom_cbdata = cbdata;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetErrorCallback()' - Set the error message callback.
|
||||
//
|
||||
// This function sets a function to use when reporting errors. The callback
|
||||
// `cb` accepts the data pointer `cbdata` and a string pointer containing the
|
||||
// error message:
|
||||
//
|
||||
// ```c
|
||||
// void my_error_cb(void *cbdata, const char *message)
|
||||
// {
|
||||
// fprintf(stderr, "myprogram: %s\n", message);
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// The default error callback writes the error message to the `stderr` file.
|
||||
//
|
||||
|
||||
void
|
||||
mxmlSetErrorCallback(
|
||||
mxml_error_cb_t cb, // I - Error callback function
|
||||
void *cbdata) // I - Error callback data
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
global->error_cb = cb;
|
||||
global->error_cbdata = cbdata;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetStringCallbacks()' - Set the string copy/free callback functions.
|
||||
//
|
||||
// This function sets the string copy/free callback functions for the current
|
||||
// thread. The `strcopy_cb` function makes a copy of the provided string while
|
||||
// the `strfree_cb` function frees the copy. Each callback accepts the
|
||||
// `str_cbdata` pointer along with the pointer to the string:
|
||||
//
|
||||
// ```c
|
||||
// char *my_strcopy_cb(void *cbdata, const char *s)
|
||||
// {
|
||||
// ... make a copy of "s" ...
|
||||
// }
|
||||
//
|
||||
// void my_strfree_cb(void *cbdata, char *s)
|
||||
// {
|
||||
// ... release the memory used by "s" ...
|
||||
// }
|
||||
// ```
|
||||
//
|
||||
// The default `strcopy_cb` function calls `strdup` while the default
|
||||
// `strfree_cb` function calls `free`.
|
||||
//
|
||||
|
||||
void
|
||||
mxmlSetStringCallbacks(
|
||||
mxml_strcopy_cb_t strcopy_cb, // I - String copy callback function
|
||||
mxml_strfree_cb_t strfree_cb, // I - String free callback function
|
||||
void *str_cbdata) // I - String callback data
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
global->strcopy_cb = strcopy_cb;
|
||||
global->strfree_cb = strfree_cb;
|
||||
global->str_cbdata = str_cbdata;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_mxml_error()' - Display an error message.
|
||||
//
|
||||
@ -70,6 +248,48 @@ _mxml_error(const char *format, // I - Printf-style format string
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_mxml_strcopy()' - Copy a string.
|
||||
//
|
||||
|
||||
char * // O - Copy of string
|
||||
_mxml_strcopy(const char *s) // I - String
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
if (!s)
|
||||
return (NULL);
|
||||
|
||||
if (global->strcopy_cb)
|
||||
return ((global->strcopy_cb)(global->str_cbdata, s));
|
||||
else
|
||||
return (strdup(s));
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// '_mxml_strfree()' - Free a string.
|
||||
//
|
||||
|
||||
void
|
||||
_mxml_strfree(char *s) // I - String
|
||||
{
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
|
||||
if (!s)
|
||||
return;
|
||||
|
||||
if (global->strfree_cb)
|
||||
(global->strfree_cb)(global->str_cbdata, s);
|
||||
else
|
||||
free((void *)s);
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_PTHREAD_H // POSIX threading
|
||||
# include <pthread.h>
|
||||
|
||||
|
@ -107,6 +107,9 @@ typedef struct _mxml_global_s // Global, per-thread data
|
||||
struct lconv *loc; // Locale data
|
||||
size_t loc_declen; // Length of decimal point string
|
||||
bool loc_set; // Locale data set?
|
||||
mxml_strcopy_cb_t strcopy_cb; // String copy callback function
|
||||
mxml_strfree_cb_t strfree_cb; // String free callback function
|
||||
void *str_cbdata; // String callback data
|
||||
int wrap; // Wrap margin
|
||||
} _mxml_global_t;
|
||||
|
||||
@ -119,6 +122,7 @@ extern _mxml_global_t *_mxml_global(void);
|
||||
extern int _mxml_entity_cb(void *cbdata, const char *name);
|
||||
extern const char *_mxml_entity_string(int ch);
|
||||
extern void _mxml_error(const char *format, ...) MXML_FORMAT(1,2);
|
||||
|
||||
extern char *_mxml_strcopy(const char *s);
|
||||
extern void _mxml_strfree(char *s);
|
||||
|
||||
#endif // !MXML_PRIVATE_H
|
||||
|
52
mxml-set.c
52
mxml-set.c
@ -47,13 +47,13 @@ mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
||||
}
|
||||
|
||||
// Allocate the new value, free any old element value, and set the new value...
|
||||
if ((s = strdup(data)) == NULL)
|
||||
if ((s = _mxml_strcopy(data)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.cdata);
|
||||
_mxml_strfree(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
|
||||
return (true);
|
||||
@ -94,13 +94,13 @@ mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.cdata);
|
||||
_mxml_strfree(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
|
||||
return (true);
|
||||
@ -137,13 +137,13 @@ mxmlSetComment(mxml_node_t *node, // I - Node
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(comment)) == NULL)
|
||||
if ((s = _mxml_strcopy(comment)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.comment);
|
||||
_mxml_strfree(node->value.comment);
|
||||
node->value.comment = s;
|
||||
|
||||
return (true);
|
||||
@ -184,13 +184,13 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.comment);
|
||||
_mxml_strfree(node->value.comment);
|
||||
node->value.comment = s;
|
||||
|
||||
return (true);
|
||||
@ -267,13 +267,13 @@ mxmlSetDeclaration(
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(declaration)) == NULL)
|
||||
if ((s = _mxml_strcopy(declaration)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.declaration);
|
||||
_mxml_strfree(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
|
||||
return (true);
|
||||
@ -314,13 +314,13 @@ mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.declaration);
|
||||
_mxml_strfree(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
|
||||
return (true);
|
||||
@ -357,13 +357,13 @@ mxmlSetDirective(mxml_node_t *node, // I - Node
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(directive)) == NULL)
|
||||
if ((s = _mxml_strcopy(directive)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.directive);
|
||||
_mxml_strfree(node->value.directive);
|
||||
node->value.directive = s;
|
||||
|
||||
return (true);
|
||||
@ -404,13 +404,13 @@ mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.directive);
|
||||
_mxml_strfree(node->value.directive);
|
||||
node->value.directive = s;
|
||||
|
||||
return (true);
|
||||
@ -446,13 +446,13 @@ mxmlSetElement(mxml_node_t *node, // I - Node to set
|
||||
return (true);
|
||||
|
||||
// Free any old element value and set the new value...
|
||||
if ((s = strdup(name)) == NULL)
|
||||
if ((s = _mxml_strcopy(name)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for element name.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.element.name);
|
||||
_mxml_strfree(node->value.element.name);
|
||||
node->value.element.name = s;
|
||||
|
||||
return (true);
|
||||
@ -518,13 +518,13 @@ mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
||||
return (true);
|
||||
|
||||
// Free any old opaque value and set the new value...
|
||||
if ((s = strdup(opaque)) == NULL)
|
||||
if ((s = _mxml_strcopy(opaque)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.opaque);
|
||||
_mxml_strfree(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
|
||||
return (true);
|
||||
@ -567,13 +567,13 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.opaque);
|
||||
_mxml_strfree(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
|
||||
return (true);
|
||||
@ -646,13 +646,13 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
}
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(string)) == NULL)
|
||||
if ((s = _mxml_strcopy(string)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for text string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.text.string);
|
||||
_mxml_strfree(node->value.text.string);
|
||||
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = s;
|
||||
@ -698,13 +698,13 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for text string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.text.string);
|
||||
_mxml_strfree(node->value.text.string);
|
||||
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = s;
|
||||
|
8
mxml.h
8
mxml.h
@ -124,6 +124,11 @@ typedef ssize_t (*mxml_read_cb_t)(void *cbdata, void *buffer, size_t bytes);
|
||||
typedef const char *(*mxml_save_cb_t)(void *cbdata, mxml_node_t *node, mxml_ws_t when);
|
||||
// Save callback function
|
||||
|
||||
typedef char *(*mxml_strcopy_cb_t)(void *cbdata, const char *s);
|
||||
// String copy/allocation callback
|
||||
typedef void (*mxml_strfree_cb_t)(void *cbdata, char *s);
|
||||
// String free callback
|
||||
|
||||
typedef ssize_t (*mxml_write_cb_t)(void *cbdata, const void *buffer, size_t bytes);
|
||||
// Write callback function
|
||||
|
||||
@ -220,7 +225,7 @@ extern bool mxmlSetDeclaration(mxml_node_t *node, const char *declaration);
|
||||
extern bool mxmlSetDeclarationf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetDirective(mxml_node_t *node, const char *directive);
|
||||
extern bool mxmlSetDirectivef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custom_destroy_cb_t destroy);
|
||||
extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custom_destroy_cb_t destroy_cb);
|
||||
extern void mxmlSetCustomCallbacks(mxml_custom_load_cb_t load_cb, mxml_custom_save_cb_t save_cb, void *cbdata);
|
||||
extern bool mxmlSetElement(mxml_node_t *node, const char *name);
|
||||
extern void mxmlSetErrorCallback(mxml_error_cb_t cb, void *cbdata);
|
||||
@ -228,6 +233,7 @@ extern bool mxmlSetInteger(mxml_node_t *node, long integer);
|
||||
extern bool mxmlSetOpaque(mxml_node_t *node, const char *opaque);
|
||||
extern bool mxmlSetOpaquef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetReal(mxml_node_t *node, double real);
|
||||
extern void mxmlSetStringCallbacks(mxml_strcopy_cb_t strcopy_cb, mxml_strfree_cb_t strfree_cb, void *str_cbdata);
|
||||
extern bool mxmlSetText(mxml_node_t *node, bool whitespace, const char *string);
|
||||
extern bool mxmlSetTextf(mxml_node_t *node, bool whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern bool mxmlSetUserData(mxml_node_t *node, void *data);
|
||||
|
Loading…
Reference in New Issue
Block a user