mirror of
https://github.com/michaelrsweet/mxml.git
synced 2025-02-20 17:35:30 +00:00
Add new mxmlLoadFd() and mxmlSaveFd() functions.
This commit is contained in:
parent
666dd31820
commit
3cc3f8a63d
9
CHANGES
9
CHANGES
@ -1,5 +1,10 @@
|
||||
CHANGES - 06/25/2004
|
||||
-------------------
|
||||
CHANGES - 07/11/2004
|
||||
--------------------
|
||||
|
||||
CHANGES IN Mini-XML 2.1
|
||||
|
||||
- Added mxmlLoadFd() and mxmlSaveFd() functions.
|
||||
|
||||
|
||||
CHANGES IN Mini-XML 2.0
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
|
||||
<head>
|
||||
<title>Documentation</title>
|
||||
<meta name='creator' content='Mini-XML v2.0rc1'/>
|
||||
<meta name='creator' content='Mini-XML v2.0'/>
|
||||
<style><!--
|
||||
h1, h2, h3, p { font-family: sans-serif; text-align: justify; }
|
||||
tt, pre a:link, pre a:visited, tt a:link, tt a:visited { font-weight: bold; color: #7f0000; }
|
||||
@ -56,6 +56,7 @@
|
||||
<li><a href='#mxmlIndexFind'><tt>mxmlIndexFind()</tt></a></li>
|
||||
<li><a href='#mxmlIndexNew'><tt>mxmlIndexNew()</tt></a></li>
|
||||
<li><a href='#mxmlIndexReset'><tt>mxmlIndexReset()</tt></a></li>
|
||||
<li><a href='#mxmlLoadFd'><tt>mxmlLoadFd()</tt></a></li>
|
||||
<li><a href='#mxmlLoadFile'><tt>mxmlLoadFile()</tt></a></li>
|
||||
<li><a href='#mxmlLoadString'><tt>mxmlLoadString()</tt></a></li>
|
||||
<li><a href='#mxmlNewElement'><tt>mxmlNewElement()</tt></a></li>
|
||||
@ -66,6 +67,7 @@
|
||||
<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='#mxmlSaveFd'><tt>mxmlSaveFd()</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>
|
||||
@ -424,6 +426,40 @@ mxmlIndexReset(
|
||||
<h4>Returns</h4>
|
||||
<p>First node or NULL if there is none</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlLoadFd'>mxmlLoadFd()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Load a file descriptor into an XML node tree.
|
||||
|
||||
The nodes in the specified file are added to the specified top node.
|
||||
If no top node is provided, the XML file MUST be well-formed with a
|
||||
single parent node like <?xml> for the entire file. The callback
|
||||
function returns the value type that should be used for child nodes.
|
||||
If MXML_NO_CALLBACK is specified then all child nodes will be either
|
||||
MXML_ELEMENT or MXML_TEXT nodes.
|
||||
|
||||
The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
|
||||
MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
|
||||
child nodes of the specified type.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> *
|
||||
mxmlLoadFd(
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> * top,
|
||||
int fd,
|
||||
<a href='#mxml_type_t'>mxml_type_t</a> (*cb)(mxml_node_t *node));
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>top</tt></td><td>Top node</td></tr>
|
||||
<tr><td><tt>fd</tt></td><td>File descriptor to read from</td></tr>
|
||||
<tr><td><tt>(*cb)(mxml_node_t *node)</tt></td><td>Callback function or MXML_NO_CALLBACK</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>First node or NULL if the file could not be read.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlLoadFile'>mxmlLoadFile()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -684,7 +720,13 @@ This function returns a pointer to a string containing the textual
|
||||
representation of the XML node tree. The string should be freed
|
||||
using the free() function when you are done with it. NULL is returned
|
||||
if the node would produce an empty string or if the string cannot be
|
||||
allocated.</p>
|
||||
allocated.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
char *
|
||||
@ -702,13 +744,42 @@ mxmlSaveAllocString(
|
||||
<h4>Returns</h4>
|
||||
<p>Allocated string or NULL</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlSaveFd'>mxmlSaveFd()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Save an XML tree to a file descriptor.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
int
|
||||
mxmlSaveFd(
|
||||
<a href='#mxml_node_t'>mxml_node_t</a> * node,
|
||||
int fd,
|
||||
const char * (*cb)(mxml_node_t *node, int ws));
|
||||
</pre>
|
||||
<h4>Arguments</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>node</tt></td><td>Node to write</td></tr>
|
||||
<tr><td><tt>fd</tt></td><td>File descriptor to write to</td></tr>
|
||||
<tr><td><tt>(*cb)(mxml_node_t *node, int ws)</tt></td><td>Whitespace callback or MXML_NO_CALLBACK</td></tr>
|
||||
</tbody></table></p>
|
||||
<h4>Returns</h4>
|
||||
<p>0 on success, -1 on error.</p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxmlSaveFile'>mxmlSaveFile()</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>Save an XML tree to a file.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
character or nul (0) before and after each element. If MXML_NO_CALLBACK
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</p>
|
||||
@ -738,7 +809,13 @@ mxmlSaveFile(
|
||||
|
||||
This function returns the total number of bytes that would be
|
||||
required for the string but only copies (bufsize - 1) characters
|
||||
into the specified buffer.</p>
|
||||
into the specified buffer.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</p>
|
||||
<h4>Syntax</h4>
|
||||
<pre>
|
||||
int
|
||||
@ -980,6 +1057,7 @@ mxmlWalkPrev(
|
||||
<h2><a name='_structures'>Structures</a></h2>
|
||||
<ul>
|
||||
<li><a href='#mxml_attr_s'><tt>mxml_attr_s</tt></a></li>
|
||||
<li><a href='#mxml_fdbuf_s'><tt>mxml_fdbuf_s</tt></a></li>
|
||||
<li><a href='#mxml_index_s'><tt>mxml_index_s</tt></a></li>
|
||||
<li><a href='#mxml_node_s'><tt>mxml_node_s</tt></a></li>
|
||||
<li><a href='#mxml_text_s'><tt>mxml_text_s</tt></a></li>
|
||||
@ -1006,6 +1084,28 @@ struct mxml_attr_s
|
||||
<tr><td><tt>value</tt></td><td>Attribute value</td></tr>
|
||||
</tbody></table></p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_fdbuf_s'>mxml_fdbuf_s</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>File descriptor buffer (@private)</p>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
struct mxml_fdbuf_s
|
||||
{
|
||||
end buffer[8192];
|
||||
unsigned char * current;
|
||||
int fd;
|
||||
};
|
||||
</pre>
|
||||
<h4>Members</h4>
|
||||
<p class='table'><table align='center' border='1' width='80%' cellpadding='5' cellspacing='0' width='80%'>
|
||||
<thead><tr bgcolor='#cccccc'><th>Name</th><th>Description</th></tr></thead>
|
||||
<tbody>
|
||||
<tr><td><tt>buffer[8192]</tt></td><td>Character buffer</td></tr>
|
||||
<tr><td><tt>current</tt></td><td>Current position in buffer</td></tr>
|
||||
<tr><td><tt>fd</tt></td><td>File descriptor</td></tr>
|
||||
</tbody></table></p>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_index_s'>mxml_index_s</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
@ -1108,6 +1208,7 @@ struct mxml_value_s
|
||||
<ul>
|
||||
<li><a href='#mxml_attr_t'><tt>mxml_attr_t</tt></a></li>
|
||||
<li><a href='#mxml_element_t'><tt>mxml_element_t</tt></a></li>
|
||||
<li><a href='#mxml_fdbuf_t'><tt>mxml_fdbuf_t</tt></a></li>
|
||||
<li><a href='#mxml_index_t'><tt>mxml_index_t</tt></a></li>
|
||||
<li><a href='#mxml_node_t'><tt>mxml_node_t</tt></a></li>
|
||||
<li><a href='#mxml_text_t'><tt>mxml_text_t</tt></a></li>
|
||||
@ -1133,6 +1234,15 @@ typedef struct <a href='#mxml_attr_s'>mxml_attr_s</a> mxml_attr_t;
|
||||
typedef struct <a href='#mxml_value_s'>mxml_value_s</a> mxml_element_t;
|
||||
</pre>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_fdbuf_t'>mxml_fdbuf_t</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
<p>File descriptor buffer (@private)</p>
|
||||
<h4>Definition</h4>
|
||||
<pre>
|
||||
typedef struct <a href='#mxml_fdbuf_s'>mxml_fdbuf_s</a> mxml_fdbuf_t;
|
||||
</pre>
|
||||
<!-- NEW PAGE -->
|
||||
<h3><a name='mxml_index_t'>mxml_index_t</a></h3>
|
||||
<hr noshade/>
|
||||
<h4>Description</h4>
|
||||
|
@ -3,6 +3,14 @@
|
||||
|
||||
<h1 align='right'><a name='RELNOTES'>B - Release Notes</a></h1>
|
||||
|
||||
<h2>Changes in Mini-XML 2.1</h2>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Added mxmlLoadFd() and mxmlSaveFd() functions.
|
||||
|
||||
</ul>
|
||||
|
||||
<h2>Changes in Mini-XML 2.0</h2>
|
||||
|
||||
<ul>
|
||||
|
630
mxml-file.c
630
mxml-file.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* "$Id: mxml-file.c,v 1.33 2004/06/25 18:52:34 mike Exp $"
|
||||
* "$Id: mxml-file.c,v 1.34 2004/07/11 13:14:07 mike Exp $"
|
||||
*
|
||||
* File loading code for Mini-XML, a small XML-like file parsing library.
|
||||
*
|
||||
@ -17,16 +17,22 @@
|
||||
*
|
||||
* Contents:
|
||||
*
|
||||
* mxmlLoadFd() - Load a file descriptor into an XML node tree.
|
||||
* mxmlLoadFile() - Load a file into an XML node tree.
|
||||
* mxmlLoadString() - Load a string into an XML node tree.
|
||||
* mxmlSaveAllocString() - Save an XML node tree to an allocated string.
|
||||
* mxmlSaveFd() - Save an XML tree to a file descriptor.
|
||||
* mxmlSaveFile() - Save an XML tree to a file.
|
||||
* mxmlSaveString() - Save an XML node tree to a string.
|
||||
* mxmlSetErrorCallback() - Set the error message callback.
|
||||
* mxml_add_char() - Add a character to a buffer, expanding as needed.
|
||||
* mxml_get_entity() - Get the character corresponding to an entity...
|
||||
* mxml_fd_getc() - Read a character from a file descriptor.
|
||||
* mxml_fd_putc() - Write a character to a file descriptor.
|
||||
* mxml_fd_read() - Read a buffer of data from a file descriptor.
|
||||
* mxml_fd_write() - Write a buffer of data to a file descriptor.
|
||||
* mxml_file_getc() - Get a character from a file.
|
||||
* mxml_file_putc() - Write a character to a file.
|
||||
* mxml_get_entity() - Get the character corresponding to an entity...
|
||||
* mxml_load_data() - Load data into an XML node tree.
|
||||
* mxml_parse_element() - Parse an element for any attributes...
|
||||
* mxml_string_getc() - Get a character from a string.
|
||||
@ -42,6 +48,11 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "mxml.h"
|
||||
#ifdef WIN32
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
/*
|
||||
@ -53,6 +64,19 @@
|
||||
#define ENCODE_UTF16LE 2 /* UTF-16 Little-Endian */
|
||||
|
||||
|
||||
/*
|
||||
* File descriptor buffer...
|
||||
*/
|
||||
|
||||
typedef struct mxml_fdbuf_s /**** File descriptor buffer (@private) ****/
|
||||
{
|
||||
int fd; /* File descriptor */
|
||||
unsigned char *current, /* Current position in buffer */
|
||||
*end, /* End of buffer */
|
||||
buffer[8192]; /* Character buffer */
|
||||
} mxml_fdbuf_t;
|
||||
|
||||
|
||||
/*
|
||||
* Global error handler...
|
||||
*/
|
||||
@ -66,11 +90,15 @@ extern void (*mxml_error_cb)(const char *);
|
||||
|
||||
static int mxml_add_char(int ch, char **ptr, char **buffer,
|
||||
int *bufsize);
|
||||
static int mxml_fd_getc(void *p, int *encoding);
|
||||
static int mxml_fd_putc(int ch, void *p);
|
||||
static int mxml_fd_read(mxml_fdbuf_t *buf);
|
||||
static int mxml_fd_write(mxml_fdbuf_t *buf);
|
||||
static int mxml_file_getc(void *p, int *encoding);
|
||||
static int mxml_file_putc(int ch, void *p);
|
||||
static int mxml_get_entity(mxml_node_t *parent, void *p,
|
||||
int *encoding,
|
||||
int (*getc_cb)(void *, int *));
|
||||
static int mxml_file_getc(void *p, int *encoding);
|
||||
static int mxml_file_putc(int ch, void *p);
|
||||
static mxml_node_t *mxml_load_data(mxml_node_t *top, void *p,
|
||||
mxml_type_t (*cb)(mxml_node_t *),
|
||||
int (*getc_cb)(void *, int *));
|
||||
@ -92,6 +120,46 @@ static int mxml_write_ws(mxml_node_t *node, void *p,
|
||||
int col, int (*putc_cb)(int, void *));
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlLoadFd()' - Load a file descriptor into an XML node tree.
|
||||
*
|
||||
* The nodes in the specified file are added to the specified top node.
|
||||
* If no top node is provided, the XML file MUST be well-formed with a
|
||||
* single parent node like <?xml> for the entire file. The callback
|
||||
* function returns the value type that should be used for child nodes.
|
||||
* If MXML_NO_CALLBACK is specified then all child nodes will be either
|
||||
* MXML_ELEMENT or MXML_TEXT nodes.
|
||||
*
|
||||
* The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
|
||||
* MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
|
||||
* child nodes of the specified type.
|
||||
*/
|
||||
|
||||
mxml_node_t * /* O - First node or NULL if the file could not be read. */
|
||||
mxmlLoadFd(mxml_node_t *top, /* I - Top node */
|
||||
int fd, /* I - File descriptor to read from */
|
||||
mxml_type_t (*cb)(mxml_node_t *node))
|
||||
/* I - Callback function or MXML_NO_CALLBACK */
|
||||
{
|
||||
mxml_fdbuf_t buf; /* File descriptor buffer */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the file descriptor buffer...
|
||||
*/
|
||||
|
||||
buf.fd = fd;
|
||||
buf.current = buf.buffer;
|
||||
buf.end = buf.buffer;
|
||||
|
||||
/*
|
||||
* Read the XML data...
|
||||
*/
|
||||
|
||||
return (mxml_load_data(top, &buf, cb, mxml_fd_getc));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlLoadFile()' - Load a file into an XML node tree.
|
||||
*
|
||||
@ -113,6 +181,10 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
|
||||
mxml_type_t (*cb)(mxml_node_t *node))
|
||||
/* I - Callback function or MXML_NO_CALLBACK */
|
||||
{
|
||||
/*
|
||||
* Read the XML data...
|
||||
*/
|
||||
|
||||
return (mxml_load_data(top, fp, cb, mxml_file_getc));
|
||||
}
|
||||
|
||||
@ -138,6 +210,10 @@ mxmlLoadString(mxml_node_t *top, /* I - Top node */
|
||||
mxml_type_t (*cb)(mxml_node_t *node))
|
||||
/* I - Callback function or MXML_NO_CALLBACK */
|
||||
{
|
||||
/*
|
||||
* Read the XML data...
|
||||
*/
|
||||
|
||||
return (mxml_load_data(top, &s, cb, mxml_string_getc));
|
||||
}
|
||||
|
||||
@ -150,6 +226,12 @@ mxmlLoadString(mxml_node_t *top, /* I - Top node */
|
||||
* using the free() function when you are done with it. NULL is returned
|
||||
* if the node would produce an empty string or if the string cannot be
|
||||
* allocated.
|
||||
*
|
||||
* The callback argument specifies a function that returns a whitespace
|
||||
* string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
* is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
* with leading whitespace and before attribute names inside opening
|
||||
* element tags.
|
||||
*/
|
||||
|
||||
char * /* O - Allocated string or NULL */
|
||||
@ -199,11 +281,58 @@ mxmlSaveAllocString(mxml_node_t *node, /* I - Node to write */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlSaveFd()' - Save an XML tree to a file descriptor.
|
||||
*
|
||||
* The callback argument specifies a function that returns a whitespace
|
||||
* string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
* is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
* with leading whitespace and before attribute names inside opening
|
||||
* element tags.
|
||||
*/
|
||||
|
||||
int /* O - 0 on success, -1 on error. */
|
||||
mxmlSaveFd(mxml_node_t *node, /* I - Node to write */
|
||||
int fd, /* I - File descriptor to write to */
|
||||
const char *(*cb)(mxml_node_t *node, int ws))
|
||||
/* I - Whitespace callback or MXML_NO_CALLBACK */
|
||||
{
|
||||
int col; /* Final column */
|
||||
mxml_fdbuf_t buf; /* File descriptor buffer */
|
||||
|
||||
|
||||
/*
|
||||
* Initialize the file descriptor buffer...
|
||||
*/
|
||||
|
||||
buf.fd = fd;
|
||||
buf.current = buf.buffer;
|
||||
buf.end = buf.buffer + sizeof(buf.buffer) - 4;
|
||||
|
||||
/*
|
||||
* Write the node...
|
||||
*/
|
||||
|
||||
if ((col = mxml_write_node(node, &buf, cb, 0, mxml_fd_putc)) < 0)
|
||||
return (-1);
|
||||
|
||||
if (col > 0)
|
||||
if (mxml_fd_putc('\n', &buf) < 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Flush and return...
|
||||
*/
|
||||
|
||||
return (mxml_fd_write(&buf));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxmlSaveFile()' - Save an XML tree to a file.
|
||||
*
|
||||
* The callback argument specifies a function that returns a whitespace
|
||||
* character or nul (0) before and after each element. If MXML_NO_CALLBACK
|
||||
* string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
* is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
* with leading whitespace and before attribute names inside opening
|
||||
* element tags.
|
||||
@ -243,6 +372,12 @@ mxmlSaveFile(mxml_node_t *node, /* I - Node to write */
|
||||
* This function returns the total number of bytes that would be
|
||||
* required for the string but only copies (bufsize - 1) characters
|
||||
* into the specified buffer.
|
||||
*
|
||||
* The callback argument specifies a function that returns a whitespace
|
||||
* string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
* is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
* with leading whitespace and before attribute names inside opening
|
||||
* element tags.
|
||||
*/
|
||||
|
||||
int /* O - Size of string */
|
||||
@ -379,59 +514,405 @@ mxml_add_char(int ch, /* I - Character to add */
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_get_entity()' - Get the character corresponding to an entity...
|
||||
* 'mxml_fd_getc()' - Read a character from a file descriptor.
|
||||
*/
|
||||
|
||||
static int /* O - Character value or EOF on error */
|
||||
mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
|
||||
void *p, /* I - Pointer to source */
|
||||
int *encoding, /* IO - Character encoding */
|
||||
int (*getc_cb)(void *, int *))
|
||||
/* I - Get character function */
|
||||
static int /* O - Character or EOF */
|
||||
mxml_fd_getc(void *p, /* I - File descriptor buffer */
|
||||
int *encoding) /* IO - Encoding */
|
||||
{
|
||||
int ch; /* Current character */
|
||||
char entity[64], /* Entity string */
|
||||
*entptr; /* Pointer into entity */
|
||||
mxml_fdbuf_t *buf; /* File descriptor buffer */
|
||||
int ch, /* Current character */
|
||||
temp; /* Temporary character */
|
||||
|
||||
|
||||
entptr = entity;
|
||||
/*
|
||||
* Grab the next character in the buffer...
|
||||
*/
|
||||
|
||||
while ((ch = (*getc_cb)(p, encoding)) != EOF)
|
||||
if (ch > 126 || (!isalnum(ch) && ch != '#'))
|
||||
break;
|
||||
else if (entptr < (entity + sizeof(entity) - 1))
|
||||
*entptr++ = ch;
|
||||
else
|
||||
{
|
||||
mxml_error("Entity name too long under parent <%s>!",
|
||||
parent ? parent->value.element.name : "null");
|
||||
break;
|
||||
}
|
||||
buf = (mxml_fdbuf_t *)p;
|
||||
|
||||
*entptr = '\0';
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
if (ch != ';')
|
||||
ch = *(buf->current)++;
|
||||
|
||||
switch (*encoding)
|
||||
{
|
||||
mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
|
||||
entity, parent ? parent->value.element.name : "null");
|
||||
return (EOF);
|
||||
}
|
||||
case ENCODE_UTF8 :
|
||||
/*
|
||||
* Got a UTF-8 character; convert UTF-8 to Unicode and return...
|
||||
*/
|
||||
|
||||
if (entity[1] == '#')
|
||||
{
|
||||
if (entity[2] == 'x')
|
||||
ch = strtol(entity + 3, NULL, 16);
|
||||
else
|
||||
ch = strtol(entity + 2, NULL, 10);
|
||||
if (!(ch & 0x80))
|
||||
return (ch);
|
||||
else if (ch == 0xfe)
|
||||
{
|
||||
/*
|
||||
* UTF-16 big-endian BOM?
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
ch = *(buf->current)++;
|
||||
|
||||
if (ch != 0xff)
|
||||
return (EOF);
|
||||
|
||||
*encoding = ENCODE_UTF16BE;
|
||||
|
||||
return (mxml_fd_getc(p, encoding));
|
||||
}
|
||||
else if (ch == 0xff)
|
||||
{
|
||||
/*
|
||||
* UTF-16 little-endian BOM?
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
ch = *(buf->current)++;
|
||||
|
||||
if (ch != 0xfe)
|
||||
return (EOF);
|
||||
|
||||
*encoding = ENCODE_UTF16LE;
|
||||
|
||||
return (mxml_fd_getc(p, encoding));
|
||||
}
|
||||
else if ((ch & 0xe0) == 0xc0)
|
||||
{
|
||||
/*
|
||||
* Two-byte value...
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = ((ch & 0x1f) << 6) | (temp & 0x3f);
|
||||
}
|
||||
else if ((ch & 0xf0) == 0xe0)
|
||||
{
|
||||
/*
|
||||
* Three-byte value...
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = ((ch & 0x0f) << 6) | (temp & 0x3f);
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = (ch << 6) | (temp & 0x3f);
|
||||
}
|
||||
else if ((ch & 0xf8) == 0xf0)
|
||||
{
|
||||
/*
|
||||
* Four-byte value...
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = ((ch & 0x07) << 6) | (temp & 0x3f);
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = (ch << 6) | (temp & 0x3f);
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
if ((temp & 0xc0) != 0x80)
|
||||
return (EOF);
|
||||
|
||||
ch = (ch << 6) | (temp & 0x3f);
|
||||
}
|
||||
else
|
||||
return (EOF);
|
||||
break;
|
||||
|
||||
case ENCODE_UTF16BE :
|
||||
/*
|
||||
* Read UTF-16 big-endian char...
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
ch = (ch << 8) | temp;
|
||||
|
||||
if (ch >= 0xd800 && ch <= 0xdbff)
|
||||
{
|
||||
/*
|
||||
* Multi-word UTF-16 char...
|
||||
*/
|
||||
|
||||
int lch;
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
lch = *(buf->current)++;
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
lch = (lch << 8) | temp;
|
||||
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
break;
|
||||
|
||||
case ENCODE_UTF16LE :
|
||||
/*
|
||||
* Read UTF-16 little-endian char...
|
||||
*/
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
ch |= (temp << 8);
|
||||
|
||||
if (ch >= 0xd800 && ch <= 0xdbff)
|
||||
{
|
||||
/*
|
||||
* Multi-word UTF-16 char...
|
||||
*/
|
||||
|
||||
int lch;
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
lch = *(buf->current)++;
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_read(buf) < 0)
|
||||
return (EOF);
|
||||
|
||||
temp = *(buf->current)++;
|
||||
|
||||
lch |= (temp << 8);
|
||||
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if ((ch = mxmlEntityGetValue(entity)) < 0)
|
||||
mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
|
||||
entity, parent ? parent->value.element.name : "null");
|
||||
|
||||
return (ch);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_fd_putc()' - Write a character to a file descriptor.
|
||||
*/
|
||||
|
||||
static int /* O - 0 on success, -1 on error */
|
||||
mxml_fd_putc(int ch, /* I - Character */
|
||||
void *p) /* I - File descriptor buffer */
|
||||
{
|
||||
mxml_fdbuf_t *buf; /* File descriptor buffer */
|
||||
|
||||
|
||||
/*
|
||||
* Flush the write buffer as needed - note above that "end" still leaves
|
||||
* 4 characters at the end so that we can avoid a lot of extra tests...
|
||||
*/
|
||||
|
||||
buf = (mxml_fdbuf_t *)p;
|
||||
|
||||
if (buf->current >= buf->end)
|
||||
if (mxml_fd_write(buf) < 0)
|
||||
return (-1);
|
||||
|
||||
if (ch < 128)
|
||||
{
|
||||
/*
|
||||
* Write ASCII character directly...
|
||||
*/
|
||||
|
||||
*(buf->current)++ = ch;
|
||||
}
|
||||
else if (ch < 2048)
|
||||
{
|
||||
/*
|
||||
* Two-byte UTF-8 character...
|
||||
*/
|
||||
|
||||
*(buf->current)++ = 0xc0 | (ch >> 6);
|
||||
*(buf->current)++ = 0x80 | (ch & 0x3f);
|
||||
}
|
||||
else if (ch < 65536)
|
||||
{
|
||||
/*
|
||||
* Three-byte UTF-8 character...
|
||||
*/
|
||||
|
||||
*(buf->current)++ = 0xe0 | (ch >> 12);
|
||||
*(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
|
||||
*(buf->current)++ = 0x80 | (ch & 0x3f);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Four-byte UTF-8 character...
|
||||
*/
|
||||
|
||||
*(buf->current)++ = 0xf0 | (ch >> 18);
|
||||
*(buf->current)++ = 0x80 | ((ch >> 12) & 0x3f);
|
||||
*(buf->current)++ = 0x80 | ((ch >> 6) & 0x3f);
|
||||
*(buf->current)++ = 0x80 | (ch & 0x3f);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return successfully...
|
||||
*/
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_fd_read()' - Read a buffer of data from a file descriptor.
|
||||
*/
|
||||
|
||||
static int /* O - 0 on success, -1 on error */
|
||||
mxml_fd_read(mxml_fdbuf_t *buf) /* I - File descriptor buffer */
|
||||
{
|
||||
int bytes; /* Bytes read... */
|
||||
|
||||
|
||||
/*
|
||||
* Range check input...
|
||||
*/
|
||||
|
||||
if (!buf)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Read from the file descriptor...
|
||||
*/
|
||||
|
||||
while ((bytes = read(buf->fd, buf->buffer, sizeof(buf->buffer))) < 0)
|
||||
if (errno != EAGAIN && errno != EINTR)
|
||||
return (-1);
|
||||
|
||||
if (bytes == 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Update the pointers and return success...
|
||||
*/
|
||||
|
||||
buf->current = buf->buffer;
|
||||
buf->end = buf->buffer + bytes;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_fd_write()' - Write a buffer of data to a file descriptor.
|
||||
*/
|
||||
|
||||
static int /* O - 0 on success, -1 on error */
|
||||
mxml_fd_write(mxml_fdbuf_t *buf) /* I - File descriptor buffer */
|
||||
{
|
||||
int bytes; /* Bytes written */
|
||||
unsigned char *ptr; /* Pointer into buffer */
|
||||
|
||||
|
||||
/*
|
||||
* Range check...
|
||||
*/
|
||||
|
||||
if (!buf)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* Return 0 if there is nothing to write...
|
||||
*/
|
||||
|
||||
if (buf->current == buf->buffer)
|
||||
return (0);
|
||||
|
||||
/*
|
||||
* Loop until we have written everything...
|
||||
*/
|
||||
|
||||
for (ptr = buf->buffer; ptr < buf->current; ptr += bytes)
|
||||
if ((bytes = write(buf->fd, ptr, buf->current - ptr)) < 0)
|
||||
return (-1);
|
||||
|
||||
/*
|
||||
* All done, reset pointers and return success...
|
||||
*/
|
||||
|
||||
buf->current = buf->buffer;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_file_getc()' - Get a character from a file.
|
||||
*/
|
||||
@ -559,7 +1040,7 @@ mxml_file_getc(void *p, /* I - Pointer to file */
|
||||
|
||||
int lch = (getc(fp) << 8) | getc(fp);
|
||||
|
||||
if (ch < 0xdc00 || ch >= 0xdfff)
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
@ -581,7 +1062,7 @@ mxml_file_getc(void *p, /* I - Pointer to file */
|
||||
|
||||
int lch = getc(fp) | (getc(fp) << 8);
|
||||
|
||||
if (ch < 0xdc00 || ch >= 0xdfff)
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
@ -648,6 +1129,60 @@ mxml_file_putc(int ch, /* I - Character to write */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_get_entity()' - Get the character corresponding to an entity...
|
||||
*/
|
||||
|
||||
static int /* O - Character value or EOF on error */
|
||||
mxml_get_entity(mxml_node_t *parent, /* I - Parent node */
|
||||
void *p, /* I - Pointer to source */
|
||||
int *encoding, /* IO - Character encoding */
|
||||
int (*getc_cb)(void *, int *))
|
||||
/* I - Get character function */
|
||||
{
|
||||
int ch; /* Current character */
|
||||
char entity[64], /* Entity string */
|
||||
*entptr; /* Pointer into entity */
|
||||
|
||||
|
||||
entptr = entity;
|
||||
|
||||
while ((ch = (*getc_cb)(p, encoding)) != EOF)
|
||||
if (ch > 126 || (!isalnum(ch) && ch != '#'))
|
||||
break;
|
||||
else if (entptr < (entity + sizeof(entity) - 1))
|
||||
*entptr++ = ch;
|
||||
else
|
||||
{
|
||||
mxml_error("Entity name too long under parent <%s>!",
|
||||
parent ? parent->value.element.name : "null");
|
||||
break;
|
||||
}
|
||||
|
||||
*entptr = '\0';
|
||||
|
||||
if (ch != ';')
|
||||
{
|
||||
mxml_error("Character entity \"%s\" not terminated under parent <%s>!",
|
||||
entity, parent ? parent->value.element.name : "null");
|
||||
return (EOF);
|
||||
}
|
||||
|
||||
if (entity[1] == '#')
|
||||
{
|
||||
if (entity[2] == 'x')
|
||||
ch = strtol(entity + 3, NULL, 16);
|
||||
else
|
||||
ch = strtol(entity + 2, NULL, 10);
|
||||
}
|
||||
else if ((ch = mxmlEntityGetValue(entity)) < 0)
|
||||
mxml_error("Entity name \"%s;\" not supported under parent <%s>!",
|
||||
entity, parent ? parent->value.element.name : "null");
|
||||
|
||||
return (ch);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 'mxml_load_data()' - Load data into an XML node tree.
|
||||
*/
|
||||
@ -1419,7 +1954,7 @@ mxml_string_getc(void *p, /* I - Pointer to file */
|
||||
lch = ((*s[0] & 255) << 8) | (*s[1] & 255);
|
||||
(*s) += 2;
|
||||
|
||||
if (ch < 0xdc00 || ch >= 0xdfff)
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
@ -1457,7 +1992,7 @@ mxml_string_getc(void *p, /* I - Pointer to file */
|
||||
lch = ((*s[1] & 255) << 8) | (*s[0] & 255);
|
||||
(*s) += 2;
|
||||
|
||||
if (ch < 0xdc00 || ch >= 0xdfff)
|
||||
if (lch < 0xdc00 || lch >= 0xdfff)
|
||||
return (EOF);
|
||||
|
||||
ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000;
|
||||
@ -1636,7 +2171,6 @@ mxml_write_node(mxml_node_t *node, /* I - Node to write */
|
||||
width; /* Width of attr + value */
|
||||
mxml_attr_t *attr; /* Current attribute */
|
||||
char s[255]; /* Temporary string */
|
||||
int slen; /* Length of temporary string */
|
||||
|
||||
|
||||
while (node != NULL)
|
||||
@ -1936,5 +2470,5 @@ mxml_write_ws(mxml_node_t *node, /* I - Current node */
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: mxml-file.c,v 1.33 2004/06/25 18:52:34 mike Exp $".
|
||||
* End of "$Id: mxml-file.c,v 1.34 2004/07/11 13:14:07 mike Exp $".
|
||||
*/
|
||||
|
8
mxml.h
8
mxml.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* "$Id: mxml.h,v 1.21 2004/06/01 20:19:34 mike Exp $"
|
||||
* "$Id: mxml.h,v 1.22 2004/07/11 13:14:07 mike Exp $"
|
||||
*
|
||||
* Header file for Mini-XML, a small XML-like file parsing library.
|
||||
*
|
||||
@ -161,6 +161,8 @@ extern mxml_node_t *mxmlIndexFind(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_type_t (*cb)(mxml_node_t *));
|
||||
extern mxml_node_t *mxmlLoadFile(mxml_node_t *top, FILE *fp,
|
||||
mxml_type_t (*cb)(mxml_node_t *));
|
||||
extern mxml_node_t *mxmlLoadString(mxml_node_t *top, const char *s,
|
||||
@ -180,6 +182,8 @@ __attribute__ ((__format__ (__printf__, 3, 4)))
|
||||
extern void mxmlRemove(mxml_node_t *node);
|
||||
extern char *mxmlSaveAllocString(mxml_node_t *node,
|
||||
const char *(*cb)(mxml_node_t *, int));
|
||||
extern int mxmlSaveFd(mxml_node_t *node, int fd,
|
||||
const char *(*cb)(mxml_node_t *, int));
|
||||
extern int mxmlSaveFile(mxml_node_t *node, FILE *fp,
|
||||
const char *(*cb)(mxml_node_t *, int));
|
||||
extern int mxmlSaveString(mxml_node_t *node, char *buffer,
|
||||
@ -225,5 +229,5 @@ extern mxml_type_t mxml_real_cb(mxml_node_t *node);
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: mxml.h,v 1.21 2004/06/01 20:19:34 mike Exp $".
|
||||
* End of "$Id: mxml.h,v 1.22 2004/07/11 13:14:07 mike Exp $".
|
||||
*/
|
||||
|
92
mxml.xml
92
mxml.xml
@ -243,6 +243,36 @@ mxmlIndexFind() for the first time.</description>
|
||||
<description>Index to reset</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlLoadFd">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
<description>First node or NULL if the file could not be read.</description>
|
||||
</returnvalue>
|
||||
<description>Load a file descriptor into an XML node tree.
|
||||
|
||||
The nodes in the specified file are added to the specified top node.
|
||||
If no top node is provided, the XML file MUST be well-formed with a
|
||||
single parent node like <?xml> for the entire file. The callback
|
||||
function returns the value type that should be used for child nodes.
|
||||
If MXML_NO_CALLBACK is specified then all child nodes will be either
|
||||
MXML_ELEMENT or MXML_TEXT nodes.
|
||||
|
||||
The constants MXML_INTEGER_CALLBACK, MXML_OPAQUE_CALLBACK,
|
||||
MXML_REAL_CALLBACK, and MXML_TEXT_CALLBACK are defined for loading
|
||||
child nodes of the specified type.</description>
|
||||
<argument name="top" direction="I">
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Top node</description>
|
||||
</argument>
|
||||
<argument name="fd" direction="I">
|
||||
<type>int</type>
|
||||
<description>File descriptor to read from</description>
|
||||
</argument>
|
||||
<argument name="(*cb)(mxml_node_t *node)" direction="I">
|
||||
<type>mxml_type_t</type>
|
||||
<description>Callback function or MXML_NO_CALLBACK</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlLoadFile">
|
||||
<returnvalue>
|
||||
<type>mxml_node_t *</type>
|
||||
@ -454,7 +484,13 @@ This function returns a pointer to a string containing the textual
|
||||
representation of the XML node tree. The string should be freed
|
||||
using the free() function when you are done with it. NULL is returned
|
||||
if the node would produce an empty string or if the string cannot be
|
||||
allocated.</description>
|
||||
allocated.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</description>
|
||||
<argument name="node" direction="I">
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Node to write</description>
|
||||
@ -464,6 +500,31 @@ allocated.</description>
|
||||
<description>Whitespace callback or MXML_NO_CALLBACK</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlSaveFd">
|
||||
<returnvalue>
|
||||
<type>int</type>
|
||||
<description>0 on success, -1 on error.</description>
|
||||
</returnvalue>
|
||||
<description>Save an XML tree to a file descriptor.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</description>
|
||||
<argument name="node" direction="I">
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Node to write</description>
|
||||
</argument>
|
||||
<argument name="fd" direction="I">
|
||||
<type>int</type>
|
||||
<description>File descriptor to write to</description>
|
||||
</argument>
|
||||
<argument name="(*cb)(mxml_node_t *node, int ws)" direction="I">
|
||||
<type>const char *</type>
|
||||
<description>Whitespace callback or MXML_NO_CALLBACK</description>
|
||||
</argument>
|
||||
</function>
|
||||
<function name="mxmlSaveFile">
|
||||
<returnvalue>
|
||||
<type>int</type>
|
||||
@ -472,7 +533,7 @@ allocated.</description>
|
||||
<description>Save an XML tree to a file.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
character or nul (0) before and after each element. If MXML_NO_CALLBACK
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</description>
|
||||
@ -498,7 +559,13 @@ element tags.</description>
|
||||
|
||||
This function returns the total number of bytes that would be
|
||||
required for the string but only copies (bufsize - 1) characters
|
||||
into the specified buffer.</description>
|
||||
into the specified buffer.
|
||||
|
||||
The callback argument specifies a function that returns a whitespace
|
||||
string or NULL before and after each element. If MXML_NO_CALLBACK
|
||||
is specified, whitespace will only be added before MXML_TEXT nodes
|
||||
with leading whitespace and before attribute names inside opening
|
||||
element tags.</description>
|
||||
<argument name="node" direction="I">
|
||||
<type>mxml_node_t *</type>
|
||||
<description>Node to write</description>
|
||||
@ -701,6 +768,25 @@ the walk to the node's children.</description>
|
||||
<type>struct mxml_value_s</type>
|
||||
<description>An XML element value.</description>
|
||||
</typedef>
|
||||
<struct name="mxml_fdbuf_s">
|
||||
<description>File descriptor buffer (@private)</description>
|
||||
<variable name="buffer[8192]">
|
||||
<type>end</type>
|
||||
<description>Character buffer</description>
|
||||
</variable>
|
||||
<variable name="current">
|
||||
<type>unsigned char *</type>
|
||||
<description>Current position in buffer</description>
|
||||
</variable>
|
||||
<variable name="fd">
|
||||
<type>int</type>
|
||||
<description>File descriptor</description>
|
||||
</variable>
|
||||
</struct>
|
||||
<typedef name="mxml_fdbuf_t">
|
||||
<type>struct mxml_fdbuf_s</type>
|
||||
<description>File descriptor buffer (@private)</description>
|
||||
</typedef>
|
||||
<struct name="mxml_index_s">
|
||||
<description>An XML node index.</description>
|
||||
<variable name="alloc_nodes">
|
||||
|
11
test.xml
11
test.xml
@ -3,7 +3,7 @@
|
||||
<keyword type="opaque">InputSlot</keyword>
|
||||
<default type="opaque">Auto</default>
|
||||
<text>Media Source</text>
|
||||
<order type="real">10.0</order>
|
||||
<order type="real">10.000000</order>
|
||||
<choice>
|
||||
<keyword type="opaque">Auto</keyword>
|
||||
<text>Auto Tray Selection</text>
|
||||
@ -12,16 +12,13 @@
|
||||
<choice>
|
||||
<keyword type="opaque">Upper</keyword>
|
||||
<text>Tray 1</text>
|
||||
<code type="opaque"><</MediaPosition 0>>setpagedevice</code>
|
||||
<code type="opaque"><</MediaPosition 0>>setpagedevice</code>
|
||||
</choice>
|
||||
<choice>
|
||||
<keyword type="opaque">Lower</keyword>
|
||||
<text>Tray 2</text>
|
||||
<code type="opaque"><</MediaPosition 1>>setpagedevice</code>
|
||||
<code type="opaque"><</MediaPosition 1>>setpagedevice</code>
|
||||
</choice>
|
||||
</option>
|
||||
|
||||
<integer>123</integer>
|
||||
|
||||
<string>Now is the time for all good men to come to the aid of
|
||||
their country.</string>
|
||||
<string>Now is the time for all good men to come to the aid of their country.</string>
|
||||
|
107
testmxml.c
107
testmxml.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* "$Id: testmxml.c,v 1.17 2004/05/16 18:25:20 mike Exp $"
|
||||
* "$Id: testmxml.c,v 1.18 2004/07/11 13:14:07 mike Exp $"
|
||||
*
|
||||
* Test program for Mini-XML, a small XML-like file parsing library.
|
||||
*
|
||||
@ -29,6 +29,12 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "mxml.h"
|
||||
#ifdef WIN32
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
# include <fcntl.h>
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
/*
|
||||
@ -49,6 +55,7 @@ main(int argc, /* I - Number of command-line args */
|
||||
{
|
||||
int i; /* Looping var */
|
||||
FILE *fp; /* File to read */
|
||||
int fd; /* File descriptor */
|
||||
mxml_node_t *tree, /* XML tree */
|
||||
*node; /* Node which should be in test.xml */
|
||||
mxml_index_t *ind; /* XML index */
|
||||
@ -456,11 +463,67 @@ main(int argc, /* I - Number of command-line args */
|
||||
fputs(buffer, stderr);
|
||||
|
||||
/*
|
||||
* Delete the tree and return...
|
||||
* Delete the tree...
|
||||
*/
|
||||
|
||||
mxmlDelete(tree);
|
||||
|
||||
/*
|
||||
* Read from/write to file descriptors...
|
||||
*/
|
||||
|
||||
if (argv[1][0] != '<')
|
||||
{
|
||||
/*
|
||||
* Open the file again...
|
||||
*/
|
||||
|
||||
if ((fd = open(argv[1], O_RDONLY)) < 0)
|
||||
{
|
||||
perror(argv[1]);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the file...
|
||||
*/
|
||||
|
||||
tree = mxmlLoadFd(NULL, fd, type_cb);
|
||||
|
||||
close(fd);
|
||||
|
||||
/*
|
||||
* Create filename.xmlfd...
|
||||
*/
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%sfd", argv[1]);
|
||||
|
||||
if ((fd = open(buffer, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
|
||||
{
|
||||
perror(buffer);
|
||||
mxmlDelete(tree);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the file...
|
||||
*/
|
||||
|
||||
mxmlSaveFd(tree, fd, whitespace_cb);
|
||||
|
||||
close(fd);
|
||||
|
||||
/*
|
||||
* Delete the tree...
|
||||
*/
|
||||
|
||||
mxmlDelete(tree);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return...
|
||||
*/
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -502,7 +565,12 @@ const char * /* O - Whitespace string or NULL */
|
||||
whitespace_cb(mxml_node_t *node, /* I - Element node */
|
||||
int where) /* I - Open or close tag? */
|
||||
{
|
||||
const char *name; /* Name of element */
|
||||
mxml_node_t *parent; /* Parent node */
|
||||
int level; /* Indentation level */
|
||||
const char *name; /* Name of element */
|
||||
static const char *tabs = "\t\t\t\t\t\t\t\t";
|
||||
/* Tabs for indentation */
|
||||
|
||||
|
||||
/*
|
||||
* We can conditionally break to a new line before or after any element.
|
||||
@ -542,6 +610,37 @@ whitespace_cb(mxml_node_t *node, /* I - Element node */
|
||||
else if (where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "?xml"))
|
||||
{
|
||||
return (NULL);
|
||||
}
|
||||
else if (!strcmp(name, "option"))
|
||||
{
|
||||
if (where == MXML_WS_AFTER_OPEN || where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
}
|
||||
else if (!strcmp(name, "choice"))
|
||||
{
|
||||
if (where == MXML_WS_BEFORE_OPEN || where == MXML_WS_BEFORE_CLOSE)
|
||||
return ("\t");
|
||||
else
|
||||
return ("\n");
|
||||
}
|
||||
else if (where == MXML_WS_BEFORE_OPEN)
|
||||
{
|
||||
for (level = -1, parent = node->parent;
|
||||
parent;
|
||||
level ++, parent = parent->parent);
|
||||
|
||||
if (level > 8)
|
||||
level = 8;
|
||||
|
||||
return (tabs + 8 - level);
|
||||
}
|
||||
else if (where == MXML_WS_AFTER_CLOSE)
|
||||
return ("\n");
|
||||
else if (!strcmp(name, "code") && where == MXML_WS_AFTER_OPEN && !node->child)
|
||||
return ("\n");
|
||||
|
||||
/*
|
||||
* Return NULL for no added whitespace...
|
||||
@ -552,5 +651,5 @@ whitespace_cb(mxml_node_t *node, /* I - Element node */
|
||||
|
||||
|
||||
/*
|
||||
* End of "$Id: testmxml.c,v 1.17 2004/05/16 18:25:20 mike Exp $".
|
||||
* End of "$Id: testmxml.c,v 1.18 2004/07/11 13:14:07 mike Exp $".
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user