jwoolley 01/08/07 16:02:40
Modified: . CHANGES
include apr_xml.h
test .cvsignore Makefile.in
xml apr_xml.c
Added: test testxml.c
Log:
Added apr_xml_parse_file() routine and a testxml program.
Submitted by: Ian Holsman <[EMAIL PROTECTED]>
Reviewed by: Cliff Woolley
Revision Changes Path
1.27 +3 -0 apr-util/CHANGES
Index: CHANGES
===================================================================
RCS file: /home/cvs/apr-util/CHANGES,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -u -r1.26 -r1.27
--- CHANGES 2001/08/03 14:21:52 1.26
+++ CHANGES 2001/08/07 23:02:40 1.27
@@ -1,5 +1,8 @@
Changes with APR-util b1
+ *) Added apr_xml_parse_file() routine and a testxml program.
+ [Ian Holsman <[EMAIL PROTECTED]>]
+
*) Extend apr_bucket_type_t to add a pointer to a function used
to free the bucket. This change enables custom buckets to
completely specify how they are to be allocated and freed.
1.14 +18 -0 apr-util/include/apr_xml.h
Index: apr_xml.h
===================================================================
RCS file: /home/cvs/apr-util/include/apr_xml.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -u -r1.13 -r1.14
--- apr_xml.h 2001/05/16 17:22:34 1.13
+++ apr_xml.h 2001/08/07 23:02:40 1.14
@@ -57,6 +57,7 @@
#include "apr_pools.h"
#include "apr_tables.h"
+#include "apr_file_io.h"
#include "apu.h"
@@ -243,6 +244,23 @@
* @return The new parser.
*/
APU_DECLARE(apr_xml_parser *) apr_xml_parser_create(apr_pool_t *pool);
+
+/**
+ * Parse a File, producing a xml_doc
+ * @param pool The pool for allocating the parse results.
+ * @param parser A pointer to *parser (needed so calling function can get
+ * errors), will be set to NULL on successfull completion.
+ * @param pdoc A pointer to *apr_xml_doc (which has the parsed results in it)
+ * @param xmlfd A file to read from.
+ * @param int Buffer length which would be suitable
+ * @return Any errors found during parsing.
+ */
+APU_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+ apr_xml_parser **parser,
+ apr_xml_doc **ppdoc,
+ apr_file_t *xmlfd,
+ int buffer_length);
+
/**
* Feed input into the parser
1.5 +1 -0 apr-util/test/.cvsignore
Index: .cvsignore
===================================================================
RCS file: /home/cvs/apr-util/test/.cvsignore,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -u -r1.4 -r1.5
--- .cvsignore 2001/08/07 22:23:19 1.4
+++ .cvsignore 2001/08/07 23:02:40 1.5
@@ -5,3 +5,4 @@
testdbm
testmd4
testdate
+testxml
1.13 +6 -1 apr-util/test/Makefile.in
Index: Makefile.in
===================================================================
RCS file: /home/cvs/apr-util/test/Makefile.in,v
retrieving revision 1.12
retrieving revision 1.13
diff -u -d -u -r1.12 -r1.13
--- Makefile.in 2001/08/01 20:32:59 1.12
+++ Makefile.in 2001/08/07 23:02:40 1.13
@@ -1,7 +1,7 @@
[EMAIL PROTECTED]@
INCLUDES=-I$(top_builddir)/include -I$(top_builddir)/include/private [EMAIL
PROTECTED]@/include
TARGETS =
-PROGRAMS = testdbm testdate testmd4
+PROGRAMS = testdbm testdate testmd4 testxml
# bring in rules.mk for standard functionality
@INCLUDE_RULES@
@@ -17,6 +17,11 @@
testdate_LDADD = ../libaprutil.la @APR_SOURCE_DIR@/libapr.la
testdate: $(testdate_OBJECTS) $(testdate_LDADD)
$(LINK) $(testdate_OBJECTS) $(testdate_LDADD) $(LIBS)
+
+testxml_OBJECTS = testxml.lo
+testxml_LDADD = ../libaprutil.la @APR_SOURCE_DIR@/libapr.la
../xml/expat/lib/libexpat.la
+testxml: $(testxml_OBJECTS) $(testxml_LDADD)
+ $(LINK) $(testxml_OBJECTS) $(testxml_LDADD) $(LIBS)
testmd4_OBJECTS = testmd4.lo
testmd4_LDADD = ../libaprutil.la @APR_SOURCE_DIR@/libapr.la
1.1 apr-util/test/testxml.c
Index: testxml.c
===================================================================
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000-2001 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
#include "apr.h"
#include "apr_general.h"
#include "apr_xml.h"
#if APR_HAVE_STDLIB_H
#include <stdlib.h> /* for exit() */
#endif
static const char *progname;
static const char *usage = "%s [xmlfile]\nIt will create "
"a dummy XML file if none is supplied";
/*
* If our platform knows about the tmpnam() external buffer size, create
* a buffer to pass in. This is needed in a threaded environment, or
* one that thinks it is (like HP-UX).
*/
#ifdef L_tmpnam
static char tname_buf[L_tmpnam];
#else
static char *tname_buf = NULL;
#endif
static apr_status_t create_dummy_file_error(apr_pool_t *p, apr_file_t **fd)
{
apr_status_t rv;
char *tmpfile;
int i;
apr_off_t off = 0L;
tmpfile = tmpnam(tname_buf);
if ((tmpfile == NULL) || (*tmpfile == '\0')) {
fprintf(stderr, "unable to generate temporary filename\n");
if (errno == 0) {
errno = ENOENT;
}
perror("tmpnam");
return APR_EGENERAL;
}
rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
if (rv != APR_SUCCESS)
return rv;
rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<maryx>"
"<had a=\"little\"/><lamb its='fleece "
"was white as snow' />\n", *fd);
if (rv != APR_SUCCESS)
return rv;
for (i = 0; i < 5000; i++) {
rv = apr_file_puts("<hmm roast=\"lamb\" "
"for=\"dinner\">yummy</hmm>\n", *fd);
if (rv != APR_SUCCESS)
return rv;
}
rv = apr_file_puts("</mary>\n", *fd);
if (rv != APR_SUCCESS)
return rv;
return apr_file_seek(*fd, APR_SET, &off);
}
static apr_status_t create_dummy_file(apr_pool_t *p, apr_file_t **fd)
{
apr_status_t rv;
char *tmpfile;
int i;
apr_off_t off = 0L;
tmpfile = tmpnam(tname_buf);
if ((tmpfile == NULL) || (*tmpfile == '\0')) {
fprintf(stderr, "unable to generate temporary filename\n");
if (errno == 0) {
errno = ENOENT;
}
perror("tmpnam");
return APR_EGENERAL;
}
rv = apr_file_open(fd, tmpfile, APR_CREATE|APR_TRUNCATE|APR_DELONCLOSE|
APR_READ|APR_WRITE|APR_EXCL, APR_OS_DEFAULT, p);
if (rv != APR_SUCCESS)
return rv;
rv = apr_file_puts("<?xml version=\"1.0\" ?>\n<mary>"
"<had a=\"little\"/><lamb its='fleece "
"was white as snow' />\n", *fd);
if (rv != APR_SUCCESS)
return rv;
for (i = 0; i < 5000; i++) {
rv = apr_file_puts("<hmm roast=\"lamb\" "
"for=\"dinner\">yummy</hmm>\n", *fd);
if (rv != APR_SUCCESS)
return rv;
}
rv = apr_file_puts("</mary>\n", *fd);
if (rv != APR_SUCCESS)
return rv;
rv = apr_file_seek(*fd, APR_SET, &off);
return rv;
}
static void dump_xml(apr_xml_elem *e, int level)
{
apr_xml_attr *a;
apr_xml_elem *ec;
printf("%d: element %s\n", level, e->name);
if (e->attr) {
a = e->attr;
printf("%d:\tattrs\t", level);
while (a) {
printf("%s=%s\t", a->name, a->value);
a = a->next;
}
printf("\n");
}
if (e->first_child) {
ec = e->first_child;
while (ec) {
dump_xml(ec, level + 1);
ec = ec->next;
}
}
}
static void oops(const char *s1, const char *s2)
{
if (progname)
fprintf(stderr, "%s: ", progname);
fprintf(stderr, s1, s2);
if (errno > 0 && errno < sys_nerr)
fprintf(stderr, " (%s)", sys_errlist[errno]);
fprintf(stderr, "\n");
exit(1);
}
int main(int argc, const char *const * argv)
{
apr_pool_t *pool;
apr_file_t *fd;
apr_xml_parser *parser;
apr_xml_doc *doc;
apr_status_t rv;
char errbuf[2000];
char errbufXML[2000];
(void) apr_initialize();
apr_pool_create(&pool, NULL);
progname = argv[0];
if (argc == 1) {
rv = create_dummy_file(pool, &fd);
if (rv != APR_SUCCESS) {
oops("cannot create dummy file", "oops");
}
}
else {
if (argc == 2) {
rv = apr_file_open(&fd, argv[1], APR_READ, APR_OS_DEFAULT, pool);
if (rv != APR_SUCCESS) {
oops("cannot open: %s", argv[1]);
}
}
else {
oops("usage: %s", usage);
}
}
rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
if (rv != APR_SUCCESS) {
fprintf(stderr, "APR Error %s\nXML Error: %s\n",
apr_strerror(rv, errbuf, sizeof(errbuf)),
apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
return rv;
}
dump_xml(doc->root, 0);
apr_file_close(fd);
if (argc == 1) {
rv = create_dummy_file_error(pool, &fd);
if (rv != APR_SUCCESS) {
oops("cannot create error dummy file", "oops");
}
rv = apr_xml_parse_file(pool, &parser, &doc, fd, 2000);
if (rv != APR_SUCCESS) {
fprintf(stdout, "APR Error %s\nXML Error: %s "
"(EXPECTED) This is good.\n",
apr_strerror(rv, errbuf, sizeof(errbuf)),
apr_xml_parser_geterror(parser, errbufXML, sizeof(errbufXML)));
}
else {
fprintf(stderr, "Expected an error, but didn't get one ;( ");
return APR_EGENERAL;
}
}
apr_pool_destroy(pool);
apr_terminate();
return rv;
}
1.22 +37 -0 apr-util/xml/apr_xml.c
Index: apr_xml.c
===================================================================
RCS file: /home/cvs/apr-util/xml/apr_xml.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -u -r1.21 -r1.22
--- apr_xml.c 2001/04/26 21:29:00 1.21
+++ apr_xml.c 2001/08/07 23:02:40 1.22
@@ -479,6 +479,43 @@
return errbuf;
}
+APU_DECLARE(apr_status_t) apr_xml_parse_file(apr_pool_t *p,
+ apr_xml_parser **parser,
+ apr_xml_doc **ppdoc,
+ apr_file_t *xmlfd,
+ int buffer_length)
+{
+ apr_status_t rv;
+ char *buffer;
+ apr_size_t length;
+
+ *parser = apr_xml_parser_create(p);
+ if (*parser == NULL) {
+ /* FIXME: returning an error code would be nice,
+ * but we dont get one ;( */
+ return APR_EGENERAL;
+ }
+ buffer = apr_palloc(p, buffer_length);
+ length = buffer_length;
+
+ rv = apr_file_read(xmlfd, buffer, &length);
+
+ while (rv == APR_SUCCESS) {
+ rv = apr_xml_parser_feed(*parser, buffer, length);
+ if (rv != APR_SUCCESS) {
+ return rv;
+ }
+
+ length = buffer_length;
+ rv = apr_file_read(xmlfd, buffer, &length);
+ }
+ if (rv != APR_EOF) {
+ return rv;
+ }
+ rv = apr_xml_parser_done(*parser, ppdoc);
+ *parser = NULL;
+ return rv;
+}
APU_DECLARE(void) apr_text_append(apr_pool_t * p, apr_text_header *hdr,
const char *text)