summaryrefslogtreecommitdiffstats
path: root/cpp/sca/kernel/xml.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp/sca/kernel/xml.hpp')
-rw-r--r--cpp/sca/kernel/xml.hpp125
1 files changed, 50 insertions, 75 deletions
diff --git a/cpp/sca/kernel/xml.hpp b/cpp/sca/kernel/xml.hpp
index 7ddfd6bc44..cfae5678b8 100644
--- a/cpp/sca/kernel/xml.hpp
+++ b/cpp/sca/kernel/xml.hpp
@@ -30,8 +30,6 @@
#include <libxml/xmlwriter.h>
#include <libxml/xmlschemas.h>
#include <libxml/globals.h>
-#include <iostream>
-#include <fstream>
#include <string>
#include "list.hpp"
@@ -158,7 +156,7 @@ const list<value> readList(const list<value>& listSoFar, XMLReader& reader) {
}
/**
- * Read an XML document from a libxml2 XML reader.
+ * Read a list of values from a libxml2 XML reader.
*/
const list<value> read(XMLReader& reader) {
value nextToken = readToken(reader);
@@ -168,49 +166,35 @@ const list<value> read(XMLReader& reader) {
}
/**
- * Callback function called by libxml2 to read the XML input stream.
+ * Context passed to the read callback function.
*/
-int readCallback(void *context, char* buffer, int len) {
- std::istream* is = static_cast<std::istream*>(context);
- is->read(buffer, len);
- const int n = is->gcount();
- return n;
-}
-
-/**
- * Read an XML document from an input stream.
- */
-const list<value> readXML(std::istream& is) {
- xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &is, NULL, NULL, XML_PARSE_NONET);
- if (xml == NULL)
- return list<value>();
- XMLReader reader(xml);
- return read(reader);
-}
-
-/**
- * Callback function called by libxml2 to read the XML file input stream.
- */
-int readFileCallback(void *context, char* buffer, int len) {
- std::ifstream* is = static_cast<std::ifstream*>(context);
- is->read(buffer, len);
- return is->gcount();
-}
+class XMLReadContext {
+public:
+ XMLReadContext(const list<std::string>& ilist) : ilist(ilist) {
+ }
+ list<std::string> ilist;
+};
/**
- * Callback function called by libxml2 to close the XML file input stream.
+ * Callback function called by libxml2 to read XML.
*/
-int readCloseFileCallback(void *context) {
- std::ifstream* fis = static_cast<std::ifstream*>(context);
- fis->close();
- return 0;
+int readCallback(void *context, char* buffer, int len) {
+ XMLReadContext& rc = *static_cast<XMLReadContext*>(context);
+ if (isNil(rc.ilist))
+ return 0;
+ rc.ilist = fragment(rc.ilist, len);
+ std::string s = car(rc.ilist);
+ rc.ilist = cdr(rc.ilist);
+ s.copy(buffer, s.length());
+ return s.length();
}
/**
- * Read an XML document from a file input stream.
+ * Read a list values from a list of strings representing an XML document.
*/
-const list<value> readXML(std::ifstream& is) {
- xmlTextReaderPtr xml = xmlReaderForIO(readFileCallback, readCloseFileCallback, &is, NULL, NULL, XML_PARSE_NONET);
+const list<value> readXML(const list<std::string>& ilist) {
+ XMLReadContext cx(ilist);
+ xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET);
if (xml == NULL)
return list<value>();
XMLReader reader(xml);
@@ -313,7 +297,7 @@ const bool writeList(const list<value>& l, const xmlTextWriterPtr xml) {
}
/**
- * Write an XML document to a libxml2 XML writer.
+ * Write a list of values to a libxml2 XML writer.
*/
const bool write(const list<value>& l, const xmlTextWriterPtr xml) {
if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0)
@@ -325,56 +309,47 @@ const bool write(const list<value>& l, const xmlTextWriterPtr xml) {
}
/**
- * Callback function called by libxml2 to write to the XML output stream.
+ * Context passed to the write callback function.
*/
-int writeCallback(void *context, const char* buffer, int len) {
- std::ostream* os = static_cast<std::ostream*>(context);
- os->write(buffer, len);
- if (os->fail() || os->bad())
- return -1;
- return len;
-}
+template<typename R> class XMLWriteContext {
+public:
+ XMLWriteContext(const lambda<R(R, std::string)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ }
+ const lambda<R(R, std::string)> reduce;
+ R accum;
+};
/**
- * Write an XML document to an output stream.
+ * Callback function called by libxml2 to write XML out.
*/
-const bool writeXML(const list<value>& l, std::ostream& os) {
- xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback, NULL, &os, NULL);
- xmlTextWriterPtr xml = xmlNewTextWriter(out);
- if (xml == NULL)
- return false;
- return write(l, xml);
+template<typename R> int writeCallback(void *context, const char* buffer, int len) {
+ XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context);
+ cx.accum = cx.reduce(cx.accum, std::string(buffer, len));
+ return len;
}
/**
- * Callback function called by libxml2 to write to the XML file output stream.
+ * Write a list of values as an XML document.
*/
-int writeFileCallback(void *context, const char* buffer, int len) {
- std::ofstream* os = static_cast<std::ofstream*>(context);
- os->write(buffer, len);
- if (os->fail() || os->bad())
- return -1;
- return len;
+template<typename R> const R writeXML(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+ XMLWriteContext<R> cx(reduce, initial);
+ xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL);
+ xmlTextWriterPtr xml = xmlNewTextWriter(out);
+ if (xml != NULL)
+ write(l, xml);
+ return cx.accum;
}
-/**
- * Callback function called by libxml2 to close the XML file output stream.
- */
-int writeCloseFileCallback(void *context) {
- std::ofstream* fos = static_cast<std::ofstream*>(context);
- fos->close();
- return 0;
+const list<std::string> writeXMLList(const list<std::string>& listSoFar, const std::string& s) {
+ return cons(s, listSoFar);
}
/**
- * Write an XML document to a file output stream.
+ * Write a list of values as an XML document represented as a list of strings.
*/
-const bool writeXML(const list<value>& l, std::ofstream& os) {
- xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeFileCallback, writeCloseFileCallback, &os, NULL);
- xmlTextWriterPtr xml = xmlNewTextWriter(out);
- if (xml == NULL)
- return false;
- return write(l, xml);
+const list<std::string> writeXML(const list<value>& l) {
+ lambda<list<std::string>(list<std::string>, std::string)> writer(writeXMLList);
+ return reverse(writeXML(writer, list<std::string>(), l));
}
}