mirror of
https://github.com/michaelrsweet/mxml.git
synced 2024-11-24 03:15: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)
|
||||
- Added `mxmlLoadFilename` and `mxmlSaveFilename` functions (Issue #291)
|
||||
- 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
|
||||
strings.
|
||||
- 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 \
|
||||
CHANGES.md LICENSE NOTICE README.md
|
||||
PUBLIBOBJS = mxml-attr.o mxml-entity.o mxml-file.o mxml-get.o \
|
||||
mxml-index.o mxml-node.o mxml-search.o mxml-set.o
|
||||
PUBLIBOBJS = mxml-attr.o mxml-file.o mxml-get.o mxml-index.o \
|
||||
mxml-node.o mxml-options.o mxml-search.o mxml-set.o
|
||||
LIBOBJS = $(PUBLIBOBJS) mxml-private.o
|
||||
OBJS = testmxml.o $(LIBOBJS)
|
||||
ALLTARGETS = $(LIBMXML) testmxml
|
||||
|
@ -5,6 +5,9 @@ copyright: Copyright © 2003-2024, All Rights Reserved.
|
||||
version: 4.0
|
||||
...
|
||||
|
||||
> TODO: Update for mxmlOptions APIs!
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
|
18
mxml-attr.c
18
mxml-attr.c
@ -173,10 +173,7 @@ mxmlElementSetAttr(mxml_node_t *node, // I - Element node
|
||||
if (value)
|
||||
{
|
||||
if ((valuec = _mxml_strcopy(value)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for attribute '%s' in element %s.", name, node->value.element.name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -218,10 +215,11 @@ mxmlElementSetAttrf(mxml_node_t *node, // I - Element node
|
||||
vsnprintf(buffer, sizeof(buffer), format, ap);
|
||||
va_end(ap);
|
||||
|
||||
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))
|
||||
_mxml_strfree(value);
|
||||
if ((value = _mxml_strcopy(buffer)) != NULL)
|
||||
{
|
||||
if (!mxml_set_attr(node, name, value))
|
||||
_mxml_strfree(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -253,19 +251,13 @@ mxml_set_attr(mxml_node_t *node, // I - Element node
|
||||
|
||||
// Add a new attribute...
|
||||
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);
|
||||
}
|
||||
|
||||
node->value.element.attrs = attr;
|
||||
attr += node->value.element.num_attrs;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
755
mxml-file.c
755
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...
|
||||
if ((ind = calloc(1, sizeof(mxml_index_t))) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for index.");
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (attr)
|
||||
{
|
||||
if ((ind->attr = _mxml_strcopy(attr)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for index attribute.");
|
||||
free(ind);
|
||||
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)
|
||||
{
|
||||
// Unable to allocate memory for the index, so abort...
|
||||
_mxml_error("Unable to allocate memory for index nodes.");
|
||||
mxmlIndexDelete(ind);
|
||||
return (NULL);
|
||||
}
|
||||
|
27
mxml-node.c
27
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)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA.");
|
||||
mxmlDelete(node);
|
||||
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)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment.");
|
||||
mxmlDelete(node);
|
||||
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.
|
||||
//
|
||||
// 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
|
||||
// element node has no parent. `NULL` can be passed when the data in the
|
||||
// node is not dynamically allocated or is separately managed.
|
||||
// list. The `free_cb` argument specifies a function to call to free the custom
|
||||
// data when the node is deleted.
|
||||
//
|
||||
|
||||
mxml_node_t * // O - New node
|
||||
mxmlNewCustom(
|
||||
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
void *data, // I - Pointer to data
|
||||
mxml_custom_destroy_cb_t destroy) // I - Function to destroy data
|
||||
mxml_node_t *parent, // I - Parent node or `MXML_NO_PARENT`
|
||||
void *data, // I - Pointer to 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_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...
|
||||
if ((node = mxml_new(parent, MXML_TYPE_CUSTOM)) != NULL)
|
||||
{
|
||||
node->value.custom.data = data;
|
||||
node->value.custom.destroy = destroy;
|
||||
node->value.custom.data = data;
|
||||
node->value.custom.free_cb = free_cb;
|
||||
node->value.custom.free_cbdata = free_cbdata;
|
||||
}
|
||||
|
||||
return (node);
|
||||
@ -394,7 +393,6 @@ mxmlNewDeclaration(
|
||||
{
|
||||
if ((node->value.declaration = _mxml_strcopy(declaration)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration.");
|
||||
mxmlDelete(node);
|
||||
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)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for processing instruction.");
|
||||
mxmlDelete(node);
|
||||
return (NULL);
|
||||
}
|
||||
@ -893,8 +890,8 @@ mxml_free(mxml_node_t *node) // I - Node
|
||||
_mxml_strfree(node->value.text.string);
|
||||
break;
|
||||
case MXML_TYPE_CUSTOM :
|
||||
if (node->value.custom.data && node->value.custom.destroy)
|
||||
(*(node->value.custom.destroy))(node->value.custom.data);
|
||||
if (node->value.custom.data && node->value.custom.free_cb)
|
||||
(node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data);
|
||||
break;
|
||||
default :
|
||||
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
|
||||
|
||||
|
||||
//
|
||||
// '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.
|
||||
//
|
||||
@ -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.
|
||||
//
|
||||
@ -341,10 +172,6 @@ _mxml_global(void)
|
||||
{
|
||||
global = (_mxml_global_t *)calloc(1, sizeof(_mxml_global_t));
|
||||
pthread_setspecific(_mxml_key, global);
|
||||
|
||||
global->num_entity_cbs = 1;
|
||||
global->entity_cbs[0] = _mxml_entity_cb;
|
||||
global->wrap = 72;
|
||||
}
|
||||
|
||||
return (global);
|
||||
@ -425,10 +252,6 @@ _mxml_global(void)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -446,12 +269,9 @@ _mxml_global(void)
|
||||
{
|
||||
static _mxml_global_t global = // Global data
|
||||
{
|
||||
NULL, // error_cb
|
||||
1, // num_entity_cbs
|
||||
{ _mxml_entity_cb }, // entity_cbs
|
||||
72, // wrap
|
||||
NULL, // custom_load_cb
|
||||
NULL // custom_save_cb
|
||||
NULL, // strcopy_cb
|
||||
NULL, // strfree_cb
|
||||
NULL, // str_cbdata
|
||||
};
|
||||
|
||||
|
||||
|
@ -54,7 +54,8 @@ typedef struct _mxml_text_s // An XML text value.
|
||||
typedef struct _mxml_custom_s // An XML custom value.
|
||||
{
|
||||
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;
|
||||
|
||||
typedef union _mxml_value_u // An XML node value.
|
||||
@ -84,7 +85,14 @@ struct _mxml_node_s // An XML node.
|
||||
void *user_data; // User data
|
||||
};
|
||||
|
||||
struct _mxml_index_s // An XML node index.
|
||||
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.
|
||||
{
|
||||
char *attr; // Attribute used for indexing or NULL
|
||||
size_t num_nodes; // Number of nodes in index
|
||||
@ -93,25 +101,26 @@ struct _mxml_index_s // An XML node index.
|
||||
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
|
||||
size_t loc_declen; // Length of decimal point string
|
||||
bool loc_set; // Locale data set?
|
||||
mxml_strcopy_cb_t strcopy_cb; // String copy callback function
|
||||
mxml_strfree_cb_t strfree_cb; // String free callback function
|
||||
void *str_cbdata; // String callback data
|
||||
int wrap; // Wrap margin
|
||||
} _mxml_global_t;
|
||||
struct lconv *loc; // Locale data
|
||||
size_t loc_declen; // Length of decimal point string
|
||||
mxml_custload_cb_t custload_cb; // Custom load callback function
|
||||
mxml_custsave_cb_t custsave_cb; // Custom save callback function
|
||||
void *cust_cbdata; // Custom 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
|
||||
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 int _mxml_entity_cb(void *cbdata, const char *name);
|
||||
extern const char *_mxml_entity_string(int ch);
|
||||
extern void _mxml_error(const char *format, ...) MXML_FORMAT(1,2);
|
||||
extern 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 void _mxml_strfree(char *s);
|
||||
|
||||
|
150
mxml-set.c
150
mxml-set.c
@ -31,15 +31,9 @@ mxmlSetCDATA(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_CDATA)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!data)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
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...
|
||||
if ((s = _mxml_strcopy(data)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
@ -83,15 +74,9 @@ mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_CDATA)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -99,10 +84,7 @@ mxmlSetCDATAf(mxml_node_t *node, // I - Node
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for CDATA string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.cdata);
|
||||
node->value.cdata = s;
|
||||
@ -129,25 +111,16 @@ mxmlSetComment(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!comment)
|
||||
{
|
||||
_mxml_error("NULL comment not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (comment == node->value.comment)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = _mxml_strcopy(comment)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.comment);
|
||||
node->value.comment = s;
|
||||
@ -177,15 +150,9 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -193,10 +160,7 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for comment string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.comment);
|
||||
node->value.comment = s;
|
||||
@ -215,32 +179,31 @@ mxmlSetCommentf(mxml_node_t *node, // I - Node
|
||||
|
||||
bool // O - `true` on success, `false` on failure
|
||||
mxmlSetCustom(
|
||||
mxml_node_t *node, // I - Node to set
|
||||
void *data, // I - New data pointer
|
||||
mxml_custom_destroy_cb_t destroy_cb)// I - New destructor function
|
||||
mxml_node_t *node, // I - Node to set
|
||||
void *data, // I - New data pointer
|
||||
mxml_custfree_cb_t free_cb, // I - Free callback function
|
||||
void *free_cbdata) // I - Free callback data
|
||||
{
|
||||
// Range check input...
|
||||
if (node && node->type == MXML_TYPE_ELEMENT && node->child && node->child->type == MXML_TYPE_CUSTOM)
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_CUSTOM)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (data == node->value.custom.data)
|
||||
{
|
||||
node->value.custom.destroy = destroy_cb;
|
||||
return (true);
|
||||
}
|
||||
goto set_free_callback;
|
||||
|
||||
// Free any old element value and set the new value...
|
||||
if (node->value.custom.data && node->value.custom.destroy)
|
||||
(*(node->value.custom.destroy))(node->value.custom.data);
|
||||
if (node->value.custom.data && node->value.custom.free_cb)
|
||||
(node->value.custom.free_cb)(node->value.custom.free_cbdata, node->value.custom.data);
|
||||
|
||||
node->value.custom.data = data;
|
||||
node->value.custom.destroy = destroy_cb;
|
||||
node->value.custom.data = data;
|
||||
|
||||
set_free_callback:
|
||||
|
||||
node->value.custom.free_cb = free_cb;
|
||||
node->value.custom.free_cbdata = free_cbdata;
|
||||
|
||||
return (true);
|
||||
}
|
||||
@ -265,25 +228,16 @@ mxmlSetDeclaration(
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DECLARATION)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!declaration)
|
||||
{
|
||||
_mxml_error("NULL declaration not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (declaration == node->value.declaration)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = _mxml_strcopy(declaration)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
@ -313,15 +267,9 @@ mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_COMMENT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -329,10 +277,7 @@ mxmlSetDeclarationf(mxml_node_t *node, // I - Node
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for declaration string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.declaration);
|
||||
node->value.declaration = s;
|
||||
@ -359,25 +304,16 @@ mxmlSetDirective(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!directive)
|
||||
{
|
||||
_mxml_error("NULL directive not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (directive == node->value.directive)
|
||||
return (true);
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
if ((s = _mxml_strcopy(directive)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.directive);
|
||||
node->value.directive = s;
|
||||
@ -408,15 +344,9 @@ mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_DIRECTIVE)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -424,10 +354,7 @@ mxmlSetDirectivef(mxml_node_t *node, // I - Node
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for directive string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.directive);
|
||||
node->value.directive = s;
|
||||
@ -452,25 +379,16 @@ mxmlSetElement(mxml_node_t *node, // I - Node to set
|
||||
|
||||
// Range check input...
|
||||
if (!node || node->type != MXML_TYPE_ELEMENT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!name)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (name == node->value.element.name)
|
||||
return (true);
|
||||
|
||||
// Free any old element value and set the new value...
|
||||
if ((s = _mxml_strcopy(name)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for element name.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.element.name);
|
||||
node->value.element.name = s;
|
||||
@ -495,10 +413,7 @@ mxmlSetInteger(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_INTEGER)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Set the new value and return...
|
||||
node->value.integer = integer;
|
||||
@ -526,25 +441,16 @@ mxmlSetOpaque(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!opaque)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
if (node->value.opaque == opaque)
|
||||
return (true);
|
||||
|
||||
// Free any old opaque value and set the new value...
|
||||
if ((s = _mxml_strcopy(opaque)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
@ -575,15 +481,9 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_OPAQUE)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Format the new string, free any old string value, and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -591,10 +491,7 @@ mxmlSetOpaquef(mxml_node_t *node, // I - Node to set
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for opaque string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.opaque);
|
||||
node->value.opaque = s;
|
||||
@ -619,10 +516,7 @@ mxmlSetReal(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_REAL)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Set the new value and return...
|
||||
node->value.real = real;
|
||||
@ -651,15 +545,9 @@ mxmlSetText(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_TEXT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!string)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
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...
|
||||
if ((s = _mxml_strcopy(string)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for text string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.text.string);
|
||||
|
||||
@ -706,15 +591,9 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
node = node->child;
|
||||
|
||||
if (!node || node->type != MXML_TYPE_TEXT)
|
||||
{
|
||||
_mxml_error("Wrong node type.");
|
||||
return (false);
|
||||
}
|
||||
else if (!format)
|
||||
{
|
||||
_mxml_error("NULL string not allowed.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
// Free any old string value and set the new value...
|
||||
va_start(ap, format);
|
||||
@ -722,10 +601,7 @@ mxmlSetTextf(mxml_node_t *node, // I - Node to set
|
||||
va_end(ap);
|
||||
|
||||
if ((s = _mxml_strcopy(buffer)) == NULL)
|
||||
{
|
||||
_mxml_error("Unable to allocate memory for text string.");
|
||||
return (false);
|
||||
}
|
||||
|
||||
_mxml_strfree(node->value.text.string);
|
||||
|
||||
|
87
mxml.h
87
mxml.h
@ -19,12 +19,6 @@
|
||||
# include <ctype.h>
|
||||
# include <errno.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
|
||||
extern "C" {
|
||||
# endif // __cplusplus
|
||||
@ -95,45 +89,46 @@ typedef enum mxml_ws_e // Whitespace periods
|
||||
MXML_WS_AFTER_CLOSE, // Callback for after close tag
|
||||
} 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);
|
||||
// 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;
|
||||
// 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
|
||||
|
||||
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
|
||||
|
||||
typedef int (*mxml_entity_cb_t)(void *cbdata, const char *name);
|
||||
// Entity callback function
|
||||
|
||||
typedef mxml_type_t (*mxml_load_cb_t)(void *cbdata, mxml_node_t *node);
|
||||
// Load callback function
|
||||
typedef size_t (*mxml_io_cb_t)(void *cbdata, void *buffer, size_t bytes);
|
||||
// Read/write callback function
|
||||
|
||||
typedef ssize_t (*mxml_read_cb_t)(void *cbdata, void *buffer, size_t bytes);
|
||||
// Read callback function
|
||||
|
||||
typedef const char *(*mxml_save_cb_t)(void *cbdata, mxml_node_t *node, mxml_ws_t when);
|
||||
// Save callback function
|
||||
typedef bool (*mxml_sax_cb_t)(void *cbdata, mxml_node_t *node, mxml_sax_event_t event);
|
||||
// SAX callback function
|
||||
|
||||
typedef char *(*mxml_strcopy_cb_t)(void *cbdata, const char *s);
|
||||
// String copy/allocation callback
|
||||
typedef void (*mxml_strfree_cb_t)(void *cbdata, char *s);
|
||||
// String free callback
|
||||
|
||||
typedef ssize_t (*mxml_write_cb_t)(void *cbdata, const void *buffer, size_t bytes);
|
||||
// Write callback function
|
||||
typedef mxml_type_t (*mxml_type_cb_t)(void *cbdata, mxml_node_t *node);
|
||||
// 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 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 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 *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_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 *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 *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 *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 *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 *mxmlLoadFd(mxml_node_t *top, mxml_options_t *options, int fd);
|
||||
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, mxml_options_t *options, FILE *fp);
|
||||
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_options_t *options, mxml_io_cb_t io_cb, void *io_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 *mxmlNewCDATAf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewComment(mxml_node_t *parent, const char *comment);
|
||||
extern mxml_node_t *mxmlNewCommentf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern mxml_node_t *mxmlNewCustom(mxml_node_t *parent, void *data, mxml_custom_destroy_cb_t destroy);
|
||||
extern mxml_node_t *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 *mxmlNewDeclarationf(mxml_node_t *parent, const char *format, ...) MXML_FORMAT(2,3);
|
||||
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 int mxmlRetain(mxml_node_t *node);
|
||||
|
||||
extern char *mxmlSaveAllocString(mxml_node_t *node, mxml_save_cb_t save_cb, void *save_cbdata);
|
||||
extern bool mxmlSaveFd(mxml_node_t *node, int fd, mxml_save_cb_t save_cb, void *save_cbdata);
|
||||
extern bool mxmlSaveFile(mxml_node_t *node, FILE *fp, mxml_save_cb_t save_cb, void *save_cbdata);
|
||||
extern bool mxmlSaveFilename(mxml_node_t *node, const char *filename, mxml_save_cb_t save_cb, void *save_cbdata);
|
||||
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 size_t mxmlSaveString(mxml_node_t *node, char *buffer, size_t bufsize, 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, mxml_options_t *options, int fd);
|
||||
extern bool mxmlSaveFile(mxml_node_t *node, mxml_options_t *options, FILE *fp);
|
||||
extern bool mxmlSaveFilename(mxml_node_t *node, mxml_options_t *options, const char *filename);
|
||||
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, mxml_options_t *options, char *buffer, size_t bufsize);
|
||||
|
||||
extern bool mxmlSetCDATA(mxml_node_t *node, const char *data);
|
||||
extern bool mxmlSetCDATAf(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetComment(mxml_node_t *node, const char *comment);
|
||||
@ -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 mxmlSetDirective(mxml_node_t *node, const char *directive);
|
||||
extern bool mxmlSetDirectivef(mxml_node_t *node, const char *format, ...) MXML_FORMAT(2,3);
|
||||
extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custom_destroy_cb_t destroy_cb);
|
||||
extern void mxmlSetCustomCallbacks(mxml_custom_load_cb_t load_cb, mxml_custom_save_cb_t save_cb, void *cbdata);
|
||||
extern bool mxmlSetCustom(mxml_node_t *node, void *data, mxml_custfree_cb_t free_cb, void *free_cbdata);
|
||||
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 mxmlSetOpaque(mxml_node_t *node, const char *opaque);
|
||||
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 mxmlSetTextf(mxml_node_t *node, bool whitespace, const char *format, ...) MXML_FORMAT(3,4);
|
||||
extern bool mxmlSetUserData(mxml_node_t *node, void *data);
|
||||
extern void mxmlSetWrapMargin(int column);
|
||||
|
||||
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend);
|
||||
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top, mxml_descend_t descend);
|
||||
|
55
testmxml.c
55
testmxml.c
@ -52,6 +52,7 @@ main(int argc, // I - Number of command-line args
|
||||
int i; // Looping var
|
||||
FILE *fp; // File to read
|
||||
int fd; // File descriptor
|
||||
mxml_options_t *options; // Load/save options
|
||||
mxml_node_t *xml, // <?xml ...?> node
|
||||
*tree, // Element tree
|
||||
*node; // Node which should be in test.xml
|
||||
@ -83,8 +84,9 @@ main(int argc, // I - Number of command-line args
|
||||
}
|
||||
|
||||
// Test the basic functionality...
|
||||
xml = mxmlNewXML("1.0");
|
||||
tree = mxmlNewElement(xml, "element");
|
||||
options = mxmlOptionsNew();
|
||||
xml = mxmlNewXML("1.0");
|
||||
tree = mxmlNewElement(xml, "element");
|
||||
|
||||
if (!tree)
|
||||
{
|
||||
@ -111,18 +113,18 @@ main(int argc, // I - Number of command-line args
|
||||
mxmlNewReal(tree, 123.4);
|
||||
mxmlNewText(tree, 1, "text");
|
||||
|
||||
type = MXML_TYPE_TEXT;
|
||||
mxmlLoadString(tree, "<group type='string'>string string string</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
||||
mxmlOptionsSetTypeValue(options, MXML_TYPE_TEXT);
|
||||
mxmlLoadString(tree, options, "<group type='string'>string string string</group>");
|
||||
|
||||
type = MXML_TYPE_INTEGER;
|
||||
mxmlLoadString(tree, "<group type='integer'>1 2 3</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
||||
mxmlOptionsSetTypeValue(options, MXML_TYPE_INTEGER);
|
||||
mxmlLoadString(tree, options, "<group type='integer'>1 2 3</group>");
|
||||
|
||||
type = 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);
|
||||
mxmlOptionsSetTypeValue(options, MXML_TYPE_REAL);
|
||||
mxmlLoadString(tree, options, "<group type='real'>1.0 2.0 3.0</group>");
|
||||
|
||||
type = MXML_TYPE_OPAQUE;
|
||||
mxmlLoadString(tree, "<group>opaque opaque opaque</group>", /*load_cb*/NULL, /*load_cbdata*/&type, /*sax_cb*/NULL, /*sax_cbdata*/NULL);
|
||||
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);
|
||||
mxmlOptionsSetTypeValue(options, MXML_TYPE_OPAQUE);
|
||||
mxmlLoadString(tree, options, "<group>opaque opaque opaque</group>");
|
||||
mxmlLoadString(tree, options, "<foo><bar><one><two>value<two>value2</two></two></one></bar></foo>");
|
||||
|
||||
mxmlNewCDATA(tree, "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef\n");
|
||||
mxmlNewCDATA(tree,
|
||||
@ -434,11 +436,13 @@ main(int argc, // I - Number of command-line args
|
||||
|
||||
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] == '<')
|
||||
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
|
||||
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)
|
||||
{
|
||||
@ -459,7 +463,7 @@ main(int argc, // I - Number of command-line args
|
||||
if (mxmlGetType(node) != MXML_TYPE_TEXT)
|
||||
{
|
||||
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);
|
||||
return (1);
|
||||
}
|
||||
@ -475,10 +479,12 @@ main(int argc, // I - Number of command-line args
|
||||
mxmlDelete(xml);
|
||||
|
||||
// Open the file...
|
||||
mxmlOptionsSetTypeCallback(options, type_cb, /*cbdata*/NULL);
|
||||
|
||||
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
|
||||
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)
|
||||
{
|
||||
@ -505,10 +511,11 @@ main(int argc, // I - Number of command-line args
|
||||
}
|
||||
|
||||
// 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...
|
||||
if (mxmlSaveString(xml, buffer, sizeof(buffer), whitespace_cb, /*save_cbdata*/NULL) > 0)
|
||||
if (mxmlSaveString(xml, options, buffer, sizeof(buffer)) > 0)
|
||||
{
|
||||
if (argc == 3)
|
||||
{
|
||||
@ -532,7 +539,7 @@ main(int argc, // I - Number of command-line args
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
@ -547,7 +554,7 @@ main(int argc, // I - Number of command-line args
|
||||
}
|
||||
|
||||
// Write the file...
|
||||
mxmlSaveFd(xml, fd, whitespace_cb, /*save_cbdata*/NULL);
|
||||
mxmlSaveFd(xml, options, fd);
|
||||
|
||||
close(fd);
|
||||
|
||||
@ -558,10 +565,12 @@ main(int argc, // I - Number of command-line args
|
||||
// Test SAX methods...
|
||||
memset(event_counts, 0, sizeof(event_counts));
|
||||
|
||||
mxmlOptionsSetSAXCallback(options, sax_cb, /*cbdata*/NULL);
|
||||
|
||||
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
|
||||
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"))
|
||||
{
|
||||
|
@ -8,9 +8,6 @@ EXPORTS
|
||||
mxmlElementGetAttr
|
||||
mxmlElementSetAttr
|
||||
mxmlElementSetAttrf
|
||||
mxmlEntityAddCallback
|
||||
mxmlEntityGetValue
|
||||
mxmlEntityRemoveCallback
|
||||
mxmlFindElement
|
||||
mxmlFindPath
|
||||
mxmlGetCDATA
|
||||
@ -59,6 +56,16 @@ EXPORTS
|
||||
mxmlNewText
|
||||
mxmlNewTextf
|
||||
mxmlNewXML
|
||||
mxmlOptionsDelete
|
||||
mxmlOptionsNew
|
||||
mxmlOptionsSetCustomCallbacks
|
||||
mxmlOptionsSetEntityCallback
|
||||
mxmlOptionsSetErrorCallback
|
||||
mxmlOptionsSetSAXCallback
|
||||
mxmlOptionsSetTypeCallback
|
||||
mxmlOptionsSetTypeValue
|
||||
mxmlOptionsSetWhitespaceCallback
|
||||
mxmlOptionsSetWrapMargin
|
||||
mxmlRelease
|
||||
mxmlRemove
|
||||
mxmlRetain
|
||||
@ -73,20 +80,18 @@ EXPORTS
|
||||
mxmlSetComment
|
||||
mxmlSetCommentf
|
||||
mxmlSetCustom
|
||||
mxmlSetCustomCallbacks
|
||||
mxmlSetDeclaration
|
||||
mxmlSetDeclarationf
|
||||
mxmlSetDirective
|
||||
mxmlSetDirectivef
|
||||
mxmlSetElement
|
||||
mxmlSetErrorCallback
|
||||
mxmlSetInteger
|
||||
mxmlSetOpaque
|
||||
mxmlSetOpaquef
|
||||
mxmlSetReal
|
||||
mxmlSetStringCallbacks
|
||||
mxmlSetText
|
||||
mxmlSetTextf
|
||||
mxmlSetUserData
|
||||
mxmlSetWrapMargin
|
||||
mxmlWalkNext
|
||||
mxmlWalkPrev
|
||||
|
@ -191,11 +191,11 @@
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\mxml-attr.c" />
|
||||
<ClCompile Include="..\mxml-entity.c" />
|
||||
<ClCompile Include="..\mxml-file.c" />
|
||||
<ClCompile Include="..\mxml-get.c" />
|
||||
<ClCompile Include="..\mxml-index.c" />
|
||||
<ClCompile Include="..\mxml-node.c" />
|
||||
<ClCompile Include="..\mxml-options.c" />
|
||||
<ClCompile Include="..\mxml-private.c" />
|
||||
<ClCompile Include="..\mxml-search.c" />
|
||||
<ClCompile Include="..\mxml-set.c" />
|
||||
|
@ -24,12 +24,12 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\mxml-attr.c" />
|
||||
<ClCompile Include="..\mxml-entity.c" />
|
||||
<ClCompile Include="..\mxml-file.c" />
|
||||
<ClCompile Include="..\mxml-get.c" />
|
||||
<ClCompile Include="..\mxml-index.c" />
|
||||
<ClCompile Include="..\mxml-node.c" />
|
||||
<ClCompile Include="..\mxml-private.c" />
|
||||
<ClCompile Include="..\mxml-options.c" />
|
||||
<ClCompile Include="..\mxml-search.c" />
|
||||
<ClCompile Include="..\mxml-set.c" />
|
||||
</ItemGroup>
|
||||
|
@ -23,7 +23,6 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
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 */; };
|
||||
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 */; };
|
||||
@ -36,6 +35,7 @@
|
||||
272C00261E8C66CF007EBCAC /* config.h in Headers */ = {isa = PBXBuildFile; fileRef = 272C00251E8C66CF007EBCAC /* config.h */; };
|
||||
272C00421E8C6B30007EBCAC /* testmxml.c in Sources */ = {isa = PBXBuildFile; fileRef = 272C00401E8C6B1B007EBCAC /* testmxml.c */; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -77,7 +77,6 @@
|
||||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@ -92,6 +91,7 @@
|
||||
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; };
|
||||
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 */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -128,11 +128,11 @@
|
||||
272C00181E8C66C8007EBCAC /* mxml.h */,
|
||||
272C00141E8C66C8007EBCAC /* mxml-private.h */,
|
||||
272C000D1E8C66C8007EBCAC /* mxml-attr.c */,
|
||||
272C000E1E8C66C8007EBCAC /* mxml-entity.c */,
|
||||
272C000F1E8C66C8007EBCAC /* mxml-file.c */,
|
||||
272C00101E8C66C8007EBCAC /* mxml-get.c */,
|
||||
272C00111E8C66C8007EBCAC /* mxml-index.c */,
|
||||
272C00121E8C66C8007EBCAC /* mxml-node.c */,
|
||||
27459CD82BA8BAC300EAF97D /* mxml-options.c */,
|
||||
272C00131E8C66C8007EBCAC /* mxml-private.c */,
|
||||
272C00151E8C66C8007EBCAC /* mxml-search.c */,
|
||||
272C00161E8C66C8007EBCAC /* mxml-set.c */,
|
||||
@ -226,7 +226,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastUpgradeCheck = 1520;
|
||||
LastUpgradeCheck = 1530;
|
||||
ORGANIZATIONNAME = "Michael R Sweet";
|
||||
TargetAttributes = {
|
||||
272C00041E8C6664007EBCAC = {
|
||||
@ -271,7 +271,7 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
272C001A1E8C66C8007EBCAC /* mxml-entity.c in Sources */,
|
||||
27459CD92BA8BAC300EAF97D /* mxml-options.c in Sources */,
|
||||
272C001E1E8C66C8007EBCAC /* mxml-node.c in Sources */,
|
||||
272C001B1E8C66C8007EBCAC /* mxml-file.c in Sources */,
|
||||
272C001C1E8C66C8007EBCAC /* mxml-get.c in Sources */,
|
||||
|
Loading…
Reference in New Issue
Block a user