mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-24 11:25:30 +00:00
Add separate node types for comments, CDATA, directives, and declarations (Issue #250)
This commit is contained in:
parent
933dd8716d
commit
0cd995c772
@ -1,7 +1,10 @@
|
||||
# Changes in Mini-XML 4.0.0
|
||||
|
||||
- Now require C99 support.
|
||||
- Added new `MXML_TYPE_CDATA`, `MXML_TYPE_COMMENT`, `MXML_TYPE_DECLARATION`, and
|
||||
`MXML_TYPE_DIRECTIVE` node types (Issue #250)
|
||||
- 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.
|
||||
|
||||
|
||||
# Changes in Mini-XML 3.3.2
|
||||
|
@ -281,18 +281,21 @@ test: testmxml
|
||||
$(RM) temp2.xml temp2s.xml; \
|
||||
else \
|
||||
echo Stdio file test failed!; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if cmp temp1.xml temp1s.xml; then \
|
||||
echo String test passed!; \
|
||||
$(RM) temp1.xml temp1s.xml; \
|
||||
else \
|
||||
echo String test failed!; \
|
||||
exit 1; \
|
||||
fi
|
||||
@if cmp test.xml test.xmlfd; then \
|
||||
echo File descriptor test passed!; \
|
||||
$(RM) test.xmlfd temp1.xmlfd; \
|
||||
else \
|
||||
echo File descriptor test failed!; \
|
||||
exit 1; \
|
||||
fi
|
||||
|
||||
|
||||
|
24
mxml-attr.c
24
mxml-attr.c
@ -16,7 +16,7 @@
|
||||
// Local functions...
|
||||
//
|
||||
|
||||
static int mxml_set_attr(mxml_node_t *node, const char *name, char *value);
|
||||
static bool mxml_set_attr(mxml_node_t *node, const char *name, char *value);
|
||||
|
||||
|
||||
//
|
||||
@ -27,7 +27,7 @@ void
|
||||
mxmlElementDeleteAttr(mxml_node_t *node,// I - Element
|
||||
const char *name)// I - Attribute name
|
||||
{
|
||||
int i; // Looping var
|
||||
size_t i; // Looping var
|
||||
_mxml_attr_t *attr; // Cirrent attribute
|
||||
|
||||
|
||||
@ -73,7 +73,7 @@ const char * // O - Attribute value or @code NULL@
|
||||
mxmlElementGetAttr(mxml_node_t *node, // I - Element node
|
||||
const char *name) // I - Name of attribute
|
||||
{
|
||||
int i; // Looping var
|
||||
size_t i; // Looping var
|
||||
_mxml_attr_t *attr; // Cirrent attribute
|
||||
|
||||
|
||||
@ -129,9 +129,9 @@ mxmlElementGetAttrByIndex(
|
||||
// 'mxmlElementGetAttrCount()' - Get the number of element attributes.
|
||||
//
|
||||
|
||||
int // O - Number of attributes
|
||||
size_t // O - Number of attributes
|
||||
mxmlElementGetAttrCount(
|
||||
mxml_node_t *node) // I - Node
|
||||
mxml_node_t *node) // I - Node
|
||||
{
|
||||
if (node && node->type == MXML_TYPE_ELEMENT)
|
||||
return (node->value.element.num_attrs);
|
||||
@ -176,7 +176,7 @@ mxmlElementSetAttr(mxml_node_t *node, // I - Element node
|
||||
valuec = NULL;
|
||||
}
|
||||
|
||||
if (mxml_set_attr(node, name, valuec))
|
||||
if (!mxml_set_attr(node, name, valuec))
|
||||
free(valuec);
|
||||
}
|
||||
|
||||
@ -214,7 +214,7 @@ mxmlElementSetAttrf(mxml_node_t *node, // I - Element node
|
||||
|
||||
if ((value = strdup(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))
|
||||
else if (!mxml_set_attr(node, name, value))
|
||||
free(value);
|
||||
}
|
||||
|
||||
@ -223,7 +223,7 @@ mxmlElementSetAttrf(mxml_node_t *node, // I - Element node
|
||||
// 'mxml_set_attr()' - Set or add an attribute name/value pair.
|
||||
//
|
||||
|
||||
static int // O - 0 on success, -1 on failure
|
||||
static bool // O - `true` on success, `false` on failure
|
||||
mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
const char *name, // I - Attribute name
|
||||
char *value) // I - Attribute value
|
||||
@ -241,7 +241,7 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
free(attr->value);
|
||||
attr->value = value;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,7 +251,7 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
if (!attr)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
node->value.element.attrs = attr;
|
||||
@ -260,12 +260,12 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
if ((attr->name = strdup(name)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
attr->value = value;
|
||||
|
||||
node->value.element.num_attrs ++;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
@ -16,7 +16,7 @@
|
||||
// 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlEntityAddCallback(
|
||||
mxml_entity_cb_t cb) // I - Callback function to add
|
||||
{
|
||||
@ -24,18 +24,18 @@ mxmlEntityAddCallback(
|
||||
// Global data
|
||||
|
||||
|
||||
if (global->num_entity_cbs < (int)(sizeof(global->entity_cbs) / sizeof(global->entity_cbs[0])))
|
||||
if (global->num_entity_cbs < (sizeof(global->entity_cbs) / sizeof(global->entity_cbs[0])))
|
||||
{
|
||||
global->entity_cbs[global->num_entity_cbs] = cb;
|
||||
global->num_entity_cbs ++;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mxml_error("Unable to add entity callback!");
|
||||
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -72,14 +72,14 @@ mxmlEntityGetName(int val) // I - Character value
|
||||
//
|
||||
// 'mxmlEntityGetValue()' - Get the character corresponding to a named entity.
|
||||
//
|
||||
// The entity name can also be a numeric constant. -1 is returned if the
|
||||
// The entity name can also be a numeric constant. `-1` is returned if the
|
||||
// name is not known.
|
||||
//
|
||||
|
||||
int // O - Character value or -1 on error
|
||||
int // O - Character value or `-1` on error
|
||||
mxmlEntityGetValue(const char *name) // I - Entity name
|
||||
{
|
||||
int i; // Looping var
|
||||
size_t i; // Looping var
|
||||
int ch; // Character value
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
@ -103,7 +103,7 @@ void
|
||||
mxmlEntityRemoveCallback(
|
||||
mxml_entity_cb_t cb) // I - Callback function to remove
|
||||
{
|
||||
int i; // Looping var
|
||||
size_t i; // Looping var
|
||||
_mxml_global_t *global = _mxml_global();
|
||||
// Global data
|
||||
|
||||
@ -131,10 +131,10 @@ mxmlEntityRemoveCallback(
|
||||
int // O - Unicode value or -1
|
||||
_mxml_entity_cb(const char *name) // I - Entity name
|
||||
{
|
||||
int diff, // Difference between names
|
||||
current, // Current entity in search
|
||||
first, // First entity in search
|
||||
last; // Last entity in search
|
||||
int diff; // Difference between names
|
||||
size_t current, // Current entity in search
|
||||
first, // First entity in search
|
||||
last; // Last entity in search
|
||||
static const struct
|
||||
{
|
||||
const char *name; // Entity name
|
||||
@ -403,7 +403,7 @@ _mxml_entity_cb(const char *name) // I - Entity name
|
||||
|
||||
// Do a binary search for the named entity...
|
||||
first = 0;
|
||||
last = (int)(sizeof(entities) / sizeof(entities[0]) - 1);
|
||||
last = sizeof(entities) / sizeof(entities[0]) - 1;
|
||||
|
||||
while ((last - first) > 1)
|
||||
{
|
||||
|
260
mxml-file.c
260
mxml-file.c
@ -1220,8 +1220,8 @@ mxml_load_data(
|
||||
*first = NULL, // First node added
|
||||
*parent = NULL; // Current parent node
|
||||
int line = 1, // Current line number
|
||||
ch, // Character from file
|
||||
whitespace; // Non-zero if whitespace seen
|
||||
ch; // Character from file
|
||||
bool whitespace; // Whitespace seen?
|
||||
char *buffer, // String buffer
|
||||
*bufptr; // Pointer into buffer
|
||||
int bufsize; // Size of buffer
|
||||
@ -1231,6 +1231,10 @@ mxml_load_data(
|
||||
// Global data
|
||||
static const char * const types[] = // Type strings...
|
||||
{
|
||||
"MXML_TYPE_CDATA", // CDATA
|
||||
"MXML_TYPE_COMMENT", // Comment
|
||||
"MXML_TYPE_DECLARATION",// Declaration
|
||||
"MXML_TYPE_DIRECTIVE",// Processing instruction/directive
|
||||
"MXML_TYPE_ELEMENT", // XML element with attributes
|
||||
"MXML_TYPE_INTEGER", // Integer value
|
||||
"MXML_TYPE_OPAQUE", // Opaque string
|
||||
@ -1251,7 +1255,7 @@ mxml_load_data(
|
||||
bufptr = buffer;
|
||||
parent = top;
|
||||
first = NULL;
|
||||
whitespace = 0;
|
||||
whitespace = false;
|
||||
encoding = ENCODE_UTF8;
|
||||
|
||||
if (cb && parent)
|
||||
@ -1275,9 +1279,7 @@ mxml_load_data(
|
||||
|
||||
do
|
||||
{
|
||||
if ((ch == '<' ||
|
||||
(mxml_isspace(ch) && type != MXML_TYPE_OPAQUE && type != MXML_TYPE_CUSTOM)) &&
|
||||
bufptr > buffer)
|
||||
if ((ch == '<' || (mxml_isspace(ch) && type != MXML_TYPE_OPAQUE && type != MXML_TYPE_CUSTOM)) && bufptr > buffer)
|
||||
{
|
||||
// Add a new value node...
|
||||
*bufptr = '\0';
|
||||
@ -1285,7 +1287,7 @@ mxml_load_data(
|
||||
switch (type)
|
||||
{
|
||||
case MXML_TYPE_INTEGER :
|
||||
node = mxmlNewInteger(parent, (int)strtol(buffer, &bufptr, 0));
|
||||
node = mxmlNewInteger(parent, strtol(buffer, &bufptr, 0));
|
||||
break;
|
||||
|
||||
case MXML_TYPE_OPAQUE :
|
||||
@ -1350,7 +1352,7 @@ mxml_load_data(
|
||||
}
|
||||
else if (mxml_isspace(ch) && type == MXML_TYPE_TEXT)
|
||||
{
|
||||
whitespace = 1;
|
||||
whitespace = true;
|
||||
}
|
||||
|
||||
if (ch == '\n')
|
||||
@ -1375,7 +1377,7 @@ mxml_load_data(
|
||||
first = node;
|
||||
}
|
||||
|
||||
whitespace = 0;
|
||||
whitespace = false;
|
||||
}
|
||||
|
||||
if (ch == '<')
|
||||
@ -1444,16 +1446,16 @@ mxml_load_data(
|
||||
}
|
||||
|
||||
// Otherwise add this as an element under the current parent...
|
||||
*bufptr = '\0';
|
||||
bufptr[-2] = '\0';
|
||||
|
||||
if (!parent && first)
|
||||
{
|
||||
// There can only be one root element!
|
||||
mxml_error("<%s> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
mxml_error("<%s--> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((node = mxmlNewElement(parent, buffer)) == NULL)
|
||||
if ((node = mxmlNewComment(parent, buffer + 3)) == NULL)
|
||||
{
|
||||
// Just print error for now...
|
||||
mxml_error("Unable to add comment node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
|
||||
@ -1500,16 +1502,16 @@ mxml_load_data(
|
||||
}
|
||||
|
||||
// Otherwise add this as an element under the current parent...
|
||||
*bufptr = '\0';
|
||||
bufptr[-2] = '\0';
|
||||
|
||||
if (!parent && first)
|
||||
{
|
||||
// There can only be one root element!
|
||||
mxml_error("<%s> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
mxml_error("<%s]]> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((node = mxmlNewElement(parent, buffer)) == NULL)
|
||||
if ((node = mxmlNewCDATA(parent, buffer + 8)) == NULL)
|
||||
{
|
||||
// Print error and return...
|
||||
mxml_error("Unable to add CDATA node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
|
||||
@ -1550,16 +1552,16 @@ mxml_load_data(
|
||||
}
|
||||
|
||||
// Otherwise add this as an element under the current parent...
|
||||
*bufptr = '\0';
|
||||
bufptr[-1] = '\0';
|
||||
|
||||
if (!parent && first)
|
||||
{
|
||||
// There can only be one root element!
|
||||
mxml_error("<%s> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
mxml_error("<%s?> cannot be a second root node after <%s> on line %d.", buffer, first->value.element.name, line);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((node = mxmlNewElement(parent, buffer)) == NULL)
|
||||
if ((node = mxmlNewDirective(parent, buffer + 1)) == NULL)
|
||||
{
|
||||
// Print error and return...
|
||||
mxml_error("Unable to add processing instruction node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
|
||||
@ -1570,7 +1572,7 @@ mxml_load_data(
|
||||
{
|
||||
(*sax_cb)(node, MXML_SAX_EVENT_DIRECTIVE, sax_data);
|
||||
|
||||
if (strncmp(node->value.element.name, "?xml ", 5) && !mxmlRelease(node))
|
||||
if (strncmp(node->value.directive, "xml ", 4) && !mxmlRelease(node))
|
||||
node = NULL;
|
||||
}
|
||||
|
||||
@ -1634,7 +1636,7 @@ mxml_load_data(
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((node = mxmlNewElement(parent, buffer)) == NULL)
|
||||
if ((node = mxmlNewDeclaration(parent, buffer + 1)) == NULL)
|
||||
{
|
||||
// Print error and return...
|
||||
mxml_error("Unable to add declaration node to parent <%s> on line %d.", parent ? parent->value.element.name : "null", line);
|
||||
@ -1643,7 +1645,7 @@ mxml_load_data(
|
||||
|
||||
if (sax_cb)
|
||||
{
|
||||
(*sax_cb)(node, MXML_SAX_EVENT_DIRECTIVE, sax_data);
|
||||
(*sax_cb)(node, MXML_SAX_EVENT_DECLARATION, sax_data);
|
||||
|
||||
if (!mxmlRelease(node))
|
||||
node = NULL;
|
||||
@ -2394,6 +2396,7 @@ mxml_write_node(mxml_node_t *node, // I - Node to write
|
||||
width; // Width of attr + value
|
||||
_mxml_attr_t *attr; // Current attribute
|
||||
char s[255]; // Temporary string
|
||||
const char *ptr; // Pointer into string
|
||||
|
||||
|
||||
// Loop through this node and all of its children...
|
||||
@ -2402,39 +2405,181 @@ mxml_write_node(mxml_node_t *node, // I - Node to write
|
||||
// Print the node value...
|
||||
switch (current->type)
|
||||
{
|
||||
case MXML_TYPE_CDATA :
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
|
||||
|
||||
if ((*putc_cb)('<', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('!', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('[', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('C', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('D', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('A', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('T', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('A', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('[', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
for (ptr = current->value.cdata; *ptr; ptr ++)
|
||||
{
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
else if (*ptr == '\n')
|
||||
col = 0;
|
||||
else
|
||||
col ++;
|
||||
}
|
||||
if ((*putc_cb)(']', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)(']', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
break;
|
||||
|
||||
case MXML_TYPE_COMMENT :
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
|
||||
|
||||
if ((*putc_cb)('<', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('!', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('-', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('-', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
for (ptr = current->value.comment; *ptr; ptr ++)
|
||||
{
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
else if (*ptr == '\n')
|
||||
col = 0;
|
||||
else
|
||||
col ++;
|
||||
}
|
||||
if ((*putc_cb)('-', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('-', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
break;
|
||||
|
||||
case MXML_TYPE_DECLARATION :
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
|
||||
|
||||
if ((*putc_cb)('<', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('!', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
for (ptr = current->value.declaration; *ptr; ptr ++)
|
||||
{
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
else if (*ptr == '\n')
|
||||
col = 0;
|
||||
else
|
||||
col ++;
|
||||
}
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
break;
|
||||
|
||||
case MXML_TYPE_DIRECTIVE :
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
|
||||
|
||||
if ((*putc_cb)('<', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('?', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
for (ptr = current->value.directive; *ptr; ptr ++)
|
||||
{
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
else if (*ptr == '\n')
|
||||
col = 0;
|
||||
else
|
||||
col ++;
|
||||
}
|
||||
if ((*putc_cb)('?', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
break;
|
||||
|
||||
case MXML_TYPE_ELEMENT :
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_OPEN, col, putc_cb);
|
||||
|
||||
if ((*putc_cb)('<', p) < 0)
|
||||
return (-1);
|
||||
if (current->value.element.name[0] == '?' || !strncmp(current->value.element.name, "!--", 3))
|
||||
{
|
||||
// Comments and processing instructions do not use character entities.
|
||||
const char *ptr; // Pointer into name
|
||||
|
||||
for (ptr = current->value.element.name; *ptr; ptr ++)
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
}
|
||||
else if (!strncmp(current->value.element.name, "![CDATA[", 8))
|
||||
{
|
||||
// CDATA elements do not use character entities, but also need the
|
||||
// "]]" terminator added at the end.
|
||||
const char *ptr; // Pointer into name
|
||||
|
||||
for (ptr = current->value.element.name; *ptr; ptr ++)
|
||||
if ((*putc_cb)(*ptr, p) < 0)
|
||||
return (-1);
|
||||
|
||||
if ((*putc_cb)(']', p) < 0)
|
||||
return (-1);
|
||||
if ((*putc_cb)(']', p) < 0)
|
||||
return (-1);
|
||||
}
|
||||
else if (mxml_write_name(current->value.element.name, p, putc_cb) < 0)
|
||||
{
|
||||
return (-1);
|
||||
}
|
||||
|
||||
col += strlen(current->value.element.name) + 1;
|
||||
|
||||
@ -2488,27 +2633,14 @@ mxml_write_node(mxml_node_t *node, // I - Node to write
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
}
|
||||
else if (current->value.element.name[0] == '!' || current->value.element.name[0] == '?')
|
||||
{
|
||||
// The ? and ! elements are special-cases...
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
else
|
||||
col ++;
|
||||
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((*putc_cb)(' ', p) < 0)
|
||||
return (-1);
|
||||
if ((*putc_cb)('/', p) < 0)
|
||||
return (-1);
|
||||
if ((*putc_cb)('>', p) < 0)
|
||||
return (-1);
|
||||
|
||||
col += 3;
|
||||
|
||||
col += 2;
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_AFTER_OPEN, col, putc_cb);
|
||||
}
|
||||
break;
|
||||
@ -2533,7 +2665,7 @@ mxml_write_node(mxml_node_t *node, // I - Node to write
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(s, sizeof(s), "%d", current->value.integer);
|
||||
snprintf(s, sizeof(s), "%ld", current->value.integer);
|
||||
if (mxml_write_string(s, p, putc_cb) < 0)
|
||||
return (-1);
|
||||
|
||||
@ -2643,10 +2775,10 @@ mxml_write_node(mxml_node_t *node, // I - Node to write
|
||||
if (current == node || !current->parent)
|
||||
break;
|
||||
|
||||
// The ? and ! elements are special-cases and have no end tags...
|
||||
// Declarations and directives have no end tags...
|
||||
current = current->parent;
|
||||
|
||||
if (current->value.element.name[0] != '!' && current->value.element.name[0] != '?')
|
||||
if (current->type == MXML_TYPE_ELEMENT)
|
||||
{
|
||||
col = mxml_write_ws(current, p, cb, MXML_WS_BEFORE_CLOSE, col, putc_cb);
|
||||
|
||||
|
70
mxml-get.c
70
mxml-get.c
@ -22,11 +22,29 @@ const char * // O - CDATA value or `NULL`
|
||||
mxmlGetCDATA(mxml_node_t *node) // I - Node to get
|
||||
{
|
||||
// Range check input...
|
||||
if (!node || node->type != MXML_TYPE_ELEMENT || strncmp(node->value.element.name, "![CDATA[", 8))
|
||||
if (!node || node->type != MXML_TYPE_CDATA)
|
||||
return (NULL);
|
||||
|
||||
// Return the text following the CDATA declaration...
|
||||
return (node->value.element.name + 8);
|
||||
// Return the CDATA string...
|
||||
return (node->value.cdata);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlGetComment()' - Get the value for a comment node.
|
||||
//
|
||||
// `NULL` is returned if the node is not a comment.
|
||||
//
|
||||
|
||||
const char * // O - Comment value or `NULL`
|
||||
mxmlGetComment(mxml_node_t *node) // I - Node to get
|
||||
{
|
||||
// Range check input...
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
return (NULL);
|
||||
|
||||
// Return the comment string...
|
||||
return (node->value.comment);
|
||||
}
|
||||
|
||||
|
||||
@ -54,6 +72,42 @@ mxmlGetCustom(mxml_node_t *node) // I - Node to get
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlGetDeclaration()' - Get the value for a declaration node.
|
||||
//
|
||||
// `NULL` is returned if the node is not a declaration.
|
||||
//
|
||||
|
||||
const char * // O - Declaraction value or `NULL`
|
||||
mxmlGetDeclaration(mxml_node_t *node) // I - Node to get
|
||||
{
|
||||
// Range check input...
|
||||
if (!node || node->type != MXML_TYPE_DECLARATION)
|
||||
return (NULL);
|
||||
|
||||
// Return the comment string...
|
||||
return (node->value.declaration);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlGetDirective()' - Get the value for a processing instruction node.
|
||||
//
|
||||
// `NULL` is returned if the node is not a processing instruction.
|
||||
//
|
||||
|
||||
const char * // O - Comment value or `NULL`
|
||||
mxmlGetDirective(mxml_node_t *node) // I - Node to get
|
||||
{
|
||||
// Range check input...
|
||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||
return (NULL);
|
||||
|
||||
// Return the comment string...
|
||||
return (node->value.directive);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlGetElement()' - Get the name for an element node.
|
||||
//
|
||||
@ -95,10 +149,10 @@ mxmlGetFirstChild(mxml_node_t *node) // I - Node to get
|
||||
// 'mxmlGetInteger()' - Get the integer value from the specified node or its
|
||||
// first child.
|
||||
//
|
||||
// 0 is returned if the node (or its first child) is not an integer value node.
|
||||
// `0` is returned if the node (or its first child) is not an integer value node.
|
||||
//
|
||||
|
||||
int // O - Integer value or 0
|
||||
long // O - Integer value or `0`
|
||||
mxmlGetInteger(mxml_node_t *node) // I - Node to get
|
||||
{
|
||||
// Range check input...
|
||||
@ -250,13 +304,13 @@ mxmlGetReal(mxml_node_t *node) // I - Node to get
|
||||
|
||||
const char * // O - Text string or `NULL`
|
||||
mxmlGetText(mxml_node_t *node, // I - Node to get
|
||||
int *whitespace) // O - 1 if string is preceded by whitespace, 0 otherwise
|
||||
bool *whitespace) // O - `true` if string is preceded by whitespace, `false` otherwise
|
||||
{
|
||||
// Range check input...
|
||||
if (!node)
|
||||
{
|
||||
if (whitespace)
|
||||
*whitespace = 0;
|
||||
*whitespace = false;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
@ -279,7 +333,7 @@ mxmlGetText(mxml_node_t *node, // I - Node to get
|
||||
else
|
||||
{
|
||||
if (whitespace)
|
||||
*whitespace = 0;
|
||||
*whitespace = false;
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
|
@ -109,7 +109,7 @@ mxmlIndexFind(mxml_index_t *ind, // I - Index to search
|
||||
first = 0;
|
||||
last = ind->num_nodes - 1;
|
||||
|
||||
MXML_DEBUG("mxmlIndexFind: Find first time, num_nodes=%d...\n", ind->num_nodes);
|
||||
MXML_DEBUG("mxmlIndexFind: Find first time, num_nodes=%lu...\n", (unsigned long)ind->num_nodes);
|
||||
|
||||
while ((last - first) > 1)
|
||||
{
|
||||
@ -165,7 +165,7 @@ mxmlIndexFind(mxml_index_t *ind, // I - Index to search
|
||||
else if (ind->cur_node < ind->num_nodes && !index_find(ind, element, value, ind->nodes[ind->cur_node]))
|
||||
{
|
||||
// Return the next matching node...
|
||||
MXML_DEBUG("mxmlIndexFind: Returning next match %d...\n", ind->cur_node);
|
||||
MXML_DEBUG("mxmlIndexFind: Returning next match %lu...\n", (unsigned long)ind->cur_node);
|
||||
return (ind->nodes[ind->cur_node ++]);
|
||||
}
|
||||
|
||||
|
309
mxml-node.c
309
mxml-node.c
@ -170,7 +170,7 @@ mxmlDelete(mxml_node_t *node) // I - Node to delete
|
||||
// reference count.
|
||||
//
|
||||
|
||||
int // O - Reference count
|
||||
size_t // O - Reference count
|
||||
mxmlGetRefCount(mxml_node_t *node) // I - Node
|
||||
{
|
||||
// Range check input...
|
||||
@ -206,18 +206,129 @@ mxmlNewCDATA(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_ELEMENT)) != NULL)
|
||||
if ((node = mxml_new(parent, MXML_TYPE_CDATA)) != NULL)
|
||||
{
|
||||
size_t datalen = strlen(data); // Length of data
|
||||
|
||||
if ((node->value.element.name = malloc(datalen + 9)) == NULL)
|
||||
if ((node->value.cdata = strdup(data)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for CDATA.");
|
||||
mxmlDelete(node);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(node->value.element.name, datalen + 9, "![CDATA[%s", data);
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewCDATAf()' - Create a new formatted CDATA node.
|
||||
//
|
||||
// The new CDATA node is added to the end of the specified parent's
|
||||
// child list. The constant `MXML_NO_PARENT` can be used to specify that
|
||||
// the new opaque string node has no parent. The format string must be
|
||||
// nul-terminated and is formatted into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewCDATAf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional args as needed
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewCDATAf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!format)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the text value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_CDATA)) != NULL)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.cdata = strdup(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewComment()' - Create a new comment node.
|
||||
//
|
||||
// The new comment node is added to the end of the specified parent's child
|
||||
// list. The constant `MXML_NO_PARENT` can be used to specify that the new
|
||||
// comment node has no parent. The comment string must be nul-terminated and
|
||||
// is copied into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewComment(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *comment) // I - Comment string
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewComment(parent=%p, comment=\"%s\")\n", parent, comment ? comment : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!comment)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_COMMENT)) != NULL)
|
||||
{
|
||||
if ((node->value.comment = strdup(comment)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for comment.");
|
||||
mxmlDelete(node);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewCommentf()' - Create a new formatted comment string node.
|
||||
//
|
||||
// The new comment string node is added to the end of the specified parent's
|
||||
// child list. The constant `MXML_NO_PARENT` can be used to specify that
|
||||
// the new opaque string node has no parent. The format string must be
|
||||
// nul-terminated and is formatted into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewCommentf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional args as needed
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewCommentf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!format)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the text value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_COMMENT)) != NULL)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.comment = strdup(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -255,6 +366,160 @@ mxmlNewCustom(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewDeclaration()' - Create a new declaraction node.
|
||||
//
|
||||
// The new declaration node is added to the end of the specified parent's child
|
||||
// list. The constant `MXML_NO_PARENT` can be used to specify that the new
|
||||
// declaration node has no parent. The declaration string must be nul-
|
||||
// terminated and is copied into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewDeclaration(
|
||||
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *declaration) // I - Declaration string
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewDeclaration(parent=%p, declaration=\"%s\")\n", parent, declaration ? declaration : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!declaration)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DECLARATION)) != NULL)
|
||||
{
|
||||
if ((node->value.declaration = strdup(declaration)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for declaration.");
|
||||
mxmlDelete(node);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewDeclarationf()' - Create a new formatted declaration node.
|
||||
//
|
||||
// The new declaration node is added to the end of the specified parent's
|
||||
// child list. The constant `MXML_NO_PARENT` can be used to specify that
|
||||
// the new opaque string node has no parent. The format string must be
|
||||
// nul-terminated and is formatted into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewDeclarationf(
|
||||
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional args as needed
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewDeclarationf(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!format)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the text value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DECLARATION)) != NULL)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.declaration = strdup(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewDirective()' - Create a new processing instruction node.
|
||||
//
|
||||
// The new processing instruction node is added to the end of the specified
|
||||
// parent's child list. The constant `MXML_NO_PARENT` can be used to specify
|
||||
// that the new processing instruction node has no parent. The data string must
|
||||
// be nul-terminated and is copied into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewDirective(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *directive)// I - Directive string
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewDirective(parent=%p, directive=\"%s\")\n", parent, directive ? directive : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!directive)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the name value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DIRECTIVE)) != NULL)
|
||||
{
|
||||
if ((node->value.directive = strdup(directive)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for processing instruction.");
|
||||
mxmlDelete(node);
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewDirectivef()' - Create a new formatted processing instruction node.
|
||||
//
|
||||
// The new processing instruction node is added to the end of the specified parent's
|
||||
// child list. The constant `MXML_NO_PARENT` can be used to specify that
|
||||
// the new opaque string node has no parent. The format string must be
|
||||
// nul-terminated and is formatted into the new node.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewDirectivef(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional args as needed
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewDirectivef(parent=%p, format=\"%s\", ...)\n", parent, format ? format : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!format)
|
||||
return (NULL);
|
||||
|
||||
// Create the node and set the text value...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_DIRECTIVE)) != NULL)
|
||||
{
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
node->value.directive = strdup(buffer);
|
||||
}
|
||||
|
||||
return (node);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlNewElement()' - Create a new element node.
|
||||
//
|
||||
@ -294,12 +559,12 @@ mxmlNewElement(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewInteger(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
int integer) // I - Integer value
|
||||
long integer) // I - Integer value
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewInteger(parent=%p, integer=%d)\n", parent, integer);
|
||||
MXML_DEBUG("mxmlNewInteger(parent=%p, integer=%ld)\n", parent, integer);
|
||||
|
||||
// Create the node and set the element name...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_INTEGER)) != NULL)
|
||||
@ -415,13 +680,13 @@ mxmlNewReal(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewText(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
int whitespace, // I - 1 = leading whitespace, 0 = no whitespace
|
||||
bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace
|
||||
const char *string) // I - String
|
||||
{
|
||||
mxml_node_t *node; // New node
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewText(parent=%p, whitespace=%d, string=\"%s\")\n", parent, whitespace, string ? string : "(null)");
|
||||
MXML_DEBUG("mxmlNewText(parent=%p, whitespace=%s, string=\"%s\")\n", parent, whitespace ? "true" : "false", string ? string : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!string)
|
||||
@ -450,7 +715,7 @@ mxmlNewText(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewTextf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
int whitespace, // I - 1 = leading whitespace, 0 = no whitespace
|
||||
bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional args as needed
|
||||
{
|
||||
@ -459,7 +724,7 @@ mxmlNewTextf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
char buffer[16384]; // Format buffer
|
||||
|
||||
|
||||
MXML_DEBUG("mxmlNewTextf(parent=%p, whitespace=%d, format=\"%s\", ...)\n", parent, whitespace, format ? format : "(null)");
|
||||
MXML_DEBUG("mxmlNewTextf(parent=%p, whitespace=%s, format=\"%s\", ...)\n", parent, whitespace ? "true" : "false", format ? format : "(null)");
|
||||
|
||||
// Range check input...
|
||||
if (!format)
|
||||
@ -517,18 +782,18 @@ mxmlRemove(mxml_node_t *node) // I - Node to remove
|
||||
// 'mxmlNewXML()' - Create a new XML document tree.
|
||||
//
|
||||
// The "version" argument specifies the version number to put in the
|
||||
// ?xml element node. If `NULL`, version "1.0" is assumed.
|
||||
// ?xml directive node. If `NULL`, version "1.0" is assumed.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New ?xml node
|
||||
mxmlNewXML(const char *version) // I - Version number to use
|
||||
{
|
||||
char element[1024]; // Element text
|
||||
char directive[1024]; // Directive text
|
||||
|
||||
|
||||
snprintf(element, sizeof(element), "?xml version=\"%s\" encoding=\"utf-8\"?", version ? version : "1.0");
|
||||
snprintf(directive, sizeof(directive), "xml version=\"%s\" encoding=\"utf-8\"", version ? version : "1.0");
|
||||
|
||||
return (mxmlNewElement(NULL, element));
|
||||
return (mxmlNewDirective(NULL, directive));
|
||||
}
|
||||
|
||||
|
||||
@ -589,6 +854,18 @@ mxml_free(mxml_node_t *node) // I - Node
|
||||
|
||||
switch (node->type)
|
||||
{
|
||||
case MXML_TYPE_CDATA :
|
||||
free(node->value.cdata);
|
||||
break;
|
||||
case MXML_TYPE_COMMENT :
|
||||
free(node->value.comment);
|
||||
break;
|
||||
case MXML_TYPE_DECLARATION :
|
||||
free(node->value.declaration);
|
||||
break;
|
||||
case MXML_TYPE_DIRECTIVE :
|
||||
free(node->value.directive);
|
||||
break;
|
||||
case MXML_TYPE_ELEMENT :
|
||||
free(node->value.element.name);
|
||||
|
||||
|
@ -39,13 +39,13 @@ typedef struct _mxml_attr_s // An XML element attribute value.
|
||||
typedef struct _mxml_element_s // An XML element value.
|
||||
{
|
||||
char *name; // Name of element
|
||||
int num_attrs; // Number of attributes
|
||||
size_t num_attrs; // Number of attributes
|
||||
_mxml_attr_t *attrs; // Attributes
|
||||
} _mxml_element_t;
|
||||
|
||||
typedef struct _mxml_text_s // An XML text value.
|
||||
{
|
||||
int whitespace; // Leading whitespace?
|
||||
bool whitespace; // Leading whitespace?
|
||||
char *string; // Fragment string
|
||||
} _mxml_text_t;
|
||||
|
||||
@ -57,12 +57,16 @@ typedef struct _mxml_custom_s // An XML custom value.
|
||||
|
||||
typedef union _mxml_value_u // An XML node value.
|
||||
{
|
||||
char *cdata; // CDATA string
|
||||
char *comment; // Common string
|
||||
char *declaration; // Declaration string
|
||||
char *directive; // Processing instruction string
|
||||
_mxml_element_t element; // Element
|
||||
int integer; // Integer number
|
||||
long integer; // Integer number
|
||||
char *opaque; // Opaque string
|
||||
double real; // Real number
|
||||
_mxml_text_t text; // Text fragment
|
||||
_mxml_custom_t custom; // Custom data @since Mini-XML 2.1@
|
||||
_mxml_custom_t custom; // Custom data
|
||||
} _mxml_value_t;
|
||||
|
||||
struct _mxml_node_s // An XML node.
|
||||
@ -74,26 +78,26 @@ struct _mxml_node_s // An XML node.
|
||||
struct _mxml_node_s *child; // First child node
|
||||
struct _mxml_node_s *last_child; // Last child node
|
||||
_mxml_value_t value; // Node value
|
||||
int ref_count; // Use count
|
||||
size_t ref_count; // Use count
|
||||
void *user_data; // User data
|
||||
};
|
||||
|
||||
struct _mxml_index_s // An XML node index.
|
||||
{
|
||||
char *attr; // Attribute used for indexing or NULL
|
||||
int num_nodes; // Number of nodes in index
|
||||
int alloc_nodes; // Allocated nodes in index
|
||||
int cur_node; // Current node
|
||||
size_t num_nodes; // Number of nodes in index
|
||||
size_t alloc_nodes; // Allocated nodes in index
|
||||
size_t cur_node; // Current node
|
||||
mxml_node_t **nodes; // Node array
|
||||
};
|
||||
|
||||
typedef struct _mxml_global_s // Global, per-thread data
|
||||
|
||||
{
|
||||
void (*error_cb)(const char *);
|
||||
int num_entity_cbs;
|
||||
int (*entity_cbs[100])(const char *name);
|
||||
int wrap;
|
||||
void (*error_cb)(const char *);
|
||||
size_t num_entity_cbs;
|
||||
int (*entity_cbs[100])(const char *name);
|
||||
int wrap;
|
||||
mxml_custom_load_cb_t custom_load_cb;
|
||||
mxml_custom_save_cb_t custom_save_cb;
|
||||
} _mxml_global_t;
|
||||
|
445
mxml-set.c
445
mxml-set.c
@ -13,54 +13,187 @@
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetCDATA()' - Set the element name of a CDATA node.
|
||||
// 'mxmlSetCDATA()' - Set the data for a CDATA node.
|
||||
//
|
||||
// The node is not changed if it (or its first child) is not a CDATA element node.
|
||||
// The node is not changed if it (or its first child) is not a CDATA node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
||||
const char *data) // I - New data string
|
||||
{
|
||||
size_t datalen; // Length of data string
|
||||
char *s; // New element name
|
||||
char *s; // New element name
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && strncmp(node->value.element.name, "![CDATA[", 8) && node->child && node->child->type == MXML_TYPE_ELEMENT && !strncmp(node->child->value.element.name, "![CDATA[", 8))
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CDATA)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_ELEMENT || strncmp(node->value.element.name, "![CDATA[", 8))
|
||||
if (!node || node->type != MXML_TYPE_CDATA)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!data)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (data == (node->value.element.name + 8))
|
||||
if (data == node->value.cdata)
|
||||
{
|
||||
// Don't change the value...
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Allocate the new value, free any old element value, and set the new value...
|
||||
datalen = strlen(data);
|
||||
|
||||
if ((s = malloc(datalen + 9)) == NULL)
|
||||
if ((s = strdup(data)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for CDATA.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.element.name);
|
||||
node->value.element.name = s;
|
||||
snprintf(node->value.element.name, datalen + 9, "![CDATA[%s", data);
|
||||
free(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetCDATAf()' - Set the data for a CDATA to a formatted string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
char *s; // Temporary string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CDATA)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_CDATA)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for CDATA string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetComment()' - Set a comment to a literal string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetComment(mxml_node_t *node, // I - Node
|
||||
const char *comment) // I - Literal string
|
||||
{
|
||||
char *s; // New string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_COMMENT)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!comment)
|
||||
{
|
||||
mxml_error("NULL comment not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (comment == node->value.comment)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(comment)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.comment);
|
||||
node->value.comment = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetCommentf()' - Set a comment to a formatted string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetCommentf(mxml_node_t *node, // I - Node
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
char *s; // Temporary string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_COMMENT)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.comment);
|
||||
node->value.comment = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +203,7 @@ mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not a custom node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetCustom(
|
||||
mxml_node_t *node, // I - Node to set
|
||||
void *data, // I - New data pointer
|
||||
@ -83,13 +216,13 @@ mxmlSetCustom(
|
||||
if (!node || node->type != MXML_TYPE_CUSTOM)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (data == node->value.custom.data)
|
||||
{
|
||||
node->value.custom.destroy = destroy;
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Free any old element value and set the new value...
|
||||
@ -99,7 +232,188 @@ mxmlSetCustom(
|
||||
node->value.custom.data = data;
|
||||
node->value.custom.destroy = destroy;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetDeclaration()' - Set a comment to a literal string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetDeclaration(
|
||||
mxml_node_t *node, // I - Node
|
||||
const char *declaration) // I - Literal string
|
||||
{
|
||||
char *s; // New string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DECLARATION)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DECLARATION)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!declaration)
|
||||
{
|
||||
mxml_error("NULL declaration not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (declaration == node->value.declaration)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(declaration)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetDeclarationf()' - Set a comment to a formatted string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
char *s; // Temporary string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_COMMENT)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetDirective()' - Set a directive to a literal string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetDirective(mxml_node_t *node, // I - Node
|
||||
const char *directive)// I - Literal string
|
||||
{
|
||||
char *s; // New string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DIRECTIVE)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!directive)
|
||||
{
|
||||
mxml_error("NULL directive not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (directive == node->value.directive)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(directive)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.directive);
|
||||
node->value.directive = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// 'mxmlSetDirectivef()' - Set a directive to a formatted string.
|
||||
//
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
||||
const char *format, // I - `printf`-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
va_list ap; // Pointer to arguments
|
||||
char buffer[16384]; // Format buffer
|
||||
char *s; // Temporary string
|
||||
|
||||
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_DIRECTIVE)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.directive);
|
||||
node->value.directive = s;
|
||||
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -109,7 +423,7 @@ mxmlSetCustom(
|
||||
// The node is not changed if it is not an element node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetElement(mxml_node_t *node, // I - Node to set
|
||||
const char *name) // I - New name string
|
||||
{
|
||||
@ -120,28 +434,28 @@ mxmlSetElement(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_ELEMENT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!name)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (name == node->value.element.name)
|
||||
return (0);
|
||||
return (true);
|
||||
|
||||
// Free any old element value and set the new value...
|
||||
if ((s = strdup(name)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for element name.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.element.name);
|
||||
node->value.element.name = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -151,9 +465,9 @@ mxmlSetElement(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not an integer node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetInteger(mxml_node_t *node, // I - Node to set
|
||||
int integer) // I - Integer value
|
||||
long integer) // I - Integer value
|
||||
{
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_INTEGER)
|
||||
@ -162,13 +476,13 @@ mxmlSetInteger(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_INTEGER)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Set the new value and return...
|
||||
node->value.integer = integer;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -178,7 +492,7 @@ mxmlSetInteger(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not an opaque node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
||||
const char *opaque) // I - Opaque string
|
||||
{
|
||||
@ -192,28 +506,28 @@ mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!opaque)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (node->value.opaque == opaque)
|
||||
return (0);
|
||||
return (true);
|
||||
|
||||
// Free any old opaque value and set the new value...
|
||||
if ((s = strdup(opaque)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -223,7 +537,7 @@ mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not an opaque node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
@ -240,12 +554,12 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
@ -256,13 +570,13 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -272,7 +586,7 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not a real number node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetReal(mxml_node_t *node, // I - Node to set
|
||||
double real) // I - Real number value
|
||||
{
|
||||
@ -286,13 +600,13 @@ mxmlSetReal(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_REAL)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Set the new value and return...
|
||||
node->value.real = real;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -302,9 +616,9 @@ mxmlSetReal(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not a text node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
int whitespace, // I - 1 = leading whitespace, 0 = no whitespace
|
||||
bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace
|
||||
const char *string) // I - String
|
||||
{
|
||||
char *s; // New string
|
||||
@ -317,25 +631,25 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_TEXT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!string)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (string == node->value.text.string)
|
||||
{
|
||||
node->value.text.whitespace = whitespace;
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = strdup(string)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for text string.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.text.string);
|
||||
@ -343,7 +657,7 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -353,9 +667,9 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
// The node is not changed if it (or its first child) is not a text node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
int whitespace, // I - 1 = leading whitespace, 0 = no whitespace
|
||||
bool whitespace, // I - `true` = leading whitespace, `false` = no whitespace
|
||||
const char *format, // I - Printf-style format string
|
||||
...) // I - Additional arguments as needed
|
||||
{
|
||||
@ -371,18 +685,15 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
if (!node || node->type != MXML_TYPE_TEXT)
|
||||
{
|
||||
mxml_error("Wrong node type.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
mxml_error("NULL string not allowed.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free any old string value and set the new value...
|
||||
*/
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
va_start(ap, format);
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
@ -390,7 +701,7 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
if ((s = strdup(buffer)) == NULL)
|
||||
{
|
||||
mxml_error("Unable to allocate memory for text string.");
|
||||
return (-1);
|
||||
return (false);
|
||||
}
|
||||
|
||||
free(node->value.text.string);
|
||||
@ -398,7 +709,7 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
node->value.text.whitespace = whitespace;
|
||||
node->value.text.string = s;
|
||||
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
||||
|
||||
@ -406,15 +717,15 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
// 'mxmlSetUserData()' - Set the user data pointer for a node.
|
||||
//
|
||||
|
||||
int // O - 0 on success, -1 on failure
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetUserData(mxml_node_t *node, // I - Node to set
|
||||
void *data) // I - User data pointer
|
||||
{
|
||||
// Range check input...
|
||||
if (!node)
|
||||
return (-1);
|
||||
return (false);
|
||||
|
||||
// Set the user data pointer and return...
|
||||
node->user_data = data;
|
||||
return (0);
|
||||
return (true);
|
||||
}
|
||||
|
58
mxml.h
58
mxml.h
@ -13,6 +13,7 @@
|
||||
# define MXML_H
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <stdbool.h>
|
||||
# include <string.h>
|
||||
# include <ctype.h>
|
||||
# include <errno.h>
|
||||
@ -72,7 +73,8 @@ typedef enum mxml_sax_event_e // SAX event type.
|
||||
MXML_SAX_EVENT_CDATA, // CDATA node
|
||||
MXML_SAX_EVENT_COMMENT, // Comment node
|
||||
MXML_SAX_EVENT_DATA, // Data node
|
||||
MXML_SAX_EVENT_DIRECTIVE, // Processing directive node
|
||||
MXML_SAX_EVENT_DECLARATION, // Declaration node
|
||||
MXML_SAX_EVENT_DIRECTIVE, // Processing instruction node
|
||||
MXML_SAX_EVENT_ELEMENT_CLOSE, // Element closed
|
||||
MXML_SAX_EVENT_ELEMENT_OPEN // Element opened
|
||||
} mxml_sax_event_t;
|
||||
@ -80,6 +82,10 @@ typedef enum mxml_sax_event_e // SAX event type.
|
||||
typedef enum mxml_type_e // The XML node type.
|
||||
{
|
||||
MXML_TYPE_IGNORE = -1, // Ignore/throw away node
|
||||
MXML_TYPE_CDATA, // CDATA value ("<[CDATA[...]]>")
|
||||
MXML_TYPE_COMMENT, // Comment ("<!--...-->")
|
||||
MXML_TYPE_DECLARATION, // Declaration ("<!...>")
|
||||
MXML_TYPE_DIRECTIVE, // Processing instruction ("<?...?>")
|
||||
MXML_TYPE_ELEMENT, // XML element with attributes
|
||||
MXML_TYPE_INTEGER, // Integer value
|
||||
MXML_TYPE_OPAQUE, // Opaque string
|
||||
@ -127,10 +133,10 @@ extern void mxmlDelete(mxml_node_t *node);
|
||||
extern void mxmlElementDeleteAttr(mxml_node_t *node, const char *name);
|
||||
extern const char *mxmlElementGetAttr(mxml_node_t *node, const char *name);
|
||||
extern const char *mxmlElementGetAttrByIndex(mxml_node_t *node, int idx, const char **name);
|
||||
extern int mxmlElementGetAttrCount(mxml_node_t *node);
|
||||
extern size_t mxmlElementGetAttrCount(mxml_node_t *node);
|
||||
extern void mxmlElementSetAttr(mxml_node_t *node, const char *name, const char *value);
|
||||
extern void mxmlElementSetAttrf(mxml_node_t *node, const char *name, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern int mxmlEntityAddCallback(mxml_entity_cb_t cb);
|
||||
extern bool mxmlEntityAddCallback(mxml_entity_cb_t cb);
|
||||
extern const char *mxmlEntityGetName(int val);
|
||||
extern int mxmlEntityGetValue(const char *name);
|
||||
extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
|
||||
@ -140,15 +146,15 @@ extern const char *mxmlGetCDATA(mxml_node_t *node);
|
||||
extern const void *mxmlGetCustom(mxml_node_t *node);
|
||||
extern const char *mxmlGetElement(mxml_node_t *node);
|
||||
extern mxml_node_t *mxmlGetFirstChild(mxml_node_t *node);
|
||||
extern int mxmlGetInteger(mxml_node_t *node);
|
||||
extern long mxmlGetInteger(mxml_node_t *node);
|
||||
extern mxml_node_t *mxmlGetLastChild(mxml_node_t *node);
|
||||
extern mxml_node_t *mxmlGetNextSibling(mxml_node_t *node);
|
||||
extern const char *mxmlGetOpaque(mxml_node_t *node);
|
||||
extern mxml_node_t *mxmlGetParent(mxml_node_t *node);
|
||||
extern mxml_node_t *mxmlGetPrevSibling(mxml_node_t *node);
|
||||
extern double mxmlGetReal(mxml_node_t *node);
|
||||
extern int mxmlGetRefCount(mxml_node_t *node);
|
||||
extern const char *mxmlGetText(mxml_node_t *node, int *whitespace);
|
||||
extern size_t mxmlGetRefCount(mxml_node_t *node);
|
||||
extern const char *mxmlGetText(mxml_node_t *node, bool *whitespace);
|
||||
extern mxml_type_t mxmlGetType(mxml_node_t *node);
|
||||
extern void *mxmlGetUserData(mxml_node_t *node);
|
||||
extern void mxmlIndexDelete(mxml_index_t *ind);
|
||||
@ -160,14 +166,21 @@ extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
|
||||
extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd, mxml_load_cb_t cb); extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp, mxml_load_cb_t cb);
|
||||
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s, mxml_load_cb_t cb);
|
||||
extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
|
||||
extern mxml_node_t *mxmlNewCDATAf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewComment(mxml_node_t *parent, const char *comment);
|
||||
extern mxml_node_t *mxmlNewCommentf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data, mxml_custom_destroy_cb_t destroy);
|
||||
extern mxml_node_t *mxmlNewDeclaration(mxml_node_t *parent, const char *declaration);
|
||||
extern mxml_node_t *mxmlNewDeclarationf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewDirective(mxml_node_t *parent, const char *directive);
|
||||
extern mxml_node_t *mxmlNewDirectivef(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewElement(mxml_node_t *parent, const char *name);
|
||||
extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, int integer);
|
||||
extern mxml_node_t *mxmlNewInteger(mxml_node_t *parent, long integer);
|
||||
extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
|
||||
extern mxml_node_t *mxmlNewOpaquef(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
|
||||
extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace, const char *string);
|
||||
extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern mxml_node_t *mxmlNewText(mxml_node_t *parent, bool whitespace, const char *string);
|
||||
extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, bool whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern mxml_node_t *mxmlNewXML(const char *version);
|
||||
extern int mxmlRelease(mxml_node_t *node);
|
||||
extern void mxmlRemove(mxml_node_t *node);
|
||||
@ -179,18 +192,25 @@ extern int mxmlSaveString(mxml_node_t *node, char *buffer, int bufsize, mxml_sa
|
||||
extern mxml_node_t *mxmlSAXLoadFd(mxml_node_t *top, int fd, mxml_load_cb_t cb, mxml_sax_cb_t sax, void *sax_data);
|
||||
extern mxml_node_t *mxmlSAXLoadFile(mxml_node_t *top, FILE *fp, mxml_load_cb_t cb, mxml_sax_cb_t sax, void *sax_data);
|
||||
extern mxml_node_t *mxmlSAXLoadString(mxml_node_t *top, const char *s, mxml_load_cb_t cb, mxml_sax_cb_t sax, void *sax_data);
|
||||
extern int mxmlSetCDATA(mxml_node_t *node, const char *data);
|
||||
extern int mxmlSetCustom(mxml_node_t *node, void *data, mxml_custom_destroy_cb_t destroy);
|
||||
extern bool mxmlSetCDATA(mxml_node_t *node, const char *data);
|
||||
extern bool mxmlSetCDATAf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetComment(mxml_node_t *node, const char *comment);
|
||||
extern bool mxmlSetCommentf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
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 void mxmlSetCustomHandlers(mxml_custom_load_cb_t load, mxml_custom_save_cb_t save);
|
||||
extern int mxmlSetElement(mxml_node_t *node, const char *name);
|
||||
extern bool mxmlSetElement(mxml_node_t *node, const char *name);
|
||||
extern void mxmlSetErrorCallback(mxml_error_cb_t cb);
|
||||
extern int mxmlSetInteger(mxml_node_t *node, int integer);
|
||||
extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque);
|
||||
extern int mxmlSetOpaquef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern int mxmlSetReal(mxml_node_t *node, double real);
|
||||
extern int mxmlSetText(mxml_node_t *node, int whitespace, const char *string);
|
||||
extern int mxmlSetTextf(mxml_node_t *node, int whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern int mxmlSetUserData(mxml_node_t *node, void *data);
|
||||
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 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);
|
||||
extern void mxmlSetWrapMargin(int column);
|
||||
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, int descend);
|
||||
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, int descend);
|
||||
|
2
test.xml
2
test.xml
@ -8,7 +8,7 @@
|
||||
<choice>
|
||||
<keyword type="opaque">Auto</keyword>
|
||||
<text>Auto Tray Selection</text>
|
||||
<code type="opaque" />
|
||||
<code type="opaque"/>
|
||||
</choice>
|
||||
<choice>
|
||||
<keyword type="opaque">Upper</keyword>
|
||||
|
34
testmxml.c
34
testmxml.c
@ -28,7 +28,7 @@
|
||||
// Globals...
|
||||
//
|
||||
|
||||
int event_counts[6];
|
||||
int event_counts[7];
|
||||
|
||||
|
||||
//
|
||||
@ -99,7 +99,7 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
mxmlNewInteger(tree, 123);
|
||||
mxmlNewOpaque(tree, "opaque");
|
||||
mxmlNewReal(tree, 123.4f);
|
||||
mxmlNewReal(tree, 123.4);
|
||||
mxmlNewText(tree, 1, "text");
|
||||
|
||||
mxmlLoadString(tree, "<group type='string'>string string string</group>", MXML_NO_CALLBACK);
|
||||
@ -141,7 +141,7 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
if (node->value.integer != 123)
|
||||
{
|
||||
fprintf(stderr, "ERROR: First child value is %d, expected 123.\n", node->value.integer);
|
||||
fprintf(stderr, "ERROR: First child value is %ld, expected 123.\n", node->value.integer);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
}
|
||||
@ -185,7 +185,7 @@ main(int argc, // I - Number of command-line args
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (node->value.real != 123.4f)
|
||||
if (node->value.real != 123.4)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Third child value is %f, expected 123.4.\n", node->value.real);
|
||||
mxmlDelete(tree);
|
||||
@ -286,9 +286,9 @@ main(int argc, // I - Number of command-line args
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (ind->num_nodes != 13)
|
||||
if (ind->num_nodes != 10)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Index of all nodes contains %d nodes; expected 13.\n", ind->num_nodes);
|
||||
fprintf(stderr, "ERROR: Index of all nodes contains %lu nodes; expected 10.\n", (unsigned long)ind->num_nodes);
|
||||
mxmlIndexDelete(ind);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
@ -315,7 +315,7 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
if (ind->num_nodes != 4)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Index of groups contains %d nodes; expected 4.\n", ind->num_nodes);
|
||||
fprintf(stderr, "ERROR: Index of groups contains %lu nodes; expected 4.\n", (unsigned long)ind->num_nodes);
|
||||
mxmlIndexDelete(ind);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
@ -342,7 +342,7 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
if (ind->num_nodes != 3)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Index of type attributes contains %d nodes; expected 3.\n", ind->num_nodes);
|
||||
fprintf(stderr, "ERROR: Index of type attributes contains %lu nodes; expected 3.\n", (unsigned long)ind->num_nodes);
|
||||
mxmlIndexDelete(ind);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
@ -369,7 +369,7 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
if (ind->num_nodes != 3)
|
||||
{
|
||||
fprintf(stderr, "ERROR: Index of elements and attributes contains %d nodes; expected 3.\n", ind->num_nodes);
|
||||
fprintf(stderr, "ERROR: Index of elements and attributes contains %lu nodes; expected 3.\n", (unsigned long)ind->num_nodes);
|
||||
mxmlIndexDelete(ind);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
@ -602,6 +602,12 @@ main(int argc, // I - Number of command-line args
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (event_counts[MXML_SAX_EVENT_DECLARATION] != 0)
|
||||
{
|
||||
fprintf(stderr, "MXML_SAX_EVENT_DECLARATION seen %d times, expected 0 times.\n", event_counts[MXML_SAX_EVENT_DECLARATION]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
if (event_counts[MXML_SAX_EVENT_DIRECTIVE] != 1)
|
||||
{
|
||||
fprintf(stderr, "MXML_SAX_EVENT_DIRECTIVE seen %d times, expected 1 times.\n", event_counts[MXML_SAX_EVENT_DIRECTIVE]);
|
||||
@ -657,7 +663,8 @@ sax_cb(mxml_node_t *node, // I - Current node
|
||||
"MXML_SAX_EVENT_CDATA", // CDATA node
|
||||
"MXML_SAX_EVENT_COMMENT", // Comment node
|
||||
"MXML_SAX_EVENT_DATA", // Data node
|
||||
"MXML_SAX_EVENT_DIRECTIVE", // Processing directive node
|
||||
"MXML_SAX_EVENT_DECLARATION", // Declaration node
|
||||
"MXML_SAX_EVENT_DIRECTIVE", // Processing directive node
|
||||
"MXML_SAX_EVENT_ELEMENT_CLOSE", // Element closed
|
||||
"MXML_SAX_EVENT_ELEMENT_OPEN" // Element opened
|
||||
};
|
||||
@ -716,7 +723,8 @@ whitespace_cb(mxml_node_t *node, // I - Element node
|
||||
|
||||
// We can conditionally break to a new line before or after any element.
|
||||
// These are just common HTML elements...
|
||||
name = node->value.element.name;
|
||||
if ((name = mxmlGetElement(node)) == NULL)
|
||||
name = "";
|
||||
|
||||
if (!strcmp(name, "html") || !strcmp(name, "head") || !strcmp(name, "body") || !strcmp(name, "pre") || !strcmp(name, "p") || !strcmp(name, "h1") || !strcmp(name, "h2") || !strcmp(name, "h3") || !strcmp(name, "h4") || !strcmp(name, "h5") || !strcmp(name, "h6"))
|
||||
{
|
||||
@ -737,7 +745,7 @@ whitespace_cb(mxml_node_t *node, // I - Element node
|
||||
else if (where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strncmp(name, "?xml", 4))
|
||||
else if (mxmlGetType(node) == MXML_TYPE_DIRECTIVE)
|
||||
{
|
||||
if (where == MXML_WS_AFTER_OPEN)
|
||||
return ("\n");
|
||||
@ -757,7 +765,7 @@ whitespace_cb(mxml_node_t *node, // I - Element node
|
||||
}
|
||||
else if (where == MXML_WS_AFTER_CLOSE || ((!strcmp(name, "group") || !strcmp(name, "option") || !strcmp(name, "choice")) && where == MXML_WS_AFTER_OPEN))
|
||||
return ("\n");
|
||||
else if (where == MXML_WS_AFTER_OPEN && !node->child)
|
||||
else if (where == MXML_WS_AFTER_OPEN && !mxmlGetFirstChild(node))
|
||||
return ("\n");
|
||||
|
||||
// Return NULL for no added whitespace...
|
||||
|
Loading…
Reference in New Issue
Block a user