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.
This commit is contained in:
Michael R Sweet 2003-09-28 12:44:39 +00:00
parent c02f86dd83
commit 337baeddb5
11 changed files with 1480 additions and 334 deletions

11
CHANGES
View File

@ -1,12 +1,19 @@
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

View File

@ -1,5 +1,5 @@
#
# "$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 $".
#

View File

@ -1,5 +1,5 @@
/*
* "$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 $".
*/

893
configure vendored

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
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

View File

@ -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>

View File

@ -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>

View File

@ -1,5 +1,5 @@
/*
* "$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 $".
*/

View File

@ -1,5 +1,5 @@
/*
* "$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)
{
if (*format == '%')
{
bufformat = format;
format ++;
if (*format == '%')
{
*bufptr++ = *format++;
continue;
}
else if (strchr(" -+#\'", *format))
sign = *format++;
else
sign = 0;
width = 0;
while (isdigit(*format))
width = width * 10 + *format++ - '0';
if (*format == '.')
{
format ++;
prec = 0;
while (isdigit(*format))
prec = prec * 10 + *format++ - '0';
}
else
prec = -1;
if (*format == 'l' && format[1] == 'l')
{
size = 'L';
format += 2;
}
else if (*format == 'h' || *format == 'l' || *format == 'L')
size = *format++;
if (!*format)
break;
type = *format++;
switch (type)
{
case 'E' : /* Floating point formats */
case 'G' :
case 'e' :
case 'f' :
case 'g' :
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, double));
bytes += strlen(temp);
if (bufptr)
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
}
else
{
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'B' : /* Integer formats */
case 'X' :
case 'b' :
case 'd' :
case 'i' :
case 'o' :
case 'u' :
case 'x' :
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
if (bufptr)
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
}
else
{
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'p' : /* Pointer value */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, void *));
bytes += strlen(temp);
if (bufptr)
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
}
else
{
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
case 'c' : /* Character or character array */
bytes += width;
if (bufptr)
{
if (width <= 1)
*bufptr++ = va_arg(ap, int);
else
{
if ((bufptr + width) > bufend)
width = bufend - bufptr;
memcpy(bufptr, va_arg(ap, char *), width);
bufptr += width;
}
}
break;
case 's' : /* String */
if ((s = va_arg(ap, char *)) == NULL)
s = "(null)";
slen = strlen(s);
if (slen > width && prec != width)
width = slen;
bytes += width;
if (bufptr)
{
if ((bufptr + width) > bufend)
width = bufend - bufptr;
if (slen > width)
slen = width;
if (sign == '-')
{
strncpy(bufptr, s, slen);
memset(bufptr + slen, ' ', width - slen);
}
else
{
memset(bufptr, ' ', width - slen);
strncpy(bufptr + width - slen, s, slen);
}
bufptr += width;
}
break;
case 'n' : /* Output number of chars so far */
if ((format - bufformat + 1) > sizeof(tformat) ||
(width + 2) > sizeof(temp))
break;
strncpy(tformat, bufformat, format - bufformat);
tformat[format - bufformat] = '\0';
sprintf(temp, tformat, va_arg(ap, int));
bytes += strlen(temp);
if (bufptr)
{
if ((bufptr + strlen(temp)) > bufend)
{
strncpy(bufptr, temp, bufend - bufptr);
bufptr = bufend;
break;
}
else
{
strcpy(bufptr, temp);
bufptr += strlen(temp);
}
}
break;
}
}
else
{
bytes ++;
if (bufptr && bufptr < bufend)
*bufptr++ = *format++;
}
}
/*
* Nul-terminate the string and return the number of characters needed.
*/
*bufptr = '\0';
return (bytes);
}
#endif /* !HAVE_VSNPRINTF */
/*
* End of "$Id: mxml-string.c,v 1.2 2003/09/28 12:44:39 mike Exp $".
*/

31
mxml.h
View File

@ -1,5 +1,5 @@
/*
* "$Id: mxml.h,v 1.12 2003/07/22 10:29:19 mike Exp $"
* "$Id: mxml.h,v 1.13 2003/09/28 12:44:39 mike Exp $"
*
* Header file for mini-XML, a small XML-like file parsing library.
*
@ -42,6 +42,8 @@
# define MXML_TAB 8 /* Tabs every N columns */
# define MXML_NO_CALLBACK 0 /* Don't use a type callback */
# define MXML_OPAQUE_CALLBACK _mxml_opaque_cb
/* Treat all data as opaque */
# define MXML_NO_PARENT 0 /* No parent for the node */
# define MXML_DESCEND 1 /* Descend when finding/walking */
@ -144,6 +146,12 @@ extern mxml_node_t *mxmlNewOpaque(mxml_node_t *parent, const char *opaque);
extern mxml_node_t *mxmlNewReal(mxml_node_t *parent, double real);
extern mxml_node_t *mxmlNewText(mxml_node_t *parent, int whitespace,
const char *string);
extern mxml_node_t *mxmlNewTextf(mxml_node_t *parent, int whitespace,
const char *format, ...)
# ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 3, 4)))
# endif /* __GNUC__ */
;
extern void mxmlRemove(mxml_node_t *node);
extern char *mxmlSaveAllocString(mxml_node_t *node,
int (*cb)(mxml_node_t *, int));
@ -152,12 +160,31 @@ extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
extern int mxmlSaveString(mxml_node_t *node, char *buffer,
int bufsize,
int (*cb)(mxml_node_t *, int));
extern int mxmlSetElement(mxml_node_t *node, const char *name);
extern int mxmlSetInteger(mxml_node_t *node, int integer);
extern int mxmlSetOpaque(mxml_node_t *node, const char *opaque);
extern int mxmlSetReal(mxml_node_t *node, double real);
extern int mxmlSetText(mxml_node_t *node, int whitespace,
const char *string);
extern int mxmlSetTextf(mxml_node_t *node, int whitespace,
const char *format, ...)
# ifdef __GNUC__
__attribute__ ((__format__ (__printf__, 3, 4)))
# endif /* __GNUC__ */
;
extern mxml_node_t *mxmlWalkNext(mxml_node_t *node, mxml_node_t *top,
int descend);
extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
int descend);
/*
* Private functions...
*/
extern mxml_type_t _mxml_opaque_cb(mxml_node_t *node);
/*
* C++ support...
*/
@ -169,5 +196,5 @@ extern mxml_node_t *mxmlWalkPrev(mxml_node_t *node, mxml_node_t *top,
/*
* End of "$Id: mxml.h,v 1.12 2003/07/22 10:29:19 mike Exp $".
* End of "$Id: mxml.h,v 1.13 2003/09/28 12:44:39 mike Exp $".
*/

View File

@ -123,6 +123,18 @@ string must be nul-terminated and is copied into the new node.</description><arg
name="string" direction="I"><type>mxml_node_t *parent, int whitespace, const
char *</type><description>String</description></argument>
</function>
<function name="mxmlNewTextf"><returnvalue><description>New node</description><type>mxml_node_t
*</type></returnvalue>
<description>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.</description><argument
name="format," direction="I"><type>mxml_node_t *parent, int whitespace, const
char *</type><description>Additional args as needed</description></argument>
</function>
<function name="mxmlRemove"><description>Remove a node from its parent.
Does not free memory used by the node - use mxmlDelete() for that.
@ -161,6 +173,44 @@ into the specified buffer.</description><argument
name="(*cb)(mxml_node_t *node, int ws)" direction="I"><type>mxml_node_t *node,
char *buffer, int bufsize, int</type><description>Whitespace callback or MXML_NO_CALLBACK</description></argument>
</function>
<function name="mxmlSetElement"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the name of an element node.
If the node is not changed if it is not an element node.</description><argument
name="name" direction="I"><type>mxml_node_t *node, const char *</type><description>New name string</description></argument>
</function>
<function name="mxmlSetInteger"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the value of an integer node.
If the node is not changed if it is not an integer node.</description><argument
name="integer" direction="I"><type>mxml_node_t *node, int</type><description>Integer value</description></argument>
</function>
<function name="mxmlSetOpaque"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the value of an opaque node.
If the node is not changed if it is not an opaque node.</description><argument
name="opaque" direction="I"><type>mxml_node_t *node, const char *</type><description>Opaque string</description></argument>
</function>
<function name="mxmlSetReal"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the value of a real number node.
If the node is not changed if it is not a real number node.</description><argument
name="real" direction="I"><type>mxml_node_t *node, double</type><description>Real number value</description></argument>
</function>
<function name="mxmlSetText"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the value of a text node.
If the node is not changed if it is not a text node.</description><argument
name="string" direction="I"><type>mxml_node_t *node, int whitespace, const
char *</type><description>String</description></argument>
</function>
<function name="mxmlSetTextf"><returnvalue><description>0 on success, -1 on failure</description><type>int</type></returnvalue>
<description>Set the value of a text node to a formatted string.
If the node is not changed if it is not a text node.</description><argument
name="format," direction="I"><type>mxml_node_t *node, int whitespace, const
char *</type><description>Additional arguments as needed</description></argument>
</function>
<function name="mxmlWalkNext"><returnvalue><description>Next node or NULL</description><type>mxml_node_t
*</type></returnvalue>
<description>Walk to the next logical node in the tree.
@ -202,6 +252,11 @@ name="child"><type>mxml_node_t *</type><description>First child node</descriptio
<description>Duplicate a string.</description><argument name="s"
direction="I"><type>const char *</type><description>String to duplicate</description></argument>
</function>
<function name="mxml_strdupf"><returnvalue><description>New string pointer</description><type>char
*</type></returnvalue>
<description>Format and duplicate a string.</description><argument
name="ap" direction="I"><type>const char *format, va_list</type><description>Pointer to additional arguments</description></argument>
</function>
<struct name="mxml_text_s"><description>An XML text value.</description><variable
name="string"><type>char *</type><description>Fragment string</description></variable>
<variable name="whitespace"><type>int</type><description>Leading whitespace?</description></variable>
@ -230,4 +285,8 @@ name="element"><type>mxml_element_t</type><description>Element</description></va
<variable name="opaque"><type>char *</type><description>Opaque string</description></variable>
<variable name="real"><type>double</type><description>Real number</description></variable>
<variable name="text"><type>mxml_text_t</type><description>Text fragment</description></variable>
</union>
</union><function name="mxml_vsnprintf"><returnvalue><description>Number of bytes formatted</description><type>int</type></returnvalue>
<description>Format a string into a fixed size buffer.</description><argument
name="ap" direction="I"><type>char *buffer, size_t bufsize, const char *format,
va_list</type><description>Pointer to additional arguments</description></argument>
</function>