Dynamically allocate element name, attribute name, and attribute value

buffers.

Bump version number to 1.0.1.
This commit is contained in:
Michael R Sweet 2003-06-15 21:31:45 +00:00
parent 208408cf01
commit 243f70768f
7 changed files with 190 additions and 91 deletions

View File

@ -1,6 +1,13 @@
README - 06/14/2003
README - 06/15/2003
-------------------
CHANGES IN Mini-XML 1.0.1
- The mxmlLoadFile() function now uses dynamically
allocated string buffers for element names, attribute
names, and attribute values. Previously they were
capped at 16383, 255, and 255 bytes, respectively.
CHANGES IN Mini-XML 1.0

3
README
View File

@ -4,7 +4,8 @@ README - 06/14/2003
INTRODUCTION
This README file describes the Mini-XML library version 1.0.
This README file describes the Mini-XML library version
1.0.1.
Mini-XML is a small XML parsing library that you can use to
read XML and XML-like data files in your application without

12
TODO
View File

@ -1,11 +1,5 @@
TODO - 06/05/2003
TODO - 06/15/2003
-----------------
- Finish up documentation generator, specifically:
- Structure/class/enumeration/typedef support.
- Support for argument names with type info,
e.g. "int (*cb)(mxml_node_t *)"
- Links at top to jump to specific sections?
- Code documentation cleanup to take advantage of mxmldoc...
- Dynamically allocate memory for attribute values.
- Add C++ class.

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.0, June 14, 2003<br/>
<p class="title" align="center">Current Release: v1.0.1, June 15, 2003<br/>
[&nbsp;<a
href="mxml-1.0.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;64k)</a>
href="mxml-1.0.1.tar.gz">Download&nbsp;Source&nbsp;(.tar.gz&nbsp;64k)</a>
| <a
href="mxml-1.0-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;42k)</a>
href="mxml-1.0.1-1.i386.rpm">Download&nbsp;Linux&nbsp;RPM&nbsp;(.i386.rpm&nbsp;42k)</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-file.c,v 1.10 2003/06/14 23:56:47 mike Exp $"
* "$Id: mxml-file.c,v 1.11 2003/06/15 21:31:45 mike Exp $"
*
* File loading code for mini-XML, a small XML-like file parsing library.
*
@ -36,6 +36,7 @@
* Local functions...
*/
static int mxml_add_char(int ch, char **ptr, char **buffer, int *bufsize);
static int mxml_parse_element(mxml_node_t *node, FILE *fp);
static int mxml_write_node(mxml_node_t *node, FILE *fp,
int (*cb)(mxml_node_t *, int), int col);
@ -65,8 +66,9 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
*parent; /* Current parent node */
int ch, /* Character from file */
whitespace; /* Non-zero if whitespace seen */
char buffer[16384], /* String buffer */
char *buffer, /* String buffer */
*bufptr; /* Pointer into buffer */
int bufsize; /* Size of buffer */
mxml_type_t type; /* Current node type */
@ -74,6 +76,13 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
* Read elements and other nodes from the file...
*/
if ((buffer = malloc(64)) == NULL)
{
fputs("Unable to allocate string buffer!\n", stderr);
return (NULL);
}
bufsize = 64;
bufptr = buffer;
parent = top;
whitespace = 0;
@ -180,13 +189,13 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
while ((ch = getc(fp)) != EOF)
if (isspace(ch) || ch == '>' || (ch == '/' && bufptr > buffer))
break;
else if (bufptr < (buffer + sizeof(buffer) - 1))
else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
{
*bufptr++ = ch;
if ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3))
break;
}
free(buffer);
return (NULL);
}
else if ((bufptr - buffer) == 3 && !strncmp(buffer, "!--", 3))
break;
*bufptr = '\0';
@ -201,13 +210,10 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
if (ch == '>' && bufptr > (buffer + 4) &&
!strncmp(bufptr - 2, "--", 2))
break;
else if (bufptr < (buffer + sizeof(buffer) - 1))
*bufptr++ = ch;
else
else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
{
fprintf(stderr, "Comment too long in file under parent <%s>!\n",
parent ? parent->value.element.name : "null");
break;
free(buffer);
return (NULL);
}
}
@ -245,13 +251,10 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
{
if (ch == '>')
break;
else if (bufptr < (buffer + sizeof(buffer) - 1))
*bufptr++ = ch;
else
else if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
{
fprintf(stderr, "Declaration too long in file under parent <%s>!\n",
parent ? parent->value.element.name : "null");
break;
free(buffer);
return (NULL);
}
}
while ((ch = getc(fp)) != EOF);
@ -439,13 +442,10 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
* Plain ASCII doesn't need special encoding...
*/
if (bufptr < (buffer + sizeof(buffer) - 1))
*bufptr++ = ch;
else
if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
{
fprintf(stderr, "String too long in file under parent <%s>!\n",
parent ? parent->value.element.name : "null");
break;
free(buffer);
return (NULL);
}
}
else
@ -454,32 +454,59 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
* Use UTF-8 encoding for the Unicode char...
*/
if (bufptr < (buffer + sizeof(buffer) - 5))
if (ch < 2048)
{
if (ch < 2048)
if (mxml_add_char(0xc0 | (ch >> 6), &bufptr, &buffer, &bufsize))
{
*bufptr++ = 0xc0 | (ch >> 6);
*bufptr++ = 0x80 | (ch & 63);
}
else if (ch < 65536)
{
*bufptr++ = 0xe0 | (ch >> 12);
*bufptr++ = 0x80 | ((ch >> 6) & 63);
*bufptr++ = 0x80 | (ch & 63);
free(buffer);
return (NULL);
}
else
if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
{
*bufptr++ = 0xf0 | (ch >> 18);
*bufptr++ = 0x80 | ((ch >> 12) & 63);
*bufptr++ = 0x80 | ((ch >> 6) & 63);
*bufptr++ = 0x80 | (ch & 63);
free(buffer);
return (NULL);
}
}
else if (ch < 65536)
{
if (mxml_add_char(0xe0 | (ch >> 12), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
if (mxml_add_char(0x80 | ((ch >> 6) & 63), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
}
else
{
fprintf(stderr, "String too long in file under parent <%s>!\n",
parent ? parent->value.element.name : "null");
break;
if (mxml_add_char(0xf0 | (ch >> 18), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
if (mxml_add_char(0x80 | ((ch >> 12) & 63), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
if (mxml_add_char(0x80 | ((ch >> 6) & 63), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
if (mxml_add_char(0x80 | (ch & 63), &bufptr, &buffer, &bufsize))
{
free(buffer);
return (NULL);
}
}
}
}
@ -489,17 +516,20 @@ mxmlLoadFile(mxml_node_t *top, /* I - Top node */
* Add character to current buffer...
*/
if (bufptr < (buffer + sizeof(buffer) - 1))
*bufptr++ = ch;
else
if (mxml_add_char(ch, &bufptr, &buffer, &bufsize))
{
fprintf(stderr, "String too long in file under parent <%s>!\n",
parent ? parent->value.element.name : "null");
break;
free(buffer);
return (NULL);
}
}
}
/*
* Free the string buffer - we don't need it anymore...
*/
free(buffer);
/*
* Find the top element and return it...
*/
@ -552,6 +582,49 @@ mxmlSaveFile(mxml_node_t *node, /* I - Node to write */
}
/*
* 'mxml_add_char()' - Add a character to a buffer, expanding as needed.
*/
static int /* O - 0 on success, -1 on error */
mxml_add_char(int ch, /* I - Character to add */
char **bufptr, /* IO - Current position in buffer */
char **buffer, /* IO - Current buffer */
int *bufsize) /* IO - Current buffer size */
{
char *newbuffer; /* New buffer value */
if (*bufptr >= (*buffer + *bufsize - 1))
{
/*
* Increase the size of the buffer...
*/
if (*bufsize < 1024)
(*bufsize) *= 2;
else
(*bufsize) += 1024;
if ((newbuffer = realloc(*buffer, *bufsize)) == NULL)
{
free(*buffer);
fprintf(stderr, "Unable to expand string buffer to %d bytes!\n",
*bufsize);
return (-1);
}
*bufptr = newbuffer + (*bufptr - *buffer);
}
*(*bufptr)++ = ch;
return (0);
}
/*
* 'mxml_parse_element()' - Parse an element for any attributes...
*/
@ -562,11 +635,34 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
{
int ch, /* Current character in file */
quote; /* Quoting character */
char name[256], /* Attribute name */
value[256], /* Attribute value */
char *name, /* Attribute name */
*value, /* Attribute value */
*ptr; /* Pointer into name/value */
int namesize, /* Size of name string */
valsize; /* Size of value string */
/*
* Initialize the name and value buffers...
*/
if ((name = malloc(64)) == NULL)
{
fputs("Unable to allocate memory for name!\n", stderr);
return (EOF);
}
namesize = 64;
if ((value = malloc(64)) == NULL)
{
free(name);
fputs("Unable to allocate memory for value!\n", stderr);
return (EOF);
}
valsize = 64;
/*
* Loop until we hit a >, /, ?, or EOF...
*/
@ -614,13 +710,11 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
while ((ch = getc(fp)) != EOF)
if (isspace(ch) || ch == '=' || ch == '/' || ch == '>' || ch == '?')
break;
else if (ptr < (name + sizeof(name) - 1))
*ptr++ = ch;
else
else if (mxml_add_char(ch, &ptr, &name, &namesize))
{
fprintf(stderr, "Attribute name too long for element %s!\n",
node->value.element.name);
return (EOF);
free(name);
free(value);
return (EOF);
}
*ptr = '\0';
@ -650,13 +744,11 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
while ((ch = getc(fp)) != EOF)
if (ch == quote)
break;
else if (ptr < (value + sizeof(value) - 1))
*ptr++ = ch;
else
else if (mxml_add_char(ch, &ptr, &value, &valsize))
{
fprintf(stderr, "Attribute value too long for attribute '%s' in element %s!\n",
name, node->value.element.name);
return (EOF);
free(name);
free(value);
return (EOF);
}
*ptr = '\0';
@ -673,13 +765,11 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
while ((ch = getc(fp)) != EOF)
if (isspace(ch) || ch == '=' || ch == '/' || ch == '>')
break;
else if (ptr < (value + sizeof(value) - 1))
*ptr++ = ch;
else
else if (mxml_add_char(ch, &ptr, &value, &valsize))
{
fprintf(stderr, "Attribute value too long for attribute '%s' in element %s!\n",
name, node->value.element.name);
return (EOF);
free(name);
free(value);
return (EOF);
}
*ptr = '\0';
@ -702,6 +792,13 @@ mxml_parse_element(mxml_node_t *node, /* I - Element node */
mxmlElementSetAttr(node, name, value);
}
/*
* Free the name and value buffers and return...
*/
free(name);
free(value);
return (ch);
}
@ -1012,5 +1109,5 @@ mxml_write_ws(mxml_node_t *node, /* I - Current node */
/*
* End of "$Id: mxml-file.c,v 1.10 2003/06/14 23:56:47 mike Exp $".
* End of "$Id: mxml-file.c,v 1.11 2003/06/15 21:31:45 mike Exp $".
*/

View File

@ -1,5 +1,5 @@
#
# "$Id: mxml.list.in,v 1.3 2003/06/15 01:29:02 mike Exp $"
# "$Id: mxml.list.in,v 1.4 2003/06/15 21:31:45 mike Exp $"
#
# EPM software list file for mini-XML, a small XML-like file parsing library.
#
@ -32,7 +32,7 @@ $srcdir=@srcdir@
%vendor Michael Sweet
%license ${srcdir}/COPYING
%readme ${srcdir}/README
%version 1.0
%version 1.0.1
%description <<EOF
Mini-XML is a small XML parsing library that you can use to read
@ -88,5 +88,5 @@ f 0444 root sys ${mandir}/cat3/mxml.$CAT3EXT $srcdir/mxml.$CAT3EXT
f 0444 root sys ${mandir}/man3/mxml.$MAN3EXT $srcdir/mxml.man
#
# End of "$Id: mxml.list.in,v 1.3 2003/06/15 01:29:02 mike Exp $".
# End of "$Id: mxml.list.in,v 1.4 2003/06/15 21:31:45 mike Exp $".
#

View File

@ -1,5 +1,5 @@
#
# "$Id: mxml.spec,v 1.2 2003/06/15 01:22:37 mike Exp $"
# "$Id: mxml.spec,v 1.3 2003/06/15 21:31:45 mike Exp $"
#
# RPM "spec" file for mini-XML, a small XML-like file parsing library.
#
@ -18,7 +18,7 @@
Summary: Miniature XML development library
Name: mxml
Version: 1.0
Version: 1.0.1
Release: 1
Copyright: GPL
Group: Development/Libraries
@ -94,5 +94,5 @@ rm -rf $RPM_BUILD_ROOT
/usr/share/man/man3/*
#
# End of "$Id: mxml.spec,v 1.2 2003/06/15 01:22:37 mike Exp $".
# End of "$Id: mxml.spec,v 1.3 2003/06/15 21:31:45 mike Exp $".
#