mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-24 11:25:30 +00:00
Implement mxmlOptions APIs to normalize all of the load/save option stuff (Issue #312)
This commit is contained in:
parent
726dc0dce7
commit
e676eb35cb
@ -9,6 +9,8 @@
|
|||||||
`MXML_TYPE_DIRECTIVE` node types (Issue #250)
|
`MXML_TYPE_DIRECTIVE` node types (Issue #250)
|
||||||
- Added `mxmlLoadFilename` and `mxmlSaveFilename` functions (Issue #291)
|
- Added `mxmlLoadFilename` and `mxmlSaveFilename` functions (Issue #291)
|
||||||
- Added AFL fuzzing support (Issue #306)
|
- Added AFL fuzzing support (Issue #306)
|
||||||
|
- Added `mxmlOptions` APIs to replace the long list of callbacks and options for
|
||||||
|
each of the load and save functions (Issue #312)
|
||||||
- Added string copy/free callbacks to support alternate memory management of
|
- Added string copy/free callbacks to support alternate memory management of
|
||||||
strings.
|
strings.
|
||||||
- Renamed `mxml_type_t` enumerations to `MXML_TYPE_xxx` (Issue #251)
|
- Renamed `mxml_type_t` enumerations to `MXML_TYPE_xxx` (Issue #251)
|
||||||
|
@ -150,8 +150,8 @@ BUILDROOT = $(DSTROOT)$(DESTDIR)
|
|||||||
|
|
||||||
DOCFILES = doc/mxml.epub doc/mxml.html doc/mxml-cover.png \
|
DOCFILES = doc/mxml.epub doc/mxml.html doc/mxml-cover.png \
|
||||||
CHANGES.md LICENSE NOTICE README.md
|
CHANGES.md LICENSE NOTICE README.md
|
||||||
PUBLIBOBJS = mxml-attr.o mxml-entity.o mxml-file.o mxml-get.o \
|
PUBLIBOBJS = mxml-attr.o mxml-file.o mxml-get.o mxml-index.o \
|
||||||
mxml-index.o mxml-node.o mxml-search.o mxml-set.o
|
mxml-node.o mxml-options.o mxml-search.o mxml-set.o
|
||||||
LIBOBJS = $(PUBLIBOBJS) mxml-private.o
|
LIBOBJS = $(PUBLIBOBJS) mxml-private.o
|
||||||
OBJS = testmxml.o $(LIBOBJS)
|
OBJS = testmxml.o $(LIBOBJS)
|
||||||
ALLTARGETS = $(LIBMXML) testmxml
|
ALLTARGETS = $(LIBMXML) testmxml
|
||||||
|
@ -5,6 +5,9 @@ copyright: Copyright © 2003-2024, All Rights Reserved.
|
|||||||
version: 4.0
|
version: 4.0
|
||||||
...
|
...
|
||||||
|
|
||||||
|
> TODO: Update for mxmlOptions APIs!
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
============
|
============
|
||||||
|
|
||||||
|
16
mxml-attr.c
16
mxml-attr.c
@ -173,11 +173,8 @@ mxmlElementSetAttr(mxml_node_t *node, // I - Element node
|
|||||||
if (value)
|
if (value)
|
||||||
{
|
{
|
||||||
if ((valuec = _mxml_strcopy(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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
valuec = NULL;
|
valuec = NULL;
|
||||||
@ -218,10 +215,11 @@ mxmlElementSetAttrf(mxml_node_t *node, // I - Element node
|
|||||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((value = _mxml_strcopy(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))
|
if (!mxml_set_attr(node, name, value))
|
||||||
_mxml_strfree(value);
|
_mxml_strfree(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -253,19 +251,13 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
|||||||
|
|
||||||
// Add a new attribute...
|
// Add a new attribute...
|
||||||
if ((attr = realloc(node->value.element.attrs, (node->value.element.num_attrs + 1) * sizeof(_mxml_attr_t))) == NULL)
|
if ((attr = realloc(node->value.element.attrs, (node->value.element.num_attrs + 1) * sizeof(_mxml_attr_t))) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
node->value.element.attrs = attr;
|
node->value.element.attrs = attr;
|
||||||
attr += node->value.element.num_attrs;
|
attr += node->value.element.num_attrs;
|
||||||
|
|
||||||
if ((attr->name = _mxml_strcopy(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);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
attr->value = value;
|
attr->value = value;
|
||||||
|
|
||||||
|
433
mxml-entity.c
433
mxml-entity.c
@ -1,433 +0,0 @@
|
|||||||
//
|
|
||||||
// Character entity support code for Mini-XML, a small XML file parsing library.
|
|
||||||
//
|
|
||||||
// https://www.msweet.org/mxml
|
|
||||||
//
|
|
||||||
// Copyright © 2003-2024 by Michael R Sweet.
|
|
||||||
//
|
|
||||||
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
|
||||||
// information.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include "mxml-private.h"
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 'mxmlEntityAddCallback()' - Add a callback to convert entities to Unicode.
|
|
||||||
//
|
|
||||||
// This function adds a callback to the current thread that converts named
|
|
||||||
// XML character entities to Unicode characters. The callback function `cb`
|
|
||||||
// accepts the callback data pointer `cbdata` and the entity name and returns a
|
|
||||||
// Unicode character value or `-1` if the entity is not known. For example, the
|
|
||||||
// following entity callback supports the "euro" entity:
|
|
||||||
//
|
|
||||||
// ```c
|
|
||||||
// int my_entity_cb(void *cbdata, const char *name)
|
|
||||||
// {
|
|
||||||
// if (!strcmp(name, "euro"))
|
|
||||||
// return (0x20ac);
|
|
||||||
// else
|
|
||||||
// return (-1);
|
|
||||||
// }
|
|
||||||
// ```
|
|
||||||
//
|
|
||||||
|
|
||||||
bool // O - `true` on success, `false` on failure
|
|
||||||
mxmlEntityAddCallback(
|
|
||||||
mxml_entity_cb_t cb, // I - Callback function to add
|
|
||||||
void *cbdata) // I - Callback data
|
|
||||||
{
|
|
||||||
_mxml_global_t *global = _mxml_global();
|
|
||||||
// Global data
|
|
||||||
|
|
||||||
|
|
||||||
if (global->num_entity_cbs < (sizeof(global->entity_cbs) / sizeof(global->entity_cbs[0])))
|
|
||||||
{
|
|
||||||
global->entity_cbs[global->num_entity_cbs] = cb;
|
|
||||||
global->entity_cbdatas[global->num_entity_cbs] = cbdata;
|
|
||||||
global->num_entity_cbs ++;
|
|
||||||
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_mxml_error("Unable to add entity callback!");
|
|
||||||
|
|
||||||
return (false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// '_mxml_entity_string()' - Get the entity that corresponds to the character, if any.
|
|
||||||
//
|
|
||||||
|
|
||||||
const char * // O - Entity or `NULL` for none
|
|
||||||
_mxml_entity_string(int ch) // I - Character
|
|
||||||
{
|
|
||||||
switch (ch)
|
|
||||||
{
|
|
||||||
case '&' :
|
|
||||||
return ("&");
|
|
||||||
|
|
||||||
case '<' :
|
|
||||||
return ("<");
|
|
||||||
|
|
||||||
case '>' :
|
|
||||||
return (">");
|
|
||||||
|
|
||||||
case '\"' :
|
|
||||||
return (""");
|
|
||||||
|
|
||||||
default :
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 'mxmlEntityGetValue()' - Get the character corresponding to a named entity.
|
|
||||||
//
|
|
||||||
// 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
|
|
||||||
mxmlEntityGetValue(const char *name) // I - Entity name
|
|
||||||
{
|
|
||||||
size_t i; // Looping var
|
|
||||||
int ch; // Character value
|
|
||||||
_mxml_global_t *global = _mxml_global();
|
|
||||||
// Global data
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < global->num_entity_cbs; i ++)
|
|
||||||
{
|
|
||||||
if ((ch = (global->entity_cbs[i])(global->entity_cbdatas[i], name)) >= 0)
|
|
||||||
return (ch);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// 'mxmlEntityRemoveCallback()' - Remove a callback.
|
|
||||||
//
|
|
||||||
|
|
||||||
void
|
|
||||||
mxmlEntityRemoveCallback(
|
|
||||||
mxml_entity_cb_t cb) // I - Callback function to remove
|
|
||||||
{
|
|
||||||
size_t i; // Looping var
|
|
||||||
_mxml_global_t *global = _mxml_global();
|
|
||||||
// Global data
|
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < global->num_entity_cbs; i ++)
|
|
||||||
{
|
|
||||||
if (cb == global->entity_cbs[i])
|
|
||||||
{
|
|
||||||
// Remove the callback...
|
|
||||||
global->num_entity_cbs --;
|
|
||||||
|
|
||||||
if (i < global->num_entity_cbs)
|
|
||||||
{
|
|
||||||
memmove(global->entity_cbs + i, global->entity_cbs + i + 1, (global->num_entity_cbs - i) * sizeof(global->entity_cbs[0]));
|
|
||||||
memmove(global->entity_cbdatas + i, global->entity_cbdatas + i + 1, (global->num_entity_cbs - i) * sizeof(global->entity_cbdatas[0]));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// '_mxml_entity_cb()' - Lookup standard (X)HTML entities.
|
|
||||||
//
|
|
||||||
|
|
||||||
int // O - Unicode value or -1
|
|
||||||
_mxml_entity_cb(void *cbdata, // I - Callback data (unused)
|
|
||||||
const char *name) // I - Entity name
|
|
||||||
{
|
|
||||||
size_t i; // Looping var
|
|
||||||
int diff; // Difference
|
|
||||||
static const struct
|
|
||||||
{
|
|
||||||
const char *name; // Entity name
|
|
||||||
int val; // Character value
|
|
||||||
} entities[] =
|
|
||||||
{
|
|
||||||
{ "AElig", 198 },
|
|
||||||
{ "Aacute", 193 },
|
|
||||||
{ "Acirc", 194 },
|
|
||||||
{ "Agrave", 192 },
|
|
||||||
{ "Alpha", 913 },
|
|
||||||
{ "Aring", 197 },
|
|
||||||
{ "Atilde", 195 },
|
|
||||||
{ "Auml", 196 },
|
|
||||||
{ "Beta", 914 },
|
|
||||||
{ "Ccedil", 199 },
|
|
||||||
{ "Chi", 935 },
|
|
||||||
{ "Dagger", 8225 },
|
|
||||||
{ "Delta", 916 },
|
|
||||||
{ "Dstrok", 208 },
|
|
||||||
{ "ETH", 208 },
|
|
||||||
{ "Eacute", 201 },
|
|
||||||
{ "Ecirc", 202 },
|
|
||||||
{ "Egrave", 200 },
|
|
||||||
{ "Epsilon", 917 },
|
|
||||||
{ "Eta", 919 },
|
|
||||||
{ "Euml", 203 },
|
|
||||||
{ "Gamma", 915 },
|
|
||||||
{ "Iacute", 205 },
|
|
||||||
{ "Icirc", 206 },
|
|
||||||
{ "Igrave", 204 },
|
|
||||||
{ "Iota", 921 },
|
|
||||||
{ "Iuml", 207 },
|
|
||||||
{ "Kappa", 922 },
|
|
||||||
{ "Lambda", 923 },
|
|
||||||
{ "Mu", 924 },
|
|
||||||
{ "Ntilde", 209 },
|
|
||||||
{ "Nu", 925 },
|
|
||||||
{ "OElig", 338 },
|
|
||||||
{ "Oacute", 211 },
|
|
||||||
{ "Ocirc", 212 },
|
|
||||||
{ "Ograve", 210 },
|
|
||||||
{ "Omega", 937 },
|
|
||||||
{ "Omicron", 927 },
|
|
||||||
{ "Oslash", 216 },
|
|
||||||
{ "Otilde", 213 },
|
|
||||||
{ "Ouml", 214 },
|
|
||||||
{ "Phi", 934 },
|
|
||||||
{ "Pi", 928 },
|
|
||||||
{ "Prime", 8243 },
|
|
||||||
{ "Psi", 936 },
|
|
||||||
{ "Rho", 929 },
|
|
||||||
{ "Scaron", 352 },
|
|
||||||
{ "Sigma", 931 },
|
|
||||||
{ "THORN", 222 },
|
|
||||||
{ "Tau", 932 },
|
|
||||||
{ "Theta", 920 },
|
|
||||||
{ "Uacute", 218 },
|
|
||||||
{ "Ucirc", 219 },
|
|
||||||
{ "Ugrave", 217 },
|
|
||||||
{ "Upsilon", 933 },
|
|
||||||
{ "Uuml", 220 },
|
|
||||||
{ "Xi", 926 },
|
|
||||||
{ "Yacute", 221 },
|
|
||||||
{ "Yuml", 376 },
|
|
||||||
{ "Zeta", 918 },
|
|
||||||
{ "aacute", 225 },
|
|
||||||
{ "acirc", 226 },
|
|
||||||
{ "acute", 180 },
|
|
||||||
{ "aelig", 230 },
|
|
||||||
{ "agrave", 224 },
|
|
||||||
{ "alefsym", 8501 },
|
|
||||||
{ "alpha", 945 },
|
|
||||||
{ "amp", '&' },
|
|
||||||
{ "and", 8743 },
|
|
||||||
{ "ang", 8736 },
|
|
||||||
{ "apos", '\'' },
|
|
||||||
{ "aring", 229 },
|
|
||||||
{ "asymp", 8776 },
|
|
||||||
{ "atilde", 227 },
|
|
||||||
{ "auml", 228 },
|
|
||||||
{ "bdquo", 8222 },
|
|
||||||
{ "beta", 946 },
|
|
||||||
{ "brkbar", 166 },
|
|
||||||
{ "brvbar", 166 },
|
|
||||||
{ "bull", 8226 },
|
|
||||||
{ "cap", 8745 },
|
|
||||||
{ "ccedil", 231 },
|
|
||||||
{ "cedil", 184 },
|
|
||||||
{ "cent", 162 },
|
|
||||||
{ "chi", 967 },
|
|
||||||
{ "circ", 710 },
|
|
||||||
{ "clubs", 9827 },
|
|
||||||
{ "cong", 8773 },
|
|
||||||
{ "copy", 169 },
|
|
||||||
{ "crarr", 8629 },
|
|
||||||
{ "cup", 8746 },
|
|
||||||
{ "curren", 164 },
|
|
||||||
{ "dArr", 8659 },
|
|
||||||
{ "dagger", 8224 },
|
|
||||||
{ "darr", 8595 },
|
|
||||||
{ "deg", 176 },
|
|
||||||
{ "delta", 948 },
|
|
||||||
{ "diams", 9830 },
|
|
||||||
{ "die", 168 },
|
|
||||||
{ "divide", 247 },
|
|
||||||
{ "eacute", 233 },
|
|
||||||
{ "ecirc", 234 },
|
|
||||||
{ "egrave", 232 },
|
|
||||||
{ "empty", 8709 },
|
|
||||||
{ "emsp", 8195 },
|
|
||||||
{ "ensp", 8194 },
|
|
||||||
{ "epsilon", 949 },
|
|
||||||
{ "equiv", 8801 },
|
|
||||||
{ "eta", 951 },
|
|
||||||
{ "eth", 240 },
|
|
||||||
{ "euml", 235 },
|
|
||||||
{ "euro", 8364 },
|
|
||||||
{ "exist", 8707 },
|
|
||||||
{ "fnof", 402 },
|
|
||||||
{ "forall", 8704 },
|
|
||||||
{ "frac12", 189 },
|
|
||||||
{ "frac14", 188 },
|
|
||||||
{ "frac34", 190 },
|
|
||||||
{ "frasl", 8260 },
|
|
||||||
{ "gamma", 947 },
|
|
||||||
{ "ge", 8805 },
|
|
||||||
{ "gt", '>' },
|
|
||||||
{ "hArr", 8660 },
|
|
||||||
{ "harr", 8596 },
|
|
||||||
{ "hearts", 9829 },
|
|
||||||
{ "hellip", 8230 },
|
|
||||||
{ "hibar", 175 },
|
|
||||||
{ "iacute", 237 },
|
|
||||||
{ "icirc", 238 },
|
|
||||||
{ "iexcl", 161 },
|
|
||||||
{ "igrave", 236 },
|
|
||||||
{ "image", 8465 },
|
|
||||||
{ "infin", 8734 },
|
|
||||||
{ "int", 8747 },
|
|
||||||
{ "iota", 953 },
|
|
||||||
{ "iquest", 191 },
|
|
||||||
{ "isin", 8712 },
|
|
||||||
{ "iuml", 239 },
|
|
||||||
{ "kappa", 954 },
|
|
||||||
{ "lArr", 8656 },
|
|
||||||
{ "lambda", 955 },
|
|
||||||
{ "lang", 9001 },
|
|
||||||
{ "laquo", 171 },
|
|
||||||
{ "larr", 8592 },
|
|
||||||
{ "lceil", 8968 },
|
|
||||||
{ "ldquo", 8220 },
|
|
||||||
{ "le", 8804 },
|
|
||||||
{ "lfloor", 8970 },
|
|
||||||
{ "lowast", 8727 },
|
|
||||||
{ "loz", 9674 },
|
|
||||||
{ "lrm", 8206 },
|
|
||||||
{ "lsaquo", 8249 },
|
|
||||||
{ "lsquo", 8216 },
|
|
||||||
{ "lt", '<' },
|
|
||||||
{ "macr", 175 },
|
|
||||||
{ "mdash", 8212 },
|
|
||||||
{ "micro", 181 },
|
|
||||||
{ "middot", 183 },
|
|
||||||
{ "minus", 8722 },
|
|
||||||
{ "mu", 956 },
|
|
||||||
{ "nabla", 8711 },
|
|
||||||
{ "nbsp", 160 },
|
|
||||||
{ "ndash", 8211 },
|
|
||||||
{ "ne", 8800 },
|
|
||||||
{ "ni", 8715 },
|
|
||||||
{ "not", 172 },
|
|
||||||
{ "notin", 8713 },
|
|
||||||
{ "nsub", 8836 },
|
|
||||||
{ "ntilde", 241 },
|
|
||||||
{ "nu", 957 },
|
|
||||||
{ "oacute", 243 },
|
|
||||||
{ "ocirc", 244 },
|
|
||||||
{ "oelig", 339 },
|
|
||||||
{ "ograve", 242 },
|
|
||||||
{ "oline", 8254 },
|
|
||||||
{ "omega", 969 },
|
|
||||||
{ "omicron", 959 },
|
|
||||||
{ "oplus", 8853 },
|
|
||||||
{ "or", 8744 },
|
|
||||||
{ "ordf", 170 },
|
|
||||||
{ "ordm", 186 },
|
|
||||||
{ "oslash", 248 },
|
|
||||||
{ "otilde", 245 },
|
|
||||||
{ "otimes", 8855 },
|
|
||||||
{ "ouml", 246 },
|
|
||||||
{ "para", 182 },
|
|
||||||
{ "part", 8706 },
|
|
||||||
{ "permil", 8240 },
|
|
||||||
{ "perp", 8869 },
|
|
||||||
{ "phi", 966 },
|
|
||||||
{ "pi", 960 },
|
|
||||||
{ "piv", 982 },
|
|
||||||
{ "plusmn", 177 },
|
|
||||||
{ "pound", 163 },
|
|
||||||
{ "prime", 8242 },
|
|
||||||
{ "prod", 8719 },
|
|
||||||
{ "prop", 8733 },
|
|
||||||
{ "psi", 968 },
|
|
||||||
{ "quot", '\"' },
|
|
||||||
{ "rArr", 8658 },
|
|
||||||
{ "radic", 8730 },
|
|
||||||
{ "rang", 9002 },
|
|
||||||
{ "raquo", 187 },
|
|
||||||
{ "rarr", 8594 },
|
|
||||||
{ "rceil", 8969 },
|
|
||||||
{ "rdquo", 8221 },
|
|
||||||
{ "real", 8476 },
|
|
||||||
{ "reg", 174 },
|
|
||||||
{ "rfloor", 8971 },
|
|
||||||
{ "rho", 961 },
|
|
||||||
{ "rlm", 8207 },
|
|
||||||
{ "rsaquo", 8250 },
|
|
||||||
{ "rsquo", 8217 },
|
|
||||||
{ "sbquo", 8218 },
|
|
||||||
{ "scaron", 353 },
|
|
||||||
{ "sdot", 8901 },
|
|
||||||
{ "sect", 167 },
|
|
||||||
{ "shy", 173 },
|
|
||||||
{ "sigma", 963 },
|
|
||||||
{ "sigmaf", 962 },
|
|
||||||
{ "sim", 8764 },
|
|
||||||
{ "spades", 9824 },
|
|
||||||
{ "sub", 8834 },
|
|
||||||
{ "sube", 8838 },
|
|
||||||
{ "sum", 8721 },
|
|
||||||
{ "sup", 8835 },
|
|
||||||
{ "sup1", 185 },
|
|
||||||
{ "sup2", 178 },
|
|
||||||
{ "sup3", 179 },
|
|
||||||
{ "supe", 8839 },
|
|
||||||
{ "szlig", 223 },
|
|
||||||
{ "tau", 964 },
|
|
||||||
{ "there4", 8756 },
|
|
||||||
{ "theta", 952 },
|
|
||||||
{ "thetasym", 977 },
|
|
||||||
{ "thinsp", 8201 },
|
|
||||||
{ "thorn", 254 },
|
|
||||||
{ "tilde", 732 },
|
|
||||||
{ "times", 215 },
|
|
||||||
{ "trade", 8482 },
|
|
||||||
{ "uArr", 8657 },
|
|
||||||
{ "uacute", 250 },
|
|
||||||
{ "uarr", 8593 },
|
|
||||||
{ "ucirc", 251 },
|
|
||||||
{ "ugrave", 249 },
|
|
||||||
{ "uml", 168 },
|
|
||||||
{ "upsih", 978 },
|
|
||||||
{ "upsilon", 965 },
|
|
||||||
{ "uuml", 252 },
|
|
||||||
{ "weierp", 8472 },
|
|
||||||
{ "xi", 958 },
|
|
||||||
{ "yacute", 253 },
|
|
||||||
{ "yen", 165 },
|
|
||||||
{ "yuml", 255 },
|
|
||||||
{ "zeta", 950 },
|
|
||||||
{ "zwj", 8205 },
|
|
||||||
{ "zwnj", 8204 }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
(void)cbdata;
|
|
||||||
|
|
||||||
// Do a linear search for the named entity...
|
|
||||||
for (i = 0; i < (sizeof(entities) / sizeof(entities[0])); i ++)
|
|
||||||
{
|
|
||||||
if ((diff = strcmp(name, entities[i].name)) == 0)
|
|
||||||
return (entities[i].val);
|
|
||||||
else if (diff < 0)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (-1);
|
|
||||||
}
|
|
735
mxml-file.c
735
mxml-file.c
File diff suppressed because it is too large
Load Diff
@ -227,16 +227,12 @@ mxmlIndexNew(mxml_node_t *node, // I - XML node tree
|
|||||||
|
|
||||||
// Create a new index...
|
// Create a new index...
|
||||||
if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
|
if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for index.");
|
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
|
||||||
|
|
||||||
if (attr)
|
if (attr)
|
||||||
{
|
{
|
||||||
if ((ind->attr = _mxml_strcopy(attr)) == NULL)
|
if ((ind->attr = _mxml_strcopy(attr)) == NULL)
|
||||||
{
|
{
|
||||||
_mxml_error("Unable to allocate memory for index attribute.");
|
|
||||||
free(ind);
|
free(ind);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -254,7 +250,6 @@ mxmlIndexNew(mxml_node_t *node, // I - XML node tree
|
|||||||
if ((temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *))) == NULL)
|
if ((temp = realloc(ind->nodes, (ind->alloc_nodes + 64) * sizeof(mxml_node_t *))) == NULL)
|
||||||
{
|
{
|
||||||
// Unable to allocate memory for the index, so abort...
|
// Unable to allocate memory for the index, so abort...
|
||||||
_mxml_error("Unable to allocate memory for index nodes.");
|
|
||||||
mxmlIndexDelete(ind);
|
mxmlIndexDelete(ind);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
21
mxml-node.c
21
mxml-node.c
@ -210,7 +210,6 @@ mxmlNewCDATA(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
|||||||
{
|
{
|
||||||
if ((node->value.cdata = _mxml_strcopy(data)) == NULL)
|
if ((node->value.cdata = _mxml_strcopy(data)) == NULL)
|
||||||
{
|
{
|
||||||
_mxml_error("Unable to allocate memory for CDATA.");
|
|
||||||
mxmlDelete(node);
|
mxmlDelete(node);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -286,7 +285,6 @@ mxmlNewComment(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
|||||||
{
|
{
|
||||||
if ((node->value.comment = _mxml_strcopy(comment)) == NULL)
|
if ((node->value.comment = _mxml_strcopy(comment)) == NULL)
|
||||||
{
|
{
|
||||||
_mxml_error("Unable to allocate memory for comment.");
|
|
||||||
mxmlDelete(node);
|
mxmlDelete(node);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -339,27 +337,28 @@ mxmlNewCommentf(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
|||||||
// 'mxmlNewCustom()' - Create a new custom data node.
|
// 'mxmlNewCustom()' - Create a new custom data node.
|
||||||
//
|
//
|
||||||
// The new custom node is added to the end of the specified parent's child
|
// The new custom 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
|
// list. The `free_cb` argument specifies a function to call to free the custom
|
||||||
// element node has no parent. `NULL` can be passed when the data in the
|
// data when the node is deleted.
|
||||||
// node is not dynamically allocated or is separately managed.
|
|
||||||
//
|
//
|
||||||
|
|
||||||
mxml_node_t * // O - New node
|
mxml_node_t * // O - New node
|
||||||
mxmlNewCustom(
|
mxmlNewCustom(
|
||||||
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||||
void *data, // I - Pointer to data
|
void *data, // I - Pointer to data
|
||||||
mxml_custom_destroy_cb_t destroy) // I - Function to destroy data
|
mxml_custfree_cb_t free_cb, // I - Free callback function or `NULL` if none needed
|
||||||
|
void *free_cbdata) // I - Free callback data
|
||||||
{
|
{
|
||||||
mxml_node_t *node; // New node
|
mxml_node_t *node; // New node
|
||||||
|
|
||||||
|
|
||||||
MXML_DEBUG("mxmlNewCustom(parent=%p, data=%p, destroy=%p)\n", parent, data, destroy);
|
MXML_DEBUG("mxmlNewCustom(parent=%p, data=%p, free_cb=%p, free_cbdata=%p)\n", parent, data, free_cb, free_cbdata);
|
||||||
|
|
||||||
// Create the node and set the value...
|
// Create the node and set the value...
|
||||||
if ((node = mxml_new(parent, MXML_TYPE_CUSTOM)) != NULL)
|
if ((node = mxml_new(parent, MXML_TYPE_CUSTOM)) != NULL)
|
||||||
{
|
{
|
||||||
node->value.custom.data = data;
|
node->value.custom.data = data;
|
||||||
node->value.custom.destroy = destroy;
|
node->value.custom.free_cb = free_cb;
|
||||||
|
node->value.custom.free_cbdata = free_cbdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (node);
|
return (node);
|
||||||
@ -394,7 +393,6 @@ mxmlNewDeclaration(
|
|||||||
{
|
{
|
||||||
if ((node->value.declaration = _mxml_strcopy(declaration)) == NULL)
|
if ((node->value.declaration = _mxml_strcopy(declaration)) == NULL)
|
||||||
{
|
{
|
||||||
_mxml_error("Unable to allocate memory for declaration.");
|
|
||||||
mxmlDelete(node);
|
mxmlDelete(node);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -471,7 +469,6 @@ mxmlNewDirective(mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
|||||||
{
|
{
|
||||||
if ((node->value.directive = _mxml_strcopy(directive)) == NULL)
|
if ((node->value.directive = _mxml_strcopy(directive)) == NULL)
|
||||||
{
|
{
|
||||||
_mxml_error("Unable to allocate memory for processing instruction.");
|
|
||||||
mxmlDelete(node);
|
mxmlDelete(node);
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
@ -893,8 +890,8 @@ mxml_free(mxml_node_t *node) // I - Node
|
|||||||
_mxml_strfree(node->value.text.string);
|
_mxml_strfree(node->value.text.string);
|
||||||
break;
|
break;
|
||||||
case MXML_TYPE_CUSTOM :
|
case MXML_TYPE_CUSTOM :
|
||||||
if (node->value.custom.data && node->value.custom.destroy)
|
if (node->value.custom.data && node->value.custom.free_cb)
|
||||||
(*(node->value.custom.destroy))(node->value.custom.data);
|
(node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data);
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
break;
|
break;
|
||||||
|
519
mxml-options.c
Normal file
519
mxml-options.c
Normal file
@ -0,0 +1,519 @@
|
|||||||
|
//
|
||||||
|
// Options functions for Mini-XML, a small XML file parsing library.
|
||||||
|
//
|
||||||
|
// https://www.msweet.org/mxml
|
||||||
|
//
|
||||||
|
// Copyright © 2003-2024 by Michael R Sweet.
|
||||||
|
//
|
||||||
|
// Licensed under Apache License v2.0. See the file "LICENSE" for more
|
||||||
|
// information.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mxml-private.h"
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsDelete()' - Free load/save options.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsDelete(
|
||||||
|
mxml_options_t *options) // I - Options
|
||||||
|
{
|
||||||
|
free(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsNew()' - Allocate load/save options.
|
||||||
|
//
|
||||||
|
|
||||||
|
mxml_options_t * // O - Options
|
||||||
|
mxmlOptionsNew(void)
|
||||||
|
{
|
||||||
|
mxml_options_t *options; // Options
|
||||||
|
|
||||||
|
|
||||||
|
if ((options = (mxml_options_t *)calloc(1, sizeof(mxml_options_t))) != NULL)
|
||||||
|
{
|
||||||
|
// Set default values...
|
||||||
|
options->type_value = MXML_TYPE_TEXT;
|
||||||
|
options->wrap = 72;
|
||||||
|
|
||||||
|
if ((options->loc = localeconv()) != NULL)
|
||||||
|
{
|
||||||
|
if (!options->loc->decimal_point || !strcmp(options->loc->decimal_point, "."))
|
||||||
|
options->loc = NULL;
|
||||||
|
else
|
||||||
|
options->loc_declen = strlen(options->loc->decimal_point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetCustomCallbacks()' - 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;
|
||||||
|
//
|
||||||
|
// void
|
||||||
|
// my_custom_free_cb(void *cbdata, void *data)
|
||||||
|
// {
|
||||||
|
// free(data);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// 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, my_custom_free, /*cbdata*/NULL);
|
||||||
|
//
|
||||||
|
// /* 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
|
||||||
|
mxmlOptionsSetCustomCallbacks(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_custload_cb_t load_cb, // I - Custom load callback function
|
||||||
|
mxml_custsave_cb_t save_cb, // I - Custom save callback function
|
||||||
|
void *cbdata) // I - Custom callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->custload_cb = load_cb;
|
||||||
|
options->custsave_cb = save_cb;
|
||||||
|
options->cust_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetEntityCallback()' - Set the entity lookup callback to use when loading XML data.
|
||||||
|
//
|
||||||
|
// This function sets the callback that is used to lookup named XML character
|
||||||
|
// entities when loading XML data. The callback function `cb` accepts the
|
||||||
|
// callback data pointer `cbdata` and the entity name. The function returns a
|
||||||
|
// Unicode character value or `-1` if the entity is not known. For example, the
|
||||||
|
// following entity callback supports the "euro" entity:
|
||||||
|
//
|
||||||
|
// ```c
|
||||||
|
// int my_entity_cb(void *cbdata, const char *name)
|
||||||
|
// {
|
||||||
|
// if (!strcmp(name, "euro"))
|
||||||
|
// return (0x20ac);
|
||||||
|
// else
|
||||||
|
// return (-1);
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// Mini-XML supports the "amp", "gt", "lt", and "quot" character entities, which
|
||||||
|
// are required by the base XML specification.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetEntityCallback(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_entity_cb_t cb, // I - Entity callback function
|
||||||
|
void *cbdata) // I - Entity callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->entity_cb = cb;
|
||||||
|
options->entity_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetErrorCallback()' - 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
|
||||||
|
mxmlOptionsSetErrorCallback(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_error_cb_t cb, // I - Error callback function
|
||||||
|
void *cbdata) // I - Error callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->error_cb = cb;
|
||||||
|
options->error_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetSAXCallback()' - Set the SAX callback to use when reading XML data.
|
||||||
|
//
|
||||||
|
// This function sets a SAX callback to use when reading XML data. The SAX
|
||||||
|
// callback function `cb` and associated callback data `cbdata` are used to
|
||||||
|
// enable the Simple API for XML streaming mode. The callback is called as the
|
||||||
|
// XML node tree is parsed and receives the `cbdata` pointer, the `mxml_node_t`
|
||||||
|
// pointer, and an event code. The function returns `true` to continue
|
||||||
|
// processing or `false` to stop:
|
||||||
|
//
|
||||||
|
// ```c
|
||||||
|
// bool
|
||||||
|
// sax_cb(void *cbdata, mxml_node_t *node,
|
||||||
|
// mxml_sax_event_t event)
|
||||||
|
// {
|
||||||
|
// ... do something ...
|
||||||
|
//
|
||||||
|
// /* Continue processing... */
|
||||||
|
// return (true);
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
// The event will be one of the following:
|
||||||
|
//
|
||||||
|
// - `MXML_SAX_EVENT_CDATA`: CDATA was just read.
|
||||||
|
// - `MXML_SAX_EVENT_COMMENT`: A comment was just read.
|
||||||
|
// - `MXML_SAX_EVENT_DATA`: Data (integer, opaque, real, or text) was just read.
|
||||||
|
// - `MXML_SAX_EVENT_DECLARATION`: A declaration was just read.
|
||||||
|
// - `MXML_SAX_EVENT_DIRECTIVE`: A processing directive/instruction was just read.
|
||||||
|
// - `MXML_SAX_EVENT_ELEMENT_CLOSE` - A close element was just read \(`</element>`)
|
||||||
|
// - `MXML_SAX_EVENT_ELEMENT_OPEN` - An open element was just read \(`<element>`)
|
||||||
|
//
|
||||||
|
// Elements are *released* after the close element is processed. All other nodes
|
||||||
|
// are released after they are processed. The SAX callback can *retain* the node
|
||||||
|
// using the [mxmlRetain](@@) function.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetSAXCallback(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_sax_cb_t cb, // I - SAX callback function
|
||||||
|
void *cbdata) // I - SAX callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->sax_cb = cb;
|
||||||
|
options->sax_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetTypeCallback()' - Set the type callback for child/value nodes.
|
||||||
|
//
|
||||||
|
// The load callback function `cb` is called to obtain the node type child/value
|
||||||
|
// nodes and receives the `cbdata` pointer and the `mxml_node_t` pointer, for
|
||||||
|
// example:
|
||||||
|
//
|
||||||
|
// ```c
|
||||||
|
// mxml_type_t
|
||||||
|
// my_type_cb(void *cbdata, mxml_node_t *node)
|
||||||
|
// {
|
||||||
|
// const char *type;
|
||||||
|
//
|
||||||
|
// /*
|
||||||
|
// * You can lookup attributes and/or use the element name,
|
||||||
|
// * hierarchy, etc...
|
||||||
|
// */
|
||||||
|
//
|
||||||
|
// type = mxmlElementGetAttr(node, "type");
|
||||||
|
// if (type == NULL)
|
||||||
|
// type = mxmlGetElement(node);
|
||||||
|
// if (type == NULL)
|
||||||
|
// type = "text";
|
||||||
|
//
|
||||||
|
// if (!strcmp(type, "integer"))
|
||||||
|
// return (MXML_TYPE_INTEGER);
|
||||||
|
// else if (!strcmp(type, "opaque"))
|
||||||
|
// return (MXML_TYPE_OPAQUE);
|
||||||
|
// else if (!strcmp(type, "real"))
|
||||||
|
// return (MXML_TYPE_REAL);
|
||||||
|
// else
|
||||||
|
// return (MXML_TYPE_TEXT);
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetTypeCallback(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_type_cb_t cb, // I - Type callback function
|
||||||
|
void *cbdata) // I - Type callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->type_cb = cb;
|
||||||
|
options->type_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetTypeValue()' - Set the type to use for all child/value nodes.
|
||||||
|
//
|
||||||
|
// This functions sets a constant node type to use for all child/value nodes.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetTypeValue(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_type_t type) // I - Value node type
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->type_cb = NULL;
|
||||||
|
options->type_value = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetWhitespaceCallback()' - Set the whitespace callback.
|
||||||
|
//
|
||||||
|
// This function sets the whitespace callback that is used when saving XML data.
|
||||||
|
// The callback function `cb` specifies a function that returns a whitespace
|
||||||
|
// string or `NULL` before and after each element. The function receives the
|
||||||
|
// callback data pointer `cbdata`, the `mxml_node_t` pointer, and a "when"
|
||||||
|
// value indicating where the whitespace is being added, for example:
|
||||||
|
//
|
||||||
|
// ```c
|
||||||
|
// const char *my_whitespace_cb(void *cbdata, mxml_node_t *node, mxml_ws_t when)
|
||||||
|
// {
|
||||||
|
// if (when == MXML_WS_BEFORE_OPEN || when == MXML_WS_AFTER_CLOSE)
|
||||||
|
// return ("\n");
|
||||||
|
// else
|
||||||
|
// return (NULL);
|
||||||
|
// }
|
||||||
|
// ```
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetWhitespaceCallback(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
mxml_ws_cb_t cb, // I - Whitespace callback function
|
||||||
|
void *cbdata) // I - Whitespace callback data
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
{
|
||||||
|
options->ws_cb = cb;
|
||||||
|
options->ws_cbdata = cbdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// 'mxmlOptionsSetWrapMargin()' - Set the wrap margin when saving XML data.
|
||||||
|
//
|
||||||
|
// This function sets the wrap margin used when saving XML data. Wrapping is
|
||||||
|
// disabled when `column` is `0`.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
mxmlOptionsSetWrapMargin(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
int column) // I - Wrap column
|
||||||
|
{
|
||||||
|
if (options)
|
||||||
|
options->wrap = column;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// '_mxml_entity_string()' - Get the entity that corresponds to the character, if any.
|
||||||
|
//
|
||||||
|
|
||||||
|
const char * // O - Entity or `NULL` for none
|
||||||
|
_mxml_entity_string(int ch) // I - Character
|
||||||
|
{
|
||||||
|
switch (ch)
|
||||||
|
{
|
||||||
|
case '&' :
|
||||||
|
return ("&");
|
||||||
|
|
||||||
|
case '<' :
|
||||||
|
return ("<");
|
||||||
|
|
||||||
|
case '>' :
|
||||||
|
return (">");
|
||||||
|
|
||||||
|
case '\"' :
|
||||||
|
return (""");
|
||||||
|
|
||||||
|
default :
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// '_mxml_entity_value()' - Get the character corresponding to a named entity.
|
||||||
|
//
|
||||||
|
// The entity name can also be a numeric constant. `-1` is returned if the
|
||||||
|
// name is not known.
|
||||||
|
//
|
||||||
|
|
||||||
|
int // O - Unicode character
|
||||||
|
_mxml_entity_value(
|
||||||
|
mxml_options_t *options, // I - Options
|
||||||
|
const char *name) // I - Entity name
|
||||||
|
{
|
||||||
|
int ch = -1; // Unicode character
|
||||||
|
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
// No name...
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
else if (*name == '#')
|
||||||
|
{
|
||||||
|
// Numeric entity...
|
||||||
|
if (name[1] == 'x')
|
||||||
|
ch = (int)strtol(name + 2, NULL, 16);
|
||||||
|
else
|
||||||
|
ch = (int)strtol(name + 1, NULL, 10);
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "amp"))
|
||||||
|
{
|
||||||
|
// Ampersand
|
||||||
|
ch = '&';
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "gt"))
|
||||||
|
{
|
||||||
|
// Greater than
|
||||||
|
ch = '>';
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "lt"))
|
||||||
|
{
|
||||||
|
// Less than
|
||||||
|
ch = '<';
|
||||||
|
}
|
||||||
|
else if (!strcmp(name, "quot"))
|
||||||
|
{
|
||||||
|
// Double quote
|
||||||
|
ch = '\"';
|
||||||
|
}
|
||||||
|
else if (options && options->entity_cb)
|
||||||
|
{
|
||||||
|
// Use callback
|
||||||
|
ch = (options->entity_cb)(options->entity_cbdata, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// '_mxml_error()' - Display an error message.
|
||||||
|
//
|
||||||
|
|
||||||
|
void
|
||||||
|
_mxml_error(mxml_options_t *options, // I - Load/save options
|
||||||
|
const char *format, // I - Printf-style format string
|
||||||
|
...) // I - Additional arguments as needed
|
||||||
|
{
|
||||||
|
va_list ap; // Pointer to arguments
|
||||||
|
char s[1024]; // Message string
|
||||||
|
|
||||||
|
|
||||||
|
// Range check input...
|
||||||
|
if (!format)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Format the error message string...
|
||||||
|
va_start(ap, format);
|
||||||
|
vsnprintf(s, sizeof(s), format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
// And then display the error message...
|
||||||
|
if (options->error_cb)
|
||||||
|
(options->error_cb)(options->error_cbdata, s);
|
||||||
|
else
|
||||||
|
fprintf(stderr, "%s\n", s);
|
||||||
|
}
|
186
mxml-private.c
186
mxml-private.c
@ -39,144 +39,6 @@
|
|||||||
#endif // __sun
|
#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.
|
// 'mxmlSetStringCallbacks()' - Set the string copy/free callback functions.
|
||||||
//
|
//
|
||||||
@ -217,37 +79,6 @@ mxmlSetStringCallbacks(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
|
||||||
// '_mxml_error()' - Display an error message.
|
|
||||||
//
|
|
||||||
|
|
||||||
void
|
|
||||||
_mxml_error(const char *format, // I - Printf-style format string
|
|
||||||
...) // I - Additional arguments as needed
|
|
||||||
{
|
|
||||||
va_list ap; // Pointer to arguments
|
|
||||||
char s[1024]; // Message string
|
|
||||||
_mxml_global_t *global = _mxml_global();
|
|
||||||
// Global data
|
|
||||||
|
|
||||||
|
|
||||||
// Range check input...
|
|
||||||
if (!format)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Format the error message string...
|
|
||||||
va_start(ap, format);
|
|
||||||
vsnprintf(s, sizeof(s), format, ap);
|
|
||||||
va_end(ap);
|
|
||||||
|
|
||||||
// And then display the error message...
|
|
||||||
if (global->error_cb)
|
|
||||||
(*global->error_cb)(global->error_cbdata, s);
|
|
||||||
else
|
|
||||||
fprintf(stderr, "%s\n", s);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// '_mxml_strcopy()' - Copy a string.
|
// '_mxml_strcopy()' - Copy a string.
|
||||||
//
|
//
|
||||||
@ -341,10 +172,6 @@ _mxml_global(void)
|
|||||||
{
|
{
|
||||||
global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
|
global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
|
||||||
pthread_setspecific(_mxml_key, global);
|
pthread_setspecific(_mxml_key, global);
|
||||||
|
|
||||||
global->num_entity_cbs = 1;
|
|
||||||
global->entity_cbs[0] = _mxml_entity_cb;
|
|
||||||
global->wrap = 72;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (global);
|
return (global);
|
||||||
@ -425,10 +252,6 @@ _mxml_global(void)
|
|||||||
{
|
{
|
||||||
global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
|
global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
|
||||||
|
|
||||||
global->num_entity_cbs = 1;
|
|
||||||
global->entity_cbs[0] = _mxml_entity_cb;
|
|
||||||
global->wrap = 72;
|
|
||||||
|
|
||||||
TlsSetValue(_mxml_tls_index, (LPVOID)global);
|
TlsSetValue(_mxml_tls_index, (LPVOID)global);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -446,12 +269,9 @@ _mxml_global(void)
|
|||||||
{
|
{
|
||||||
static _mxml_global_t global = // Global data
|
static _mxml_global_t global = // Global data
|
||||||
{
|
{
|
||||||
NULL, // error_cb
|
NULL, // strcopy_cb
|
||||||
1, // num_entity_cbs
|
NULL, // strfree_cb
|
||||||
{ _mxml_entity_cb }, // entity_cbs
|
NULL, // str_cbdata
|
||||||
72, // wrap
|
|
||||||
NULL, // custom_load_cb
|
|
||||||
NULL // custom_save_cb
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -54,7 +54,8 @@ typedef struct _mxml_text_s // An XML text value.
|
|||||||
typedef struct _mxml_custom_s // An XML custom value.
|
typedef struct _mxml_custom_s // An XML custom value.
|
||||||
{
|
{
|
||||||
void *data; // Pointer to (allocated) custom data
|
void *data; // Pointer to (allocated) custom data
|
||||||
mxml_custom_destroy_cb_t destroy; // Pointer to destructor function
|
mxml_custfree_cb_t free_cb; // Free callback function
|
||||||
|
void *free_cbdata; // Free callback data
|
||||||
} _mxml_custom_t;
|
} _mxml_custom_t;
|
||||||
|
|
||||||
typedef union _mxml_value_u // An XML node value.
|
typedef union _mxml_value_u // An XML node value.
|
||||||
@ -84,6 +85,13 @@ struct _mxml_node_s // An XML node.
|
|||||||
void *user_data; // User data
|
void *user_data; // User data
|
||||||
};
|
};
|
||||||
|
|
||||||
|
typedef struct _mxml_global_s // Global, per-thread data
|
||||||
|
{
|
||||||
|
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
|
||||||
|
} _mxml_global_t;
|
||||||
|
|
||||||
struct _mxml_index_s // An XML node index.
|
struct _mxml_index_s // An XML node index.
|
||||||
{
|
{
|
||||||
char *attr; // Attribute used for indexing or NULL
|
char *attr; // Attribute used for indexing or NULL
|
||||||
@ -93,25 +101,26 @@ struct _mxml_index_s // An XML node index.
|
|||||||
mxml_node_t **nodes; // Node array
|
mxml_node_t **nodes; // Node array
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _mxml_global_s // Global, per-thread data
|
struct _mxml_options_s // XML options
|
||||||
|
|
||||||
{
|
{
|
||||||
mxml_custom_load_cb_t custom_load_cb; // Custom load callback function
|
|
||||||
mxml_custom_save_cb_t custom_save_cb; // Custom save callback function
|
|
||||||
void *custom_cbdata; // Custom callback data
|
|
||||||
mxml_error_cb_t error_cb; // Error callback function
|
|
||||||
void *error_cbdata; // Error callback data
|
|
||||||
size_t num_entity_cbs; // Number of entity callbacks
|
|
||||||
mxml_entity_cb_t entity_cbs[100]; // Entity callback functions
|
|
||||||
void *entity_cbdatas[100]; // Entity callback data
|
|
||||||
struct lconv *loc; // Locale data
|
struct lconv *loc; // Locale data
|
||||||
size_t loc_declen; // Length of decimal point string
|
size_t loc_declen; // Length of decimal point string
|
||||||
bool loc_set; // Locale data set?
|
mxml_custload_cb_t custload_cb; // Custom load callback function
|
||||||
mxml_strcopy_cb_t strcopy_cb; // String copy callback function
|
mxml_custsave_cb_t custsave_cb; // Custom save callback function
|
||||||
mxml_strfree_cb_t strfree_cb; // String free callback function
|
void *cust_cbdata; // Custom callback data
|
||||||
void *str_cbdata; // String callback data
|
mxml_entity_cb_t entity_cb; // Entity callback function
|
||||||
|
void *entity_cbdata; // Entity callback data
|
||||||
|
mxml_error_cb_t error_cb; // Error callback function
|
||||||
|
void *error_cbdata; // Error callback data
|
||||||
|
mxml_sax_cb_t sax_cb; // SAX callback function
|
||||||
|
void *sax_cbdata; // SAX callback data
|
||||||
|
mxml_type_cb_t type_cb; // Type callback function
|
||||||
|
void *type_cbdata; // Type callback data
|
||||||
|
mxml_type_t type_value; // Fixed type value (if no type callback)
|
||||||
int wrap; // Wrap margin
|
int wrap; // Wrap margin
|
||||||
} _mxml_global_t;
|
mxml_ws_cb_t ws_cb; // Whitespace callback function
|
||||||
|
void *ws_cbdata; // Whitespace callback data
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -119,9 +128,9 @@ typedef struct _mxml_global_s // Global, per-thread data
|
|||||||
//
|
//
|
||||||
|
|
||||||
extern _mxml_global_t *_mxml_global(void);
|
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 const char *_mxml_entity_string(int ch);
|
||||||
extern void _mxml_error(const char *format, ...) MXML_FORMAT(1,2);
|
extern int _mxml_entity_value(mxml_options_t *options, const char *name);
|
||||||
|
extern void _mxml_error(mxml_options_t *options, const char *format, ...) MXML_FORMAT(2,3);
|
||||||
extern char *_mxml_strcopy(const char *s);
|
extern char *_mxml_strcopy(const char *s);
|
||||||
extern void _mxml_strfree(char *s);
|
extern void _mxml_strfree(char *s);
|
||||||
|
|
||||||
|
144
mxml-set.c
144
mxml-set.c
@ -31,15 +31,9 @@ mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_CDATA)
|
if (!node || node->type != MXML_TYPE_CDATA)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!data)
|
else if (!data)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (data == node->value.cdata)
|
if (data == node->value.cdata)
|
||||||
{
|
{
|
||||||
@ -49,10 +43,7 @@ mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
|||||||
|
|
||||||
// Allocate the new value, free any old element value, and set the new value...
|
// Allocate the new value, free any old element value, and set the new value...
|
||||||
if ((s = _mxml_strcopy(data)) == NULL)
|
if ((s = _mxml_strcopy(data)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for CDATA.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.cdata);
|
_mxml_strfree(node->value.cdata);
|
||||||
node->value.cdata = s;
|
node->value.cdata = s;
|
||||||
@ -83,15 +74,9 @@ mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_CDATA)
|
if (!node || node->type != MXML_TYPE_CDATA)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Format the new string, free any old string value, and set the new value...
|
// Format the new string, free any old string value, and set the new value...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
@ -99,10 +84,7 @@ mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for CDATA string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.cdata);
|
_mxml_strfree(node->value.cdata);
|
||||||
node->value.cdata = s;
|
node->value.cdata = s;
|
||||||
@ -129,25 +111,16 @@ mxmlSetComment(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!comment)
|
else if (!comment)
|
||||||
{
|
|
||||||
_mxml_error("NULL comment not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (comment == node->value.comment)
|
if (comment == node->value.comment)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
// Free any old string value and set the new value...
|
// Free any old string value and set the new value...
|
||||||
if ((s = _mxml_strcopy(comment)) == NULL)
|
if ((s = _mxml_strcopy(comment)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for comment string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.comment);
|
_mxml_strfree(node->value.comment);
|
||||||
node->value.comment = s;
|
node->value.comment = s;
|
||||||
@ -177,15 +150,9 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Format the new string, free any old string value, and set the new value...
|
// Format the new string, free any old string value, and set the new value...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
@ -193,10 +160,7 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for comment string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.comment);
|
_mxml_strfree(node->value.comment);
|
||||||
node->value.comment = s;
|
node->value.comment = s;
|
||||||
@ -217,30 +181,29 @@ bool // O - `true` on success, `false` on failure
|
|||||||
mxmlSetCustom(
|
mxmlSetCustom(
|
||||||
mxml_node_t *node, // I - Node to set
|
mxml_node_t *node, // I - Node to set
|
||||||
void *data, // I - New data pointer
|
void *data, // I - New data pointer
|
||||||
mxml_custom_destroy_cb_t destroy_cb)// I - New destructor function
|
mxml_custfree_cb_t free_cb, // I - Free callback function
|
||||||
|
void *free_cbdata) // I - Free callback data
|
||||||
{
|
{
|
||||||
// Range check input...
|
// Range check input...
|
||||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CUSTOM)
|
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CUSTOM)
|
||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_CUSTOM)
|
if (!node || node->type != MXML_TYPE_CUSTOM)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (data == node->value.custom.data)
|
if (data == node->value.custom.data)
|
||||||
{
|
goto set_free_callback;
|
||||||
node->value.custom.destroy = destroy_cb;
|
|
||||||
return (true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free any old element value and set the new value...
|
// Free any old element value and set the new value...
|
||||||
if (node->value.custom.data && node->value.custom.destroy)
|
if (node->value.custom.data && node->value.custom.free_cb)
|
||||||
(*(node->value.custom.destroy))(node->value.custom.data);
|
(node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data);
|
||||||
|
|
||||||
node->value.custom.data = data;
|
node->value.custom.data = data;
|
||||||
node->value.custom.destroy = destroy_cb;
|
|
||||||
|
set_free_callback:
|
||||||
|
|
||||||
|
node->value.custom.free_cb = free_cb;
|
||||||
|
node->value.custom.free_cbdata = free_cbdata;
|
||||||
|
|
||||||
return (true);
|
return (true);
|
||||||
}
|
}
|
||||||
@ -265,25 +228,16 @@ mxmlSetDeclaration(
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_DECLARATION)
|
if (!node || node->type != MXML_TYPE_DECLARATION)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!declaration)
|
else if (!declaration)
|
||||||
{
|
|
||||||
_mxml_error("NULL declaration not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (declaration == node->value.declaration)
|
if (declaration == node->value.declaration)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
// Free any old string value and set the new value...
|
// Free any old string value and set the new value...
|
||||||
if ((s = _mxml_strcopy(declaration)) == NULL)
|
if ((s = _mxml_strcopy(declaration)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for declaration string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.declaration);
|
_mxml_strfree(node->value.declaration);
|
||||||
node->value.declaration = s;
|
node->value.declaration = s;
|
||||||
@ -313,15 +267,9 @@ mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Format the new string, free any old string value, and set the new value...
|
// Format the new string, free any old string value, and set the new value...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
@ -329,10 +277,7 @@ mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for declaration string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.declaration);
|
_mxml_strfree(node->value.declaration);
|
||||||
node->value.declaration = s;
|
node->value.declaration = s;
|
||||||
@ -359,25 +304,16 @@ mxmlSetDirective(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!directive)
|
else if (!directive)
|
||||||
{
|
|
||||||
_mxml_error("NULL directive not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (directive == node->value.directive)
|
if (directive == node->value.directive)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
// Free any old string value and set the new value...
|
// Free any old string value and set the new value...
|
||||||
if ((s = _mxml_strcopy(directive)) == NULL)
|
if ((s = _mxml_strcopy(directive)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for directive string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.directive);
|
_mxml_strfree(node->value.directive);
|
||||||
node->value.directive = s;
|
node->value.directive = s;
|
||||||
@ -408,15 +344,9 @@ mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Format the new string, free any old string value, and set the new value...
|
// Format the new string, free any old string value, and set the new value...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
@ -424,10 +354,7 @@ mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for directive string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.directive);
|
_mxml_strfree(node->value.directive);
|
||||||
node->value.directive = s;
|
node->value.directive = s;
|
||||||
@ -452,25 +379,16 @@ mxmlSetElement(mxml_node_t *node, // I - Node to set
|
|||||||
|
|
||||||
// Range check input...
|
// Range check input...
|
||||||
if (!node || node->type != MXML_TYPE_ELEMENT)
|
if (!node || node->type != MXML_TYPE_ELEMENT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!name)
|
else if (!name)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (name == node->value.element.name)
|
if (name == node->value.element.name)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
// Free any old element value and set the new value...
|
// Free any old element value and set the new value...
|
||||||
if ((s = _mxml_strcopy(name)) == NULL)
|
if ((s = _mxml_strcopy(name)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for element name.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.element.name);
|
_mxml_strfree(node->value.element.name);
|
||||||
node->value.element.name = s;
|
node->value.element.name = s;
|
||||||
@ -495,10 +413,7 @@ mxmlSetInteger(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_INTEGER)
|
if (!node || node->type != MXML_TYPE_INTEGER)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Set the new value and return...
|
// Set the new value and return...
|
||||||
node->value.integer = integer;
|
node->value.integer = integer;
|
||||||
@ -526,25 +441,16 @@ mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!opaque)
|
else if (!opaque)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (node->value.opaque == opaque)
|
if (node->value.opaque == opaque)
|
||||||
return (true);
|
return (true);
|
||||||
|
|
||||||
// Free any old opaque value and set the new value...
|
// Free any old opaque value and set the new value...
|
||||||
if ((s = _mxml_strcopy(opaque)) == NULL)
|
if ((s = _mxml_strcopy(opaque)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for opaque string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.opaque);
|
_mxml_strfree(node->value.opaque);
|
||||||
node->value.opaque = s;
|
node->value.opaque = s;
|
||||||
@ -575,15 +481,9 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Format the new string, free any old string value, and set the new value...
|
// Format the new string, free any old string value, and set the new value...
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
@ -591,10 +491,7 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for opaque string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.opaque);
|
_mxml_strfree(node->value.opaque);
|
||||||
node->value.opaque = s;
|
node->value.opaque = s;
|
||||||
@ -619,10 +516,7 @@ mxmlSetReal(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_REAL)
|
if (!node || node->type != MXML_TYPE_REAL)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
// Set the new value and return...
|
// Set the new value and return...
|
||||||
node->value.real = real;
|
node->value.real = real;
|
||||||
@ -651,15 +545,9 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_TEXT)
|
if (!node || node->type != MXML_TYPE_TEXT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!string)
|
else if (!string)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
if (string == node->value.text.string)
|
if (string == node->value.text.string)
|
||||||
{
|
{
|
||||||
@ -669,10 +557,7 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
|||||||
|
|
||||||
// Free any old string value and set the new value...
|
// Free any old string value and set the new value...
|
||||||
if ((s = _mxml_strcopy(string)) == NULL)
|
if ((s = _mxml_strcopy(string)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for text string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.text.string);
|
_mxml_strfree(node->value.text.string);
|
||||||
|
|
||||||
@ -706,15 +591,9 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
|||||||
node = node->child;
|
node = node->child;
|
||||||
|
|
||||||
if (!node || node->type != MXML_TYPE_TEXT)
|
if (!node || node->type != MXML_TYPE_TEXT)
|
||||||
{
|
|
||||||
_mxml_error("Wrong node type.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
else if (!format)
|
else if (!format)
|
||||||
{
|
|
||||||
_mxml_error("NULL string not allowed.");
|
|
||||||
return (false);
|
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);
|
va_start(ap, format);
|
||||||
@ -722,10 +601,7 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||||
{
|
|
||||||
_mxml_error("Unable to allocate memory for text string.");
|
|
||||||
return (false);
|
return (false);
|
||||||
}
|
|
||||||
|
|
||||||
_mxml_strfree(node->value.text.string);
|
_mxml_strfree(node->value.text.string);
|
||||||
|
|
||||||
|
87
mxml.h
87
mxml.h
@ -19,12 +19,6 @@
|
|||||||
# include <ctype.h>
|
# include <ctype.h>
|
||||||
# include <errno.h>
|
# include <errno.h>
|
||||||
# include <limits.h>
|
# include <limits.h>
|
||||||
# if defined(_WIN32) && !defined(__CUPS_SSIZE_T_DEFINED)
|
|
||||||
# define __CUPS_SSIZE_T_DEFINED
|
|
||||||
// Windows does not provide the ssize_t type, so map it to int64_t... */
|
|
||||||
typedef int64_t ssize_t; // @private@
|
|
||||||
# define SSIZE_MAX INT64_MAX
|
|
||||||
# endif // _WIN32 && !__CUPS_SSIZE_T_DEFINED
|
|
||||||
# ifdef __cplusplus
|
# ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
# endif // __cplusplus
|
# endif // __cplusplus
|
||||||
@ -95,45 +89,46 @@ typedef enum mxml_ws_e // Whitespace periods
|
|||||||
MXML_WS_AFTER_CLOSE, // Callback for after close tag
|
MXML_WS_AFTER_CLOSE, // Callback for after close tag
|
||||||
} mxml_ws_t;
|
} mxml_ws_t;
|
||||||
|
|
||||||
typedef void (*mxml_custom_destroy_cb_t)(void *);
|
|
||||||
// Custom data destructor
|
|
||||||
|
|
||||||
typedef void (*mxml_error_cb_t)(void *cbdata, const char *message);
|
typedef void (*mxml_error_cb_t)(void *cbdata, const char *message);
|
||||||
// Error callback function
|
// Error callback function
|
||||||
|
|
||||||
typedef struct _mxml_node_s mxml_node_t;// An XML node.
|
typedef struct _mxml_node_s mxml_node_t;// An XML node
|
||||||
|
|
||||||
typedef struct _mxml_index_s mxml_index_t;
|
typedef struct _mxml_index_s mxml_index_t;
|
||||||
// An XML node index.
|
// An XML node index
|
||||||
|
|
||||||
typedef bool (*mxml_custom_load_cb_t)(void *cbdata, mxml_node_t *node, const char *s);
|
typedef struct _mxml_options_s mxml_options_t;
|
||||||
|
// XML options
|
||||||
|
|
||||||
|
typedef void (*mxml_custfree_cb_t)(void *cbdata, void *custdata);
|
||||||
|
// Custom data destructor
|
||||||
|
|
||||||
|
typedef bool (*mxml_custload_cb_t)(void *cbdata, mxml_node_t *node, const char *s);
|
||||||
// Custom data load callback function
|
// Custom data load callback function
|
||||||
|
|
||||||
typedef char *(*mxml_custom_save_cb_t)(void *cbdata, mxml_node_t *node);
|
typedef char *(*mxml_custsave_cb_t)(void *cbdata, mxml_node_t *node);
|
||||||
// Custom data save callback function
|
// Custom data save callback function
|
||||||
|
|
||||||
typedef int (*mxml_entity_cb_t)(void *cbdata, const char *name);
|
typedef int (*mxml_entity_cb_t)(void *cbdata, const char *name);
|
||||||
// Entity callback function
|
// Entity callback function
|
||||||
|
|
||||||
typedef mxml_type_t (*mxml_load_cb_t)(void *cbdata, mxml_node_t *node);
|
typedef size_t (*mxml_io_cb_t)(void *cbdata, void *buffer, size_t bytes);
|
||||||
// Load callback function
|
// Read/write callback function
|
||||||
|
|
||||||
typedef ssize_t (*mxml_read_cb_t)(void *cbdata, void *buffer, size_t bytes);
|
typedef bool (*mxml_sax_cb_t)(void *cbdata, mxml_node_t *node, mxml_sax_event_t event);
|
||||||
// Read callback function
|
// SAX callback function
|
||||||
|
|
||||||
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);
|
typedef char *(*mxml_strcopy_cb_t)(void *cbdata, const char *s);
|
||||||
// String copy/allocation callback
|
// String copy/allocation callback
|
||||||
typedef void (*mxml_strfree_cb_t)(void *cbdata, char *s);
|
typedef void (*mxml_strfree_cb_t)(void *cbdata, char *s);
|
||||||
// String free callback
|
// String free callback
|
||||||
|
|
||||||
typedef ssize_t (*mxml_write_cb_t)(void *cbdata, const void *buffer, size_t bytes);
|
typedef mxml_type_t (*mxml_type_cb_t)(void *cbdata, mxml_node_t *node);
|
||||||
// Write callback function
|
// Type callback function
|
||||||
|
|
||||||
|
typedef const char *(*mxml_ws_cb_t)(void *cbdata, mxml_node_t *node, mxml_ws_t when);
|
||||||
|
// Whitespace callback function
|
||||||
|
|
||||||
typedef bool (*mxml_sax_cb_t)(void *cbdata, mxml_node_t *node, mxml_sax_event_t event);
|
|
||||||
// SAX callback function
|
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -150,9 +145,6 @@ extern const char *mxmlElementGetAttrByIndex(mxml_node_t *node, int idx, c
|
|||||||
extern size_t 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 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 void mxmlElementSetAttrf(mxml_node_t *node, const char *name, const char *format, ...) MXML_FORMAT(3,4);
|
||||||
extern bool mxmlEntityAddCallback(mxml_entity_cb_t cb, void *cbdata);
|
|
||||||
extern int mxmlEntityGetValue(const char *name);
|
|
||||||
extern void mxmlEntityRemoveCallback(mxml_entity_cb_t cb);
|
|
||||||
|
|
||||||
extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, const char *element, const char *attr, const char *value, mxml_descend_t descend);
|
extern mxml_node_t *mxmlFindElement(mxml_node_t *node, mxml_node_t *top, const char *element, const char *attr, const char *value, mxml_descend_t descend);
|
||||||
extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path);
|
extern mxml_node_t *mxmlFindPath(mxml_node_t *node, const char *path);
|
||||||
@ -183,17 +175,28 @@ extern size_t mxmlIndexGetCount(mxml_index_t *ind);
|
|||||||
extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element, const char *attr);
|
extern mxml_index_t *mxmlIndexNew(mxml_node_t *node, const char *element, const char *attr);
|
||||||
extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
|
extern mxml_node_t *mxmlIndexReset(mxml_index_t *ind);
|
||||||
|
|
||||||
extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, int fd, mxml_load_cb_t load_cb, void *load_cbdata, mxml_sax_cb_t sax_cb, void *sax_cbdata);
|
extern mxml_node_t *mxmlLoadFd(mxml_node_t *top, mxml_options_t *options, int fd);
|
||||||
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp, mxml_load_cb_t load_cb, void *load_cbdata, mxml_sax_cb_t sax_cb, void *sax_cbdata);
|
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, mxml_options_t *options, FILE *fp);
|
||||||
extern mxml_node_t *mxmlLoadFilename(mxml_node_t *top, const char *filename, mxml_load_cb_t load_cb, void *load_cbdata, mxml_sax_cb_t sax_cb, void *sax_cbdata);
|
extern mxml_node_t *mxmlLoadFilename(mxml_node_t *top, mxml_options_t *options, const char *filename);
|
||||||
extern mxml_node_t *mxmlLoadIO(mxml_node_t *top, mxml_read_cb_t read_cb, void *read_cbdata, mxml_load_cb_t load_cb, void *load_cbdata, mxml_sax_cb_t sax_cb, void *sax_cbdata);
|
extern mxml_node_t *mxmlLoadIO(mxml_node_t *top, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata);
|
||||||
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s, mxml_load_cb_t load_cb, void *load_cbdata, mxml_sax_cb_t sax_cb, void *sax_cbdata);
|
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, mxml_options_t *options, const char *s);
|
||||||
|
|
||||||
|
extern void mxmlOptionsDelete(mxml_options_t *options);
|
||||||
|
extern mxml_options_t *mxmlOptionsNew(void);
|
||||||
|
extern void mxmlOptionsSetCustomCallbacks(mxml_options_t *options, mxml_custload_cb_t load_cb, mxml_custsave_cb_t save_cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetEntityCallback(mxml_options_t *options, mxml_entity_cb_t cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetErrorCallback(mxml_options_t *options, mxml_error_cb_t cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetSAXCallback(mxml_options_t *options, mxml_sax_cb_t cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetTypeCallback(mxml_options_t *options, mxml_type_cb_t cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetTypeValue(mxml_options_t *options, mxml_type_t type);
|
||||||
|
extern void mxmlOptionsSetWhitespaceCallback(mxml_options_t *options, mxml_ws_cb_t cb, void *cbdata);
|
||||||
|
extern void mxmlOptionsSetWrapMargin(mxml_options_t *options, int column);
|
||||||
|
|
||||||
extern mxml_node_t *mxmlNewCDATA(mxml_node_t *parent, const char *string);
|
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 *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 *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 *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 *mxmlNewCustom(mxml_node_t *parent, void *data, mxml_custfree_cb_t free_cb, void *free_cbdata);
|
||||||
extern mxml_node_t *mxmlNewDeclaration(mxml_node_t *parent, const char *declaration);
|
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 *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 *mxmlNewDirective(mxml_node_t *parent, const char *directive);
|
||||||
@ -211,12 +214,13 @@ extern int mxmlRelease(mxml_node_t *node);
|
|||||||
extern void mxmlRemove(mxml_node_t *node);
|
extern void mxmlRemove(mxml_node_t *node);
|
||||||
extern int mxmlRetain(mxml_node_t *node);
|
extern int mxmlRetain(mxml_node_t *node);
|
||||||
|
|
||||||
extern char *mxmlSaveAllocString(mxml_node_t *node, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern char *mxmlSaveAllocString(mxml_node_t *node, mxml_options_t *options);
|
||||||
extern bool mxmlSaveFd(mxml_node_t *node, int fd, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern bool mxmlSaveFd(mxml_node_t *node, mxml_options_t *options, int fd);
|
||||||
extern bool mxmlSaveFile(mxml_node_t *node, FILE *fp, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern bool mxmlSaveFile(mxml_node_t *node, mxml_options_t *options, FILE *fp);
|
||||||
extern bool mxmlSaveFilename(mxml_node_t *node, const char *filename, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern bool mxmlSaveFilename(mxml_node_t *node, mxml_options_t *options, const char *filename);
|
||||||
extern bool mxmlSaveIO(mxml_node_t *node, mxml_write_cb_t write_cb, void *write_cbdata, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern bool mxmlSaveIO(mxml_node_t *node, mxml_options_t *options, mxml_io_cb_t io_cb, void *io_cbdata);
|
||||||
extern size_t mxmlSaveString(mxml_node_t *node, char *buffer, size_t bufsize, mxml_save_cb_t save_cb, void *save_cbdata);
|
extern size_t mxmlSaveString(mxml_node_t *node, mxml_options_t *options, char *buffer, size_t bufsize);
|
||||||
|
|
||||||
extern bool mxmlSetCDATA(mxml_node_t *node, const char *data);
|
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 mxmlSetCDATAf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||||
extern bool mxmlSetComment(mxml_node_t *node, const char *comment);
|
extern bool mxmlSetComment(mxml_node_t *node, const char *comment);
|
||||||
@ -225,10 +229,8 @@ 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 mxmlSetDeclarationf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||||
extern bool mxmlSetDirective(mxml_node_t *node, const char *directive);
|
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 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_cb);
|
extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custfree_cb_t free_cb, void *free_cbdata);
|
||||||
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 bool mxmlSetElement(mxml_node_t *node, const char *name);
|
||||||
extern void mxmlSetErrorCallback(mxml_error_cb_t cb, void *cbdata);
|
|
||||||
extern bool mxmlSetInteger(mxml_node_t *node, long integer);
|
extern bool mxmlSetInteger(mxml_node_t *node, long integer);
|
||||||
extern bool mxmlSetOpaque(mxml_node_t *node, const char *opaque);
|
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 mxmlSetOpaquef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||||
@ -237,7 +239,6 @@ extern void mxmlSetStringCallbacks(mxml_strcopy_cb_t strcopy_cb, mxml_strfree_c
|
|||||||
extern bool mxmlSetText(mxml_node_t *node, bool whitespace, const char *string);
|
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 mxmlSetTextf(mxml_node_t *node, bool whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||||
extern bool mxmlSetUserData(mxml_node_t *node, void *data);
|
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, mxml_descend_t descend);
|
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend);
|
||||||
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend);
|
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend);
|
||||||
|
51
testmxml.c
51
testmxml.c
@ -52,6 +52,7 @@ main(int argc, // I - Number of command-line args
|
|||||||
int i; // Looping var
|
int i; // Looping var
|
||||||
FILE *fp; // File to read
|
FILE *fp; // File to read
|
||||||
int fd; // File descriptor
|
int fd; // File descriptor
|
||||||
|
mxml_options_t *options; // Load/save options
|
||||||
mxml_node_t *xml, // <?xml ...?> node
|
mxml_node_t *xml, // <?xml ...?> node
|
||||||
*tree, // Element tree
|
*tree, // Element tree
|
||||||
*node; // Node which should be in test.xml
|
*node; // Node which should be in test.xml
|
||||||
@ -83,6 +84,7 @@ main(int argc, // I - Number of command-line args
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test the basic functionality...
|
// Test the basic functionality...
|
||||||
|
options = mxmlOptionsNew();
|
||||||
xml = mxmlNewXML("1.0");
|
xml = mxmlNewXML("1.0");
|
||||||
tree = mxmlNewElement(xml, "element");
|
tree = mxmlNewElement(xml, "element");
|
||||||
|
|
||||||
@ -111,18 +113,18 @@ main(int argc, // I - Number of command-line args
|
|||||||
mxmlNewReal(tree, 123.4);
|
mxmlNewReal(tree, 123.4);
|
||||||
mxmlNewText(tree, 1, "text");
|
mxmlNewText(tree, 1, "text");
|
||||||
|
|
||||||
type = MXML_TYPE_TEXT;
|
mxmlOptionsSetTypeValue(options, MXML_TYPE_TEXT);
|
||||||
mxmlLoadString(tree, "<group type='string'>string string string</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
mxmlLoadString(tree, options, "<group type='string'>string string string</group>");
|
||||||
|
|
||||||
type = MXML_TYPE_INTEGER;
|
mxmlOptionsSetTypeValue(options, MXML_TYPE_INTEGER);
|
||||||
mxmlLoadString(tree, "<group type='integer'>1 2 3</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
mxmlLoadString(tree, options, "<group type='integer'>1 2 3</group>");
|
||||||
|
|
||||||
type = MXML_TYPE_REAL;
|
mxmlOptionsSetTypeValue(options, MXML_TYPE_REAL);
|
||||||
mxmlLoadString(tree, "<group type='real'>1.0 2.0 3.0</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
mxmlLoadString(tree, options, "<group type='real'>1.0 2.0 3.0</group>");
|
||||||
|
|
||||||
type = MXML_TYPE_OPAQUE;
|
mxmlOptionsSetTypeValue(options, MXML_TYPE_OPAQUE);
|
||||||
mxmlLoadString(tree, "<group>opaque opaque opaque</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
mxmlLoadString(tree, options, "<group>opaque opaque opaque</group>");
|
||||||
mxmlLoadString(tree, "<foo><bar><one><two>value<two>value2</two></two></one></bar></foo>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
mxmlLoadString(tree, options, "<foo><bar><one><two>value<two>value2</two></two></one></bar></foo>");
|
||||||
|
|
||||||
mxmlNewCDATA(tree, "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n");
|
mxmlNewCDATA(tree, "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n");
|
||||||
mxmlNewCDATA(tree,
|
mxmlNewCDATA(tree,
|
||||||
@ -434,11 +436,13 @@ main(int argc, // I - Number of command-line args
|
|||||||
|
|
||||||
mxmlDelete(xml);
|
mxmlDelete(xml);
|
||||||
|
|
||||||
// Open the file/string using the default (MXML_NO_CALLBACK) callback...
|
// Open the file/string using the default callback...
|
||||||
|
mxmlOptionsSetTypeValue(options, MXML_TYPE_TEXT);
|
||||||
|
|
||||||
if (argv[1][0] == '<')
|
if (argv[1][0] == '<')
|
||||||
xml = mxmlLoadString(/*top*/NULL, argv[1], /*load_cb*/NULL, /*load_cbdata*/NULL, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
xml = mxmlLoadString(/*top*/NULL, options, argv[1]);
|
||||||
else
|
else
|
||||||
xml = mxmlLoadFilename(/*top*/NULL, argv[1], /*load_cb*/NULL, /*load_cbdata*/NULL, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
xml = mxmlLoadFilename(/*top*/NULL, options, argv[1]);
|
||||||
|
|
||||||
if (!xml)
|
if (!xml)
|
||||||
{
|
{
|
||||||
@ -459,7 +463,7 @@ main(int argc, // I - Number of command-line args
|
|||||||
if (mxmlGetType(node) != MXML_TYPE_TEXT)
|
if (mxmlGetType(node) != MXML_TYPE_TEXT)
|
||||||
{
|
{
|
||||||
fputs("No child node of group/option/keyword.\n", stderr);
|
fputs("No child node of group/option/keyword.\n", stderr);
|
||||||
mxmlSaveFile(xml, stderr, /*save_cb*/NULL, /*save_cbdata*/NULL);
|
mxmlSaveFile(xml, options, stderr);
|
||||||
mxmlDelete(xml);
|
mxmlDelete(xml);
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
@ -475,10 +479,12 @@ main(int argc, // I - Number of command-line args
|
|||||||
mxmlDelete(xml);
|
mxmlDelete(xml);
|
||||||
|
|
||||||
// Open the file...
|
// Open the file...
|
||||||
|
mxmlOptionsSetTypeCallback(options, type_cb, /*cbdata*/NULL);
|
||||||
|
|
||||||
if (argv[1][0] == '<')
|
if (argv[1][0] == '<')
|
||||||
xml = mxmlLoadString(/*top*/NULL, argv[1], /*load_cb*/type_cb, /*load_cbdata*/NULL, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
xml = mxmlLoadString(/*top*/NULL, options, argv[1]);
|
||||||
else
|
else
|
||||||
xml = mxmlLoadFilename(/*top*/NULL, argv[1], /*load_cb*/type_cb, /*load_cbdata*/NULL, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
xml = mxmlLoadFilename(/*top*/NULL, options, argv[1]);
|
||||||
|
|
||||||
if (!xml)
|
if (!xml)
|
||||||
{
|
{
|
||||||
@ -505,10 +511,11 @@ main(int argc, // I - Number of command-line args
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Print the XML tree...
|
// Print the XML tree...
|
||||||
mxmlSaveFile(xml, stdout, whitespace_cb, /*save_cbdata*/NULL);
|
mxmlOptionsSetWhitespaceCallback(options, whitespace_cb, /*cbdata*/NULL);
|
||||||
|
mxmlSaveFile(xml, options, stdout);
|
||||||
|
|
||||||
// Save the XML tree to a string and print it...
|
// Save the XML tree to a string and print it...
|
||||||
if (mxmlSaveString(xml, buffer, sizeof(buffer), whitespace_cb, /*save_cbdata*/NULL) > 0)
|
if (mxmlSaveString(xml, options, buffer, sizeof(buffer)) > 0)
|
||||||
{
|
{
|
||||||
if (argc == 3)
|
if (argc == 3)
|
||||||
{
|
{
|
||||||
@ -532,7 +539,7 @@ main(int argc, // I - Number of command-line args
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read the file...
|
// Read the file...
|
||||||
xml = mxmlLoadFd(/*top*/NULL, fd, type_cb, /*load_cbdata*/NULL, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
xml = mxmlLoadFd(/*top*/NULL, options, fd);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -547,7 +554,7 @@ main(int argc, // I - Number of command-line args
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write the file...
|
// Write the file...
|
||||||
mxmlSaveFd(xml, fd, whitespace_cb, /*save_cbdata*/NULL);
|
mxmlSaveFd(xml, options, fd);
|
||||||
|
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
@ -558,10 +565,12 @@ main(int argc, // I - Number of command-line args
|
|||||||
// Test SAX methods...
|
// Test SAX methods...
|
||||||
memset(event_counts, 0, sizeof(event_counts));
|
memset(event_counts, 0, sizeof(event_counts));
|
||||||
|
|
||||||
|
mxmlOptionsSetSAXCallback(options, sax_cb, /*cbdata*/NULL);
|
||||||
|
|
||||||
if (argv[1][0] == '<')
|
if (argv[1][0] == '<')
|
||||||
mxmlRelease(mxmlLoadString(/*top*/NULL, argv[1], type_cb, /*load_cbdata*/NULL, sax_cb, /*sax_cbdata*/NULL));
|
mxmlRelease(mxmlLoadString(/*top*/NULL, options, argv[1]));
|
||||||
else
|
else
|
||||||
mxmlRelease(mxmlLoadFilename(/*top*/NULL, argv[1], type_cb, /*load_cbdata*/NULL, sax_cb, /*sax_cbdata*/NULL));
|
mxmlRelease(mxmlLoadFilename(/*top*/NULL, options, argv[1]));
|
||||||
|
|
||||||
if (!strcmp(argv[1], "test.xml"))
|
if (!strcmp(argv[1], "test.xml"))
|
||||||
{
|
{
|
||||||
|
@ -8,9 +8,6 @@ EXPORTS
|
|||||||
mxmlElementGetAttr
|
mxmlElementGetAttr
|
||||||
mxmlElementSetAttr
|
mxmlElementSetAttr
|
||||||
mxmlElementSetAttrf
|
mxmlElementSetAttrf
|
||||||
mxmlEntityAddCallback
|
|
||||||
mxmlEntityGetValue
|
|
||||||
mxmlEntityRemoveCallback
|
|
||||||
mxmlFindElement
|
mxmlFindElement
|
||||||
mxmlFindPath
|
mxmlFindPath
|
||||||
mxmlGetCDATA
|
mxmlGetCDATA
|
||||||
@ -59,6 +56,16 @@ EXPORTS
|
|||||||
mxmlNewText
|
mxmlNewText
|
||||||
mxmlNewTextf
|
mxmlNewTextf
|
||||||
mxmlNewXML
|
mxmlNewXML
|
||||||
|
mxmlOptionsDelete
|
||||||
|
mxmlOptionsNew
|
||||||
|
mxmlOptionsSetCustomCallbacks
|
||||||
|
mxmlOptionsSetEntityCallback
|
||||||
|
mxmlOptionsSetErrorCallback
|
||||||
|
mxmlOptionsSetSAXCallback
|
||||||
|
mxmlOptionsSetTypeCallback
|
||||||
|
mxmlOptionsSetTypeValue
|
||||||
|
mxmlOptionsSetWhitespaceCallback
|
||||||
|
mxmlOptionsSetWrapMargin
|
||||||
mxmlRelease
|
mxmlRelease
|
||||||
mxmlRemove
|
mxmlRemove
|
||||||
mxmlRetain
|
mxmlRetain
|
||||||
@ -73,20 +80,18 @@ EXPORTS
|
|||||||
mxmlSetComment
|
mxmlSetComment
|
||||||
mxmlSetCommentf
|
mxmlSetCommentf
|
||||||
mxmlSetCustom
|
mxmlSetCustom
|
||||||
mxmlSetCustomCallbacks
|
|
||||||
mxmlSetDeclaration
|
mxmlSetDeclaration
|
||||||
mxmlSetDeclarationf
|
mxmlSetDeclarationf
|
||||||
mxmlSetDirective
|
mxmlSetDirective
|
||||||
mxmlSetDirectivef
|
mxmlSetDirectivef
|
||||||
mxmlSetElement
|
mxmlSetElement
|
||||||
mxmlSetErrorCallback
|
|
||||||
mxmlSetInteger
|
mxmlSetInteger
|
||||||
mxmlSetOpaque
|
mxmlSetOpaque
|
||||||
mxmlSetOpaquef
|
mxmlSetOpaquef
|
||||||
mxmlSetReal
|
mxmlSetReal
|
||||||
|
mxmlSetStringCallbacks
|
||||||
mxmlSetText
|
mxmlSetText
|
||||||
mxmlSetTextf
|
mxmlSetTextf
|
||||||
mxmlSetUserData
|
mxmlSetUserData
|
||||||
mxmlSetWrapMargin
|
|
||||||
mxmlWalkNext
|
mxmlWalkNext
|
||||||
mxmlWalkPrev
|
mxmlWalkPrev
|
||||||
|
@ -191,11 +191,11 @@
|
|||||||
</ItemDefinitionGroup>
|
</ItemDefinitionGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\mxml-attr.c" />
|
<ClCompile Include="..\mxml-attr.c" />
|
||||||
<ClCompile Include="..\mxml-entity.c" />
|
|
||||||
<ClCompile Include="..\mxml-file.c" />
|
<ClCompile Include="..\mxml-file.c" />
|
||||||
<ClCompile Include="..\mxml-get.c" />
|
<ClCompile Include="..\mxml-get.c" />
|
||||||
<ClCompile Include="..\mxml-index.c" />
|
<ClCompile Include="..\mxml-index.c" />
|
||||||
<ClCompile Include="..\mxml-node.c" />
|
<ClCompile Include="..\mxml-node.c" />
|
||||||
|
<ClCompile Include="..\mxml-options.c" />
|
||||||
<ClCompile Include="..\mxml-private.c" />
|
<ClCompile Include="..\mxml-private.c" />
|
||||||
<ClCompile Include="..\mxml-search.c" />
|
<ClCompile Include="..\mxml-search.c" />
|
||||||
<ClCompile Include="..\mxml-set.c" />
|
<ClCompile Include="..\mxml-set.c" />
|
||||||
|
@ -24,12 +24,12 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\mxml-attr.c" />
|
<ClCompile Include="..\mxml-attr.c" />
|
||||||
<ClCompile Include="..\mxml-entity.c" />
|
|
||||||
<ClCompile Include="..\mxml-file.c" />
|
<ClCompile Include="..\mxml-file.c" />
|
||||||
<ClCompile Include="..\mxml-get.c" />
|
<ClCompile Include="..\mxml-get.c" />
|
||||||
<ClCompile Include="..\mxml-index.c" />
|
<ClCompile Include="..\mxml-index.c" />
|
||||||
<ClCompile Include="..\mxml-node.c" />
|
<ClCompile Include="..\mxml-node.c" />
|
||||||
<ClCompile Include="..\mxml-private.c" />
|
<ClCompile Include="..\mxml-private.c" />
|
||||||
|
<ClCompile Include="..\mxml-options.c" />
|
||||||
<ClCompile Include="..\mxml-search.c" />
|
<ClCompile Include="..\mxml-search.c" />
|
||||||
<ClCompile Include="..\mxml-set.c" />
|
<ClCompile Include="..\mxml-set.c" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
272C00191E8C66C8007EBCAC /* mxml-attr.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000D1E8C66C8007EBCAC /* mxml-attr.c */; };
|
272C00191E8C66C8007EBCAC /* mxml-attr.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000D1E8C66C8007EBCAC /* mxml-attr.c */; };
|
||||||
272C001A1E8C66C8007EBCAC /* mxml-entity.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000E1E8C66C8007EBCAC /* mxml-entity.c */; };
|
|
||||||
272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000F1E8C66C8007EBCAC /* mxml-file.c */; };
|
272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C000F1E8C66C8007EBCAC /* mxml-file.c */; };
|
||||||
272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00101E8C66C8007EBCAC /* mxml-get.c */; };
|
272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00101E8C66C8007EBCAC /* mxml-get.c */; };
|
||||||
272C001D1E8C66C8007EBCAC /* mxml-index.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00111E8C66C8007EBCAC /* mxml-index.c */; };
|
272C001D1E8C66C8007EBCAC /* mxml-index.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00111E8C66C8007EBCAC /* mxml-index.c */; };
|
||||||
@ -36,6 +35,7 @@
|
|||||||
272C00261E8C66CF007EBCAC /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00251E8C66CF007EBCAC /* config.h */; };
|
272C00261E8C66CF007EBCAC /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00251E8C66CF007EBCAC /* config.h */; };
|
||||||
272C00421E8C6B30007EBCAC /* testmxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00401E8C6B1B007EBCAC /* testmxml.c */; };
|
272C00421E8C6B30007EBCAC /* testmxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00401E8C6B1B007EBCAC /* testmxml.c */; };
|
||||||
272C00501E8C6B89007EBCAC /* libmxml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 272C00051E8C6664007EBCAC /* libmxml.a */; };
|
272C00501E8C6B89007EBCAC /* libmxml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 272C00051E8C6664007EBCAC /* libmxml.a */; };
|
||||||
|
27459CD92BA8BAC300EAF97D /* mxml-options.c in Sources */ = {isa = PBXBuildFile; fileRef = 27459CD82BA8BAC300EAF97D /* mxml-options.c */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
@ -77,7 +77,6 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
272C00051E8C6664007EBCAC /* libmxml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmxml.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
272C00051E8C6664007EBCAC /* libmxml.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libmxml.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
272C000D1E8C66C8007EBCAC /* mxml-attr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-attr.c"; path = "../mxml-attr.c"; sourceTree = "<group>"; };
|
272C000D1E8C66C8007EBCAC /* mxml-attr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-attr.c"; path = "../mxml-attr.c"; sourceTree = "<group>"; };
|
||||||
272C000E1E8C66C8007EBCAC /* mxml-entity.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-entity.c"; path = "../mxml-entity.c"; sourceTree = "<group>"; };
|
|
||||||
272C000F1E8C66C8007EBCAC /* mxml-file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-file.c"; path = "../mxml-file.c"; sourceTree = "<group>"; };
|
272C000F1E8C66C8007EBCAC /* mxml-file.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-file.c"; path = "../mxml-file.c"; sourceTree = "<group>"; };
|
||||||
272C00101E8C66C8007EBCAC /* mxml-get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-get.c"; path = "../mxml-get.c"; sourceTree = "<group>"; };
|
272C00101E8C66C8007EBCAC /* mxml-get.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-get.c"; path = "../mxml-get.c"; sourceTree = "<group>"; };
|
||||||
272C00111E8C66C8007EBCAC /* mxml-index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-index.c"; path = "../mxml-index.c"; sourceTree = "<group>"; };
|
272C00111E8C66C8007EBCAC /* mxml-index.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-index.c"; path = "../mxml-index.c"; sourceTree = "<group>"; };
|
||||||
@ -92,6 +91,7 @@
|
|||||||
272C00401E8C6B1B007EBCAC /* testmxml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testmxml.c; path = ../testmxml.c; sourceTree = "<group>"; };
|
272C00401E8C6B1B007EBCAC /* testmxml.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = testmxml.c; path = ../testmxml.c; sourceTree = "<group>"; };
|
||||||
272C00551E8EF972007EBCAC /* libarchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.tbd; path = usr/lib/libarchive.tbd; sourceTree = SDKROOT; };
|
272C00551E8EF972007EBCAC /* libarchive.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libarchive.tbd; path = usr/lib/libarchive.tbd; sourceTree = SDKROOT; };
|
||||||
272C005A1E943423007EBCAC /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
272C005A1E943423007EBCAC /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; };
|
||||||
|
27459CD82BA8BAC300EAF97D /* mxml-options.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = "mxml-options.c"; path = "../mxml-options.c"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
@ -128,11 +128,11 @@
|
|||||||
272C00181E8C66C8007EBCAC /* mxml.h */,
|
272C00181E8C66C8007EBCAC /* mxml.h */,
|
||||||
272C00141E8C66C8007EBCAC /* mxml-private.h */,
|
272C00141E8C66C8007EBCAC /* mxml-private.h */,
|
||||||
272C000D1E8C66C8007EBCAC /* mxml-attr.c */,
|
272C000D1E8C66C8007EBCAC /* mxml-attr.c */,
|
||||||
272C000E1E8C66C8007EBCAC /* mxml-entity.c */,
|
|
||||||
272C000F1E8C66C8007EBCAC /* mxml-file.c */,
|
272C000F1E8C66C8007EBCAC /* mxml-file.c */,
|
||||||
272C00101E8C66C8007EBCAC /* mxml-get.c */,
|
272C00101E8C66C8007EBCAC /* mxml-get.c */,
|
||||||
272C00111E8C66C8007EBCAC /* mxml-index.c */,
|
272C00111E8C66C8007EBCAC /* mxml-index.c */,
|
||||||
272C00121E8C66C8007EBCAC /* mxml-node.c */,
|
272C00121E8C66C8007EBCAC /* mxml-node.c */,
|
||||||
|
27459CD82BA8BAC300EAF97D /* mxml-options.c */,
|
||||||
272C00131E8C66C8007EBCAC /* mxml-private.c */,
|
272C00131E8C66C8007EBCAC /* mxml-private.c */,
|
||||||
272C00151E8C66C8007EBCAC /* mxml-search.c */,
|
272C00151E8C66C8007EBCAC /* mxml-search.c */,
|
||||||
272C00161E8C66C8007EBCAC /* mxml-set.c */,
|
272C00161E8C66C8007EBCAC /* mxml-set.c */,
|
||||||
@ -226,7 +226,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastUpgradeCheck = 1520;
|
LastUpgradeCheck = 1530;
|
||||||
ORGANIZATIONNAME = "Michael R Sweet";
|
ORGANIZATIONNAME = "Michael R Sweet";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
272C00041E8C6664007EBCAC = {
|
272C00041E8C6664007EBCAC = {
|
||||||
@ -271,7 +271,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
272C001A1E8C66C8007EBCAC /* mxml-entity.c in Sources */,
|
27459CD92BA8BAC300EAF97D /* mxml-options.c in Sources */,
|
||||||
272C001E1E8C66C8007EBCAC /* mxml-node.c in Sources */,
|
272C001E1E8C66C8007EBCAC /* mxml-node.c in Sources */,
|
||||||
272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */,
|
272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */,
|
||||||
272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */,
|
272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */,
|
||||||
|
Loading…
Reference in New Issue
Block a user