Commit 337baedd authored by Michael R Sweet's avatar Michael R Sweet

New "set" and formatted string methods.

Prep for new "standard" opaque, integer, etc. callbacks.

Add new vsnprintf check.

Drop old string function checks for functions we don't actually use.
parent c02f86dd
README - 07/27/2003
README - 09/28/2003
-------------------
CHANGES IN Mini-XML 1.1.3
CHANGES IN Mini-XML 1.2
- Added new "set" methods to set the value of a node.
- Added new formatted text methods mxmlNewTextf() and
mxmlSetTextf() to create/set a text node value using
printf-style formats.
- Updated the HTML documentation to include examples of
the walk and load function output.
- Added --with/without-ansi configure option to control
the strdup() function check.
- Added --with/without-snprintf configure option to
control the snprintf() and vsnprintf() function
checks.
CHANGES IN Mini-XML 1.1.2
......
#
# "$Id: Makefile.in,v 1.11 2003/07/20 13:49:09 mike Exp $"
# "$Id: Makefile.in,v 1.12 2003/09/28 12:44:39 mike Exp $"
#
# Makefile for mini-XML, a small XML-like file parsing library.
#
......@@ -86,7 +86,7 @@ TARGETS = libmxml.a mxmldoc mxml.$(CAT3EXT) mxmldoc.$(CAT1EXT) \
# Make everything...
#
all: Makefile configure $(TARGETS)
all: Makefile configure config.h $(TARGETS)
#
......@@ -149,6 +149,8 @@ Makefile: configure Makefile.in
else \
./configure; \
fi
touch config.h
configure: configure.in
autoconf
......@@ -158,6 +160,18 @@ configure: configure.in
else \
./configure; \
fi
touch config.h
config.h: configure config.h.in
autoconf
if test -f config.status; then \
./config.status --recheck; \
./config.status; \
else \
./configure; \
fi
touch config.h
#
......@@ -224,5 +238,5 @@ $(OBJS): Makefile config.h
#
# End of "$Id: Makefile.in,v 1.11 2003/07/20 13:49:09 mike Exp $".
# End of "$Id: Makefile.in,v 1.12 2003/09/28 12:44:39 mike Exp $".
#
/*
* "$Id: config.h.in,v 1.2 2003/07/27 23:11:40 mike Exp $"
* "$Id: config.h.in,v 1.3 2003/09/28 12:44:39 mike Exp $"
*
* Configuration file for mini-XML, a small XML-like file parsing library.
*
......@@ -23,6 +23,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
/*
* Do we have the snprintf() and vsnprintf() functions?
*/
#undef HAVE_SNPRINTF
#undef HAVE_VSNPRINTF
/*
......@@ -30,8 +40,6 @@
*/
#undef HAVE_STRDUP
#undef HAVE_STRLCAT
#undef HAVE_STRLCPY
/*
......@@ -43,7 +51,13 @@ extern char *mxml_strdup(const char *);
# define strdup mxml_strdup
# endif /* !HAVE_STRDUP */
extern char *mxml_strdupf(const char *, va_list);
# ifndef HAVE_VSNPRINTF
extern int mxml_vsnprintf(char *, size_t, const char *, va_list);
# define vsnprintf mxml_vsnprintf
# endif /* !HAVE_VSNPRINTF */
/*
* End of "$Id: config.h.in,v 1.2 2003/07/27 23:11:40 mike Exp $".
* End of "$Id: config.h.in,v 1.3 2003/09/28 12:44:39 mike Exp $".
*/
This diff is collapsed.
dnl
dnl "$Id: configure.in,v 1.7 2003/07/27 23:11:40 mike Exp $"
dnl "$Id: configure.in,v 1.8 2003/09/28 12:44:39 mike Exp $"
dnl
dnl Configuration script for mini-XML, a small XML-like file parsing library.
dnl
......@@ -48,6 +48,10 @@ AC_ARG_WITH(docdir, [ --with-docdir set directory for documentation,
AC_SUBST(docdir)
AC_ARG_WITH(vsnprintf, [ --with-vsnprintf use vsnprintf emulation functions, default=auto],
use_vsnprintf="$withval",
use_vsnprintf="no")
dnl Get the operating system and version number...
uname=`uname`
uversion=`uname -r | sed -e '1,$s/[[^0-9]]//g'`
......@@ -86,12 +90,14 @@ esac
AC_SUBST(ARFLAGS)
dnl Checks for string functions.
AC_CHECK_FUNCS(strlcat strlcpy)
if test "x$use_ansi" != xyes; then
AC_CHECK_FUNCS(strdup)
fi
if test "x$use_vsnprintf" != xyes; then
AC_CHECK_FUNCS(vsnprintf)
fi
dnl Add -Wall for GCC...
if test -n "$GCC"; then
CFLAGS="-Wall $CFLAGS"
......@@ -161,5 +167,5 @@ dnl Output the makefile, etc...
AC_OUTPUT(Makefile mxml.list)
dnl
dnl End of "$Id: configure.in,v 1.7 2003/07/27 23:11:40 mike Exp $".
dnl End of "$Id: configure.in,v 1.8 2003/09/28 12:44:39 mike Exp $".
dnl
......@@ -48,13 +48,22 @@
<li><a href="#mxmlNewOpaque"><tt>mxmlNewOpaque()</tt></a></li>
<li><a href="#mxmlNewReal"><tt>mxmlNewReal()</tt></a></li>
<li><a href="#mxmlNewText"><tt>mxmlNewText()</tt></a></li>
<li><a href="#mxmlNewTextf"><tt>mxmlNewTextf()</tt></a></li>
<li><a href="#mxmlRemove"><tt>mxmlRemove()</tt></a></li>
<li><a href="#mxmlSaveAllocString"><tt>mxmlSaveAllocString()</tt></a></li>
<li><a href="#mxmlSaveFile"><tt>mxmlSaveFile()</tt></a></li>
<li><a href="#mxmlSaveString"><tt>mxmlSaveString()</tt></a></li>
<li><a href="#mxmlSetElement"><tt>mxmlSetElement()</tt></a></li>
<li><a href="#mxmlSetInteger"><tt>mxmlSetInteger()</tt></a></li>
<li><a href="#mxmlSetOpaque"><tt>mxmlSetOpaque()</tt></a></li>
<li><a href="#mxmlSetReal"><tt>mxmlSetReal()</tt></a></li>
<li><a href="#mxmlSetText"><tt>mxmlSetText()</tt></a></li>
<li><a href="#mxmlSetTextf"><tt>mxmlSetTextf()</tt></a></li>
<li><a href="#mxmlWalkNext"><tt>mxmlWalkNext()</tt></a></li>
<li><a href="#mxmlWalkPrev"><tt>mxmlWalkPrev()</tt></a></li>
<li><a href="#mxml_strdup"><tt>mxml_strdup()</tt></a></li>
<li><a href="#mxml_strdupf"><tt>mxml_strdupf()</tt></a></li>
<li><a href="#mxml_vsnprintf"><tt>mxml_vsnprintf()</tt></a></li>
</ul>
<hr noshade/>
<h2><a name="mxmlAdd">mxmlAdd()</a></h2>
......@@ -325,6 +334,29 @@ mxmlNewText(
<h3>Returns</h3>
<p>New node</p>
<hr noshade/>
<h2><a name="mxmlNewTextf">mxmlNewTextf()</a></h2>
<p>Create a new formatted text fragment node.
The new text 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
text node has no parent. The whitespace parameter is used to specify
whether leading whitespace is present before the node. The format
string must be nul-terminated and is formatted into the new node.</p>
<h3>Syntax</h3>
<pre>
<a href="#mxml_node_t">mxml_node_t</a> *
mxmlNewTextf(
<a href="#mxml_node_t">mxml_node_t</a> *parent, int whitespace, const char * format,);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>format,</tt></td><td>Additional args as needed</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>New node</p>
<hr noshade/>
<h2><a name="mxmlRemove">mxmlRemove()</a></h2>
<p>Remove a node from its parent.
......@@ -412,6 +444,120 @@ mxmlSaveString(
<h3>Returns</h3>
<p>Size of string</p>
<hr noshade/>
<h2><a name="mxmlSetElement">mxmlSetElement()</a></h2>
<p>Set the name of an element node.
If the node is not changed if it is not an element node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetElement(
<a href="#mxml_node_t">mxml_node_t</a> *node, const char * name);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>name</tt></td><td>New name string</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlSetInteger">mxmlSetInteger()</a></h2>
<p>Set the value of an integer node.
If the node is not changed if it is not an integer node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetInteger(
<a href="#mxml_node_t">mxml_node_t</a> *node, int integer);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>integer</tt></td><td>Integer value</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlSetOpaque">mxmlSetOpaque()</a></h2>
<p>Set the value of an opaque node.
If the node is not changed if it is not an opaque node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetOpaque(
<a href="#mxml_node_t">mxml_node_t</a> *node, const char * opaque);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>opaque</tt></td><td>Opaque string</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlSetReal">mxmlSetReal()</a></h2>
<p>Set the value of a real number node.
If the node is not changed if it is not a real number node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetReal(
<a href="#mxml_node_t">mxml_node_t</a> *node, double real);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>real</tt></td><td>Real number value</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlSetText">mxmlSetText()</a></h2>
<p>Set the value of a text node.
If the node is not changed if it is not a text node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetText(
<a href="#mxml_node_t">mxml_node_t</a> *node, int whitespace, const char * string);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>string</tt></td><td>String</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlSetTextf">mxmlSetTextf()</a></h2>
<p>Set the value of a text node to a formatted string.
If the node is not changed if it is not a text node.</p>
<h3>Syntax</h3>
<pre>
int
mxmlSetTextf(
<a href="#mxml_node_t">mxml_node_t</a> *node, int whitespace, const char * format,);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>format,</tt></td><td>Additional arguments as needed</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>0 on success, -1 on failure</p>
<hr noshade/>
<h2><a name="mxmlWalkNext">mxmlWalkNext()</a></h2>
<p>Walk to the next logical node in the tree.
......@@ -470,6 +616,40 @@ mxml_strdup(
</tbody></table></p>
<h3>Returns</h3>
<p>New string pointer</p>
<hr noshade/>
<h2><a name="mxml_strdupf">mxml_strdupf()</a></h2>
<p>Format and duplicate a string.</p>
<h3>Syntax</h3>
<pre>
char *
mxml_strdupf(
const char *format, va_list ap);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>ap</tt></td><td>Pointer to additional arguments</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>New string pointer</p>
<hr noshade/>
<h2><a name="mxml_vsnprintf">mxml_vsnprintf()</a></h2>
<p>Format a string into a fixed size buffer.</p>
<h3>Syntax</h3>
<pre>
int
mxml_vsnprintf(
char *buffer, size_t bufsize, const char *format, va_list ap);
</pre>
<h3>Arguments</h3>
<p class="table"><table align="center" border="1" width="80%">
<thead><tr><th>Name</th><th>Description</th></tr></thead>
<tbody>
<tr><td><tt>ap</tt></td><td>Pointer to additional arguments</td></tr>
</tbody></table></p>
<h3>Returns</h3>
<p>Number of bytes formatted</p>
<h1><a name="_structures">Structures</a></h1>
<ul>
<li><a href="#mxml_attr_s"><tt>mxml_attr_s</tt></a></li>
......
......@@ -16,11 +16,11 @@ href="../index.html">Back to Home Page</a>&nbsp;]</p>
<h1 class="title" align="center">Mini-XML Home Page</h1>
<p class="title" align="center">Current Release: v1.1.2, July 25, 2003<br/>
<p class="title" align="center">Current Release: v1.2, September 28, 2003<br/>
[&nbsp;<a
href="mxml-1.1.2.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;70k)</a>
href="mxml-1.2.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;70k)</a>
| <a
href="mxml-1.1.2-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;64k)</a>
href="mxml-1.2-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;64k)</a>
| <a href="CHANGES">Change&nbsp;Log</a> | <a
href="documentation.html">Documentation</a> | <a
href="http://freshmeat.net/projects/mxml">Rate/Make&nbsp;Comments</A>&nbsp;]</p>
......
/*
* "$Id: mxml-node.c,v 1.7 2003/07/27 23:11:40 mike Exp $"
* "$Id: mxml-node.c,v 1.8 2003/09/28 12:44:39 mike Exp $"
*
* Node support code for mini-XML, a small XML-like file parsing library.
*
......@@ -24,7 +24,14 @@
* mxmlNewOpaque() - Create a new opaque string.
* mxmlNewReal() - Create a new real number node.
* mxmlNewText() - Create a new text fragment node.
* mxmlNewTextf() - Create a new formatted text fragment node.
* mxmlRemove() - Remove a node from its parent.
* mxmlSetElement() - Set the name of an element node.
* mxmlSetInteger() - Set the value of an integer node.
* mxmlSetOpaque() - Set the value of an opaque node.
* mxmlSetReal() - Set the value of a real number node.
* mxmlSetText() - Set the value of a text node.
* mxmlSetTextf() - Set the value of a text node to a formatted string.
* mxml_new() - Create a new node.
*/
......@@ -411,6 +418,51 @@ mxmlNewText(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
}
/*
* 'mxmlNewTextf()' - Create a new formatted text fragment node.
*
* The new text 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
* text node has no parent. The whitespace parameter is used to specify
* whether leading whitespace is present before the node. The format
* string must be nul-terminated and is formatted into the new node.
*/
mxml_node_t * /* O - New node */
mxmlNewTextf(mxml_node_t *parent, /* I - Parent node or MXML_NO_PARENT */
int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
const char *format, /* I - Printf-style frmat string */
...) /* I - Additional args as needed */
{
mxml_node_t *node; /* New node */
va_list ap; /* Pointer to arguments */
/*
* Range check input...
*/
if (!parent || !format)
return (NULL);
/*
* Create the node and set the text value...
*/
if ((node = mxml_new(parent, MXML_TEXT)) != NULL)
{
va_start(ap, format);
node->value.text.whitespace = whitespace;
node->value.text.string = mxml_strdupf(format, ap);
va_end(ap);
}
return (node);
}
/*
* 'mxmlRemove()' - Remove a node from its parent.
*
......@@ -450,6 +502,192 @@ mxmlRemove(mxml_node_t *node) /* I - Node to remove */
}
/*
* 'mxmlSetElement()' - Set the name of an element node.
*
* If the node is not changed if it is not an element node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetElement(mxml_node_t *node, /* I - Node to set */
const char *name) /* I - New name string */
{
/*
* Range check input...
*/
if (!node || node->type != MXML_ELEMENT || !name)
return (-1);
/*
* Free any old element value and set the new value...
*/
if (node->value.element.name)
free(node->value.element.name);
node->value.element.name = strdup(name);
return (0);
}
/*
* 'mxmlSetInteger()' - Set the value of an integer node.
*
* If the node is not changed if it is not an integer node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetInteger(mxml_node_t *node, /* I - Node to set */
int integer) /* I - Integer value */
{
/*
* Range check input...
*/
if (!node || node->type != MXML_INTEGER)
return (-1);
/*
* Set the new value and return...
*/
node->value.integer = integer;
return (0);
}
/*
* 'mxmlSetOpaque()' - Set the value of an opaque node.
*
* If the node is not changed if it is not an opaque node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetOpaque(mxml_node_t *node, /* I - Node to set */
const char *opaque) /* I - Opaque string */
{
/*
* Range check input...
*/
if (!node || node->type != MXML_OPAQUE || !opaque)
return (-1);
/*
* Free any old opaque value and set the new value...
*/
if (node->value.opaque)
free(node->value.opaque);
node->value.opaque = strdup(opaque);
return (0);
}
/*
* 'mxmlSetReal()' - Set the value of a real number node.
*
* If the node is not changed if it is not a real number node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetReal(mxml_node_t *node, /* I - Node to set */
double real) /* I - Real number value */
{
/*
* Range check input...
*/
if (!node || node->type != MXML_REAL)
return (-1);
/*
* Set the new value and return...
*/
node->value.real = real;
return (0);
}
/*
* 'mxmlSetText()' - Set the value of a text node.
*
* If the node is not changed if it is not a text node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetText(mxml_node_t *node, /* I - Node to set */
int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
const char *string) /* I - String */
{
/*
* Range check input...
*/
if (!node || node->type != MXML_TEXT || !string)
return (-1);
/*
* Free any old string value and set the new value...
*/
if (node->value.text.string)
free(node->value.text.string);
node->value.text.whitespace = whitespace;
node->value.text.string = strdup(string);
return (0);
}
/*
* 'mxmlSetTextf()' - Set the value of a text node to a formatted string.
*
* If the node is not changed if it is not a text node.
*/
int /* O - 0 on success, -1 on failure */
mxmlSetTextf(mxml_node_t *node, /* I - Node to set */
int whitespace, /* I - 1 = leading whitespace, 0 = no whitespace */
const char *format, /* I - Printf-style format string */
...) /* I - Additional arguments as needed */
{
va_list ap; /* Pointer to arguments */
/*
* Range check input...
*/
if (!node || node->type != MXML_TEXT || !format)
return (-1);
/*
* Free any old string value and set the new value...
*/
if (node->value.text.string)
free(node->value.text.string);
va_start(ap, format);
node->value.text.whitespace = whitespace;
node->value.text.string = mxml_strdupf(format, ap);
va_end(ap);
return (0);
}
/*
* 'mxml_new()' - Create a new node.
*/
......@@ -490,5 +728,5 @@ mxml_new(mxml_node_t *parent, /* I - Parent node */
/*
* End of "$Id: mxml-node.c,v 1.7 2003/07/27 23:11:40 mike Exp $".
* End of "$Id: mxml-node.c,v 1.8 2003/09/28 12:44:39 mike Exp $".
*/
/*
* "$Id: mxml-string.c,v 1.1 2003/07/20 13:41:17 mike Exp $"
* "$Id: mxml-string.c,v 1.2 2003/09/28 12:44:39 mike Exp $"
*
* String functions for mini-XML, a small XML-like file parsing library.
*
......@@ -17,7 +17,8 @@
*
* Contents:
*
* mxml_strdup() - Duplicate a string.
* mxml_strdup() - Duplicate a string.
* mxml_vsnprintf() - Format a string into a fixed size buffer.
*/
/*
......@@ -32,10 +33,10 @@
*/
#ifndef HAVE_STRDUP
char * /* O - New string pointer */
mxml_strdup(const char *s) /* I - String to duplicate */
char * /* O - New string pointer */
mxml_strdup(const char *s) /* I - String to duplicate */
{
char *t; /* New string pointer */
char *t; /* New string pointer */
if (s == NULL)
......@@ -50,5 +51,326 @@ mxml_strdup(const char *s) /* I - String to duplicate */
/*
* End of "$Id: mxml-string.c,v 1.1 2003/07/20 13:41:17 mike Exp $".
* 'mxml_strdupf()' - Format and duplicate a string.
*/
char * /* O - New string pointer */
mxml_strdupf(const char *format, /* I - Printf-style format string */
va_list ap) /* I - Pointer to additional arguments */
{
int bytes; /* Number of bytes required */
char *buffer, /* String buffer */
temp[256]; /* Small buffer for first vsnprintf */
/*
* First format with a tiny buffer; this will tell us how many bytes are
* needed...
*/
bytes = vsnprintf(temp, sizeof(temp), format, ap);
if (bytes < sizeof(temp))
{
/*
* Hey, the formatted string fits in the tiny buffer, so just dup that...
*/
return (strdup(temp));
}
/*
* Allocate memory for the whole thing and reformat to the new, larger
* buffer...
*/
if ((buffer = calloc(1, bytes + 1)) != NULL)
vsnprintf(buffer, bytes + 1, format, ap);
/*
* Return the new string...
*/
return (buffer);
}
#ifndef HAVE_VSNPRINTF
/*
* 'mxml_vsnprintf()' - Format a string into a fixed size buffer.
*/
int /* O - Number of bytes formatted */
mxml_vsnprintf(char *buffer, /* O - Output buffer */
size_t bufsize, /* O - Size of output buffer */
const char *format, /* I - Printf-style format string */
va_list ap) /* I - Pointer to additional arguments */
{
char *bufptr, /* Pointer to position in buffer */
*bufend, /* Pointer to end of buffer */
sign, /* Sign of format width */
size, /* Size character (h, l, L) */
type; /* Format type character */
const char *bufformat; /* Start of format */
int width, /* Width of field */
prec; /* Number of characters of precision */
char tformat[100], /* Temporary format string for sprintf() */
temp[1024]; /* Buffer for formatted numbers */
char *s; /* Pointer to string */
int slen; /* Length of string */
int bytes; /* Total number of bytes needed */
/*
* Loop through the format string, formatting as needed...
*/
bufptr = buffer;
bufend = buffer + bufsize - 1;
bytes = 0;
while (*format)
{