summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-05 08:21:40 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-05 08:21:40 +0000
commit71fb4b80593369073dbd5f3c892aef2865c5a2ae (patch)
tree4c4d464b65b37d3d96a6de60ce031942200c9317
parent217907b995a000ed949d976f706d72676c270d84 (diff)
Changed XML and JSON databindings to use lazy lists and writer functions instead of STL streams, to help integrate them with HTTPD and CURL, which don't use streams.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@821715 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--cpp/sca/kernel/kernel-test.cpp68
-rw-r--r--cpp/sca/kernel/slist.hpp96
-rw-r--r--cpp/sca/kernel/xml.hpp125
-rw-r--r--cpp/sca/modules/json/json-test.cpp22
-rw-r--r--cpp/sca/modules/json/json.hpp85
5 files changed, 258 insertions, 138 deletions
diff --git a/cpp/sca/kernel/kernel-test.cpp b/cpp/sca/kernel/kernel-test.cpp
index 7eaa6a6354..576775b75e 100644
--- a/cpp/sca/kernel/kernel-test.cpp
+++ b/cpp/sca/kernel/kernel-test.cpp
@@ -31,6 +31,7 @@
#include <sstream>
#include "function.hpp"
#include "list.hpp"
+#include "slist.hpp"
#include "parallel.hpp"
#include "value.hpp"
#include "xml.hpp"
@@ -218,6 +219,15 @@ bool testReverse() {
return true;
}
+bool testTokenize() {
+ assert(tokenize("/", "aaa/bbb/ccc/ddd") == makeList<std::string>("aaa", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/ddd") == makeList<std::string>("", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/") == makeList<std::string>("", "bbb", "ccc"));
+ assert(tokenize("/", "/bbb//ccc/") == makeList<std::string>("", "bbb", "", "ccc"));
+ assert(tokenize("/", "abc/def/") == makeList<std::string>("abc", "def"));
+ return true;
+}
+
double testSeqMap(double x) {
return x;
}
@@ -285,15 +295,42 @@ double fib(double n) {
bool testCppPerf() {
struct timeval start;
struct timeval end;
- gettimeofday(&start, NULL);
+ {
+ gettimeofday(&start, NULL);
+
+ list<double> s = seq(0.0, 999.0);
+ list<double> r = map((lambda<double(double)> )fib, s);
+ assert(1000 == length(r));
- list<double> s = seq(0.0, 999.0);
- list<double> r = map((lambda<double(double)> )fib, s);
- assert(1000 == length(r));
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Fib cpp function map perf test " << t << " ms" << std::endl;
+ }
+
+ {
+ struct nested {
+ static double fib(double n) {
+ struct nested {
+ static double fib_aux(double n, double a, double b) {
+ if(n == 0.0)
+ return a;
+ return fib_aux(n - 1.0, b, a + b);
+ }
+ };
+ return nested::fib_aux(n, 0.0, 1.0);
+ }
+ };
- gettimeofday(&end, NULL);
- //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
- //std::cout << "Fib cpp perf test " << t << " ms" << std::endl;
+ gettimeofday(&start, NULL);
+
+ list<double> s = seq(0.0, 999.0);
+ list<double> r = map(lambda<double(double)>(nested::fib), s);
+ assert(1000 == length(r));
+
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Fib cpp nested function map perf test " << t << " ms" << std::endl;
+ }
return true;
}
@@ -390,7 +427,7 @@ const bool isName(const value& token) {
bool testReadXML() {
std::istringstream is(currencyXML);
- const list<value> currency = readXML(is);
+ const list<value> currency = readXML(makeStreamList(is));
const value composite = car(currency);
assert(isElement(composite));
@@ -401,12 +438,22 @@ bool testReadXML() {
return true;
}
+std::ostringstream* xmlWriter(std::ostringstream* os, const std::string& s) {
+ (*os) << s;
+ return os;
+}
+
bool testWriteXML() {
std::istringstream is(currencyXML);
- const list<value> currency = readXML(is);
+ const list<std::string> il = makeStreamList(is);
+
+ const list<value> currency = readXML(il);
std::ostringstream os;
- writeXML(currency, os);
+ lambda<std::ostringstream*(std::ostringstream*, std::string)> writer(xmlWriter);
+ writeXML(writer, &os, currency);
assert(os.str() == currencyXML);
+
+ assert(writeXML(currency) == il);
return true;
}
@@ -429,6 +476,7 @@ int main() {
tuscany::testFilter();
tuscany::testMember();
tuscany::testReverse();
+ tuscany::testTokenize();
tuscany::testSeq();
tuscany::testValue();
tuscany::testValueGC();
diff --git a/cpp/sca/kernel/slist.hpp b/cpp/sca/kernel/slist.hpp
new file mode 100644
index 0000000000..54c2d77574
--- /dev/null
+++ b/cpp/sca/kernel/slist.hpp
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+#ifndef tuscany_slist_hpp
+#define tuscany_slist_hpp
+
+/**
+ * Useful functions to work with lists of strings and character streams.
+ */
+
+#include <iostream>
+#include <string>
+#include "function.hpp"
+#include "list.hpp"
+
+namespace tuscany {
+
+/**
+ * Tokenize a string into a list of strings.
+ */
+const list<std::string> tokenize(const std::string& sep, const std::string& str) {
+ struct nested {
+ static const list<std::string> tokenize(const std::string& sep, const std::string& str, const unsigned int start = 0) {
+ if (start >= str.length())
+ return list<std::string>();
+ const unsigned int i = str.find_first_of(sep, start);
+ if (i == std::string::npos)
+ return makeList(str.substr(start));
+ return cons(str.substr(start, i - start), tokenize(sep, str, i + 1));
+ }
+ };
+ return nested::tokenize(sep, str, 0);
+}
+
+/**
+ * Returns a lazy list view of an input stream.
+ */
+struct ilistRead{
+ std::istream &is;
+ ilistRead(std::istream& is) : is(is) {
+ }
+ const list<std::string> operator()() {
+ char buffer[1024];
+ is.read(buffer, 1024);
+ const int n = is.gcount();
+ if (n ==0)
+ return list<std::string>();
+ return cons(std::string(buffer, n), (*this)());
+ }
+};
+
+const list<std::string> makeStreamList(std::istream& is) {
+ return ilistRead(is)();
+}
+
+/**
+ * Fragment the first element of a list of strings to fit the given max length.
+ */
+const list<std::string> fragment(list<std::string> l, unsigned int max) {
+ const std::string s = car(l);
+ if (s.length() <= max)
+ return l;
+ return cons(s.substr(0, max), cons(s.substr(max), cdr(l)));
+}
+
+/**
+ * Write a list of strings to an output stream.
+ */
+std::ostream& write(const list<std::string>& l, std::ostream& os) {
+ if(isNil(l))
+ return os;
+ os << car(l);
+ return write(cdr(l), os);
+}
+
+}
+
+#endif /* tuscany_slist_hpp */
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));
}
}
diff --git a/cpp/sca/modules/json/json-test.cpp b/cpp/sca/modules/json/json-test.cpp
index 42cdb1d643..5a1dcc5d51 100644
--- a/cpp/sca/modules/json/json-test.cpp
+++ b/cpp/sca/modules/json/json-test.cpp
@@ -27,6 +27,7 @@
#include <iostream>
#include <sstream>
#include <string>
+#include "slist.hpp"
#include "json.hpp"
namespace tuscany {
@@ -41,6 +42,11 @@ bool testJSEval() {
return true;
}
+std::ostringstream* jsonWriter(std::ostringstream* os, const std::string& s) {
+ (*os) << s;
+ return os;
+}
+
bool testJSON() {
JSONContext cx;
@@ -49,16 +55,22 @@ bool testJSON() {
print(l, std::cout);
std::cout << std::endl;
- std::ostringstream sos;
- writeJSON(cx, l, sos);
- std::cout << sos.str() << std::endl;
+ std::ostringstream os;
+ lambda<std::ostringstream*(std::ostringstream*, std::string)> writer(jsonWriter);
+ writeJSON(cx, writer, &os, l);
+ std::cout << os.str() << std::endl;
- std::istringstream is(sos.str());
- list<value> r = readJSON(cx, is);
+ std::istringstream is(os.str());
+ list<std::string> il = makeStreamList(is);
+ list<value> r = readJSON(cx, il);
print(r, std::cout);
std::cout << std::endl;
assert(r == l);
+ std::ostringstream wos;
+ write(writeJSON(cx, r), wos);
+ assert(wos.str() == os.str());
+
return true;
}
diff --git a/cpp/sca/modules/json/json.hpp b/cpp/sca/modules/json/json.hpp
index 16e3ce0320..e9938672c5 100644
--- a/cpp/sca/modules/json/json.hpp
+++ b/cpp/sca/modules/json/json.hpp
@@ -19,8 +19,8 @@
/* $Rev$ $Date$ */
-#ifndef tuscany_eval_driver_hpp
-#define tuscany_eval_driver_hpp
+#ifndef tuscany_json_hpp
+#define tuscany_json_hpp
/**
* JSON read/write functions.
@@ -29,8 +29,6 @@
#include <assert.h>
#define XP_UNIX
#include <jsapi.h>
-#include <iostream>
-#include <sstream>
#include <string>
#include "list.hpp"
#include "value.hpp"
@@ -191,41 +189,27 @@ const value jsValToValue(const JSONContext& cx, const jsval& jsv) {
}
/**
- * Reads characters from a JSON input stream.
+ * Consumes JSON strings and populates a JS object.
*/
-JSString* readCallback(const JSONContext& cx, std::istream& is) {
- char buffer[1024];
- if(is.eof())
- return NULL;
- is.read(buffer, 1024);
- const int n = is.gcount();
- if(n <= 0)
- return NULL;
- return JS_NewStringCopyN(cx, buffer, n);
-}
-
-/**
- * Consumes a JSON document and populates a JS object from it.
- */
-bool consumeJSON(const JSONContext& cx, JSONParser* parser, std::istream& is) {
- JSString* jstr = readCallback(cx, is);
- if(jstr == NULL)
+bool consumeJSON(const JSONContext& cx, JSONParser* parser, const list<std::string>& ilist) {
+ if (isNil(ilist))
return true;
+ JSString* jstr = JS_NewStringCopyZ(cx, car(ilist).c_str());
if(!JS_ConsumeJSONText(cx, parser, JS_GetStringChars(jstr), JS_GetStringLength(jstr)))
return false;
- return consumeJSON(cx, parser, is);
+ return consumeJSON(cx, parser, cdr(ilist));
}
/**
- * Read a JSON document from an input stream.
+ * Read JSON tokens from list of strings.
*/
-const list<value> readJSON(const JSONContext& cx, std::istream& is) {
+const list<value> readJSON(const JSONContext& cx, const list<std::string>& ilist) {
jsval val;
JSONParser* parser = JS_BeginJSONParse(cx, &val);
if(parser == NULL)
return list<value> ();
- bool ok = consumeJSON(cx, parser, is);
+ bool ok = consumeJSON(cx, parser, ilist);
if(!JS_FinishJSONParse(cx, parser, JSVAL_NULL))
return list<value> ();
@@ -308,42 +292,47 @@ const jsval valueToJSVal(const JSONContext& cx, const value& val) {
/**
* Context passed to JSON write callback function.
*/
-class JSONWriteContext {
+template<typename R> class JSONWriteContext {
public:
- JSONWriteContext(const JSONContext& cx, std::ostream& os) :
- os(os), cx(cx) {
+ JSONWriteContext(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& accum) : cx(cx), reduce(reduce), accum(accum) {
}
-
-private:
- std::ostream& os;
const JSONContext& cx;
-
- friend JSBool writeCallback(const jschar *buf, uint32 len, void *data);
+ const lambda<R(R, std::string)> reduce;
+ R accum;
};
/**
- * Called by JS_Stringify to write JSON document.
+ * Called by JS_Stringify to write JSON out.
*/
-JSBool writeCallback(const jschar *buf, uint32 len, void *data) {
- JSONWriteContext& cx = *(static_cast<JSONWriteContext*> (data));
- JSString* jstr = JS_NewUCStringCopyN(cx.cx, buf, len);
- cx.os.write(JS_GetStringBytes(jstr), JS_GetStringLength(jstr));
- if(cx.os.fail() || cx.os.bad())
- return JS_FALSE;
+template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *data) {
+ JSONWriteContext<R>& wcx = *(static_cast<JSONWriteContext<R>*> (data));
+ JSString* jstr = JS_NewUCStringCopyN(wcx.cx, buf, len);
+ wcx.accum = wcx.reduce(wcx.accum, std::string(JS_GetStringBytes(jstr), JS_GetStringLength(jstr)));
return JS_TRUE;
}
/**
- * Write a JSON document to an output stream.
+ * Write a list of values as a JSON document.
*/
-const bool writeJSON(const JSONContext& cx, const list<value>& l, std::ostream& os) {
+template<typename R> const R writeJSON(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
jsval val = valueToJSVal(cx, l);
- JSONWriteContext wcx(cx, os);
- if(!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback, &wcx))
- return false;
- return true;
+ JSONWriteContext<R> wcx(cx, reduce, initial);
+ JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx);
+ return wcx.accum;
+}
+
+const list<std::string> writeJSONList(const list<std::string>& listSoFar, const std::string& s) {
+ return cons(s, listSoFar);
+}
+
+/**
+ * Write a list of values as a JSON document represented as a list of strings.
+ */
+const list<std::string> writeJSON(const JSONContext& cx, const list<value>& l) {
+ lambda<list<std::string>(list<std::string>, std::string)> writer(writeJSONList);
+ return reverse(writeJSON(cx, writer, list<std::string>(), l));
}
}
-#endif
+#endif /* tuscany_json_hpp */