From ae0b7c0063db6236be2d7cf01ddbf2159f77c98c Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Tue, 11 Dec 2012 03:51:03 +0000 Subject: Port kernel to C++11 and refactor some of the core modules. Convert functors to lambdas, and add C++ const, noexcept and inline annotations to get more efficient generated code. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1419985 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/.gitignore | 6 +- sca-cpp/trunk/etc/callgrind | 25 ++ sca-cpp/trunk/etc/memgrind | 2 +- sca-cpp/trunk/kernel/Makefile.am | 10 +- sca-cpp/trunk/kernel/config.hpp | 4 +- sca-cpp/trunk/kernel/dynlib-test.cpp | 6 +- sca-cpp/trunk/kernel/dynlib.hpp | 32 +- sca-cpp/trunk/kernel/element.hpp | 103 ++--- sca-cpp/trunk/kernel/fstream.hpp | 132 ++++--- sca-cpp/trunk/kernel/function.hpp | 114 +++--- sca-cpp/trunk/kernel/gc.hpp | 370 +++++++++++------ sca-cpp/trunk/kernel/hash-test.cpp | 87 ++-- sca-cpp/trunk/kernel/hash.hpp | 10 +- sca-cpp/trunk/kernel/kernel-test.cpp | 528 +++++++++++++++++++------ sca-cpp/trunk/kernel/lambda-test.cpp | 25 +- sca-cpp/trunk/kernel/list.hpp | 210 ++++------ sca-cpp/trunk/kernel/mem-test.cpp | 56 +-- sca-cpp/trunk/kernel/monad.hpp | 225 +++++------ sca-cpp/trunk/kernel/parallel-test.cpp | 84 ++-- sca-cpp/trunk/kernel/parallel.hpp | 161 ++++---- sca-cpp/trunk/kernel/perf.hpp | 22 +- sca-cpp/trunk/kernel/sstream.hpp | 213 ++++++---- sca-cpp/trunk/kernel/stream.hpp | 91 +++-- sca-cpp/trunk/kernel/string-test.cpp | 97 ++--- sca-cpp/trunk/kernel/string.hpp | 223 ++++++----- sca-cpp/trunk/kernel/tree.hpp | 16 +- sca-cpp/trunk/kernel/value.hpp | 371 +++++++++-------- sca-cpp/trunk/kernel/xml-test.cpp | 235 ----------- sca-cpp/trunk/kernel/xml.hpp | 412 ------------------- sca-cpp/trunk/kernel/xsd-test.cpp | 107 ----- sca-cpp/trunk/modules/Makefile.am | 2 +- sca-cpp/trunk/modules/atom/atom-test.cpp | 268 ++++++------- sca-cpp/trunk/modules/atom/atom.hpp | 85 ++-- sca-cpp/trunk/modules/rss/rss-test.cpp | 208 +++++----- sca-cpp/trunk/modules/rss/rss.hpp | 70 ++-- sca-cpp/trunk/modules/scdl/scdl-test.cpp | 24 +- sca-cpp/trunk/modules/scdl/scdl.hpp | 29 +- sca-cpp/trunk/modules/scheme/Makefile.am | 14 +- sca-cpp/trunk/modules/scheme/driver.hpp | 2 +- sca-cpp/trunk/modules/scheme/element-value.cpp | 6 +- sca-cpp/trunk/modules/scheme/element-xml.cpp | 51 +++ sca-cpp/trunk/modules/scheme/environment.hpp | 16 +- sca-cpp/trunk/modules/scheme/eval.hpp | 10 +- sca-cpp/trunk/modules/scheme/io.hpp | 150 +++---- sca-cpp/trunk/modules/scheme/primitive.hpp | 86 ++-- sca-cpp/trunk/modules/scheme/scheme-shell.cpp | 2 +- sca-cpp/trunk/modules/scheme/scheme-test.cpp | 126 ++++-- sca-cpp/trunk/modules/scheme/scheme-test.hpp | 34 ++ sca-cpp/trunk/modules/scheme/test.scm | 44 +++ sca-cpp/trunk/modules/scheme/value-element.cpp | 6 +- sca-cpp/trunk/modules/scheme/value-xml.cpp | 51 --- sca-cpp/trunk/modules/scheme/xml-element.cpp | 47 +++ sca-cpp/trunk/modules/scheme/xml-value.cpp | 47 --- sca-cpp/trunk/modules/xml/Makefile.am | 29 ++ sca-cpp/trunk/modules/xml/test.xml | 2 + sca-cpp/trunk/modules/xml/xml-test.cpp | 373 +++++++++++++++++ sca-cpp/trunk/modules/xml/xml-test.hpp | 33 ++ sca-cpp/trunk/modules/xml/xml.hpp | 418 ++++++++++++++++++++ sca-cpp/trunk/modules/xml/xsd-test.cpp | 107 +++++ 59 files changed, 3512 insertions(+), 2805 deletions(-) create mode 100755 sca-cpp/trunk/etc/callgrind delete mode 100644 sca-cpp/trunk/kernel/xml-test.cpp delete mode 100644 sca-cpp/trunk/kernel/xml.hpp delete mode 100644 sca-cpp/trunk/kernel/xsd-test.cpp create mode 100644 sca-cpp/trunk/modules/scheme/element-xml.cpp create mode 100644 sca-cpp/trunk/modules/scheme/scheme-test.hpp create mode 100644 sca-cpp/trunk/modules/scheme/test.scm delete mode 100644 sca-cpp/trunk/modules/scheme/value-xml.cpp create mode 100644 sca-cpp/trunk/modules/scheme/xml-element.cpp delete mode 100644 sca-cpp/trunk/modules/scheme/xml-value.cpp create mode 100644 sca-cpp/trunk/modules/xml/Makefile.am create mode 100644 sca-cpp/trunk/modules/xml/test.xml create mode 100644 sca-cpp/trunk/modules/xml/xml-test.cpp create mode 100644 sca-cpp/trunk/modules/xml/xml-test.hpp create mode 100644 sca-cpp/trunk/modules/xml/xml.hpp create mode 100644 sca-cpp/trunk/modules/xml/xsd-test.cpp (limited to 'sca-cpp') diff --git a/sca-cpp/trunk/.gitignore b/sca-cpp/trunk/.gitignore index cb61e71d6c..fc7f1cb1c9 100644 --- a/sca-cpp/trunk/.gitignore +++ b/sca-cpp/trunk/.gitignore @@ -61,8 +61,8 @@ cache-manifest.cmf *-min.html *-min.js *-min.css +*.b64 intro*.png -intro*.b64 depcomp install-sh ltmain.sh @@ -138,8 +138,8 @@ js-shell file-test test-start* test-stop* -xml-value -value-xml +xml-element +element-xml json-value value-json element-value diff --git a/sca-cpp/trunk/etc/callgrind b/sca-cpp/trunk/etc/callgrind new file mode 100755 index 0000000000..10f9f0eb9f --- /dev/null +++ b/sca-cpp/trunk/etc/callgrind @@ -0,0 +1,25 @@ +#!/bin/sh + +# 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. + +# Run valgrind to record call history, generate a call graph and help analyze +# cache and branch prediction +here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` + +valgrind --tool=callgrind $* 2>&1 | tee callgrind.log + diff --git a/sca-cpp/trunk/etc/memgrind b/sca-cpp/trunk/etc/memgrind index 312058cc85..ea1386b0cb 100755 --- a/sca-cpp/trunk/etc/memgrind +++ b/sca-cpp/trunk/etc/memgrind @@ -20,5 +20,5 @@ # Run valgrind to analyze memory usage and track memory leaks here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here` -valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=50 --track-fds=yes --trace-children=yes --suppressions=$here/../../Python-2.6.6/Misc/valgrind-python.supp --suppressions=$here/valgrind-apr.supp $* 2>&1 | tee memgrind.log +valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=50 --track-fds=yes --trace-children=yes --suppressions=$here/../../Python-2.7.3/Misc/valgrind-python.supp --suppressions=$here/valgrind-apr.supp $* 2>&1 | tee memgrind.log diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am index e6a7fdb2b3..47c65a1889 100644 --- a/sca-cpp/trunk/kernel/Makefile.am +++ b/sca-cpp/trunk/kernel/Makefile.am @@ -37,14 +37,8 @@ mem_test_SOURCES = mem-test.cpp parallel_test_SOURCES = parallel-test.cpp -xml_test_SOURCES = xml-test.cpp -xml_test_LDFLAGS = -lxml2 - -xsd_test_SOURCES = xsd-test.cpp -xsd_test_LDFLAGS = -lxml2 - hash_test_SOURCES = hash-test.cpp -noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test xsd-test -TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test +noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test +TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test diff --git a/sca-cpp/trunk/kernel/config.hpp b/sca-cpp/trunk/kernel/config.hpp index 944b9629e7..e6af54552b 100644 --- a/sca-cpp/trunk/kernel/config.hpp +++ b/sca-cpp/trunk/kernel/config.hpp @@ -93,12 +93,12 @@ namespace tuscany #ifdef WANT_MAINTAINER_COUNTERS -bool debug_inc(long int& c) { +const bool debug_inc(long int& c) { c++; return true; } -bool debug_dec(long int& c) { +const bool debug_dec(long int& c) { c--; return true; } diff --git a/sca-cpp/trunk/kernel/dynlib-test.cpp b/sca-cpp/trunk/kernel/dynlib-test.cpp index 419fa29db5..c7f0e6238d 100644 --- a/sca-cpp/trunk/kernel/dynlib-test.cpp +++ b/sca-cpp/trunk/kernel/dynlib-test.cpp @@ -28,7 +28,7 @@ namespace tuscany { namespace test { - const int cppsquare(int x) { + const int cppsquare(const int x) { return x * x; } @@ -41,8 +41,8 @@ extern "C" { return tuscany::test::cppsquare(x); } - const tuscany::lambda csquarel() { - return tuscany::lambda(tuscany::test::cppsquare); + const tuscany::lambda csquarel() { + return tuscany::lambda(tuscany::test::cppsquare); } } diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp index 69359b4dae..ea6b50bacb 100644 --- a/sca-cpp/trunk/kernel/dynlib.hpp +++ b/sca-cpp/trunk/kernel/dynlib.hpp @@ -48,27 +48,18 @@ const string dynlibExt(".so"); */ class lib { public: - lib() : h(NULL), owner(false) { + inline lib() : h(NULL), owner(false) { } - lib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)), owner(true) { - if (h == NULL) - h = mkfailure(string("Could not load library: ") + name + ": " + dlerror()); + inline lib(const string& name) : name(name), h(open(name)), owner(true) { } - lib(const lib& l) : name(l.name), h(l.h), owner(false) { + inline lib(const lib& l) : name(l.name), h(l.h), owner(false) { } - const lib& operator=(const lib& l) { - if(this == &l) - return *this; - name = l.name; - h = l.h; - owner = false; - return *this; - } + lib& operator=(const lib& l) = delete; - ~lib() { + inline ~lib() { if (!owner) return; if (!hasContent(h) || content(h) == NULL) @@ -77,17 +68,22 @@ public: } private: + const failable open(const string& name) { + void * h = dlopen(c_str(name), RTLD_NOW); + return h != NULL? failable(h) : mkfailure(string("Could not load library: ") + name + ": " + dlerror()); + } + template friend const failable > dynlambda(const string& name, const lib& l); - string name; - failable h; - bool owner; + const string name; + const failable h; + const bool owner; }; /** * Find a lambda function in a dynamic library. */ -template const failable > dynlambda(const string& name, const lib& l) { +template inline const failable > dynlambda(const string& name, const lib& l) { if (!hasContent(l.h)) return mkfailure>(l.h); const void* s = dlsym(content(l.h), c_str(name)); diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp index 27b5af8691..9ae1e632cb 100644 --- a/sca-cpp/trunk/kernel/element.hpp +++ b/sca-cpp/trunk/kernel/element.hpp @@ -42,7 +42,7 @@ const string atsign("@"); /** * Returns true if a value is an element. */ -bool isElement(const value& v) { +inline const bool isElement(const value& v) { if (!isList(v) || isNil(v) || element != car(v)) return false; return true; @@ -51,7 +51,7 @@ bool isElement(const value& v) { /** * Returns true if a value is an attribute. */ -bool isAttribute(const value& v) { +inline const bool isAttribute(const value& v) { if (!isList(v) || isNil(v) || attribute != car(v)) return false; return true; @@ -60,42 +60,42 @@ bool isAttribute(const value& v) { /** * Returns the name of an attribute. */ -const value attributeName(const list& l) { +inline const value attributeName(const list& l) { return cadr(l); } /** * Returns the value of an attribute. */ -const value attributeValue(const list& l) { +inline const value attributeValue(const list& l) { return caddr(l); } /** * Returns the name of an element. */ -const value elementName(const list& l) { +inline const value elementName(const list& l) { return cadr(l); } /** * Returns true if an element has children. */ -const bool elementHasChildren(const list& l) { +inline const bool elementHasChildren(const list& l) { return !isNil(cddr(l)); } /** * Returns the children of an element. */ -const list elementChildren(const list& l) { +inline const list elementChildren(const list& l) { return cddr(l); } /** * Returns true if an element has a value. */ -const bool elementHasValue(const list& l) { +inline const bool elementHasValue(const list& l) { const list r = reverse(l); if (isSymbol(car(r))) return false; @@ -107,26 +107,26 @@ const bool elementHasValue(const list& l) { /** * Returns the value of an element. */ -const value elementValue(const list& l) { +inline const value elementValue(const list& l) { return car(reverse(l)); } /** * Convert an element to a value. */ -const bool elementToValueIsList(const value& v) { +inline const bool elementToValueIsList(const value& v) { if (!isList(v)) return false; const list l = v; return (isNil(l) || !isSymbol(car(l))); } -const value elementToValue(const value& t) { +inline const value elementToValue(const value& t) { const list elementsToValues(const list& e); // Convert an attribute if (isTaggedList(t, attribute)) - return mklist(c_str(atsign + attributeName(t)), attributeValue(t)); + return mklist(c_str(atsign + (string)attributeName(t)), attributeValue(t)); // Convert an element if (isTaggedList(t, element)) { @@ -155,7 +155,7 @@ const value elementToValue(const value& t) { /** * Convert a list of elements to a list of values. */ -const bool elementToValueIsSymbol(const value& v) { +inline const bool elementToValueIsSymbol(const value& v) { if (!isList(v)) return false; const list l = v; @@ -166,7 +166,7 @@ const bool elementToValueIsSymbol(const value& v) { return true; } -const list elementToValueGroupValues(const value& v, const list& l) { +inline const list elementToValueGroupValues(const value& v, const list& l) { if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) return cons(v, l); if (car(car(l)) != car(v)) @@ -180,7 +180,7 @@ const list elementToValueGroupValues(const value& v, const list& l } -const list elementsToValues(const list& e) { +inline const list elementsToValues(const list& e) { if (isNil(e)) return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); @@ -189,13 +189,13 @@ const list elementsToValues(const list& e) { /** * Convert a value to an element. */ -const value valueToElement(const value& t) { +inline const value valueToElement(const value& t) { const list valuesToElements(const list& l); // Convert a name value pair if (isList(t) && !isNil((list)t) && isSymbol(car(t))) { const value n = car(t); - const value v = isNil(cdr(t))? value() : cadr(t); + const value v = isNil(cdr(t))? nilValue : cadr(t); // Convert a single value to an attribute or an element if (!isList(v)) { @@ -221,7 +221,7 @@ const value valueToElement(const value& t) { /** * Convert a list of values to a list of elements. */ -const list valuesToElements(const list& l) { +inline const list valuesToElements(const list& l) { if (isNil(l)) return l; return cons(valueToElement(car(l)), valuesToElements(cdr(l))); @@ -231,72 +231,51 @@ const list valuesToElements(const list& l) { * Returns a selector lambda function which can be used to filter * elements against the given element pattern. */ -struct selectorLambda { - const list select; - selectorLambda(const list& s) : select(s) { - } - const bool evalSelect(const list& s, const list v) const { - if (isNil(s)) - return true; - if (isNil(v)) - return false; - if (car(s) != car(v)) - return false; - return evalSelect(cdr(s), cdr(v)); - } - const bool operator()(const value& v) const { +inline const lambda selector(const list& select) { + return [select](const value& v) -> const bool { + const lambda&, const list&)> evalSelect = [&evalSelect](const list& s, const list& v) -> const bool { + if (isNil(s)) + return true; + if (isNil(v)) + return false; + if (car(s) != car(v)) + return false; + return evalSelect(cdr(s), cdr(v)); + }; if (!isList(v)) return false; return evalSelect(select, v); - } -}; - -const lambda selector(const list s) { - return selectorLambda(s); + }; } /** * Returns the value of the attribute with the given name. */ -struct filterAttribute { - const value name; - filterAttribute(const value& n) : name(n) { - } - const bool operator()(const value& v) const { - return isAttribute(v) && attributeName((list)v) == name; - } -}; - -const value attributeValue(const value& name, const value& l) { - const list f = filter(filterAttribute(name), list(l)); +inline const value attributeValue(const value& name, const value& l) { + const list f = filter([name](const value& v) { + return isAttribute(v) && attributeName((list)v) == name; + }, list(l)); if (isNil(f)) - return value(); + return nilValue; return caddr(car(f)); } /** * Returns child elements with the given name. */ -struct filterElement { - const value name; - filterElement(const value& n) : name(n) { - } - const bool operator()(const value& v) const { - return isElement(v) && elementName((list)v) == name; - } -}; - -const value elementChildren(const value& name, const value& l) { - return filter(filterElement(name), list(l)); +inline const value elementChildren(const value& name, const value& l) { + return filter([name](const value& v) { + return isElement(v) && elementName((list)v) == name; + }, list(l)); } /** * Return the child element with the given name. */ -const value elementChild(const value& name, const value& l) { +inline const value elementChild(const value& name, const value& l) { const list f = elementChildren(name, l); if (isNil(f)) - return value(); + return nilValue; return car(f); } diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp index 4f7f5152aa..1ed1487707 100644 --- a/sca-cpp/trunk/kernel/fstream.hpp +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -69,24 +69,18 @@ namespace tuscany { */ class ofstream : public ostream { public: - ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) { + inline ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) { } - ofstream(FILE* file) : file(file), owner(false) { + inline ofstream(FILE* const file) : file(file), owner(false) { } - ofstream(const ofstream& os) : file(os.file), owner(false) { + inline ofstream(const ofstream& os) : file(os.file), owner(false) { } - const ofstream& operator=(const ofstream& os) { - if(this == &os) - return *this; - file = os.file; - owner = false; - return *this; - } + ofstream& operator=(const ofstream& os) = delete; - ~ofstream() { + inline ~ofstream() { if (!owner) return; if (file == NULL) @@ -94,11 +88,11 @@ public: fclose(file); } - const bool fail() { + inline const bool fail() { return file == NULL; } - ofstream& vprintf(const char* fmt, ...) { + inline ofstream& vprintf(const char* const fmt, ...) { va_list args; va_start (args, fmt); vfprintf (file, fmt, args); @@ -106,19 +100,24 @@ public: return *this; } - ofstream& write(const string& s) { + inline ofstream& write(const string& s) { fwrite(c_str(s), 1, length(s), file); return *this; } - ofstream& flush() { + inline ofstream& write(const char c) { + fwrite(&c, 1, 1, file); + return *this; + } + + inline ofstream& flush() { fflush(file); return *this; } private: - FILE* file; - bool owner; + FILE* const file; + const bool owner; }; /* @@ -126,24 +125,18 @@ private: */ class ifstream : public istream { public: - ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) { + inline ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) { } - ifstream(FILE* file) : file(file), owner(false) { + inline ifstream(FILE* const file) : file(file), owner(false) { } - ifstream(const ifstream& is) : file(is.file), owner(false) { + inline ifstream(const ifstream& is) : file(is.file), owner(false) { } - const ifstream& operator=(const ifstream& is) { - if(this == &is) - return *this; - file = is.file; - owner = false; - return *this; - } + ifstream& operator=(const ifstream& is) = delete; - ~ifstream() { + inline ~ifstream() { if (!owner) return; if (file == NULL) @@ -151,23 +144,23 @@ public: fclose(file); } - const size_t read(void* buf, size_t size) { + inline const size_t read(void* const buf, const size_t size) { return fread(buf, 1, size, file); } - const bool eof() { + inline const bool eof() { return feof(file); } - const bool fail() { + inline const bool fail() { return file == NULL; } - const int get() { + inline const int get() { return fgetc(file); } - const int peek() { + inline const int peek() { int c = fgetc(file); if (c == -1) return c; @@ -176,8 +169,8 @@ public: } private: - FILE* file; - bool owner; + FILE* const file; + const bool owner; }; /** @@ -198,24 +191,24 @@ ifstream cin(stdin); */ class loghstream : public ostream { public: - loghstream(const int level) : level(level), len(0) { + inline loghstream(const int level) : level(level), len(0) { } - ~loghstream() { + inline ~loghstream() { } - ostream& vprintf(const char* fmt, ...) { + inline ostream& vprintf(const char* const fmt, ...) { va_list args; - va_start (args, fmt); + va_start(args, fmt); const int l = vsnprintf(buf + len, (sizeof(buf) - 1) - len, fmt, args); - va_end (args); + va_end(args); len += l; if (len > (int)(sizeof(buf) - 1)) len = sizeof(buf) - 1; return *this; } - ostream& write(const string& s) { + inline ostream& write(const string& s) { if (s != "\n") return this->vprintf("%s", c_str(s)); buf[len] = '\0'; @@ -224,14 +217,23 @@ public: return *this; } - ostream& flush() { + inline ostream& write(const char c) { + if (c != '\n') + return this->vprintf("%c", c); + buf[len] = '\0'; + ap_log_error(NULL, 0, -1, level, 0, ap_server_conf, "%s", buf); + len = 0; + return *this; + } + + inline ostream& flush() { return *this; } private: const int level; int len; - char buf[2049]; + char buf[513]; }; /** @@ -259,11 +261,11 @@ loghstream cdebug(APLOG_DEBUG); /** * Format the current time. */ -const string logTime() { +inline const string logTime() { struct timeval tv; gettimeofday(&tv, NULL); const time_t t = tv.tv_sec; - const tm* lt = localtime(&t); + const tm* const lt = localtime(&t); char ft[32]; strftime(ft, 20, "%a %b %d %H:%M:%S", lt); sprintf(ft + 19, ".%06lu ", (unsigned long)tv.tv_usec); @@ -276,16 +278,16 @@ const string logTime() { */ class logfstream : public ostream { public: - logfstream(FILE* file, const string& type) : file(file), type(type), head(false) { + inline logfstream(FILE* const file, const string& type) : file(file), type(type), head(false) { } - logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) { + inline logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) { } - ~logfstream() { + inline ~logfstream() { } - ostream& vprintf(const char* fmt, ...) { + inline ostream& vprintf(const char* const fmt, ...) { whead(); va_list args; va_start (args, fmt); @@ -294,7 +296,7 @@ public: return *this; } - ostream& write(const string& s) { + inline ostream& write(const string& s) { whead(); fwrite(c_str(s), 1, length(s), file); if (s == "\n") @@ -302,17 +304,25 @@ public: return *this; } - ostream& flush() { + inline ostream& write(const char c) { + whead(); + fwrite(&c, 1, 1, file); + if (c == '\n') + head = false; + return *this; + } + + inline ostream& flush() { fflush(file); return *this; } private: - FILE* file; + FILE* const file; const string type; bool head; - const unsigned long tid() const { + inline const unsigned long tid() const { #ifdef WANT_THREADS return (unsigned long)pthread_self(); #else @@ -320,7 +330,7 @@ private: #endif } - ostream& whead() { + inline ostream& whead() { if (head) return *this; head = true; @@ -348,7 +358,7 @@ logfstream cdebug(stderr, "debug"); bool debug_isLoggingSet = false; bool debug_isLoggingEnv = false; -const bool debug_isLogging() { +inline const bool debug_isLogging() { if (debug_isLoggingSet) return debug_isLoggingEnv; debug_isLoggingEnv = getenv("TUSCANY_DEBUG_LOG") != NULL; @@ -366,8 +376,8 @@ const bool debug_isLogging() { /** * Log a debug message. */ -const bool debugLog(const string& msg) { - gc_scoped_pool p; +inline const bool debugLog(const string& msg) { + const gc_scoped_pool p; cdebug << msg << endl; return true; } @@ -375,8 +385,8 @@ const bool debugLog(const string& msg) { /** * Log a debug message and a value. */ -template const bool debugLog(const V& v, const string& msg) { - gc_scoped_pool p; +template inline const bool debugLog(const V& v, const string& msg) { + const gc_scoped_pool p; cdebug << msg << ": " << v << endl; return true; } @@ -384,8 +394,8 @@ template const bool debugLog(const V& v, const string& msg) { /** * Log a debug message and two values. */ -template const bool debugLog(const V& v, const W& w, const string& msg) { - gc_scoped_pool p; +template inline const bool debugLog(const V& v, const W& w, const string& msg) { + const gc_scoped_pool p; cdebug << msg << ": " << v << " : " << w << endl; return true; } diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp index 60117dab98..0a88cf51d9 100644 --- a/sca-cpp/trunk/kernel/function.hpp +++ b/sca-cpp/trunk/kernel/function.hpp @@ -23,7 +23,9 @@ #define tuscany_function_hpp /** - * Lambda function type. + * Lambda function type that enforces pass by ref and constant parameters, + * allocates memory only as needed and using an APR memory pool, is about + * 2 times faster than std::function and between 1/4 and 1/6 of its size. */ #include @@ -46,16 +48,16 @@ long int countELambdas = 0; long int countCLambdas = 0; long int countFLambdas = 0; -bool resetLambdaCounters() { +inline const bool resetLambdaCounters() { countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0; return true; } -bool checkLambdaCounters() { +inline const bool checkLambdaCounters() { return countLambdas == 0; } -bool printLambdaCounters() { +inline const bool printLambdaCounters() { cout << "countLambdas " << countLambdas << endl; cout << "countELambdas " << countELambdas << endl; cout << "countFLambdas " << countFLambdas << endl; @@ -80,38 +82,32 @@ bool printLambdaCounters() { template class Callable { public: - Callable() { + inline Callable() noexcept { } - virtual const size_t size() const = 0; - - virtual const R operator()(P... p) const = 0; + virtual const R operator()(const P&&... p) const noexcept = 0; - virtual ~Callable() { + inline virtual ~Callable() noexcept { } - template class Proxy: public Callable { + template class Proxy: public Callable { public: - Proxy(const F& f) : function(f) { + inline Proxy(const F& f) noexcept : function(f) { debug_inc(countProxies); debug_inc(countFProxies); } - Proxy(const Proxy& p) : function(p.function) { + inline Proxy(const Proxy& p) noexcept : function(p.function) { debug_inc(countProxies); debug_inc(countCProxies); } - ~Proxy() { + inline ~Proxy() noexcept { debug_dec(countProxies); } - virtual const R operator() (P... p) const { - return function(std::forward

(p)...); - } - - virtual const size_t size() const { - return sizeof(function); + virtual const R operator() (const P&&... p) const noexcept { + return function(std::forward(p)...); } private: @@ -123,67 +119,68 @@ template class lambda; template class lambda { public: - lambda() : callable(0) { + inline lambda() noexcept : callable(NULL) { debug_inc(countLambdas); debug_inc(countELambdas); } - template lambda(const F f) { + template inline lambda(const F f) noexcept : callable(mkproxy(f)) { debug_inc(countLambdas); debug_inc(countFLambdas); + } - typedef typename CallableType::template Proxy ProxyType; - callable = gc_ptr(new (gc_new()) ProxyType(f)); + template inline lambda(const gc_mutable_ref& r) noexcept : callable(mkproxy(*(F*)r)) { + debug_inc(countLambdas); + debug_inc(countFLambdas); } - lambda(const lambda& l) { + inline lambda(const lambda& l) noexcept : callable(l.callable) { debug_inc(countLambdas); debug_inc(countCLambdas); - callable = l.callable; } - const lambda& operator=(const lambda& l) { - if (this == &l) - return *this; - callable = l.callable; - return *this; - } + lambda& operator=(const lambda& l) = delete; - ~lambda() { + inline ~lambda() noexcept { debug_dec(countLambdas); } - const bool operator==(const lambda& l) const { + inline const bool operator==(const lambda& l) const noexcept { if (this == &l) return true; - return callable == l.callable; + return false; } - const bool operator!=(const lambda& l) const { + inline const bool operator!=(const lambda& l) const noexcept { return !this->operator==(l); } - const R operator()(P... p) const { - return (*callable)(std::forward

(p)...); + inline const R operator()(const P&... p) const noexcept { + return (*callable)(std::forward(p)...); } template friend ostream& operator<<(ostream&, const lambda&); - template friend const bool isNil(const lambda& l); + template friend const bool isNil(const lambda& l) noexcept; private: typedef Callable CallableType; - gc_ptr callable; + const gc_ptr callable; + + template inline gc_ptr mkproxy(const F& f) noexcept { + typedef typename CallableType::template Proxy ProxyType; + return gc_ptr(new (gc_new()) ProxyType(f)); + } }; -template ostream& operator<<(ostream& out, const lambda& l) { +template inline ostream& operator<<(ostream& out, const lambda& l) { return out << "lambda::" << l.callable; } /** * Return true if a lambda is nil. */ -template const bool isNil(const lambda& l) { - return ((void*)l.callable) == 0; +template inline const bool isNil(const lambda& l) noexcept { + return (const void*)l.callable == NULL; } /** @@ -191,11 +188,11 @@ template const bool isNil(const lambda& l) { */ template class curried { public: - curried(const lambda& f, const T& v): v(v), f(f) { + inline curried(const lambda& f, const T& v) noexcept: v(v), f(f) { } - const R operator()(P... p) const { - return f(v, std::forward

(p)...); + inline const R operator()(const P&... p) const noexcept { + return f(v, std::forward(p)...); } private: @@ -203,36 +200,29 @@ private: const lambdaf; }; -template const lambda curry(const lambda& f, const T& t) { +template inline const lambda curry(const lambda& f, const T& t) noexcept { return curried(f, t); } -template const lambda curry(const lambda& f, const T& t, const U& u) { +template inline const lambda curry(const lambda& f, const T& t, const U& u) noexcept { return curry(curry(f, t), u); } -template const lambda curry(const lambda& f, const T& t, const U& u, const V& v) { +template inline const lambda curry(const lambda& f, const T& t, const U& u, const V& v) noexcept { return curry(curry(curry(f, t), u), v); } /** * A lambda function that returns the given value. */ -template class returnResult { -public: - returnResult(const T& v) : - v(v) { - } - const T operator()() const { - return v; - } -private: - const T v; -}; - -template const lambda result(const T& v) { - return returnResult (v); +template inline const lambda result(const T& v) { + return [v]()->T { return v; }; } +/** + * Commonly used lambda types. + */ +typedef lambda blambda; + } #endif /* tuscany_function_hpp */ diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index 32ad8160cc..7853c551dc 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -49,7 +49,7 @@ namespace tuscany /** * Force a core dump on assertion violation. */ -bool assertOrFail(const bool expr) { +inline const bool assertOrFail(const bool expr) { if (!expr) abort(); return true; @@ -64,63 +64,135 @@ bool assertOrFail(const bool expr) { /** * Pointer to a value. */ +#ifdef WANT_RAW_PTR + +template using gc_ptr = T*; + +#else + template class gc_ptr { public: - gc_ptr(T* ptr = NULL) throw() : ptr(ptr) { + inline gc_ptr(T* const ptr = NULL) noexcept : ptr(ptr) { + } + + inline ~gc_ptr() noexcept { + } + + inline gc_ptr(const gc_ptr& r) noexcept : ptr(r.ptr) { + } + + gc_ptr& operator=(const gc_ptr& r) = delete; + + inline const bool operator==(const gc_ptr& r) const noexcept { + if (this == &r) + return true; + return ptr == r.ptr; + } + + inline const bool operator==(const T* const p) const noexcept { + return ptr == p; + } + + inline const bool operator!=(const gc_ptr& r) const noexcept { + return !this->operator==(r); + } + + inline const bool operator!=(const T* const p) const noexcept { + return !this->operator==(p); + } + + inline T& operator*() const noexcept { + return *ptr; + } + + inline T* const operator->() const noexcept { + return ptr; + } + + inline operator T* const () const noexcept { + return ptr; + } + +private: + T* const ptr; +}; + +#endif + +/** + * Mutable pointer to an immutable value. + */ +#ifdef WANT_RAW_PTR + +template using gc_mutable_ptr = T*; + +#else + +template class gc_mutable_ptr { +public: + inline gc_mutable_ptr(T* const ptr = NULL) noexcept : ptr(ptr) { } - ~gc_ptr() throw() { + inline ~gc_mutable_ptr() noexcept { } - gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) { + inline gc_mutable_ptr(const gc_mutable_ptr& r) noexcept : ptr(r.ptr) { } - gc_ptr& operator=(const gc_ptr& r) throw() { - if(this == &r) + inline gc_mutable_ptr& operator=(T* const p) noexcept { + ptr = p; + return *this; + } + + inline gc_mutable_ptr& operator=(const gc_mutable_ptr& r) noexcept { + if (this == &r) return *this; ptr = r.ptr; return *this; } - const bool operator==(const gc_ptr& r) const throw() { + inline const bool operator==(const gc_mutable_ptr& r) const noexcept { if (this == &r) return true; return ptr == r.ptr; } - const bool operator==(T* p) const throw() { + inline const bool operator==(T* const p) const noexcept { return ptr == p; } - const bool operator!=(const gc_ptr& r) const throw() { + inline const bool operator!=(const gc_mutable_ptr& r) const noexcept { return !this->operator==(r); } - const bool operator!=(T* p) const throw() { + inline const bool operator!=(T* const p) const noexcept { return !this->operator==(p); } - T& operator*() const throw() { + inline T& operator*() const noexcept { return *ptr; } - T* operator->() const throw() { + inline T* const operator->() const noexcept { return ptr; } - operator T*() const throw() { + inline operator T* const () const noexcept { return ptr; } +private: T* ptr; }; +#endif + /** * Initialize APR. */ class gc_apr_context_t { public: - gc_apr_context_t() { + inline gc_apr_context_t() { apr_initialize(); } } gc_apr_context; @@ -130,36 +202,31 @@ public: */ class gc_pool { public: - gc_pool() : apr_pool(NULL) { + inline gc_pool() noexcept : apr_pool(NULL) { } - gc_pool(apr_pool_t* p) : apr_pool(p) { + inline gc_pool(apr_pool_t* const p) noexcept : apr_pool(p) { } - gc_pool(const gc_pool& pool) : apr_pool(pool.apr_pool) { + inline gc_pool(const gc_pool& pool) noexcept : apr_pool(pool.apr_pool) { } - gc_pool& operator=(const gc_pool& pool) { - if (this == &pool) - return *this; - apr_pool = pool.apr_pool; - return *this; - } + gc_pool& operator=(const gc_pool& pool) = delete; private: - friend apr_pool_t* pool(const gc_pool& pool); + friend apr_pool_t* pool(const gc_pool& pool) noexcept; friend class gc_global_pool_t; friend class gc_child_pool; friend class gc_local_pool; friend class gc_scoped_pool; - apr_pool_t* apr_pool; + apr_pool_t* const apr_pool; }; /** * Return the APR pool used by a gc_pool. */ -apr_pool_t* pool(const gc_pool& pool) { +inline apr_pool_t* pool(const gc_pool& pool) noexcept { return pool.apr_pool; } @@ -168,35 +235,51 @@ apr_pool_t* pool(const gc_pool& pool) { */ #ifdef WANT_THREADS +#ifdef __clang__ + class gc_pool_stack_t { public: - gc_pool_stack_t() { - int rc = pthread_key_create(&key, NULL); - assertOrFail(rc == 0); + inline gc_pool_stack_t() noexcept : key(mkkey()) { } - operator apr_pool_t*() const { - return static_cast(pthread_getspecific(key)); + inline operator apr_pool_t*() const noexcept { + return (apr_pool_t*)pthread_getspecific(key); } - const gc_pool_stack_t& operator=(apr_pool_t* p) { + inline const gc_pool_stack_t& operator=(apr_pool_t* p) noexcept { pthread_setspecific(key, p); return *this; } private: pthread_key_t key; + + pthread_key_t mkkey() { + pthread_key_t k; + int rc = pthread_key_create(&k, NULL); + assertOrFail(rc == 0); + return k; + } + } gc_pool_stack; #else + +__thread apr_pool_t* gc_pool_stack = NULL; + +#endif + +#else + apr_pool_t* gc_pool_stack = NULL; + #endif /** * Push a pool onto the stack. */ -apr_pool_t* gc_push_pool(apr_pool_t* pool) { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_push_pool(apr_pool_t* pool) noexcept { + apr_pool_t* const p = gc_pool_stack; gc_pool_stack = pool; return p; } @@ -204,8 +287,8 @@ apr_pool_t* gc_push_pool(apr_pool_t* pool) { /** * Pop a pool from the stack. */ -apr_pool_t* gc_pop_pool(apr_pool_t* pool) { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_pop_pool(apr_pool_t* pool) noexcept { + apr_pool_t* const p = gc_pool_stack; gc_pool_stack = pool; return p; } @@ -213,16 +296,17 @@ apr_pool_t* gc_pop_pool(apr_pool_t* pool) { /** * Return the current memory pool. */ -apr_pool_t* gc_current_pool() { - apr_pool_t* p = gc_pool_stack; +inline apr_pool_t* const gc_current_pool() noexcept { + apr_pool_t* const p = gc_pool_stack; if (p != NULL) return p; // Create a parent pool for the current thread - apr_pool_create(&p, NULL); - assertOrFail(p != NULL); - gc_push_pool(p); - return p; + apr_pool_t* pp; + apr_pool_create(&pp, NULL); + assertOrFail(pp != NULL); + gc_push_pool(pp); + return pp; } /** @@ -231,25 +315,23 @@ apr_pool_t* gc_current_pool() { class gc_child_pool : public gc_pool { public: - gc_child_pool() : gc_pool(NULL), owner(true) { - apr_pool_create(&apr_pool, gc_current_pool()); - assertOrFail(apr_pool != NULL); + inline gc_child_pool() noexcept : gc_pool(mkpool()), owner(true) { } - gc_child_pool(const gc_child_pool& p) : gc_pool(p.apr_pool), owner(false) { - } - - const gc_child_pool& operator=(const gc_child_pool& p) { - if(this == &p) - return *this; - apr_pool = p.apr_pool; - owner = false; - return *this; + inline gc_child_pool(const gc_child_pool& p) noexcept : gc_pool(p.apr_pool), owner(false) { } + gc_child_pool& operator=(const gc_child_pool& p) = delete; private: - bool owner; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** @@ -258,29 +340,28 @@ private: class gc_local_pool : public gc_pool { public: - gc_local_pool() : gc_pool(NULL), owner(true) { - apr_pool_create(&apr_pool, gc_current_pool()); - assertOrFail(apr_pool != NULL); + inline gc_local_pool() noexcept : gc_pool(mkpool()), owner(true) { } - ~gc_local_pool() { + inline ~gc_local_pool() noexcept { if (owner) apr_pool_destroy(apr_pool); } - gc_local_pool(const gc_local_pool& p) : gc_pool(p.apr_pool), owner(false) { + inline gc_local_pool(const gc_local_pool& p) noexcept : gc_pool(p.apr_pool), owner(false) { } - const gc_local_pool& operator=(const gc_local_pool& p) { - if(this == &p) - return *this; - apr_pool = p.apr_pool; - owner = false; - return *this; - } + gc_local_pool& operator=(const gc_local_pool& p) = delete; private: - bool owner; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** @@ -290,66 +371,64 @@ private: class gc_scoped_pool : public gc_pool { public: - gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owner(true) { - apr_pool_create(&apr_pool, prev); - assertOrFail(apr_pool != NULL); + inline gc_scoped_pool() noexcept : gc_pool(mkpool()), prev(gc_current_pool()), owner(true) { gc_push_pool(apr_pool); } - gc_scoped_pool(apr_pool_t* p) : gc_pool(p), prev(gc_current_pool()), owner(false) { + inline gc_scoped_pool(apr_pool_t* p) noexcept : gc_pool(p), prev(gc_current_pool()), owner(false) { gc_push_pool(apr_pool); } - ~gc_scoped_pool() { + inline ~gc_scoped_pool() noexcept { if (owner) apr_pool_destroy(apr_pool); gc_pop_pool(prev); } - gc_scoped_pool(const gc_scoped_pool& p) : gc_pool(p.apr_pool), prev(p.prev), owner(false) { + inline gc_scoped_pool(const gc_scoped_pool& p) noexcept : gc_pool(p.apr_pool), prev(p.prev), owner(false) { } - const gc_scoped_pool& operator=(const gc_scoped_pool& p) { - if(this == &p) - return *this; - apr_pool = p.apr_pool; - prev = p.prev; - owner = false; - return *this; - } + gc_scoped_pool& operator=(const gc_scoped_pool& p) = delete; private: - apr_pool_t* prev; - bool owner; + apr_pool_t* const prev; + const bool owner; + + apr_pool_t* const mkpool() { + apr_pool_t* p; + apr_pool_create(&p, gc_current_pool()); + assertOrFail(p != NULL); + return p; + } }; /** * Allocates a pointer to an object allocated from a memory pool and * register a cleanup callback for it. */ -template apr_status_t gc_pool_cleanup(void* v) { +template inline apr_status_t gc_pool_cleanup(void* v) { T* t = (T*)v; t->~T(); return APR_SUCCESS; } -template T* gc_new(apr_pool_t* p) { +template inline T* const gc_new(apr_pool_t* const p) noexcept { void* gc_new_ptr = apr_palloc(p, sizeof(T)); assertOrFail(gc_new_ptr != NULL); apr_pool_cleanup_register(p, gc_new_ptr, gc_pool_cleanup, apr_pool_cleanup_null) ; return (T*)(gc_new_ptr); } -template T* gc_new(const gc_pool& p) { +template inline T* const gc_new(const gc_pool& p) noexcept { return gc_new(pool(p)); } -template T* gc_new() { +template inline T* const gc_new() noexcept { return gc_new(gc_current_pool()); } -template apr_status_t gc_pool_acleanup(void* v) { - size_t* m = static_cast(v); +template inline apr_status_t gc_pool_acleanup(void* v) { + size_t* m = (size_t*)v; size_t n = *m; T* t = (T*)(m + 1); for (size_t i = 0; i < n; i++, t++) @@ -357,40 +436,101 @@ template apr_status_t gc_pool_acleanup(void* v) { return APR_SUCCESS; } -template T* gc_anew(apr_pool_t* p, size_t n) { - size_t* gc_anew_ptr = static_cast(apr_palloc(p, sizeof(size_t) + sizeof(T) * n)); +template inline T* const gc_anew(apr_pool_t* const p, const size_t n) noexcept { + size_t* const gc_anew_ptr = (size_t*)apr_palloc(p, sizeof(size_t) + sizeof(T) * n); assertOrFail(gc_anew_ptr != NULL); *gc_anew_ptr = n; apr_pool_cleanup_register(p, gc_anew_ptr, gc_pool_acleanup, apr_pool_cleanup_null) ; return (T*)(gc_anew_ptr + 1); } -template T* gc_anew(const gc_pool& p, size_t n) { +template inline T* const gc_anew(const gc_pool& p, const size_t n) noexcept { return gc_anew(pool(p), n); } -template T* gc_anew(size_t n) { +template inline T* const gc_anew(const size_t n) noexcept { return gc_anew(gc_current_pool(), n); } /** * Allocate an array of chars. */ -char* gc_cnew(apr_pool_t* p, size_t n) { - char* gc_cnew_ptr = static_cast(apr_palloc(p, n)); +inline char* const gc_cnew(apr_pool_t* const p, const size_t n) noexcept { + char* const gc_cnew_ptr = (char*)apr_palloc(p, n); assertOrFail(gc_cnew_ptr != NULL); return gc_cnew_ptr; } -char* gc_cnew(size_t n) { +inline char* const gc_cnew(const size_t n) noexcept { return gc_cnew(gc_current_pool(), n); } +/** + * Mutable reference to an immutable value. + */ +template class gc_mutable_ref { +public: + inline gc_mutable_ref() noexcept : ptr(new (gc_new()) T()) { + } + + inline ~gc_mutable_ref() noexcept { + } + + inline gc_mutable_ref(const gc_mutable_ref& r) noexcept : ptr(r.ptr) { + } + + inline gc_mutable_ref(const T& v) noexcept : ptr(new (gc_new()) T(v)) { + } + + inline gc_mutable_ref& operator=(const gc_mutable_ref& r) noexcept { + if (this == &r) + return *this; + ptr = r.ptr; + return *this; + } + + inline gc_mutable_ref& operator=(const T& v) noexcept { + ptr = new (gc_new()) T(v); + return *this; + } + + inline const bool operator==(const gc_mutable_ref& r) const noexcept { + if (this == &r) + return true; + if (ptr == r.ptr) + return true; + return *ptr == *r.ptr; + } + + inline const bool operator==(const T& v) const noexcept { + return *ptr == v; + } + + inline const bool operator!=(const gc_mutable_ref& r) const noexcept { + return !this->operator==(r); + } + + inline const bool operator!=(const T& v) const noexcept { + return !this->operator==(v); + } + + inline operator T&() const noexcept { + return *ptr; + } + + inline operator T* const () const noexcept { + return ptr; + } + +private: + T* ptr; +}; + /** * Pool based equivalent of the standard malloc function. */ -void* gc_pool_malloc(size_t n) { - size_t* ptr = static_cast(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); +inline void* gc_pool_malloc(size_t n) { + size_t* ptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n); assertOrFail(ptr != NULL); *ptr = n; return ptr + 1; @@ -399,9 +539,9 @@ void* gc_pool_malloc(size_t n) { /** * Pool based equivalent of the standard realloc function. */ -void* gc_pool_realloc(void* ptr, size_t n) { - size_t size = *(static_cast(ptr) - 1); - size_t* rptr = static_cast(apr_palloc(gc_current_pool(), sizeof(size_t) + n)); +inline void* gc_pool_realloc(void* ptr, size_t n) { + size_t size = *(((size_t*)ptr) - 1); + size_t* rptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n); assertOrFail(rptr != NULL); *rptr = n; memcpy(rptr + 1, ptr, size < n? size : n); @@ -411,15 +551,15 @@ void* gc_pool_realloc(void* ptr, size_t n) { /** * Pool based equivalent of the standard free function. */ -void gc_pool_free(unused void* ptr) { +inline void gc_pool_free(unused void* ptr) { // Memory allocated from a pool is freed when the pool is freed } /** * Pool based equivalent of the standard strdup function. */ -char* gc_pool_strdup(const char* str) { - char* dptr = static_cast(gc_pool_malloc(strlen(str) + 1)); +inline char* gc_pool_strdup(const char* str) { + char* dptr = (char*)gc_pool_malloc(strlen(str) + 1); assertOrFail(dptr != NULL); strcpy(dptr, str); return dptr; @@ -434,9 +574,9 @@ char* gc_pool_strdup(const char* str) { /** * Mmap based equivalent of the standard malloc function. */ -void* gc_mmap_malloc(size_t n, unused const void* caller) { +inline void* gc_mmap_malloc(size_t n, unused const void* caller) { //printf("gc_mmap_malloc %d", n); - size_t* ptr = static_cast(mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); + size_t* ptr = (size_t*)mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); assertOrFail(ptr != NULL); *ptr = n; //printf(" %p\n", ptr + 1); @@ -446,12 +586,12 @@ void* gc_mmap_malloc(size_t n, unused const void* caller) { /** * Mmap based equivalent of the standard realloc function. */ -void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { +inline void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { if (ptr == NULL) return gc_mmap_malloc(n, caller);; //printf("gc_mmap_realloc %p %d", ptr, n); - size_t size = *(static_cast(ptr) - 1); - size_t* rptr = static_cast(mremap(static_cast(ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL)); + size_t size = *(((size_t*)ptr) - 1); + size_t* rptr = (size_t*)mremap(((size_t*)ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL); assertOrFail(rptr != NULL); *rptr = n; //printf(" %p\n", rptr + 1); @@ -461,18 +601,18 @@ void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) { /** * Mmap based equivalent of the standard free function. */ -void gc_mmap_free(void* ptr, unused const void* caller) { +inline void gc_mmap_free(void* ptr, unused const void* caller) { //printf("gc_mmap_free %p\n", ptr); if (ptr == NULL) return; - size_t size = *(static_cast(ptr) - 1); - munmap(static_cast(ptr) - 1, sizeof(size_t) + size); + size_t size = *(((size_t*)ptr) - 1); + munmap(((size_t*)ptr) - 1, sizeof(size_t) + size); } /** * Mmap based equivalent of the standard memalign function. */ -void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) { +inline void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) { //printf("gc_mmap_memalign %d %d\n", alignment, n); return gc_mmap_malloc(n, caller); } @@ -480,7 +620,7 @@ void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* cal /** * Install the mmap based memory allocation functions. */ -void gc_mmap_init_hook(void) { +inline void gc_mmap_init_hook(void) { __malloc_hook = gc_mmap_malloc; __realloc_hook = gc_mmap_realloc; __free_hook = gc_mmap_free; diff --git a/sca-cpp/trunk/kernel/hash-test.cpp b/sca-cpp/trunk/kernel/hash-test.cpp index 4e6a3654e5..a012cd5ee7 100644 --- a/sca-cpp/trunk/kernel/hash-test.cpp +++ b/sca-cpp/trunk/kernel/hash-test.cpp @@ -30,89 +30,64 @@ namespace tuscany { -bool testCrc32hash() { +const bool testCrc32hash() { const string key("This is a test key"); - unsigned int h = crc32hash(c_str(key), length(key)); + const unsigned int h = crc32hash(c_str(key), length(key)); assert(h != 0); return true; } -bool testTimes33hash() { +const bool testTimes33hash() { const string key("This is a test key"); - unsigned int h = times33hash(c_str(key), length(key)); + const unsigned int h = times33hash(c_str(key), length(key)); assert(h != 0); return true; } -bool testMurmurhash() { +const bool testMurmurhash() { const string key("This is a test key"); - unsigned int h = murmurhash(c_str(key), length(key)); + const unsigned int h = murmurhash(c_str(key), length(key)); assert(h != 0); return true; } -bool testPortablemurmurhash() { +const bool testPortablemurmurhash() { const string key("This is a test key"); - unsigned int h = portablemurmurhash(c_str(key), length(key)); + const unsigned int h = portablemurmurhash(c_str(key), length(key)); assert(h != 0); return true; } -struct crc32hashTest { - const string key; - crc32hashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = crc32hash(c_str(key), length(key)); +const bool testHashPerf() { + const string key("This is a test key"); + const int count = 100000; + + const blambda crc32 = [key]() -> const bool { + const unsigned int h = crc32hash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct times33hashTest { - const string key; - times33hashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = times33hash(c_str(key), length(key)); + }; + cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl; + + const blambda times33 = [key]() -> const bool { + const unsigned int h = times33hash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct murmurhashTest { - const string key; - murmurhashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = murmurhash(c_str(key), length(key)); + }; + cout << "times33hash test " << time(times33, 5, count) << " ms" << endl; + + const blambda murmur = [key]() -> const bool { + const unsigned int h = murmurhash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -struct portablemurmurhashTest { - const string key; - portablemurmurhashTest(const string& key) : key(key) { - } - bool operator()() const { - unsigned int h = portablemurmurhash(c_str(key), length(key)); + }; + cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl; + + const blambda portablemurmur = [key]() -> const bool { + const unsigned int h = portablemurmurhash(c_str(key), length(key)); assert(h != 0); return true; - } -}; - -bool testHashPerf() { - const string key("This is a test key"); - const int count = 100000; - - const lambda crc32 = crc32hashTest(key); - cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl; - const lambda times33 = times33hashTest(key); - cout << "times33hash test " << time(times33, 5, count) << " ms" << endl; - const lambda murmur = murmurhashTest(key); - cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl; - const lambda portablemurmur = portablemurmurhashTest(key); + }; cout << "portable murmurhash test " << time(portablemurmur, 5, count) << " ms" << endl; return true; @@ -121,7 +96,7 @@ bool testHashPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testCrc32hash(); diff --git a/sca-cpp/trunk/kernel/hash.hpp b/sca-cpp/trunk/kernel/hash.hpp index 993511e3c2..9e80c977fe 100644 --- a/sca-cpp/trunk/kernel/hash.hpp +++ b/sca-cpp/trunk/kernel/hash.hpp @@ -43,7 +43,7 @@ namespace tuscany * tree at contrib/ltree/crc32.[ch] and from FreeBSD at * src/usr.bin/cksum/crc32.c. */ -const unsigned int crc32hash(const char* data, const size_t len) { +inline const unsigned int crc32hash(const char* const data, const size_t len) { return (unsigned int)apr_memcache_hash_default(NULL, data, len); } @@ -89,7 +89,7 @@ const unsigned int crc32hash(const char* data, const size_t len) { * * -- Ralf S. Engelschall */ -const unsigned int times33hash(const char* data, const size_t len) { +inline const unsigned int times33hash(const char* const data, const size_t len) { apr_ssize_t l = len; return apr_hashfunc_default(data, &l); } @@ -107,7 +107,7 @@ const unsigned int times33hash(const char* data, const size_t len) { * Passes Bob Jenkin's frog.c torture-test. No collisions possible for 4 byte * keys, no small 1 to 7 bit differentials. */ -const unsigned int murmurhash(const char* key, const size_t klen) { +inline const unsigned int murmurhash(const char* const key, const size_t klen) { unsigned int len = (unsigned int)klen; const unsigned int seed = 0; @@ -153,7 +153,7 @@ const unsigned int murmurhash(const char* key, const size_t klen) { * An endian and alignment neutral, but half the speed, version of * the murmur hash. */ -const unsigned int portablemurmurhash(const char* key, const size_t klen) { +inline const unsigned int portablemurmurhash(const char* const key, const size_t klen) { unsigned int len = (unsigned int)klen; const unsigned int seed = 0; @@ -199,7 +199,7 @@ const unsigned int portablemurmurhash(const char* key, const size_t klen) { return h; } -const unsigned int hashselect(const unsigned int hash, const unsigned int max) { +inline const unsigned int hashselect(const unsigned int hash, const unsigned int max) { return hash % max; } diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp index 4d2ca2ba81..0e2a14246a 100644 --- a/sca-cpp/trunk/kernel/kernel-test.cpp +++ b/sca-cpp/trunk/kernel/kernel-test.cpp @@ -23,6 +23,7 @@ * Test kernel functions. */ +#include #include #include "string.hpp" #include "sstream.hpp" @@ -36,58 +37,324 @@ namespace tuscany { -struct inc { - int i; - inc(int i) : +const bool ptrPerf() { + int x = 1; + for (int i = 0; i < 10000; i++) { + int* const y = &x; + int z = *y + *y; + z = z + 1; + } + return true; +} + +const bool gcptrPerf() { + int x = 1; + for (int i = 0; i < 10000; i++) { + const gc_ptr y = &x; + int z = *y + *y; + z = z + 1; + } + return true; +} + +const bool testPtrPerf() { + { + const gc_scoped_pool gcp; + const blambda pp = ptrPerf; + cout << "Pointer test " << (time(pp, 5, 10000) / 10000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda gpp = gcptrPerf; + cout << "GC Pointer test " << (time(gpp, 5, 10000) / 10000) << " ms" << endl; + } + return true; +} + +class incFunctor { +public: + incFunctor(const int i) : i(i) { } const int operator()(const int x) const { return x + i; } +private: + const int i; }; const int square(const int x) { return x * x; } -int mapLambda(lambda f, int v) { +const int mapLambda(lambda f, int v) { return f(v); } -bool testLambda() { - const lambda sq(square); +const lambda mksquare() { + return square; +} + +const bool testSizes() { + const gc_ptr p(NULL); + cout << "sizeof gc_ptr " << sizeof(p) << endl; + const lambda sq(square); + cout << "sizeof C function lambda " << sizeof(sq) << endl; + const lambda incl(incFunctor(10)); + cout << "sizeof functor lambda " << sizeof(incl) << endl; + const std::function sqf(square); + cout << "sizeof C function std::function " << sizeof(sqf) << endl; + const std::function incf(incFunctor(10)); + cout << "sizeof functor std::function " << sizeof(incf) << endl; + const string s("abcd"); + cout << "sizeof string " << sizeof(s) << endl; + const string v(s); + cout << "sizeof val " << sizeof(v) << endl; + const list li = cons(2, mklist(3, 4)); + cout << "sizeof list " << sizeof(li) << endl; + const list ls = cons("a", mklist("b", "c")); + cout << "sizeof list " << sizeof(ls) << endl; + const list lv = cons("a", mklist("b", "c")); + cout << "sizeof list " << sizeof(lv) << endl; + return true; +} + +const bool testLambda() { + const lambda sq(square); assert(sq(2) == 4); + + const lambda()> mksq(mksquare); + assert(mksq()(2) == 4); + assert(mapLambda(sq, 2) == 4); assert(mapLambda(square, 2) == 4); - const lambda incf(inc(10)); + const lambda incf(incFunctor(10)); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); - assert(mapLambda(inc(10), 1) == 11); + assert(mapLambda(incFunctor(10), 1) == 11); + + const int base = 10; + auto incl11 = [base](const int i) { return base + i; }; + const lambda incl(incl11); + assert(incl(1) == 11); + assert(mapLambda(incl, 1) == 11); + assert(mapLambda(incl11, 1) == 11); + + const lambda il(incf); + assert(il(1) == 11); + const lambda sl(square); + assert(sl(2) == 4); + return true; +} + +int constructCopiable = 0; +int copyCopiable = 0; + +class Copiable { +public: + Copiable() { + assert(false); + } + + Copiable(const string& s) : s(s) { + constructCopiable++; + } + + Copiable(const Copiable& c) : s(c.s) { + copyCopiable++; + } + + Copiable& operator=(const Copiable& c) = delete; + + ~Copiable() { + } + + void doit() const { + } + +private: + const string s; +}; + +bool testLambdaRef(const Copiable& c) { + [&c] { c.doit(); }(); + return true; +} + +bool testLambdaCopy(const Copiable& c) { + [c] { c.doit(); }(); + return true; +} + +const bool testCopiable() { + const Copiable ac = Copiable("assigned"); + ac.doit(); + assert(constructCopiable = 1); + assert(copyCopiable = 1); + + const Copiable ac2 = []{ return Copiable("returned"); }(); + ac2.doit(); + assert(constructCopiable = 2); + assert(copyCopiable = 2); + + const Copiable rc = Copiable("captured by ref"); + testLambdaRef(rc); + assert(constructCopiable = 3); + assert(copyCopiable = 3); + + const Copiable cc = Copiable("captured by value"); + testLambdaCopy(cc); + assert(constructCopiable = 4); + assert(copyCopiable = 5); - lambda l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); return true; } -bool testLambdaGC() { +const bool testMutable() { + { + gc_mutable_ref s = string("aaa"); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref s; + assert(s == ""); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref v; + assert(isNil((value)v)); + v = 1; + assert(v == 1); + } + return true; +} + +const bool testLambdaGC() { resetLambdaCounters(); { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testLambda(); } assert(checkLambdaCounters()); return true; } -int countElements = 0; +class sint { +public: + sint(const int i) : i(i) { + } + const int i; + char b[4]; +}; -struct Element { - int i; +const int mult(const sint& a, const sint& b) { + return a.i * b.i; +} + +const bool testCurry() { + const lambda mult2 = curry((lambda)mult, sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool curryPerf() { + const sint a(2); + const sint b(3); + const lambda mult2 = curry((lambda)mult, a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +class multFunctor { +public: + multFunctor(const sint& a) : a(a) { + } + const int operator()(const sint& b) const { + return a.i * b.i; + } +private: + const sint a; +}; + +const bool testFunctor() { + const lambda mult2 = multFunctor(sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool functorPerf() { + const sint a(2); + const sint b(3); + const lambda mult2 = lambda(multFunctor(a)); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const bool test11Lambda() { + const sint a(2); + assert(6 == [a](const sint& b) { return a.i * b.i; } (sint(3))); + return true; +} + +const lambda multlambda11(const sint& a) { + return [a](const sint& b) { return a.i * b.i; }; +} + +const bool lambda11Perf() { + const sint a(2); + const sint b(3); + const lambda mult2 = multlambda11(a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const std::function multfunction11(const sint& a) { + return [a](const sint& b) { return a.i * b.i; }; +} + +const bool function11Perf() { + const sint a(2); + const sint b(3); + const std::function mult2 = multfunction11(a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const bool testFuncPerf() { + { + const gc_scoped_pool gcp; + const blambda cp = curryPerf; + cout << "Curry test " << (time(cp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda fp = functorPerf; + cout << "Functor test " << (time(fp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = lambda11Perf; + cout << "Lambda11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = function11Perf; + cout << "Function11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + return true; +} +int countElements = 0; + +class Element { +public: Element() : i(0) { countElements++; } @@ -107,13 +374,16 @@ struct Element { const bool operator==(const Element& o) const { return o.i == i; } + + int i; }; + ostream& operator<<(ostream& out, const Element& v) { out << v.i ; return out; } -bool testCons() { +const bool testCons() { assert(car(cons(2, mklist(3))) == 2); assert(car(cdr(cons(2, mklist(3)))) == 3); assert(isNil(cdr(cdr(cons(2, mklist(3)))))); @@ -122,12 +392,12 @@ bool testCons() { return true; } -bool testListGC() { +const bool testListGC() { resetLambdaCounters(); resetListCounters(); countElements = 0; { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testCons(); } assert(checkLambdaCounters()); @@ -136,7 +406,41 @@ bool testListGC() { return true; } -bool testOut() { +template const list listPerf(const T& v, const long int i) { + if (i == 0) + return list(); + return cons(v, listPerf(v, i -1)); +} + +const bool testListPerf() { + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf(0, 1000); + return true; + }; + cout << "List test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf(string("x"), 1000); + return true; + }; + cout << "List test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf(value("x"), 1000); + return true; + }; + cout << "List test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + return true; +} + +const bool testOut() { ostringstream os1; os1 << list (); assert(str(os1) == "()"); @@ -147,7 +451,7 @@ bool testOut() { return true; } -bool testEquals() { +const bool testEquals() { assert(list() == list()); assert(mklist(1, 2) == mklist(1, 2)); assert(list() != mklist(1, 2)); @@ -156,14 +460,14 @@ bool testEquals() { return true; } -bool testLength() { +const bool testLength() { assert(0 == length(list())); assert(1 == length(mklist(1))); assert(2 == length(cons(1, mklist(2)))); return true; } -bool testAppend() { +const bool testAppend() { assert(car(append(mklist(1), mklist(2))) == 1); assert(car(cdr(append(mklist(1), mklist(2)))) == 2); assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3); @@ -173,21 +477,23 @@ bool testAppend() { return true; } -struct Complex { - int x; - int y; - Complex() { +class Complex { +public: + Complex() : x(0), y(0) { } - Complex(int x, int y) : - x(x), y(y) { + Complex(const int x, const int y) : x(x), y(y) { } + + const int x; + const int y; }; + ostream& operator<<(ostream& out, const Complex& v) { out << "[" << v.x << ":" << v.y << "]"; return out; } -bool testComplex() { +const bool testComplex() { const list p = mklist(Complex(1, 2), Complex(3, 4)); assert(car(p).x == 1); assert(car(cdr(p)).x == 3); @@ -195,7 +501,7 @@ bool testComplex() { return true; } -bool testMap() { +const bool testMap() { assert(isNil(map(square, list()))); const list m = map(square, mklist(2, 3)); @@ -209,26 +515,26 @@ const int add(const int x, const int y) { return x + y; } -bool testReduce() { - const lambda r(add); +const bool testReduce() { + const lambda r(add); assert(reduce(r, 0, mklist(1, 2, 3)) == 6); return true; } -bool isPositive(const int x) { +const bool isPositive(const int x) { if(x >= 0) return true; else return false; } -bool testFilter() { +const bool testFilter() { assert(car(filter(isPositive, mklist(1, -1, 2, -2))) == 1); assert(cadr(filter(isPositive, mklist(1, -1, 2, -2))) == 2); return true; } -bool testMember() { +const bool testMember() { assert(isNil(member(4, mklist(1, 2, 3)))); assert(car(member(1, mklist(1, 2, 3))) == 1); assert(car(member(2, mklist(1, 2, 3))) == 2); @@ -236,14 +542,14 @@ bool testMember() { return true; } -bool testReverse() { +const bool testReverse() { assert(isNil(reverse(list()))); assert(car(reverse(mklist(1, 2, 3))) == 3); assert(cadr(reverse(mklist(1, 2, 3))) == 2); return true; } -bool testListRef() { +const bool testListRef() { assert(listRef(mklist(1), 0) == 1); assert(listRef(mklist(1, 2, 3), 0) == 1); assert(listRef(mklist(1, 2, 3), 1) == 2); @@ -251,7 +557,7 @@ bool testListRef() { return true; } -bool testAssoc() { +const bool testAssoc() { const list > l = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(assoc("a", l) == mklist("a", "A")); assert(isNil(assoc("z", l))); @@ -261,10 +567,13 @@ bool testAssoc() { const list v = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); assert(assoc("a", v) == mklist("a", "A")); + + const list v2 = mklist(mklist("x", "X"), "a", mklist("a", "A"), mklist("y", "Y"), mklist("a", "AA")); + assert(assoc("a", v2) == mklist("a", "A")); return true; } -bool testZip() { +const bool testZip() { const list k = mklist("x", "a", "y", "a"); const list v = mklist("X", "A", "Y", "AA"); const list > z = mklist(k, v); @@ -274,7 +583,7 @@ bool testZip() { return true; } -bool testTokenize() { +const bool testTokenize() { assert(tokenize("/", "") == list()); assert(tokenize("/", "aaa") == mklist("aaa")); assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist("aaa", "bbb", "ccc", "ddd")); @@ -292,11 +601,11 @@ bool testTokenize() { return true; } -double testSeqMap(double x) { +const double testSeqMap(const double x) { return x; } -double testSeqReduce(unused double v, double accum) { +double testSeqReduce(unused const double v, const double accum) { return accum + 1.0; } @@ -316,16 +625,16 @@ bool testSeq() { return true; } -value valueSquare(list x) { +const value valueSquare(const list& x) { return (int)car(x) * (int)car(x); } -bool testValue() { - assert(value(true) == value(true)); +const bool testValue() { + assert(value(true) == trueValue); assert(value(1) == value(1)); assert(value("abcd") == value("abcd")); - lambda&)> vl(valueSquare); - assert(value(vl) == value(vl)); + lvvlambda vl(valueSquare); + //assert(value(vl) == value(vl)); assert(value(mklist(1, 2)) == value(mklist(1, 2))); const list v = mklist(mklist("x", "X"), mklist("a", "A"), mklist("y", "Y")); @@ -339,12 +648,12 @@ bool testValue() { return true; } -bool testValueGC() { +const bool testValueGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); { - gc_scoped_pool gc; + const gc_scoped_pool gcp; testValue(); } assert(checkValueCounters()); @@ -353,8 +662,8 @@ bool testValueGC() { return true; } -bool testTree() { - const list t = mktree("a", list(), list()); +const bool testTree() { + const list t = mktree("a", nilListValue, nilListValue); const list ct = constree("d", constree("f", constree("c", constree("e", constree("b", t))))); const list mt = mktree(mklist("d", "f", "c", "e", "b", "a")); assert(mt == ct); @@ -371,8 +680,8 @@ const list lta(const string& x) { return mklist(c_str(x), c_str(x + x)); } -bool testTreeAssoc() { - const list t = mktree(lta("a"), list(), list()); +const bool testTreeAssoc() { + const list t = mktree(lta("a"), nilListValue, nilListValue); const list at = constree(lta("d"), constree(lta("f"), constree(lta("c"), constree(lta("e"), constree(lta("b"), t))))); const list l = flatten(at); assert(length(l) == 6); @@ -387,58 +696,46 @@ bool testTreeAssoc() { return true; } -double fib_aux(double n, double a, double b) { +const double fib_aux(const double n, const double a, const double b) { if(n == 0.0) return a; return fib_aux(n - 1.0, b, a + b); } -double fib(double n) { +const double fib(const double n) { return fib_aux(n, 0.0, 1.0); } -struct fibMapPerf { - const bool operator()() const { - list s = seq(0.0, 999.0); - list r = map(fib, s); - assert(1000 == length(r)); - return true; - } -}; - -struct nestedFibMapPerf { - const lambda fib; - nestedFibMapPerf(const lambda& fib) : fib(fib) { - } - const bool operator()() const { - list s = seq(0.0, 999.0); - list r = map(fib, s); - assert(1000 == length(r)); - return true; - } -}; +const bool fibMapPerf() { + const list s = seq(0.0, 999.0); + const list r = map(fib, s); + assert(1000 == length(r)); + return true; +} -bool testCppPerf() { +const bool testCppPerf() { { - const lambda fml = fibMapPerf(); + const gc_scoped_pool gcp; + const blambda fml = fibMapPerf; cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << 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); - } + const lambda fib = [](const double n) -> const double { + const lambda fib_aux = [&fib_aux](double n, double a, double b) -> const double { + if(n == 0.0) + return a; + return fib_aux(n - 1.0, b, a + b); + }; + return fib_aux(n, 0.0, 1.0); }; - const lambda nfml = nestedFibMapPerf(lambda(nested::fib)); + const blambda nfml = [fib]() -> const bool { + const list s = seq(0.0, 999.0); + const list r = map(fib, s); + assert(1000 == length(r)); + return true; + }; cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl; } return true; @@ -456,7 +753,7 @@ const id idH(const int v) { return idF(v) >> idG; } -bool testIdMonad() { +const bool testIdMonad() { const id m(2); assert(m >> idF == idF(2)); assert(m >> unit() == m); @@ -476,7 +773,7 @@ const maybe maybeH(const int v) { return maybeF(v) >> maybeG; } -bool testMaybeMonad() { +const bool testMaybeMonad() { const maybe m(2); assert(m >> maybeF == maybeF(2)); assert((m >> just()) == m); @@ -498,7 +795,7 @@ const failable failableH(const int v) { return failableF(v) >> failableG; } -bool testFailableMonad() { +const bool testFailableMonad() { const failable m(2); assert(m >> failableF == failableF(2)); assert((m >> success()) == m); @@ -515,23 +812,16 @@ bool testFailableMonad() { assert(rcode(vooops) == 500); const value v = value(vooops); - assert(car(v) == value()); + assert(car(v) == nilValue); assert(cadr(v) == string("test")); assert(caddr(v) == value((double)500)); return true; } -struct tickInc { - const double v; - tickInc(const double v) : v(v) { - } - const scp operator()(int s) const { - return scp(s + 1, v); - } -}; - const state tick(const double v) { - return transformer(tickInc(v)); + return transformer([v](const int s) { + return scp(s + 1, v); + }); } const state stateF(const double v) { @@ -546,8 +836,8 @@ const state stateH(const double v) { return stateF(v) >> stateG; } -bool testStateMonad() { - const lambda(const double)> r(result); +const bool testStateMonad() { + const lambda(const double)> r(result); state m = result(2.0); assert((m >> stateF)(0) == stateF(2.0)(0)); @@ -558,30 +848,40 @@ bool testStateMonad() { return true; } -bool testDynLib() { +const bool testDynLib() { const lib dl(string("./libdynlib-test") + dynlibExt); - const failable > sq(dynlambda("csquare", dl)); + const failable > sq(dynlambda("csquare", dl)); assert(hasContent(sq)); - lambda l(content(sq)); + lambda l(content(sq)); assert(l(2) == 4); - const failable()> > sql(dynlambda()>("csquarel", dl)); + const failable()> > sql(dynlambda()>("csquarel", dl)); assert(hasContent(sql)); - lambda()> ll(content(sql)); + lambda()> ll(content(sql)); assert(ll()(3) == 9); return true; } + } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; + tuscany::testSizes(); + tuscany::testCopiable(); + tuscany::testMutable(); + tuscany::testPtrPerf(); tuscany::testLambda(); tuscany::testLambdaGC(); + tuscany::testCurry(); + tuscany::testFunctor(); + tuscany::test11Lambda(); + tuscany::testFuncPerf(); tuscany::testCons(); tuscany::testListGC(); + tuscany::testListPerf(); tuscany::testOut(); tuscany::testEquals(); tuscany::testLength(); diff --git a/sca-cpp/trunk/kernel/lambda-test.cpp b/sca-cpp/trunk/kernel/lambda-test.cpp index 05a16c2eb8..81f17a57b0 100644 --- a/sca-cpp/trunk/kernel/lambda-test.cpp +++ b/sca-cpp/trunk/kernel/lambda-test.cpp @@ -34,7 +34,7 @@ namespace tuscany { #ifdef HAS_CXX0X_LAMBDAS const lambda inc(const int i) { - return [=](const int x)->const int { + return [i](const int x)->const int { return x + i; }; } @@ -43,27 +43,26 @@ const int square(const int x) { return x * x; } -int mapLambda(const lambda f, int v) { +const int mapLambda(const lambda f, int v) { return f(v); } -bool testLambda() { +const bool testLambda() { const lambda sq = square; assert(sq(2) == 4); assert(mapLambda(square, 2) == 4); assert(mapLambda(sq, 2) == 4); assert(mapLambda([](const int x)->const int { return x * x; }, 2) == 4); - const lambda incf = inc(10); + const lambda incf = inc(10); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); assert(mapLambda(inc(10), 1) == 11); - lambda l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); + const lambda il(incf); + assert(il(1) == 11); + const lambda sl(square); + assert(sl(2) == 4); return true; } @@ -72,13 +71,13 @@ const double fib_aux(const double n, const double a, const double b) { } const bool fibMapPerf() { - list s = seq(0.0, 4999.0); - list r = map([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s); + const list s = seq(0.0, 4999.0); + const list r = map([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s); assert(5000 == length(r)); return true; } -bool testCppPerf() { +const bool testCppPerf() { cout << "Fibonacci map test " << (time([]()->const bool { return fibMapPerf(); }, 1, 1) / 5000) << " ms" << endl; return true; } @@ -87,7 +86,7 @@ bool testCppPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; #ifdef HAS_CXX0X_LAMBDAS diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index d3736de62c..16a0649fe9 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -43,16 +43,16 @@ long countILists = 0; long countCLists = 0; long countELists = 0; -bool resetListCounters() { +inline const bool resetListCounters() { countLists = countILists = countCLists = countELists = 0; return true; } -bool checkListCounters() { +inline const bool checkListCounters() { return countLists == 0; } -bool printListCounters() { +inline const bool printListCounters() { cout << "countLists " << countLists << endl; cout << "countELists " << countELists << endl; cout << "countILists " << countILists << endl; @@ -91,19 +91,19 @@ bool printListCounters() { template class list { public: - list() { + inline list() : car() { debug_inc(countLists); debug_inc(countELists); debug_watchList(); } - list(const T car, const lambda()>& cdr) : car(car), cdr(cdr) { + inline list(const T& car, const lambda()>& cdr) : car(car), cdr(cdr) { debug_inc(countLists); debug_inc(countILists); debug_watchList(); } - list(const list& p) : car(p.car), cdr(p.cdr) { + inline list(const list& p) : car(p.car), cdr(p.cdr) { debug_inc(countLists); debug_inc(countCLists); #ifdef WANT_MAINTAINER_WATCH @@ -111,22 +111,13 @@ public: #endif } - const list& operator=(const list& p) { - if(this == &p) - return *this; - car = p.car; - cdr = p.cdr; -#ifdef WANT_MAINTAINER_WATCH - watch = p.watch; -#endif - return *this; - } + list& operator=(const list& p) = delete; - ~list() { + inline ~list() { debug_dec(countLists); } - const bool operator==(const list& p) const { + inline const bool operator==(const list& p) const { if(this == &p) return true; if(isNil(cdr)) @@ -140,7 +131,7 @@ public: return cdr() == p.cdr(); } - const bool operator<(const list& p) const { + inline const bool operator<(const list& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -154,7 +145,7 @@ public: return cdr() < p.cdr(); } - const bool operator>(const list& p) const { + inline const bool operator>(const list& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -168,11 +159,11 @@ public: return cdr() > p.cdr(); } - const bool operator!=(const list& p) const { + inline const bool operator!=(const list& p) const { return !this->operator==(p); } - operator const list >() const { + inline operator const list >() const { return (list >)T(*this); } @@ -185,9 +176,10 @@ private: template friend const bool isNil(const list& p); template friend const X car(const list& p); template friend const list cdr(const list& p); + template friend const bool setlist(list& target, const list& l); - T car; - lambda()> cdr; + const T car; + const lambda()> cdr; }; #ifdef WANT_MAINTAINER_WATCH @@ -196,7 +188,7 @@ private: * Debug utility used to write the contents of a list to a string, easier * to watch than the list itself in a debugger. */ -template const string watchList(const list& p) { +template inline const string watchList(const list& p) { if(isNil(p)) return "()"; odebugstream os; @@ -209,21 +201,21 @@ template const string watchList(const list& p) { /** * Returns true if the given list is nil. */ -template const bool isNil(const list& p) { +template inline const bool isNil(const list& p) { return isNil(p.cdr); } /** * Write a list to an output stream. */ -template ostream& writeHelper(ostream& out, const list& l) { +template inline ostream& writeHelper(ostream& out, const list& l) { if (isNil(l)) return out; out << " " << car(l); return writeHelper(out, cdr(l)); } -template ostream& operator<<(ostream& out, const list& l) { +template inline ostream& operator<<(ostream& out, const list& l) { if(isNil(l)) return out << "()"; out << "(" << car(l); @@ -234,74 +226,74 @@ template ostream& operator<<(ostream& out, const list& l) { /** * Construct a (lazy) list from a value and a lambda function that returns the cdr. */ -template const list cons(const T& car, const lambda()>& cdr) { +template inline const list cons(const T& car, const lambda()>& cdr) { return list (car, cdr); } /** * Construct a list from a value and a cdr list. */ -template const list cons(const T& car, const list& cdr) { +template inline const list cons(const T& car, const list& cdr) { return list (car, result(cdr)); } /** * Cons variations for use with the reduce and reduceRight functions. */ -template const list lcons(const list& cdr, const T& car) { +template inline const list lcons(const list& cdr, const T& car) { return cons(car, cdr); } -template const list rcons(const T& car, const list& cdr) { +template inline const list rcons(const T& car, const list& cdr) { return cons(car, cdr); } /** * Construct a list of one value. */ -template const list mklist(const T& car) { +template inline const list mklist(const T& car) { return list (car, result(list ())); } /** * Construct a list of two values. */ -template const list mklist(const T& a, const T& b) { +template inline const list mklist(const T& a, const T& b) { return cons(a, mklist(b)); } /** * Construct a list of three values. */ -template const list mklist(const T& a, const T& b, const T& c) { +template inline const list mklist(const T& a, const T& b, const T& c) { return cons(a, cons(b, mklist(c))); } /** * Construct a list of four values. */ -template const list mklist(const T& a, const T& b, const T& c, const T& d) { +template inline const list mklist(const T& a, const T& b, const T& c, const T& d) { return cons(a, cons(b, cons(c, mklist(d)))); } /** * Construct a list of five values. */ -template const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { +template inline const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { return cons(a, cons(b, cons(c, cons(d, mklist(e))))); } /** * Construct a list of six values. */ -template const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { +template inline const list mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f)))))); } /** * Returns the car of a list. */ -template const T car(const list& p) { +template inline const T car(const list& p) { // Abort if trying to access the car of a nil list assertOrFail(!isNil(p.cdr)); return p.car; @@ -310,159 +302,144 @@ template const T car(const list& p) { /** * Returns the cdr of a list. */ -template const list cdr(const list& p) { +template inline const list cdr(const list& p) { return p.cdr(); } /** * Returns the car of the cdr (the 2nd element) of a list. */ -template const T cadr(const list& p) { +template inline const T cadr(const list& p) { return car(cdr(p)); } /** * Returns the 3rd element of a list. */ -template const T caddr(const list& p) { +template inline const T caddr(const list& p) { return car(cdr(cdr(p))); } /** * Returns the 4th element of a list. */ -template const T cadddr(const list& p) { +template inline const T cadddr(const list& p) { return car(cdr(cdr(cdr(p)))); } /** * Returns the 5th element of a list. */ -template const T caddddr(const list& p) { +template inline const T caddddr(const list& p) { return car(cdr(cdr(cdr(cdr(p))))); } /** * Returns the 6th element of a list. */ -template const T cadddddr(const list& p) { +template inline const T cadddddr(const list& p) { return car(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns the 7th element of a list. */ -template const T caddddddr(const list& p) { +template inline const T caddddddr(const list& p) { return car(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the 8th element of a list. */ -template const T cadddddddr(const list& p) { +template inline const T cadddddddr(const list& p) { return car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))))); } /** * Returns a list of elements from the 3rd to the end of a list. */ -template const list cddr(const list& p) { +template inline const list cddr(const list& p) { return cdr(cdr(p)); } /** * Returns a list of elements from the 4th to the end of a list. */ -template const list cdddr(const list& p) { +template inline const list cdddr(const list& p) { return cdr(cdr(cdr(p))); } /** * Returns a list of elements from the 5th to the end of a list. */ -template const list cddddr(const list& p) { +template inline const list cddddr(const list& p) { return cdr(cdr(cdr(cdr(p)))); } /** * Returns a list of elements from the 6th to the end of a list. */ -template const list cdddddr(const list& p) { +template inline const list cdddddr(const list& p) { return cdr(cdr(cdr(cdr(cdr(p))))); } /** * Returns a list of elements from the 7th to the end of a list. */ -template const list cddddddr(const list& p) { +template inline const list cddddddr(const list& p) { return cdr(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns a list of elements from the 8th to the end of a list. */ -template const list cdddddddr(const list& p) { +template inline const list cdddddddr(const list& p) { return cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the length of a list. */ -template struct lengthRef { - const size_t operator()(const size_t c, const list& p) { +template inline const size_t length(const list& p) { + const lambda&)> lengthRef = [&lengthRef](const size_t c, const list& p) -> const size_t { if(isNil(p)) return c; - return (*this)(c + 1, cdr(p)); - } -}; - -template const size_t length(const list& p) { - return lengthRef ()(0, p); + return lengthRef(c + 1, cdr(p)); + }; + return lengthRef(0, p); } /** * Appends a list and a lambda function returning a list. */ -template struct appendCdr { - const list a; - const lambda()> fb; - appendCdr(const list& a, const lambda()>& fb) : - a(a), fb(fb) { - } - const list operator()() const { - return append(a, fb); - } -}; - -template const list append(const list&a, const lambda()>& fb) { +template inline const list append(const list&a, const lambda()>& fb) { if(isNil(a)) return fb(); - - return cons(car(a), appendCdr (cdr(a), fb)); + return cons(car(a), [a, fb]() { return append(cdr(a), fb); }); } /** * Appends two lists. */ -template const list append(const list&a, const list& b) { +template inline const list append(const list&a, const list& b) { return append(a, result(b)); } /** * Append a value to a list. */ -template const list operator+(const list& l, const T& v) { +template inline const list operator+(const list& l, const T& v) { return append(l, mklist(v)); } -template const list operator+(const list& l, const V& v) { +template const list inline operator+(const list& l, const V& v) { return append(l, mklist(v)); } /** * Map a lambda function on a list. */ -template const list map(const lambda& f, const list& p) { +template inline const list map(const lambda& f, const list& p) { if(isNil(p)) return list (); return cons(f(car(p)), map(f, cdr(p))); @@ -471,46 +448,32 @@ template const list map(const lambda& f, /** * Run a reduce lambda function on a list. */ -template struct reduceAccumulate { - const lambda f; - reduceAccumulate(const lambda& f) : - f(f) { - } - R operator()(const R& acc, const list& p) const { +template inline const R reduce(const lambda& f, const R& initial, const list& p) { + const lambda&p)> reduceAccumulate = [f, &reduceAccumulate](const R& acc, const list& p) -> R { if(isNil(p)) return acc; - return (*this)(f(acc, car(p)), cdr(p)); - } -}; - -template const R reduce(const lambda& f, const R& initial, const list& p) { - return reduceAccumulate (f)(initial, p); + return reduceAccumulate(f(acc, car(p)), cdr(p)); + }; + return reduceAccumulate(initial, p); } -template struct reduceRightAccumulate { - const lambda f; - reduceRightAccumulate(const lambda& f) : - f(f) { - } - R operator()(const list& p, const R& acc) const { +template inline const R reduceRight(const lambda& f, const R& initial, const list& p) { + const lambda&p, const R&)> reduceRightAccumulate = [f, &reduceRightAccumulate](const list& p, const R& acc) -> R { if(isNil(p)) return acc; - return (*this)(cdr(p), f(car(p), acc)); - } -}; - -template const R reduceRight(const lambda& f, const R& initial, const list& p) { - return reduceRightAccumulate (f)(p, initial); + return reduceRightAccumulate(cdr(p), f(car(p), acc)); + }; + return reduceRightAccumulate(p, initial); } /** * Run a filter lambda function on a list. */ -template const list filter(const lambda& f, const list& p) { +template inline const list filter(const lambda& f, const list& p) { if(isNil(p)) return list (); if(f(car(p))) { - const lambda(const lambda, const list)> ff(filter); + const lambda(const lambda, const list)> ff(filter); return cons(car(p), curry(ff, f, cdr(p))); } return filter(f, cdr(p)); @@ -519,7 +482,7 @@ template const list filter(const lambda& f, const /** * Returns a list pointing to a member of a list. */ -template const list member(const T& t, const list& p) { +template inline const list member(const T& t, const list& p) { if(isNil(p)) return list (); if(t == car(p)) @@ -530,44 +493,31 @@ template const list member(const T& t, const list& p) { /** * Reverse a list. */ -template const list reverseIter(const list& acc, const list& p) { +template inline const list reverseIter(const list& acc, const list& p) { if(isNil(p)) return acc; return reverseIter(cons(car(p), acc), cdr(p)); } -template const list reverse(const list& p) { +template inline const list reverse(const list& p) { return reverseIter(list (), p); } -template const list seq(const T& start, const T& end); - -template struct seqGenerate { - const T start; - const T end; - seqGenerate(const T& start, const T&end) : - start(start), end(end) { - } - const list operator()() const { - return seq (start, end); - } -}; - /** * Returns a sequence of values between the given bounds. */ -template const list seq(const T& start, const T& end) { +template inline const list seq(const T& start, const T& end) { if(start == end) return mklist(start); if(start < end) - return cons(start, seqGenerate (start + 1, end)); - return cons(start, seqGenerate (start - 1, end)); + return cons(start, [start, end] { return seq (start + 1, end); }); + return cons(start, [start, end] { return seq (start - 1, end); }); } /** * Returns the i-th element of a list. */ -template const T listRef(const list& l, const size_t i) { +template inline const T listRef(const list& l, const size_t i) { if (i == 0) return car(l); return listRef(cdr(l), i - 1); @@ -576,7 +526,7 @@ template const T listRef(const list& l, const size_t i) { /** * Returns the first pair matching a key from a list of key value pairs. */ -template const list assoc(const T& k, const list >& p) { +template inline const list assoc(const T& k, const list >& p) { if(isNil(p)) return list (); if(k == car(car(p))) @@ -587,7 +537,7 @@ template const list assoc(const T& k, const list >& p) { /** * Returns a list of lists containing elements from two input lists. */ -template const list > zip(const list& a, const list& b) { +template inline const list > zip(const list& a, const list& b) { if (isNil(a) || isNil(b)) return list >(); return cons >(mklist(car(a), car(b)), zip(cdr(a), cdr(b))); @@ -596,19 +546,19 @@ template const list > zip(const list& a, const list& b /** * Converts a list of key value pairs to a list containing the list of keys and the list of values. */ -template const list unzipKeys(const list >& l) { +template inline const list unzipKeys(const list >& l) { if (isNil(l)) return list(); return cons(car(car(l)), unzipKeys(cdr(l))); } -template const list unzipValues(const list >& l) { +template inline const list unzipValues(const list >& l) { if (isNil(l)) return list(); return cons(cadr(car(l)), unzipValues(cdr(l))); } -template const list > unzip(const list >& l) { +template inline const list > unzip(const list >& l) { return mklist >(unzipKeys(l), unzipValues(l)); } diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp index 668dabe749..2072da9f68 100644 --- a/sca-cpp/trunk/kernel/mem-test.cpp +++ b/sca-cpp/trunk/kernel/mem-test.cpp @@ -43,7 +43,7 @@ public: maxElements = countElements; } - Element(int i) : i(i) { + Element(const int i) : i(i) { countElements++; if (countElements > maxElements) maxElements = countElements; @@ -66,7 +66,7 @@ public: private: friend ostream& operator<<(ostream& out, const Element& v); - int i; + const int i; char c[20]; }; @@ -75,14 +75,14 @@ ostream& operator<<(ostream& out, const Element& v) { return out; } -bool poolAlloc(Element** p, const int count) { +const bool poolAlloc(Element** const p, const int count) { if (count == 0) return true; p[count - 1] = new (gc_new()) Element(); return poolAlloc(p, count - 1); }; -bool poolFree(Element** p, const int count) { +bool poolFree(Element** const p, const int count) { if (count == 0) return true; // Do nothing to free the element, but cycle through them just @@ -90,21 +90,14 @@ bool poolFree(Element** p, const int count) { return poolFree(p, count - 1); }; -struct poolAllocPerf { - const int n; - Element** p; - poolAllocPerf(const int n) : n(n), p(new Element*[n]) { - } - const bool operator()() const { - gc_scoped_pool gc; - poolAlloc(p, n); - return true; - } -}; - -bool testPoolAllocPerf() { +const bool testPoolAllocPerf() { const int count = 10000; - const lambda pl = poolAllocPerf(count); + Element** const elements = new Element*[count]; + const blambda pl = [elements, count]() -> const bool { + const gc_scoped_pool gc; + poolAlloc(elements, count); + return true; + }; maxElements = 0; cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl; assert(countElements == 0); @@ -112,35 +105,28 @@ bool testPoolAllocPerf() { return true; } -bool stdAlloc(Element** p, const int count) { +const bool stdAlloc(Element** const p, const int count) { if (count == 0) return true; p[count - 1] = new Element(); return stdAlloc(p, count - 1); }; -bool stdFree(Element** p, const int count) { +const bool stdFree(Element** const p, const int count) { if (count == 0) return true; delete p[count -1]; return stdFree(p, count - 1); }; -struct stdAllocPerf { - const int n; - Element** p; - stdAllocPerf(const int n) : n(n), p(new Element*[n]) { - } - const bool operator()() const { - stdAlloc(p, n); - stdFree(p, n); - return true; - } -}; - -bool testStdAllocPerf() { +const bool testStdAllocPerf() { const int count = 10000; - const lambda sl = stdAllocPerf(count); + Element** const elements = new Element*[count]; + const blambda sl = [elements, count]() -> const bool { + stdAlloc(elements, count); + stdFree(elements, count); + return true; + }; maxElements = 0; cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl; assert(countElements == 0); @@ -151,7 +137,7 @@ bool testStdAllocPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testPoolAllocPerf(); diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp index b67e92ad79..de79780e7a 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -26,8 +26,11 @@ * Simple monad implementations. */ +#ifdef WANT_MAINTAINER_BACKTRACE #include #include +#endif + #include "function.hpp" #include "string.hpp" #include "stream.hpp" @@ -43,21 +46,16 @@ namespace tuscany */ template class id { public: - id(const V& v) : v(v) { + inline id(const V& v) : v(v) { } - const id& operator=(const id& m) { - if(this == &m) - return *this; - v = m.v; - return *this; - } + id& operator=(const id& m) = delete; - const bool operator!=(const id& m) const { + inline const bool operator!=(const id& m) const { return !this->operator==(m); } - const bool operator==(const id& m) const { + inline const bool operator==(const id& m) const { if (&m == this) return true; return v == m.v; @@ -72,7 +70,7 @@ private: /** * Write an identity monad to a stream. */ -template ostream& operator<<(ostream& out, const id& m) { +template inline ostream& operator<<(ostream& out, const id& m) { out << content(m); return out; } @@ -80,29 +78,29 @@ template ostream& operator<<(ostream& out, const id& m) { /** * Returns the content of an identity monad. */ -template const V content(const id& m) { +template inline const V content(const id& m) { return m.v; } /** * Return an identity monad from a value. */ -template const id mkunit(const V& v) { +template inline const id mkunit(const V& v) { return id(v); } -template const lambda(const V)> unit() { +template inline const lambda(const V)> unit() { return mkunit; } /** * Bind a function to an identity monad. Pass the value in the monad to the function. */ -template const id operator>>(const id& m, const lambda(const V)>& f) { +template inline const id operator>>(const id& m, const lambda(const V)>& f) { return f(content(m)); } -template const id operator>>(const id& m, const id (* const f)(const V)) { +template inline const id operator>>(const id& m, const id (* const f)(const V)) { return f(content(m)); } @@ -112,26 +110,22 @@ template const id operator>>(const id& m, const id */ template class maybe { public: - maybe(const V& v) : hasv(true), v(v) { + inline maybe(const V& v) : hasv(true), v(v) { } - maybe() : hasv(false) { + inline maybe() : hasv(false), v() { } - const maybe& operator=(const maybe& m) { - if(this == &m) - return *this; - hasv = m.hasv; - if (hasv) - v = m.v; - return *this; + inline maybe(const maybe& m) : hasv(m.hasv), v(m.v) { } - const bool operator!=(const maybe& m) const { + maybe& operator=(const maybe& m) = delete; + + inline const bool operator!=(const maybe& m) const { return !this->operator==(m); } - const bool operator==(const maybe& m) const { + inline const bool operator==(const maybe& m) const { if (this == &m) return true; if (!hasv) @@ -141,7 +135,7 @@ public: private: const bool hasv; - V v; + const V v; template friend const bool hasContent(const maybe& m); template friend const X content(const maybe& m); @@ -150,7 +144,7 @@ private: /** * Write a maybe monad to a stream. */ -template ostream& operator<<(ostream& out, const maybe& m) { +template inline ostream& operator<<(ostream& out, const maybe& m) { if (!hasContent(m)) { out << "nothing"; return out; @@ -162,25 +156,25 @@ template ostream& operator<<(ostream& out, const maybe& m) { /** * Return a maybe monad with a value in it. */ -template const maybe mkjust(const V& v) { +template inline const maybe mkjust(const V& v) { return maybe(v); } -template const lambda(const V)> just() { +template inline const lambda(const V)> just() { return mkjust; } /** * Returns true if a maybe monad contains a content. */ -template const bool hasContent(const maybe& m) { +template inline const bool hasContent(const maybe& m) { return m.hasv; } /** * Returns the content of a maybe monad. */ -template const V content(const maybe& m) { +template inline const V content(const maybe& m) { return m.v; } @@ -188,13 +182,13 @@ template const V content(const maybe& m) { * Bind a function to a maybe monad. Passes the value in the monad to the function * if present, or does nothing if there's no value. */ -template const maybe operator>>(const maybe& m, const lambda(const V)>& f) { +template inline const maybe operator>>(const maybe& m, const lambda(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } -template const maybe operator>>(const maybe& m, const maybe (* const f)(const V)) { +template inline const maybe operator>>(const maybe& m, const maybe (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -207,30 +201,22 @@ template const maybe operator>>(const maybe& m, co */ template class failable { public: - failable() : hasv(false), c(-1) { + inline failable() : hasv(false), v(), c(-1) { } - failable(const V& v) : hasv(true), v(v), c(-1) { + inline failable(const V& v) : hasv(true), v(v), c(-1) { } - failable(const failable& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { + inline failable(const failable& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { } - const failable& operator=(const failable& m) { - if (&m == this) - return *this; - hasv = m.hasv; - v = m.v; - f = m.f; - c = m.c; - return *this; - } + failable& operator=(const failable& m) = delete; - const bool operator!=(const failable& m) const { + inline const bool operator!=(const failable& m) const { return !this->operator==(m); } - const bool operator==(const failable& m) const { + inline const bool operator==(const failable& m) const { if (this == &m) return true; if (!hasv) @@ -239,7 +225,7 @@ public: } private: - failable(const bool hasv, const F& f, const C& c) : hasv(hasv), f(f), c(c) { + inline failable(const bool hasv, const F& f, const C& c) : hasv(hasv), v(), f(f), c(c) { } template friend const bool hasContent(const failable& m); @@ -250,16 +236,16 @@ private: template friend const failable mkfailure(const B& f, const int c, const bool log); template friend const failable mkfailure(); - bool hasv; - V v; - F f; - C c; + const bool hasv; + const V v; + const F f; + const C c; }; /** * Write a failable monad to a stream. */ -template ostream& operator<<(ostream& out, const failable& m) { +template inline ostream& operator<<(ostream& out, const failable& m) { if (!hasContent(m)) { out << reason(m) << " : " << rcode(m); return out; @@ -271,20 +257,22 @@ template ostream& operator<<(ostream& out, c /** * Returns a failable monad with a success value in it. */ -template const failable mksuccess(const V& v) { +template inline const failable mksuccess(const V& v) { return failable(v); } -template const lambda(const V)> success() { +template inline const lambda(const V)> success() { return mksuccess; } +#ifdef WANT_MAINTAINER_BACKTRACE + /** * Demangle a C++ function name. */ -const string demangleFrame(const char* fun) { +inline const string demangleFrame(const char* fun) { int status; - char* name = abi::__cxa_demangle(fun, 0, 0, &status); + char* const name = abi::__cxa_demangle(fun, 0, 0, &status); if (name == NULL) return fun; const string s = name; @@ -295,12 +283,12 @@ const string demangleFrame(const char* fun) { /** * Format a backtrace frame. */ -const char* formatFrameFile(const char* file) { - const char* s = strrchr(file, '/'); +inline const char* const formatFrameFile(const char* const file) { + const char* const s = strrchr(file, '/'); return s == NULL? file : s + 1; } -const string formatFrame(const char* symbol) { +inline const string formatFrame(const char* const symbol) { #ifdef __clang__ // Mac OS X CLang/LLVM stack frame format // 0 kernel-test 0x000000010d440179 _ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b + 265 @@ -349,7 +337,7 @@ const string formatFrame(const char* symbol) { /** * Log backtrace frames. */ -const bool logFrames(char** symbols, const int frames, const bool log) { +inline const bool logFrames(char** const symbols, const int frames, const bool log) { if (frames == 0) return true; #ifdef WANT_MAINTAINER_LOG @@ -364,26 +352,30 @@ const bool logFrames(char** symbols, const int frames, const bool log) { /** * Log a backtrace. */ -const bool logBacktrace(void** callstack, const int frames, const bool log) { +inline const bool logBacktrace(void** const callstack, const int frames, const bool log) { char** symbols = backtrace_symbols(callstack, frames); logFrames(symbols, frames, log); free(symbols); return true; } +#endif + /** * Returns a failable monad with a failure in it. */ -template const failable mkfailure(const F& f, const C& c, const bool log = true) { +template inline const failable mkfailure(const F& f, const C& c, const bool log = true) { #ifdef WANT_MAINTAINER_LOG if (!log) { // Log the failure debug(f, "failable::mkfailure"); +#ifdef WANT_MAINTAINER_BACKTRACE // Log the call stack void* callstack[16]; const int frames = backtrace(callstack, 16); logBacktrace(callstack, frames, log); +#endif } #endif if (log) { @@ -393,63 +385,65 @@ template const failable mkfailure(c // Log the failure cfailure << "failable::mkfailure: " << f << " : " << c << endl; +#ifdef WANT_MAINTAINER_BACKTRACE // Print the call stack void* callstack[16]; const int frames = backtrace(callstack, 16); logBacktrace(callstack, frames, log); +#endif } } return failable(false, f, c); } -template const failable mkfailure(const F& f, const int c = -1, const bool log = true) { +template inline const failable mkfailure(const F& f, const int c = -1, const bool log = true) { return mkfailure(f, c, log); } -template const failable mkfailure(const char* f, const int c = -1, const bool log = true) { +template inline const failable mkfailure(const char* f, const int c = -1, const bool log = true) { return mkfailure(string(f), c, log); } -template const failable mkfailure() { +template inline const failable mkfailure() { return failable(false, string(), -1); } -template const lambda(const V)> failure() { +template inline const lambda(const V)> failure() { return mkfailure; } /** * Convert a failable of a given type to a failable of another type. */ -template const failable mkfailure(const failable& f, const bool log = true) { +template inline const failable mkfailure(const failable& f, const bool log = false) { return mkfailure(reason(f), rcode(f), log); } /** * Returns true if the monad contains a content. */ -template const bool hasContent(const failable& m) { +template inline const bool hasContent(const failable& m) { return m.hasv; } /** * Returns the content of a failable monad. */ -template const V content(const failable& m) { +template inline const V content(const failable& m) { return m.v; } /** * Returns the reason for failure of a failable monad. */ -template const F reason(const failable& m) { +template inline const F reason(const failable& m) { return m.f; } /** * Returns the reason code for failure of a failable monad. */ -template const C rcode(const failable& m) { +template inline const C rcode(const failable& m) { return m.c; } @@ -458,14 +452,14 @@ template const C rcode(const failable -const failable operator>>(const failable& m, const lambda(const V)>& f) { +inline const failable operator>>(const failable& m, const lambda(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } template -const failable operator>>(const failable& m, const failable (* const f)(const V)) { +inline const failable operator>>(const failable& m, const failable (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -476,30 +470,27 @@ const failable operator>>(const failable& m, const failabl */ template class scp { public: - scp(const S& s, const V& v) : s(s), v(v) { + inline scp(const S& s, const V& v) : s(s), v(v) { } - operator const S() const { + inline operator const S() const { return s; } - operator const V() const { + inline operator const V() const { return v; } - const scp& operator=(const scp& p) { - if(this == &p) - return *this; - s = p.s; - v = p.v; - return *this; + inline scp(const scp& p) : s(p.s), v(p.v) { } - const bool operator!=(const scp& p) const { + scp& operator=(const scp& p) = delete; + + inline const bool operator!=(const scp& p) const { return !this->operator==(p); } - const bool operator==(const scp& p) const { + inline const bool operator==(const scp& p) const { if (this == &p) return true; return s == p.s && v == p.v; @@ -516,14 +507,14 @@ private: /** * Returns the state of a state-content pair. */ -template const S scpstate(const scp& m) { +template inline const S scpstate(const scp& m) { return m.s; } /** * Returns the content of a state-content pair. */ -template const S content(const scp& m) { +template inline const S content(const scp& m) { return m.v; } @@ -532,38 +523,36 @@ template const S content(const scp& m) { */ template class state { public: - state(const lambda(const S)>& f) : f(f) { + inline state(const lambda(const S)>& f) : f(f) { } - const scp operator()(const S& s) const { + inline const scp operator()(const S& s) const { return f(s); } - const state& operator=(const state& m) { - if(this == &m) - return *this; - f = m.f; - return *this; + inline state(const state& m) : f(m.f) { } - const bool operator!=(const state& m) const { + state& operator=(const state& m) = delete; + + inline const bool operator!=(const state& m) const { return !this->operator==(m); } - const bool operator==(const state& m) const { + inline const bool operator==(const state& m) const { if (this == &m) return true; return f == m.f; } private: - const lambda(const S)> f; + const lambda(const S)> f; }; /** * Write a state monad to a stream. */ -template ostream& operator<<(ostream& out, const state& m) { +template inline ostream& operator<<(ostream& out, const state& m) { const S s = m; const V v = m; out << '(' << s << ' ' << v << ')'; @@ -573,17 +562,10 @@ template ostream& operator<<(ostream& out, const state struct returnState { - const V v; - returnState(const V& v) : v(v) { - } - const scp operator()(const S& s) const { +template inline const state result(const V& v) { + return state([v](const S& s) -> const scp { return scp(s, v); - } -}; - -template const state result(const V& v) { - return state(returnState(v)); + }); } /** @@ -591,7 +573,7 @@ template const state result(const V& v) { * A transformer function takes a state and returns an scp pair carrying a content and a * new (transformed) state. */ -template const state transformer(const lambda(const S)>& f) { +template inline const state transformer(const lambda(const S)>& f) { return state(f); } @@ -599,28 +581,19 @@ template const state transformer(const lambda struct stateBind { - const state st; - const lambda(const A)>f; - - stateBind(const state& st, const lambda(const A)>& f) : st(st), f(f) { - } - - const scp operator()(const S& is) const { +template +inline const state operator>>(const state& st, const lambda(const A)>& f) { + const lambda(const S&)> stateBind = [st, f](const S& is) -> const scp { const scp iscp = st(is); const state m = f((A)iscp); return m((S)iscp); - } -}; - -template -const state operator>>(const state& st, const lambda(const A)>& f) { - return state(stateBind(st, f)); + }; + return state(stateBind); } template -const state operator>>(const state& st, const state (* const f)(const A)) { - return state(stateBind(st, f)); +inline const state operator>>(const state& st, const state (* const f)(const A)) { + return st >> lambda(const A)>(f); } } diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp index 28e484d42b..895bb91eb8 100644 --- a/sca-cpp/trunk/kernel/parallel-test.cpp +++ b/sca-cpp/trunk/kernel/parallel-test.cpp @@ -35,84 +35,58 @@ namespace tuscany { int inci = 0; -struct incPerf { - incPerf() { - } - const bool operator()() const { - inci = inci + 1; - return true; - } -}; - const gc_ptr tlsic() { - gc_ptr i = new (gc_new()) int(); + const gc_ptr i = new (gc_new()) int(); *i = 0; return i; } const perthread_ptr tlsi(tlsic); -struct tlsPerf { - tlsPerf() { - } - const bool operator()() const { - *tlsi = *tlsi + 1; - return true; - } -}; - #ifdef WANT_THREADS int addi = 0; - -struct addAndFetchPerf { - addAndFetchPerf() { - } - const bool operator()() const { - __sync_add_and_fetch(&addi, 1); - return true; - } -}; - int muxi = 0; -struct mutexPerf { - pthread_mutex_t* mutex; - mutexPerf(pthread_mutex_t* mutex) : mutex(mutex) { - } - const bool operator()() const { - pthread_mutex_lock(mutex); - muxi = muxi + 1; - pthread_mutex_unlock(mutex); - return true; - } -}; - #endif -bool testAtomicPerf() { +const bool testAtomicPerf() { const int count = 100000; { - const lambda l = incPerf(); + const blambda l = []() -> const bool { + inci = inci + 1; + return true; + }; cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl; assert(inci == count + 1000); } #ifdef WANT_THREADS { - const lambda l = addAndFetchPerf(); + const blambda l = []() -> const bool { + __sync_add_and_fetch(&addi, 1); + return true; + }; cout << "Atomic inc test " << time(l, 1000, count) << " ms" << endl; assert(addi == count + 1000); } { pthread_mutex_t mutex; pthread_mutex_init(&mutex, NULL); - const lambda l = mutexPerf(&mutex); + const blambda l = [&mutex]() -> const bool { + pthread_mutex_lock(&mutex); + muxi = muxi + 1; + pthread_mutex_unlock(&mutex); + return true; + }; cout << "Locked inc test " << time(l, 1000, count) << " ms" << endl; assert(muxi == count + 1000); pthread_mutex_destroy(&mutex); } #endif { - const lambda l = tlsPerf(); + const blambda l = []() -> const bool { + *tlsi = *tlsi + 1; + return true; + }; cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl; assert(*tlsi == count + 1000); } @@ -130,7 +104,7 @@ const int mtsquare(const int x) { const list > submitSquares(worker& w, const int max, const int i) { if (i == max) return list >(); - const lambda func = curry(lambda (mtsquare), i); + const lambda func = curry(lambda (mtsquare), i); return cons(submit(w, func), submitSquares(w, max, i + 1)); } @@ -143,7 +117,7 @@ bool checkSquareResults(const list > r, int i) { } const gc_ptr tlsvc() { - gc_ptr i = new (gc_new()) unsigned long(); + const gc_ptr i = new (gc_new()) unsigned long(); *i = 0l; return i; } @@ -181,11 +155,11 @@ const bool unblockWorkers(wqueue& wq, const int n) { const list > submitTLSSets(worker& w, wqueue& wq, wqueue& xq, const int max, const int i) { if (i == max) return list >(); - const lambda func = curry(lambda>, gc_ptr>)>(tlsset), (gc_ptr>)&wq, (gc_ptr>)&xq); + const lambda func = curry(lambda>, gc_ptr>)>(tlsset), (gc_ptr>)&wq, (gc_ptr>)&xq); return cons(submit(w, func), submitTLSSets(w, wq, xq, max, i + 1)); } -bool checkTLSSets(const list > s) { +const bool checkTLSSets(const list > s) { if (isNil(s)) return true; assert(car(s) == 0); @@ -195,22 +169,22 @@ bool checkTLSSets(const list > s) { const list > submitTLSChecks(worker& w, wqueue& wq, wqueue& xq, const int max, const int i) { if (i == max) return list >(); - const lambda func = curry(lambda>, gc_ptr>)>(tlscheck), (gc_ptr>)&wq, (gc_ptr>)&xq); + const blambda func = curry(lambda>, gc_ptr>)>(tlscheck), (gc_ptr>)&wq, (gc_ptr>)&xq); return cons(submit(w, func), submitTLSChecks(w, wq, xq, max, i + 1)); } -bool checkTLSResults(const list > r) { +const bool checkTLSResults(const list > r) { if (isNil(r)) return true; assert(car(r) == true); return checkTLSResults(cdr(r)); } -bool testWorker() { +const bool testWorker() { const int max = 100; worker w(max); { - const lambda func = curry(lambda (mtsquare), 2); + const lambda func = curry(lambda (mtsquare), 2); assert(submit(w, func) == 4); } { @@ -245,7 +219,7 @@ bool testWorker() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testAtomicPerf(); diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp index 3be4d3bc8e..8b01bb819f 100644 --- a/sca-cpp/trunk/kernel/parallel.hpp +++ b/sca-cpp/trunk/kernel/parallel.hpp @@ -39,7 +39,7 @@ namespace tuscany { /** * Returns the current process id. */ -unsigned long processId() { +inline const unsigned long processId() noexcept { return (unsigned long)getpid(); } @@ -48,7 +48,7 @@ unsigned long processId() { /** * Returns the current thread id. */ -unsigned long threadId() { +inline const unsigned long threadId() noexcept{ return (unsigned long)pthread_self(); } @@ -60,20 +60,20 @@ template class future { private: template class futureValue { public: - futureValue() : hasValue(false) { + inline futureValue() noexcept : hasValue(false) { pthread_mutex_init(&valueMutex, NULL); pthread_cond_init(&valueCond, NULL); } - futureValue(const futureValue& fv) : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) { + inline futureValue(const futureValue& fv) noexcept : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) { } - ~futureValue() { + inline ~futureValue() noexcept { //pthread_mutex_destroy(&valueMutex); //pthread_cond_destroy(&valueCond); } - bool set(const T& v) { + inline const bool set(const T& v) noexcept { pthread_mutex_lock(&valueMutex); if(hasValue) { pthread_mutex_unlock(&valueMutex); @@ -86,7 +86,7 @@ private: return true; } - const T get() { + inline const T get() noexcept { pthread_mutex_lock(&valueMutex); while(!hasValue) { pthread_cond_wait(&valueCond, &valueMutex); @@ -100,37 +100,32 @@ private: pthread_mutex_t valueMutex; pthread_cond_t valueCond; bool hasValue; - X value; + gc_mutable_ref value; }; - gc_ptr > fvalue; + const gc_ptr > fvalue; - template friend const X get(const future& f); - template friend bool set(const future& f, const X& v); + template friend const X get(const future& f) noexcept; + template friend bool set(const future& f, const X& v) noexcept; public: - future() : fvalue(new (gc_new >()) futureValue()) { + inline future() noexcept : fvalue(new (gc_new >()) futureValue()) { } - ~future() { + inline ~future() noexcept { } - future(const future& f) : fvalue(f.fvalue) { + inline future(const future& f) noexcept : fvalue(f.fvalue) { } - const future& operator=(const future& f) { - if (&f == this) - return *this; - fvalue = f.fvalue; - return *this; - } + const future& operator=(const future& f) = delete; - const future& operator=(const T& v) const { + inline const future& operator=(const T& v) const noexcept { fvalue->set(v); return *this; } - operator const T() const { + inline operator const T() const noexcept { return fvalue->get(); } }; @@ -140,16 +135,16 @@ public: */ template class wqueue { public: - wqueue(size_t max) : max(max), size(0), tail(0), head(0), values(new (gc_anew(max)) T[max]) { + inline wqueue(size_t max) noexcept : max(max), size(0), tail(0), head(0), values(new (gc_anew >(max)) gc_mutable_ref[max]) { pthread_mutex_init(&mutex, NULL); pthread_cond_init(&full, NULL); pthread_cond_init(&empty, NULL); } - wqueue(const wqueue& wq) : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) { + inline wqueue(const wqueue& wq) noexcept : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) { } - ~wqueue() { + inline ~wqueue() { //pthread_mutex_destroy(&mutex); //pthread_cond_destroy(&full); //pthread_cond_destroy(&empty); @@ -163,16 +158,16 @@ private: pthread_mutex_t mutex; pthread_cond_t full; pthread_cond_t empty; - gc_ptr values; + gc_ptr > values; - template friend const size_t enqueue(wqueue& q, const X& v); - template friend const X dequeue(wqueue& q); + template friend const size_t enqueue(wqueue& q, const X& v) noexcept; + template friend const X dequeue(wqueue& q) noexcept; }; /** * Adds an element to the tail of the queue. */ -template const size_t enqueue(wqueue&q, const T& v) { +template inline const size_t enqueue(wqueue&q, const T& v) noexcept { pthread_mutex_lock(&q.mutex); while(q.size == q.max) pthread_cond_wait(&q.full, &q.mutex); @@ -187,7 +182,7 @@ template const size_t enqueue(wqueue&q, const T& v) { /** * Returns the element at the head of the queue. */ -template const T dequeue(wqueue& q) { +template inline const T dequeue(wqueue& q) noexcept { pthread_mutex_lock(&q.mutex); while(q.size == 0) pthread_cond_wait(&q.empty, &q.mutex); @@ -202,13 +197,13 @@ template const T dequeue(wqueue& q) { /** * The worker thread function. */ -void *workerThreadFunc(void *arg) { +inline void* workerThreadFunc(void* arg) noexcept { int ost; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ost); int ot; pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ot); - wqueue >* work = reinterpret_cast >*>(arg); + wqueue* work = reinterpret_cast*>(arg); while(dequeue(*work)()) ; return NULL; @@ -217,7 +212,7 @@ void *workerThreadFunc(void *arg) { /** * Returns a list of worker threads. */ -const list workerThreads(wqueue >& wqueue, const size_t count) { +inline const list workerThreads(wqueue& wqueue, const size_t count) noexcept { if (count == 0) return list(); pthread_t thread; @@ -235,32 +230,32 @@ private: // copies of the queue and thread pool when a worker is copied class sharedWorker { public: - sharedWorker(size_t max) : work(wqueue >(max)), threads(workerThreads(work, max)) { + inline sharedWorker(size_t max) noexcept : work(wqueue(max)), threads(workerThreads(work, max)) { } - wqueue > work; + wqueue work; const list threads; }; public: - worker(size_t max) : w(*(new (gc_new()) sharedWorker(max))) { + inline worker(size_t max) noexcept : w(*(new (gc_new()) sharedWorker(max))) { } - worker(const worker& wk) : w(wk.w) { + inline worker(const worker& wk) noexcept : w(wk.w) { } private: sharedWorker& w; - template friend const future submit(worker& w, const lambda& func); - friend const bool shutdown(worker& w); - friend const bool cancel(worker& w); + template friend const future submit(const worker& w, const lambda& func) noexcept; + friend const bool shutdown(const worker& w) noexcept; + friend const bool cancel(const worker& w) noexcept; }; /** * Function used to wrap work submitted to a worker. */ -template bool submitFunc(const lambda& func, const future& fut) { +template inline const bool submitFunc(const lambda& func, const future& fut) noexcept { fut = func(); return true; } @@ -268,9 +263,9 @@ template bool submitFunc(const lambda& func, const future& f /** * Submits work to a worker. */ -template const future submit(worker& w, const lambda& func) { +template inline const future submit(const worker& w, const lambda& func) noexcept { const future fut; - const lambda f = curry(lambda, future)>(submitFunc), func, fut); + const blambda f = curry(lambda, future)>(submitFunc), func, fut); enqueue(w.w.work, f); return fut; } @@ -278,7 +273,7 @@ template const future submit(worker& w, const lambda& func) /** * Enqueues shutdown requests. */ -const bool shutdownEnqueue(const list& threads, wqueue >& work) { +inline const bool shutdownEnqueue(const list& threads, wqueue& work) noexcept { if (isNil(threads)) return true; enqueue(work, result(false)); @@ -288,7 +283,7 @@ const bool shutdownEnqueue(const list& threads, wqueue /** * Waits for shut down threads to terminate. */ -const bool shutdownJoin(const list& threads) { +inline const bool shutdownJoin(const list& threads) noexcept { if (isNil(threads)) return true; pthread_join(car(threads), NULL); @@ -298,7 +293,7 @@ const bool shutdownJoin(const list& threads) { /** * Shutdown a worker. */ -const bool shutdown(worker& w) { +inline const bool shutdown(const worker& w) noexcept { shutdownEnqueue(w.w.threads, w.w.work); shutdownJoin(w.w.threads); return true; @@ -307,14 +302,14 @@ const bool shutdown(worker& w) { /** * Cancel a worker. */ -const bool cancel(const list& threads) { +inline const bool cancel(const list& threads) noexcept { if (isNil(threads)) return true; pthread_cancel(car(threads)); return cancel(cdr(threads)); } -const bool cancel(worker& w) { +inline const bool cancel(const worker& w) noexcept { cancel(w.w.threads); return true; } @@ -324,7 +319,7 @@ const bool cancel(worker& w) { /** * Returns the current thread id. */ -unsigned long threadId() { +inline const unsigned long threadId() noexcept { return 0; } @@ -335,114 +330,106 @@ unsigned long threadId() { */ template class perthread_ptr { public: - perthread_ptr() : key(createkey()), owner(true), cl(lambda()>()), managed(false) { + inline perthread_ptr() noexcept : key(createkey()), owner(true), cl(lambda()>()), managed(false) { } - perthread_ptr(const lambda()>& cl) : key(createkey()), owner(true), cl(cl), managed(true) { + inline perthread_ptr(const lambda()>& cl) noexcept : key(createkey()), owner(true), cl(cl), managed(true) { } - ~perthread_ptr() { + inline ~perthread_ptr() noexcept { if (owner) deletekey(key); } - perthread_ptr(const perthread_ptr& c) : key(c.key), owner(false), cl(c.cl), managed(c.managed) { + inline perthread_ptr(const perthread_ptr& c) noexcept : key(c.key), owner(false), cl(c.cl), managed(c.managed) { } - perthread_ptr& operator=(const perthread_ptr& r) throw() { - if(this == &r) - return *this; - key = r.key; - owner = false; - cl = r.cl; - managed = r.managed; - return *this; - } + perthread_ptr& operator=(const perthread_ptr& r) = delete; - const perthread_ptr& operator=(const gc_ptr& v) { + inline const perthread_ptr& operator=(const gc_ptr& v) const noexcept { set(v); return *this; } - const perthread_ptr& operator=(T* v) { + inline const perthread_ptr& operator=(T* const v) const noexcept { set(v); return *this; } - const bool operator==(const gc_ptr& r) const throw() { + inline const bool operator==(const gc_ptr& r) const noexcept { return get() == r; } - const bool operator==(T* p) const throw() { + inline const bool operator==(const T* const p) const noexcept { return get() == p; } - const bool operator!=(const gc_ptr& r) const throw() { + inline const bool operator!=(const gc_ptr& r) const noexcept { return !this->operator==(r); } - const bool operator!=(T* p) const throw() { + inline const bool operator!=(const T* const p) const noexcept { return !this->operator==(p); } - T& operator*() const throw() { + inline T& operator*() const noexcept { return *get(); } - T* operator->() const throw() { + inline T* const operator->() const noexcept { return get(); } - operator gc_ptr() const { + inline operator gc_ptr() const { return get(); } - operator T*() const { + inline operator T* const () const { return get(); } private: #ifdef WANT_THREADS - pthread_key_t createkey() { + inline const pthread_key_t createkey() noexcept { pthread_key_t k; pthread_key_create(&k, NULL); return k; } - bool deletekey(pthread_key_t k) { + inline const bool deletekey(pthread_key_t k) noexcept { pthread_key_delete(k); return true; } - bool set(const gc_ptr& v) { + inline const bool set(const gc_ptr& v) const noexcept { pthread_setspecific(key, (T*)v); return true; } - gc_ptr get() const { - const gc_ptr v = static_cast(pthread_getspecific(key)); + inline const gc_ptr get() const noexcept { + const gc_ptr v = (T*)(pthread_getspecific(key)); if (v != NULL || !managed) return v; const gc_ptr nv = cl(); - pthread_setspecific(key, nv); + pthread_setspecific(key, (T*)nv); return nv; } #else - gc_ptr > createkey() { + inline const gc_ptr > createkey() noexcept { return new (gc_new >()) gc_ptr(); } - bool deletekey(unused gc_ptr > k) { + inline const bool deletekey(unused gc_ptr > k) noexcept { return true; } - bool set(const gc_ptr& v) { + inline const bool set(const gc_ptr& v) const noexcept { *key = v; return true; } - gc_ptr get() const { + inline const gc_ptr get() const noexcept { if (*key != NULL || !managed) return *key; *key = cl(); @@ -452,14 +439,14 @@ private: #endif #ifdef WANT_THREADS - pthread_key_t key; + const pthread_key_t key; #else - gc_ptr >key; + const gc_ptr >key; #endif - bool owner; - lambda()> cl; - bool managed; + const bool owner; + const lambda()> cl; + const bool managed; }; } diff --git a/sca-cpp/trunk/kernel/perf.hpp b/sca-cpp/trunk/kernel/perf.hpp index 04aad06664..07c586ce7c 100644 --- a/sca-cpp/trunk/kernel/perf.hpp +++ b/sca-cpp/trunk/kernel/perf.hpp @@ -37,21 +37,15 @@ namespace tuscany /** * Measure the time required to perform a function in msec. */ -struct timeLambda { - const lambda f; - timeLambda(const lambda& f) : f(f) { - } - bool operator()(const long count) const { +inline const double time(const blambda& f, const long warmup, const long count) { + struct timeval start; + struct timeval end; + + const lambda tl = [f](const long count) -> const bool { for (long i = 0; i < count; i++) f(); return true; - } -}; - -const double time(const lambda& f, const long warmup, const long count) { - const lambda tl = timeLambda(f); - struct timeval start; - struct timeval end; + }; tl(warmup); gettimeofday(&start, NULL); @@ -62,13 +56,13 @@ const double time(const lambda& f, const long warmup, const long count) return (double)t / (double)count; } -const unsigned long timems() { +inline const unsigned long timems() { struct timeval t; gettimeofday(&t, NULL); return (unsigned long)(t.tv_sec * 1000 + t.tv_usec / 1000); } -const unsigned long timens() { +inline const unsigned long timens() { struct timeval t; gettimeofday(&t, NULL); return (unsigned long)(t.tv_sec * 1000000000 + t.tv_usec * 1000); diff --git a/sca-cpp/trunk/kernel/sstream.hpp b/sca-cpp/trunk/kernel/sstream.hpp index 17fd28b48b..dbdc7414a1 100644 --- a/sca-cpp/trunk/kernel/sstream.hpp +++ b/sca-cpp/trunk/kernel/sstream.hpp @@ -38,14 +38,14 @@ namespace tuscany { /** * Instrumentable memcpy. */ -void* stream_memcpy(void* t, const void* s, const size_t n) { +inline void* stream_memcpy(void* t, const void* s, const size_t n) { return memcpy(t, s, n); } /** * Write a list of strings into a buffer. */ -const bool writeList(const list& l, char* buf) { +const bool writeList(const list& l, char* const buf) { if (isNil(l)) return true; const string c = car(l); @@ -59,63 +59,108 @@ const bool writeList(const list& l, char* buf) { */ class ostringstream : public ostream { public: - ostringstream() : len(0) { + inline ostringstream() : len(0), accumbuf(NULL), accumlen(0), buf() { } - ~ostringstream() { + inline ~ostringstream() { } - ostringstream(const ostringstream& os) { - len = os.len; - buf = os.buf; + inline ostringstream(const ostringstream& os) : len(os.len), accumbuf(os.accumbuf), accumlen(os.accumlen), buf(os.buf) { } - ostringstream& vprintf(const char* fmt, ...) { + inline ostringstream& vprintf(const char* const fmt, ...) { va_list args; - string s; va_start (args, fmt); - s.len = vsnprintf(NULL, 0, fmt, args); - s.buf = gc_cnew(s.len + 1); + const size_t l = vsnprintf(NULL, 0, fmt, args); + if (l <= 256) { + char c[256]; + va_start (args, fmt); + vsnprintf(c, l + 1, fmt, args); + va_end (args); + accumulate(c, l); + return *this; + } + spill(); + char* const sbuf = gc_cnew(l + 1); va_start (args, fmt); - vsnprintf(s.buf, s.len + 1, fmt, args); - buf = cons(s, buf); - len += s.len; + vsnprintf(sbuf, l + 1, fmt, args); va_end (args); + buf = cons(string(sbuf, l, false), (const list)buf); + len += l; return *this; } - ostringstream& write(const string& s) { - buf = cons(s, buf); + inline ostringstream& write(const string& s) { + if (s.len <= 256) { + accumulate(s.buf, s.len); + return *this; + } + spill(); + buf = cons(s, (const list)buf); len += s.len; return *this; } - ostringstream& flush() { + inline ostringstream& write(const char c) { + accumulate(&c, 1); + return *this; + } + + inline ostringstream& flush() { + spill(); return *this; } private: - const string str() { - if (isNil(buf)) - return string(); - string s; - s.len = len; - s.buf = gc_cnew(s.len + 1); - writeList(buf, s.buf + len); - s.buf[s.len] = '\0'; - return s; + inline const string str() { + spill(); + if (isNil((const list)buf)) + return emptyString; + char* const sbuf = gc_cnew(len + 1); + writeList(buf, sbuf + len); + sbuf[len] = '\0'; + return string(sbuf, len, false); + } + + inline const bool accumulate(const char* const c, const size_t l) { + if (accumbuf == NULL) + accumbuf = gc_cnew(65); + for(size_t i = 0; i < l; i++) { + accumbuf[accumlen] = c[i]; + accumlen++; + if (accumlen == 64) { + accumbuf[accumlen] = '\0'; + buf = cons(string(accumbuf, accumlen, false), (const list)buf); + accumbuf = i < l? gc_cnew(65) : NULL; + accumlen = 0; + } + } + accumbuf[accumlen] = '\0'; + len += l; + return true; + } + + inline const bool spill() { + if (accumbuf == NULL) + return true; + buf = cons(string(accumbuf, accumlen), (const list)buf); + accumbuf = NULL; + accumlen = 0; + return true; } friend const string str(ostringstream& os); size_t len; - list buf; + char* accumbuf; + size_t accumlen; + gc_mutable_ref > buf; }; /** * Return a string representation of a stream. */ -const string str(ostringstream& os) { +inline const string str(ostringstream& os) { return os.str(); } @@ -124,23 +169,16 @@ const string str(ostringstream& os) { */ class istringstream : public istream { public: - istringstream(const string& s) { - cur = 0; - const size_t slen = length(s); - len = slen; - buf = c_str(s); - } - - ~istringstream() { + inline istringstream(const string& s) : len(length(s)), cur(0), buf(c_str(s)) { + } + + inline ~istringstream() { } - istringstream(const istringstream& is) { - len = is.len; - cur = is.cur; - buf = is.buf; + inline istringstream(const istringstream& is) : len(is.len), cur(is.cur), buf(is.buf) { } - const size_t read(void* b, size_t size) { + inline const size_t read(void* const b, const size_t size) { const size_t n = len - cur; if (n == 0) return 0; @@ -154,30 +192,28 @@ public: return n; } - const bool eof() { + inline const bool eof() { return cur == len; } - const bool fail() { + inline const bool fail() { return false; } - const int get() { - if (eof()) + inline const int get() { + if (cur == len) return -1; - const int c = buf[cur]; - cur += 1; - return c; + return buf[cur++]; } - const int peek() { - if (eof()) + inline const int peek() { + if (cur == len) return -1; return buf[cur]; } private: - size_t len; + const size_t len; size_t cur; const char* buf; }; @@ -185,62 +221,52 @@ private: /** * Tokenize a string into a list of strings. */ -const list tokenize(const char* sep, const string& str) { - struct nested { - static const list tokenize(const char* sep, const size_t slen, const string& str, const size_t start) { - if (start >= length(str)) - return list(); - const size_t i = find(str, sep, start); - if (i == length(str)) - return mklist(string(substr(str, start))); - return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen)); - } +inline const list tokenize(const char* const sep, const string& str) { + const lambda(const char* const, const size_t, const string&, const size_t)> tokenize = [&tokenize](const char* const sep, const size_t slen, const string& str, const size_t start) -> const list { + if (start >= length(str)) + return list(); + const size_t i = find(str, sep, start); + if (i == length(str)) + return mklist(string(substr(str, start))); + return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen)); }; - return nested::tokenize(sep, strlen(sep), str, 0); + return tokenize(sep, strlen(sep), str, 0); } /** * Join a list of strings into a single string. */ -const string join(const char* sep, const list& l) { - struct nested { - static ostringstream& join(const char* sep, const list& l, ostringstream& os) { - if (isNil(l)) - return os; - os << car(l); - if (!isNil(cdr(l))) - os << sep; - return join(sep, cdr(l), os); - } - }; +inline const string join(const char* const sep, const list& l) { ostringstream os; - return str(nested::join(sep, l, os)); + const lambda&, ostringstream&)> join = [&join](const char* const sep, const list& l, ostringstream& os) -> ostringstream& { + if (isNil(l)) + return os; + os << car(l); + if (!isNil(cdr(l))) + os << sep; + return join(sep, cdr(l), os); + }; + return str(join(sep, l, os)); } /** * Returns a lazy list view of an input stream. */ -struct ilistRead{ - istream &is; - ilistRead(istream& is) : is(is) { - } - const list operator()() { +inline const list streamList(istream& is) { + const lambda()> ilistRead = [&is, &ilistRead]() -> const list { char buffer[1024]; const size_t n = read(is, buffer, sizeof(buffer)); if (n ==0) return list(); - return cons(string(buffer, n), (*this)()); - } -}; - -const list streamList(istream& is) { - return ilistRead(is)(); + return cons(string(buffer, n), ilistRead()); + }; + return ilistRead(); } /** * Fragment the first element of a list of strings to fit the given max length. */ -const list fragment(list l, size_t max) { +inline const list fragment(const list& l, const size_t max) { const string s = car(l); if (length(s) <= max) return l; @@ -250,13 +276,26 @@ const list fragment(list l, size_t max) { /** * Write a list of strings to an output stream. */ -ostream& write(const list& l, ostream& os) { +inline ostream& write(const list& l, ostream& os) { if(isNil(l)) return os; os << car(l); return write(cdr(l), os); } +/** + * Convert a list of strings to a string. + */ +inline const string write(const list& l) { + if (isNil(l)) + return emptyString; + if (isNil(cdr(l))) + return car(l); + ostringstream os; + write(l, os); + return str(os); +} + } #endif /* tuscany_sstream_hpp */ diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp index 8ccfed948f..e59e6a4ef5 100644 --- a/sca-cpp/trunk/kernel/stream.hpp +++ b/sca-cpp/trunk/kernel/stream.hpp @@ -38,66 +38,67 @@ namespace tuscany { */ class ostream { public: - virtual ostream& vprintf(const char* fmt, ...) = 0; + virtual ostream& vprintf(const char* const fmt, ...) = 0; virtual ostream& write(const string& s) = 0; + virtual ostream& write(const char c) = 0; virtual ostream& flush() = 0; }; /** * Flush a stream. */ -ostream& flush(ostream& os) { +inline ostream& flush(ostream& os) { return os.flush(); } /** * Write simple values to a stream. */ -ostream& operator<<(ostream& os, const char* v) { +inline ostream& operator<<(ostream& os, const char* const v) { return os.vprintf("%s", v); } -ostream& operator<<(ostream& os, const unsigned char* v) { +inline ostream& operator<<(ostream& os, const unsigned char* const v) { return os.vprintf("%s", v); } -ostream& operator<<(ostream& os, const char v) { - return os.vprintf("%c", v); +inline ostream& operator<<(ostream& os, const char v) { + return os.write(v); } -ostream& operator<<(ostream& os, const int v) { +inline ostream& operator<<(ostream& os, const int v) { return os.vprintf("%d", v); } -ostream& operator<<(ostream& os, const unsigned int v) { +inline ostream& operator<<(ostream& os, const unsigned int v) { return os.vprintf("%u", v); } -ostream& operator<<(ostream& os, const long int v) { +inline ostream& operator<<(ostream& os, const long int v) { return os.vprintf("%ld", v); } -ostream& operator<<(ostream& os, const long unsigned int v) { +inline ostream& operator<<(ostream& os, const long unsigned int v) { return os.vprintf("%lu", v); } -ostream& operator<<(ostream& os, const double v) { +inline ostream& operator<<(ostream& os, const double v) { return os.vprintf("%.10g", v); } -ostream& operator<<(ostream& os, const void* v) { +inline ostream& operator<<(ostream& os, const void* const v) { return os.vprintf("%p", v); } -ostream& operator<<(ostream& os, const string& v) { +inline ostream& operator<<(ostream& os, const string& v) { return os.write(v); } class stream_endl { } endl; -ostream& operator<<(ostream& os, unused const stream_endl e) { - os.write("\n"); +inline ostream& operator<<(ostream& os, unused const stream_endl e) { + os.write('\n'); return os.flush(); } @@ -106,7 +107,7 @@ ostream& operator<<(ostream& os, unused const stream_endl e) { */ class istream { public: - virtual const size_t read(void* buf, size_t size) = 0; + virtual const size_t read(void* const buf, const size_t size) = 0; virtual const bool eof() = 0; virtual const bool fail() = 0; virtual const int get() = 0; @@ -116,40 +117,61 @@ public: /** * Read from an input stream. */ -const size_t read(istream& is, void * buf, size_t size) { +inline const size_t read(istream& is, void* const buf, const size_t size) { return is.read(buf, size); } /** * Return true if the end of an input stream has been reached. */ -const bool eof(istream& is) { +inline const bool eof(istream& is) { return is.eof(); } /** * Return true if an input stream can't be accessed. */ -const bool fail(istream& is) { +inline const bool fail(istream& is) { return is.fail(); } /** * Read a character from a stream. */ -const int get(istream& is) { +inline const int get(istream& is) { return is.get(); } /** * Peek a character from a stream. */ -const int peek(istream& is) { +inline const int peek(istream& is) { return is.peek(); } -template ostream& operator<<(ostream& out, const gc_ptr& p) { - return out << p.ptr; +#ifndef WANT_RAW_PTR + +/** + * Write a pointer. + */ +template inline ostream& operator<<(ostream& out, const gc_ptr& p) { + return out << (T*)p; +} + +/** + * Write a mutable pointer. + */ +template inline ostream& operator<<(ostream& out, const gc_mutable_ptr& p) { + return out << (T*)p; +} + +#endif + +/** + * Write a mutable reference. + */ +template inline ostream& operator<<(ostream& out, const gc_mutable_ref& r) { + return out << (T)r; } #ifdef WANT_MAINTAINER_LOG @@ -159,35 +181,40 @@ template ostream& operator<<(ostream& out, const gc_ptr& p) { */ class odebugstream : public ostream { public: - odebugstream() { + inline odebugstream() : buf() { } - odebugstream& vprintf(const char* fmt, ...) { + inline odebugstream& vprintf(const char* const fmt, ...) { va_list args; string s; va_start (args, fmt); - s.len = vsnprintf(NULL, 0, fmt, args); - s.buf = gc_cnew(s.len + 1); + const size_t slen = vsnprintf(NULL, 0, fmt, args); + char* const sbuf = gc_cnew(slen + 1); va_start (args, fmt); - vsnprintf(s.buf, s.len + 1, fmt, args); - buf = buf + s; + vsnprintf(sbuf, slen + 1, fmt, args); + buf = buf + string(sbuf, slen, false); va_end (args); return *this; } - odebugstream& write(const string& s) { + inline odebugstream& write(const string& s) { buf = buf + s; return *this; } - odebugstream& flush() { + inline odebugstream& write(const char c) { + buf = buf + c; + return *this; + } + + inline odebugstream& flush() { return *this; } private: friend const string str(odebugstream& os); - string buf; + gc_mutable_ref buf; }; const string str(odebugstream& os) { diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp index b6f016b294..66716c96b5 100644 --- a/sca-cpp/trunk/kernel/string-test.cpp +++ b/sca-cpp/trunk/kernel/string-test.cpp @@ -32,15 +32,15 @@ namespace tuscany { -bool testCopies() { +const bool testCopies() { resetStringCopyCounters(); - string x("abcd"); + const string x("abcd"); assert(checkStringCopyCounters(1)); resetStringCopyCounters(); - string y = string("abcd"); + const string y = string("abcd"); assert(checkStringCopyCounters(1)); resetStringCopyCounters(); - unused string z = y; + unused const string z = y; assert(checkStringCopyCounters(0)); resetStringCopyCounters(); const list pl = list() + "abcd" + "efgh"; @@ -51,7 +51,7 @@ bool testCopies() { return true; } -bool testString() { +const bool testString() { const string s("abcd"); assert(length(s) == 4); assert(!strcmp(c_str(s), "abcd")); @@ -89,12 +89,19 @@ bool testString() { return true; } -bool testStream() { +const bool testStream() { ostringstream os; os << "ab" << "cd"; - cout << str(os) << endl; assert(str(os) == "abcd"); + ostringstream bos; + bos << "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"; + bos << "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"; + cout << str(bos) << endl; + assert(str(bos) == + "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ"); + ostringstream cs; cs << "\'"; assert(str(cs) == "\'"); @@ -113,69 +120,65 @@ bool testStream() { return true; } -std::string stdAdd(std::string& x, std::string& y) { +const std::string stdAdd(const std::string& x, const std::string& y) { return x + y; } -string add(string& x, string& y) { +const string add(const string& x, const string& y) { return x + y; } char charBuffer[16385]; -struct addStrings{ - const size_t size; - addStrings(const size_t size) : size(size) { - } - bool operator()() const { - const size_t sz = size / 4; - string x(charBuffer, sz); - string y(charBuffer, sz); - assert(length(add(x, y)) == sz * 2); - return true; - } -}; - -struct addStdStrings{ - const size_t size; - addStdStrings(const size_t size) : size(size) { - } - bool operator()() const { - const size_t sz = size / 4; - std::string x(charBuffer, sz); - std::string y(charBuffer, sz); - assert(stdAdd(x, y).length() == (unsigned int)(sz * 2)); - return true; - } -}; - -bool testStringPerf() { +const bool testStringPerf() { memset(charBuffer, 'A', 16384); charBuffer[16384] = '\0'; const int count = 10000; { - const lambda a16 = addStrings(16); + const lambda addStrings = [](const size_t size) -> const blambda { + const blambda l = [size]() -> const bool { + const size_t sz = size / 4; + const string x(charBuffer, sz); + const string y(charBuffer, sz); + assert(length(add(x, y)) == sz * 2); + return true; + }; + return l; + }; + + const blambda a16 = addStrings(16); cout << "string test " << time(a16, 5, count) << " ms" << endl; - const lambda a32 =addStrings(32); + const blambda a32 =addStrings(32); cout << "string test " << time(a32, 5, count) << " ms" << endl; - const lambda a256 =addStrings(256); + const blambda a256 =addStrings(256); cout << "string test " << time(a256, 5, count) << " ms" << endl; - const lambda a1024 =addStrings(1024); + const blambda a1024 =addStrings(1024); cout << "string test " << time(a1024, 5, count) << " ms" << endl; - const lambda a4096 =addStrings(4096); + const blambda a4096 =addStrings(4096); cout << "string test " << time(a4096, 5, count) << " ms" << endl; } { - const lambda a16 =addStdStrings(16); + const lambda addStdStrings = [](const size_t size) -> const blambda { + const blambda l = [size]() -> const bool { + const size_t sz = size / 4; + const std::string x(charBuffer, sz); + const std::string y(charBuffer, sz); + assert(stdAdd(x, y).length() == (unsigned int)(sz * 2)); + return true; + }; + return l; + }; + + const blambda a16 =addStdStrings(16); cout << "Std string test " << time(a16, 5, count) << " ms" << endl; - const lambda a32 =addStdStrings(32); + const blambda a32 =addStdStrings(32); cout << "Std string test " << time(a32, 5, count) << " ms" << endl; - const lambda a256 =addStdStrings(256); + const blambda a256 =addStdStrings(256); cout << "Std string test " << time(a256, 5, count) << " ms" << endl; - const lambda a1024 =addStdStrings(1024); + const blambda a1024 =addStdStrings(1024); cout << "Std string test " << time(a1024, 5, count) << " ms" << endl; - const lambda a4096 =addStdStrings(4096); + const blambda a4096 =addStdStrings(4096); cout << "Std string test " << time(a4096, 5, count) << " ms" << endl; } @@ -185,7 +188,7 @@ bool testStringPerf() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::testCopies(); diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp index e726a61b84..4d27ce84d7 100644 --- a/sca-cpp/trunk/kernel/string.hpp +++ b/sca-cpp/trunk/kernel/string.hpp @@ -41,16 +41,16 @@ namespace tuscany { */ long countStringCopies = 0; -bool resetStringCopyCounters() { +inline const bool resetStringCopyCounters() { countStringCopies = 0; return true; } -bool checkStringCopyCounters(long c) { +inline const bool checkStringCopyCounters(long c) { return countStringCopies == c; } -bool printStringCopyCounters() { +inline const bool printStringCopyCounters() { printf("countStringCopies %ld\n", countStringCopies); return true; } @@ -66,13 +66,19 @@ bool printStringCopyCounters() { /** * Instrumented memcpy. */ -void* string_memcpy(void* t, const void* s, const size_t n) { #ifdef WANT_MAINTAINER_COUNTERS + +inline void* string_memcpy(void* t, const void* s, const size_t n) { countStringCopies += 1; -#endif return memcpy(t, s, n); } +#else + +#define string_memcpy(t, s, n) memcpy(t, s, n) + +#endif + char stringEmptyBuffer[1] = { '\0' }; /** @@ -80,56 +86,27 @@ char stringEmptyBuffer[1] = { '\0' }; */ class string { public: - string() : len(0) { - buf = stringEmptyBuffer; + inline string() noexcept : len(0), buf(stringEmptyBuffer) { } - string(const char* s) { - len = strlen(s); - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - string_memcpy(buf, s, len + 1); + inline string(const char* const s) noexcept : len(strlen(s)), buf(mksbuf(s, len)) { } - string(const char* s, const size_t n) { - len = n; - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - string_memcpy(buf, s, len); - buf[len] = '\0'; + inline string(const char* const s, const size_t n) noexcept : len(n), buf(mksbuf(s, n)) { } - string(const size_t n, const char c) { - len = n; - if (len == 0) { - buf = stringEmptyBuffer; - return; - } - buf = gc_cnew(len + 1); - memset(buf, c, n); - buf[len] = '\0'; + inline string(const char* const s, const size_t n, const bool copy) noexcept : len(n), buf(mksbuf(s, n, copy)) { } - string(const string& s) { - len = s.len; - buf = s.buf; + inline string(const size_t n, const char c) noexcept : len(n), buf(mkcbuf(c, n)) { } - const string& operator=(const string& s) { - if (&s == this) - return *this; - len = s.len; - buf = s.buf; - return *this; + inline string(const string& s) noexcept : len(s.len), buf(s.buf) { } - const bool operator==(const string& s) const { + string& operator=(const string& s) = delete; + + inline const bool operator==(const string& s) const noexcept { if (len != s.len) return false; if (buf == s.buf) @@ -137,21 +114,21 @@ public: return memcmp(buf, s.buf, len) == 0; } - const bool operator!=(const string& s) const { + inline const bool operator!=(const string& s) const noexcept { return !(*this == s); } - const bool operator==(const char* s) const { + inline const bool operator==(const char* const s) const noexcept { if (buf == s) return true; return strcmp(buf, s) == 0; } - const bool operator!=(const char* s) const { + inline const bool operator!=(const char* const s) const noexcept { return !(*this == s); } - const bool operator<(const string& s) const { + inline const bool operator<(const string& s) const noexcept { const size_t n = len < s.len? len : s.len; const int c = memcmp(buf, s.buf, n); if (c < 0) @@ -161,9 +138,9 @@ public: return false; } - const bool operator>(const string& s) const { + inline const bool operator>(const string& s) const noexcept { const size_t n = len < s.len? len : s.len; - int c = memcmp(buf, s.buf, n); + const int c = memcmp(buf, s.buf, n); if (c > 0) return true; if (c == 0) @@ -176,91 +153,137 @@ private: friend class odebugstream; #endif friend class ostringstream; - friend const string operator+(const string& a, const string& b); - friend const string operator+(const string& a, const char* b); - friend const size_t length(const string& s); - friend const char* c_str(const string& s); - friend const size_t find(const string& s1, const char* s2, const size_t start); - friend const string substr(const string& s, const size_t pos, const size_t n); - - size_t len; - char* buf; + friend const string operator+(const string& a, const string& b) noexcept; + friend const string operator+(const string& a, const char* const b) noexcept; + friend const string operator+(const string& a, const char c) noexcept; + friend const size_t length(const string& s) noexcept; + friend const char* const c_str(const string& s) noexcept; + friend const size_t find(const string& s1, const char* const s2, const size_t start) noexcept; + friend const string substr(const string& s, const size_t pos, const size_t n) noexcept; + friend const bool setstring(string& target, const string& s); + + const size_t len; + const char* const buf; + + const char* const mkbuf(const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + b[n] = '\0'; + return b; + } + + const char* const mksbuf(const char* const s, const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + string_memcpy(b, s, n); + b[n] = '\0'; + return b; + } + + const char* const mksbuf(const char* const s, const size_t n, const bool copy) { + if (!copy) + return s; + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + string_memcpy(b, s, n); + b[n] = '\0'; + return b; + } + + const char* const mkcbuf(const char c, const size_t n) { + if (n == 0) + return stringEmptyBuffer; + char* const b = gc_cnew(n + 1); + memset(b, c, n); + b[n] = '\0'; + return b; + } }; /** * Adds two strings. */ -const string operator+(const string& a, const string& b) { - string s; - s.len = a.len + b.len; - s.buf = gc_cnew(s.len + 1); - string_memcpy(s.buf, a.buf, a.len); - string_memcpy(s.buf + a.len, b.buf, b.len); - s.buf[s.len] = '\0'; - return s; +inline const string operator+(const string& sa, const string& sb) noexcept { + const size_t n = sa.len + sb.len; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + string_memcpy(b + sa.len, sb.buf, sb.len); + b[n] = '\0'; + return string(b, n, false); } -const string operator+(const string& a, const char* b) { - string s; - const size_t blen = strlen(b); - s.len = a.len + blen; - s.buf = gc_cnew(s.len + 1); - string_memcpy(s.buf, a.buf, a.len); - string_memcpy(s.buf + a.len, b, blen); - s.buf[s.len] = '\0'; - return s; +inline const string operator+(const string& sa, const char* const sb) noexcept { + const size_t bn = strlen(sb); + const size_t n = sa.len + bn; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + string_memcpy(b + sa.len, sb, bn); + b[n] = '\0'; + return string(b, n, false); +} + +inline const string operator+(const string& sa, const char c) noexcept { + const size_t n = sa.len + 1; + char* const b = gc_cnew(n + 1); + string_memcpy(b, sa.buf, sa.len); + b[n - 1] = c; + b[n] = '\0'; + return string(b, n, false); } /** * Returns the length of a string. */ -const size_t length(const string& s) { +inline const size_t length(const string& s) noexcept { return s.len; } /** * Returns a string as a C zero terminated string. */ -const char* c_str(const string& s) { +inline const char* const c_str(const string& s) noexcept { return s.buf; } /** * Find the first occurrence of string s2 in s1, starting at the given position. */ -const size_t find(const string& s1, const char* s2, const size_t start) { +inline const size_t find(const string& s1, const char* const s2, const size_t start) noexcept { if (start >= s1.len) return s1.len; - const char *f = strstr(s1.buf + start, s2); + const char* const f = strstr(s1.buf + start, s2); if (f == NULL) return s1.len; return f - s1.buf; } -const size_t find(const string& s1, const char* s2) { +inline const size_t find(const string& s1, const char* const s2) noexcept { return find(s1, s2, 0); } /** * Return true if string s1 contains s2. */ -const bool contains(const string& s1, const char* s2) { +inline const bool contains(const string& s1, const char* const s2) noexcept { return find(s1, s2) != length(s1); } /** * Find the first occurence of any character from a string in a string. */ -const size_t find_first_of(const string& s1, const string& s2) { +inline const size_t find_first_of(const string& s1, const string& s2) noexcept { return strcspn(c_str(s1), c_str(s2)); } /** * Find the first occurence of a character in a string. */ -const size_t find(const string& s, const char c) { - const char* cs = c_str(s); - const char* f = strchr(cs, c); +inline const size_t find(const string& s, const char c) noexcept { + const char* const cs = c_str(s); + const char* const f = strchr(cs, c); if (f == NULL) return length(s); return f - cs; @@ -269,9 +292,9 @@ const size_t find(const string& s, const char c) { /** * Find the last occurence of a character in a string. */ -const size_t find_last(const string& s, const char c) { - const char* cs = c_str(s); - const char* f = strrchr(cs, c); +inline const size_t find_last(const string& s, const char c) noexcept { + const char* const cs = c_str(s); + const char* const f = strrchr(cs, c); if (f == NULL) return length(s); return f - cs; @@ -280,7 +303,7 @@ const size_t find_last(const string& s, const char c) { /** * Return a substring of a string. */ -const string substr(const string& s, const size_t pos, const size_t n) { +inline const string substr(const string& s, const size_t pos, const size_t n) noexcept { if (pos >= s.len) return string(); if (pos + n > s.len) @@ -288,17 +311,29 @@ const string substr(const string& s, const size_t pos, const size_t n) { return string(s.buf + pos, n); } -const string substr(const string& s, const size_t pos) { +inline const string substr(const string& s, const size_t pos) noexcept { return substr(s, pos, length(s)); } /** - * Common string constants. + * Set a string. Use with moderation. */ +/* +inline const bool setstring(string& target, const string& s) { + if (&target == &s) + return true; + memcpy((void*)&target.len, (void*)&s.len, sizeof(size_t)); + memcpy((void*)&target.buf, (void*)&s.buf, sizeof(char*)); + return true; +} +*/ -string trueString("true"); -string falseString("false"); -string emptyString(""); +/** + * Common string constants. + */ +const string trueString("true"); +const string falseString("false"); +const string emptyString(""); } diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp index 89a131c324..44af09fa64 100644 --- a/sca-cpp/trunk/kernel/tree.hpp +++ b/sca-cpp/trunk/kernel/tree.hpp @@ -38,14 +38,14 @@ namespace tuscany { /** * Make a tree from a leaf and two branches. */ -template const list mktree(const T& e, const list& left, const list& right) { +template inline const list mktree(const T& e, const list& left, const list& right) { return mklist(e, left, right); } /** * Find a leaf with the given key in a tree. */ -template const list assoctree(const T& k, const list& tree) { +template inline const list assoctree(const T& k, const list& tree) { if (isNil(tree)) return tree; if (k == car(car(tree))) @@ -58,7 +58,7 @@ template const list assoctree(const T& k, const list& tree) { /** * Construct a new tree from a leaf and a tree. */ -template const list constree(const T& e, const list& tree) { +template inline const list constree(const T& e, const list& tree) { if (isNil(tree)) return mktree(e, list(), list()); if (e == car(tree)) @@ -71,7 +71,7 @@ template const list constree(const T& e, const list& tree) { /** * Make a tree from an unordered list of leaves. */ -template const list mktree(const list& l) { +template inline const list mktree(const list& l) { if (isNil(l)) return l; return constree(car(l), mktree(cdr(l))); @@ -80,7 +80,7 @@ template const list mktree(const list& l) { /** * Convert a tree to an ordered list of leaves. */ -template const list flatten(const list& tree) { +template inline const list flatten(const list& tree) { if (isNil(tree)) return tree; return append(flatten(cadr(tree)), cons(car(tree), flatten(caddr(tree)))); @@ -89,14 +89,14 @@ template const list flatten(const list& tree) { /** * Sort a list. */ -template const list sort(const list& l) { +template inline const list sort(const list& l) { return flatten(mktree(l)); } /** * Make a balanced tree from an ordered list of leaves. */ -template const list btreeHelper(const list& elements, const size_t n) { +template inline const list btreeHelper(const list& elements, const size_t n) { if (n == 0) return cons(list(), elements); const size_t leftSize = (n - 1) / 2; { @@ -116,7 +116,7 @@ template const list btreeHelper(const list& elements, const si } } -template const list mkbtree(const list& elements) { +template inline const list mkbtree(const list& elements) { return car(btreeHelper(elements, length(elements))); } diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index 206fe8b32b..60fb29070c 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -50,16 +50,16 @@ long int countEValues = 0; long int countCValues = 0; long int countVValues = 0; -bool resetValueCounters() { +inline const bool resetValueCounters() { countValues = countEValues = countCValues = countVValues = 0; return true; } -bool checkValueCounters() { +inline const bool checkValueCounters() { return countValues == 0; } -bool printValueCounters() { +inline const bool printValueCounters() { cout << "countValues " << countValues << endl; cout << "countEValues " << countEValues << endl; cout << "countCValues " << countCValues << endl; @@ -92,7 +92,28 @@ bool printValueCounters() { #endif +/** + * Common value constants. + */ class value; +extern const value nilValue; +extern const list nilListValue; +extern const list nilPairValue; +extern const value emptyStringValue; +extern const value trueValue; +extern const value falseValue; + +/** + * Common value-based lambda types. + */ +typedef lambda&)> lvvlambda; +typedef lambda vvlambda; +typedef lambda vblambda; +typedef lambda vlambda; + +/** + * Generic value type class. + */ class value { public: @@ -101,346 +122,309 @@ public: Nil, Symbol, String, List, Number, Bool, Lambda, Ptr }; - value() : type(value::Nil) { + typedef union { + const void* mix; + const gc_ptr > lst; + const string str; + const lvvlambda func; + const gc_ptr ptr; + const double num; + const bool boo; + } ValueMix; + + inline value() noexcept : type(value::Nil) { debug_inc(countValues); debug_inc(countEValues); debug_watchValue(); } - value(const value& v) { + inline value(const value& v) noexcept : type(v.type) { debug_inc(countValues); debug_inc(countCValues); - type = v.type; - switch(type) { - case value::List: - lst() = v.lst(); - case value::Lambda: - func() = v.func(); - case value::Symbol: - str() = v.str(); - case value::String: - str() = v.str(); - case value::Number: - num() = v.num(); - case value::Bool: - boo() = v.boo(); - case value::Ptr: - ptr() = v.ptr(); - default: - break; - } + memcpy((void*)&mix, (void*)&v.mix, sizeof(ValueMix)); #ifdef WANT_MAINTAINER_WATCH watch = v.watch; #endif } - virtual ~value() { + inline value(const gc_mutable_ref& r) noexcept : type(((value*)r)->type) { + debug_inc(countValues); + debug_inc(countCValues); + memcpy((void*)&mix, (void*)&(((value*)r)->mix), sizeof(ValueMix)); +#ifdef WANT_MAINTAINER_WATCH + watch = v.watch; +#endif + } + + inline virtual ~value() noexcept { debug_dec(countValues); } - value(const lambda&)>& func) : type(value::Lambda), data(vdata(func)) { + inline value(const lvvlambda& f) noexcept : type(value::Lambda), func(f) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const string& str) : type(value::String), data(vdata(result(str))) { + inline value(const string& s) noexcept : type(value::String), str(s) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const char* str) : type(value::Symbol), data(vdata(result(string(str)))) { + inline value(const char* s) noexcept : type(value::Symbol), str(s) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const list& lst) : type(value::List), data(vdata(result(lst))) { + inline value(const list& l) noexcept : type(value::List), lst(new (gc_new >()) list(l)) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const list >& l) : type(value::List), data(vdata(result(listOfValues(l)))) { + inline value(const list >& l) noexcept : type(value::List), lst(new (gc_new >()) list(listOfValues(l))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const double num) : type(value::Number), data(vdata(result(num))) { + inline value(const double d) noexcept : type(value::Number), num(d) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const int num) : type(value::Number), data(vdata(result((double)num))) { + inline value(const int i) noexcept : type(value::Number), num((double)i) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const bool boo) : type(value::Bool), data(vdata(result(boo))) { + inline value(const bool b) noexcept : type(value::Bool), boo(b) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const gc_ptr ptr) : type(value::Ptr), data(vdata(result(ptr))) { + inline value(const gc_ptr p) noexcept : type(value::Ptr), ptr(p) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const failable& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist(content(m)) : rcode(m) == 1? mklist(value(), reason(m)) : mklist(value(), reason(m), rcode(m))))) { + inline value(const failable& m) noexcept : type(value::List), + lst(new (gc_new >()) list(hasContent(m)? mklist(content(m)) : + rcode(m) == 1? mklist(nilValue, reason(m)) : mklist(nilValue, reason(m), rcode(m)))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const maybe& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist(content(m)) : list()))) { + inline value(const maybe& m) noexcept : type(value::List), + lst(new (gc_new >()) list(hasContent(m)? mklist(content(m)) : nilListValue)) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - const value& operator=(const value& v) { - if(this == &v) - return *this; - type = v.type; - switch(type) { - case value::List: - lst() = v.lst(); - case value::Lambda: - func() = v.func(); - case value::Symbol: - str() = v.str(); - case value::String: - str() = v.str(); - case value::Number: - num() = v.num(); - case value::Bool: - boo() = v.boo(); - case value::Ptr: - ptr() = v.ptr(); - default: - break; - } -#ifdef WANT_MAINTAINER_WATCH - watch = v.watch; -#endif - return *this; - } + value& operator=(const value& v) = delete; - const bool operator!=(const value& v) const { + inline const bool operator!=(const value& v) const noexcept { return !this->operator==(v); } - const bool operator==(const value& v) const { + inline const bool operator==(const value& v) const noexcept { if(this == &v) return true; switch(type) { case value::Nil: return v.type == value::Nil; case value::List: - return v.type == value::List && lst()() == v.lst()(); + return v.type == value::List && *lst == *v.lst; case value::Lambda: - return v.type == value::Lambda && func() == v.func(); + return v.type == value::Lambda && func == v.func; case value::Symbol: case value::String: - return str()() == (string)v; + return (v.type == value::Symbol || v.type == value::String) && str == v.str; case value::Number: - return num()() == (double)v; + return v.type == value::Number && num == v.num; case value::Bool: - return boo()() == (bool)v; + return v.type == value::Bool && boo == v.boo; case value::Ptr: - return v.type == value::Ptr && ptr()() == v.ptr()(); + return v.type == value::Ptr && ptr == v.ptr; default: return false; } } - const bool operator<(const value& v) const { + inline const bool operator<(const value& v) const noexcept { if(this == &v) return false; switch(type) { case value::List: - return v.type == value::List && lst()() < v.lst()(); + return v.type == value::List && *lst < *v.lst; case value::Symbol: case value::String: - return str()() < (string)v; + return (v.type == value::Symbol || v.type == value::String) && str < v.str; case value::Bool: - return boo()() < (bool)v; + return v.type == value::Bool && boo < v.boo; case value::Number: - return num()() < (double)v; + return v.type == value::Number && num < v.num; default: return false; } } - const bool operator>(const value& v) const { + inline const bool operator>(const value& v) const noexcept { if(this == &v) return false; switch(type) { case value::List: - return v.type == value::List && lst()() > v.lst()(); + return v.type == value::List && *lst > *v.lst; case value::Symbol: case value::String: - return str()() > (string)v; + return (v.type == value::Symbol || v.type == value::String) && str > v.str; case value::Bool: - return boo()() > (bool)v; + return v.type == value::Bool && boo > v.boo; case value::Number: - return num()() > (double)v; + return v.type == value::Number && num > v.num; default: return false; } } - const value operator()(const list& args) const { - return func()(args); + inline const value operator()(const list& args) const noexcept { + return func(args); } - operator const string() const { + inline operator const string() const noexcept { switch(type) { case value::Symbol: case value::String: - return str()(); + return str; case value::Number: { ostringstream os; - os << num()(); + os << num; return tuscany::str(os); } case value::Bool: - return boo()()? trueString : falseString; + return boo? trueString : falseString; default: return emptyString; } } - operator const double() const { + inline operator const double() const noexcept { switch(type) { case value::Symbol: case value::String: - return atof(c_str(str()())); + return atof(c_str(str)); case value::Number: - return (double)num()(); + return (double)num; case value::Bool: - return boo()()? 1.0 : 0.0; + return boo? 1.0 : 0.0; default: return 0.0; } } - operator const int() const { + inline operator const int() const noexcept { switch(type) { case value::Symbol: case value::String: - return atoi(c_str(str()())); + return atoi(c_str(str)); case value::Number: - return (int)num()(); + return (int)num; case value::Bool: - return boo()()? 1 : 0; + return boo? 1 : 0; default: return 0; } } - operator const bool() const { + inline operator const bool() const noexcept { switch(type) { case value::Symbol: case value::String: - return str()() == string("true"); + return str == trueString; case value::Number: - return (int)num()() != 0; + return num != 0.0; case value::Bool: - return boo()(); + return boo; default: - return 0; + return false; } } - operator const gc_ptr() const { - return ptr()(); + inline operator const gc_ptr() const noexcept { + return ptr; } - operator const list() const { - return lst()(); + inline operator const list() const noexcept { + return *lst; } - operator const list >() const { - return listOfListOfValues(lst()()); + inline operator const list >() const noexcept { + return listOfListOfValues(*lst); } - operator const lambda&)>() const { - return func(); + inline operator const lvvlambda() const noexcept { + return func; } private: - template lambda& vdata() const { - return *reinterpret_cast *> (const_cast *> (&data)); - } - - template const lambda& vdata(const T& v) const { - return *reinterpret_cast *> (&v); - } - - lambda& num() const { - return vdata (); - } - - lambda& boo() const { - return vdata (); - } - - lambda()>& ptr() const { - return vdata()> (); - } - - lambda& str() const { - return vdata (); - } - - lambda()>& lst() const { - return vdata()> (); - } - - lambda&)>& func() const { - return vdata&)> (); - } - - const list listOfValues(const list >& l) const { + inline const list listOfValues(const list >& l) const noexcept { if (isNil(l)) - return list(); + return nilListValue; return cons(car(l), listOfValues(cdr(l))); } - const list > listOfListOfValues(const list& l) const { + inline const list > listOfListOfValues(const list& l) const noexcept { if (isNil(l)) return list >(); - return cons >(list(car(l)), listOfListOfValues(cdr(l))); + return cons >(car(l).type == value::List? list(car(l)) : nilPairValue, listOfListOfValues(cdr(l))); } - friend ostream& operator<<(ostream&, const value&); - friend const value::ValueType type(const value& v); + friend ostream& operator<<(ostream&, const value&) noexcept; + friend const value::ValueType type(const value& v) noexcept; + friend const bool setvalue(value& target, const value& v); #ifdef WANT_MAINTAINER_WATCH friend const string watchValue(const value& v); string watch; #endif - ValueType type; - lambda data; + const ValueType type; + union { + void* mix; + const gc_ptr > lst; + const string str; + const lvvlambda func; + const gc_ptr ptr; + const double num; + const bool boo; + }; }; +/** + * Common value constants. + */ +const value nilValue; +const list nilListValue = list(); +const list nilPairValue = mklist(nilValue, nilValue); +const value emptyStringValue(emptyString); +const value trueValue(true); +const value falseValue(false); + #ifdef WANT_MAINTAINER_WATCH /** * Debug utility used to write the contents of a value to a string, easier * to watch than the value itself in a debugger. */ -const string watchValue(const value& v) { +inline const string watchValue(const value& v) { if (v.type == value::List) return watchList(v); odebugstream os; @@ -453,7 +437,7 @@ const string watchValue(const value& v) { /** * Write an escape string to a buffer. */ -const char* escapestr(const char* s, char* buf) { +inline const char* escapestr(const char* const s, char* const buf) noexcept { if (*s == '\0') { *buf = '\0'; return buf; @@ -470,7 +454,7 @@ const char* escapestr(const char* s, char* buf) { /** * Write an escaped string value to a stream. */ -ostream& escvwrite(const string& str, ostream& out) { +inline ostream& escvwrite(const string& str, ostream& out) noexcept { char* buf = gc_cnew(length(str) * 2 + 1); escapestr(c_str(str), buf); out << buf; @@ -480,30 +464,29 @@ ostream& escvwrite(const string& str, ostream& out) { /** * Write a value to a stream. */ -ostream& operator<<(ostream& out, const value& v) { +inline ostream& operator<<(ostream& out, const value& v) noexcept { switch(v.type) { case value::List: - return out << v.lst()(); + return out << *v.lst; case value::Lambda: - return out << "lambda::" << v.func(); + return out << "lambda::" << v.func; case value::Symbol: - return out << v.str()(); + return out << v.str; case value::String: out << '\"'; - escvwrite(v.str()(), out); + escvwrite(v.str, out); return out << '\"'; case value::Number: - return out << v.num()(); + return out << v.num; case value::Bool: - if(v.boo()()) - return out << "true"; + if(v.boo) + return out << trueString; else - return out << "false"; + return out << falseString; case value::Ptr: { - const gc_ptr p = v.ptr()(); - if (p == gc_ptr(NULL)) + if (v.ptr == gc_ptr(NULL)) return out << "gc_ptr::null"; - return out << "gc_ptr::" << p; + return out << "gc_ptr::" << v.ptr; } default: return out << "nil"; @@ -513,70 +496,70 @@ ostream& operator<<(ostream& out, const value& v) { /** * Returns the type of a value. */ -const value::ValueType type(const value& v) { +inline const value::ValueType type(const value& v) noexcept { return v.type; } /** * Returns true if a value is nil. */ -const bool isNil(const value& v) { +inline const bool isNil(const value& v) noexcept { return type(v) == value::Nil; } /** * Returns true if a value is a lambda. */ -const bool isLambda(const value& v) { +inline const bool isLambda(const value& v) noexcept { return type(v) == value::Lambda; } /** * Returns true if a value is a string. */ -const bool isString(const value& v) { +inline const bool isString(const value& v) noexcept { return type(v) == value::String; } /** * Returns true if a value is a symbol. */ -const bool isSymbol(const value& v) { +inline const bool isSymbol(const value& v) noexcept { return type(v) == value::Symbol; } /** * Returns true if a value is a list. */ -const bool isList(const value& v) { +inline const bool isList(const value& v) noexcept { return type(v) == value::List; } /** * Returns true if a value is a number. */ -const bool isNumber(const value& v) { +inline const bool isNumber(const value& v) noexcept { return type(v) == value::Number; } /** * Returns true if a value is a boolean. */ -const bool isBool(const value& v) { +inline const bool isBool(const value& v) noexcept { return type(v) == value::Bool; } /** * Returns true if a value is a pointer. */ -const bool isPtr(const value& v) { +inline const bool isPtr(const value& v) noexcept { return type(v) == value::Ptr; } /** * Returns true if a value is a tagged list. */ -const bool isTaggedList(const value& exp, value tag) { +inline const bool isTaggedList(const value& exp, const value& tag) noexcept { if(isList(exp) && !isNil((list)exp)) return car((list)exp) == tag; return false; @@ -585,16 +568,16 @@ const bool isTaggedList(const value& exp, value tag) { /** * Make a list of values from a list of other things. */ -template const list mkvalues(const list& l) { +template inline const list mkvalues(const list& l) noexcept { if (isNil(l)) - return list(); + return nilListValue; return cons(car(l), mkvalues(cdr(l))); } /** * Convert a list of values to a list of other things. */ -template const list convertValues(const list& l) { +template inline const list convertValues(const list& l) noexcept { if (isNil(l)) return list(); return cons(car(l), convertValues(cdr(l))); @@ -603,7 +586,7 @@ template const list convertValues(const list& l) { /** * Convert a path string value to a list of values. */ -const list pathTokens(const char* p) { +inline const list pathTokens(const char* const p) noexcept { if (p == NULL || p[0] == '\0') return list(); if (p[0] == '/') @@ -611,23 +594,23 @@ const list pathTokens(const char* p) { return tokenize("/", p); } -const list pathValues(const value& p) { +inline const list pathValues(const value& p) noexcept { return mkvalues(pathTokens(c_str(p))); } /** * Convert a path represented as a list of values to a string value. */ -const value path(const list& p) { +inline const value path(const list& p) noexcept { if (isNil(p)) - return ""; - return string("/") + car(p) + path(cdr(p)); + return emptyString; + return string("/") + (string)car(p) + (string)path(cdr(p)); } /** * Make a uuid value. */ -const value mkuuid() { +inline const value mkuuid() noexcept { apr_uuid_t id; apr_uuid_get(&id); char buf[APR_UUID_FORMATTED_LENGTH]; @@ -638,19 +621,33 @@ const value mkuuid() { /** * Make a random alphanumeric value. */ -const int intrand() { +inline const int intrand() noexcept { const apr_uint64_t now = apr_time_now(); srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff)); return rand() & 0x0FFFF; } -const value mkrand() { +inline const value mkrand() noexcept { char buf[32]; - const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + const char* const an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; for (int i =0; i < 32; i++) buf[i] = an[intrand() % 62]; return value(string(buf, 32)); } +/** + * Set a value. Use with moderation. + */ +inline const bool setvalue(value& target, const value& v) { + if (&target == &v) + return true; +#ifdef WANT_MAINTAINER_WATCH + memcpy(&target.watch, &v.watch, sizeof(string)); +#endif + memcpy((void*)&target.type, (void*)&v.type, sizeof(value::ValueType)); + memcpy((void*)&target.mix, (void*)&v.mix, sizeof(value::ValueMix)); + return true; +} + } #endif /* tuscany_value_hpp */ diff --git a/sca-cpp/trunk/kernel/xml-test.cpp b/sca-cpp/trunk/kernel/xml-test.cpp deleted file mode 100644 index 0523cc74a6..0000000000 --- a/sca-cpp/trunk/kernel/xml-test.cpp +++ /dev/null @@ -1,235 +0,0 @@ -/* - * 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$ */ - -/** - * Test XML handling functions. - */ - -#include -#include "stream.hpp" -#include "string.hpp" -#include "list.hpp" -#include "value.hpp" -#include "element.hpp" -#include "xml.hpp" - -namespace tuscany { - -const string currencyXML = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" US\n" -" \n" -"\n"; - -const string customerXML = -"\n" -"\n" -" jdoe\n" -"

\n" -" san francisco\n" -" ca\n" -"
\n" -" \n" -" 1234\n" -" 1000\n" -" \n" -" \n" -" 6789\n" -" 2000\n" -" \n" -" \n" -" 4567\n" -" 3000\n" -" \n" -"\n"; - -const string abcXML = -"\n" -"\n" -" abc\n" -" def\n" -" xyz\n" -" tuv\n" -"\n"; - -const string xyzXML = -"\n" -"\n" -" \n" -" 123\n" -" abc\n" -" \n" -" \n" -" 234\n" -" def\n" -" \n" -" \n" -" 345\n" -" xyz\n" -" \n" -" \n" -" 456\n" -" tuv\n" -" \n" -"\n"; - -const bool isName(const value& token) { - return isTaggedList(token, attribute) && attributeName(token) == "name"; -} - -bool testReadXML() { - { - istringstream is(customerXML); - const list c = readXML(streamList(is)); - } - { - istringstream is(currencyXML); - const list c = readXML(streamList(is)); - - const value composite = car(c); - assert(isTaggedList(composite, element)); - assert(elementName(composite) == "composite"); - assert(attributeValue(car(filter(isName, elementChildren(composite)))) == string("currency")); - } - return true; -} - -ostream* xmlWriter(const string& s, ostream* os) { - (*os) << s; - return os; -} - -bool testWriteXML() { - { - istringstream is(customerXML); - const list c = readXML(streamList(is)); - ostringstream os; - writeXML(xmlWriter, &os, c); - assert(str(os) == customerXML); - } - { - istringstream is(currencyXML); - const list c = readXML(streamList(is)); - ostringstream os; - writeXML(xmlWriter, &os, c); - assert(str(os) == currencyXML); - } - return true; -} - -bool testElements() { - { - const list ad = mklist(mklist("city", string("san francisco")), mklist("state", string("ca"))); - const list ac1 = mklist(mklist("id", string("1234")), mklist("balance", 1000)); - const list ac2 = mklist(mklist("id", string("6789")), mklist("balance", 2000)); - const list ac3 = mklist(mklist("id", string("4567")), mklist("balance", 3000)); - { - const list c = mklist(mklist("customer", mklist("name", string("jdoe")), cons("address", ad), mklist("account", mklist(ac1, ac2, ac3)))); - const list e = valuesToElements(c); - const list v = elementsToValues(e); - assert(v == c); - - ostringstream os; - writeXML(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - { - const list c = mklist(mklist("customer", mklist("name", string("jdoe")), cons("address", ad), cons("account", ac1), cons("account", ac2), cons("account", ac3))); - const list e = valuesToElements(c); - const list v = elementsToValues(e); - - ostringstream os; - writeXML(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - } - { - istringstream is(abcXML); - const list c = readXML(streamList(is)); - const list v = elementsToValues(c); - const list e = valuesToElements(v); - ostringstream os; - writeXML(xmlWriter, &os, e); - assert(str(os) == abcXML); - } - { - istringstream is(xyzXML); - const list c = readXML(streamList(is)); - const list v = elementsToValues(c); - const list e = valuesToElements(v); - ostringstream os; - writeXML(xmlWriter, &os, e); - assert(str(os) == xyzXML); - } - { - istringstream is(customerXML); - const list c = readXML(streamList(is)); - const list v = elementsToValues(c); - const list e = valuesToElements(v); - ostringstream os; - writeXML(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - return true; -} - -bool testValues() { - { - const list l = mklist(list() + "ns1:echoString" + (list() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list() + "text" + string("Hello World!"))); - const list e = valuesToElements(l); - const failable > lx = writeXML(e); - ostringstream os; - write(content(lx), os); - istringstream is(str(os)); - const list x = readXML(streamList(is)); - const list v = elementsToValues(x); - assert(v == l); - } - return true; -} - -} - -int main() { - tuscany::gc_scoped_pool p; - tuscany::cout << "Testing..." << tuscany::endl; - - tuscany::testReadXML(); - tuscany::testWriteXML(); - tuscany::testElements(); - tuscany::testValues(); - - tuscany::cout << "OK" << tuscany::endl; - - return 0; -} diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp deleted file mode 100644 index d00a2905fb..0000000000 --- a/sca-cpp/trunk/kernel/xml.hpp +++ /dev/null @@ -1,412 +0,0 @@ -/* - * 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_xml_hpp -#define tuscany_xml_hpp - -/** - * XML read/write functions. - */ - -#include -#include -#include -#include -#include "string.hpp" -#include "list.hpp" -#include "stream.hpp" -#include "value.hpp" -#include "element.hpp" -#include "monad.hpp" - -namespace tuscany { - -/** - * APR-based memory management functions. - */ - - -/** - * Initializes the libxml2 library. - */ -class XMLParser { -public: - XMLParser() { - debug("xml::XMLParser"); - xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup); - xmlInitParser(); - } - - ~XMLParser() { - } -} xmlParser; - -/** - * Encapsulates a libxml2 xmlTextReader and its state. - */ -class XMLReader { -public: - enum TokenType { - None = 0, Element = 1, Attribute = 2, Text = 3, EndElement = 15, Identifier = 100, End = 101 - }; - - XMLReader(xmlTextReaderPtr xml) : xml(xml), owner(true), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) { - debug("xml::XMLReader::xml"); - xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1); - xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1); - } - - XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) { - debug("xml::XMLReader::copy"); - } - - const XMLReader& operator=(const XMLReader& r) { - debug("xml::XMLReader::operator="); - if(this == &r) - return *this; - xml = r.xml; - owner = false; - tokenType = r.tokenType; - isEmptyElement = r.isEmptyElement; - hasValue = r.hasValue; - hasAttributes = r.hasAttributes; - return *this; - } - - ~XMLReader() { - if (!owner) - return; - xmlTextReaderClose(xml); - xmlFreeTextReader(xml); - } - - /** - * Read the next XML token and return its type. - */ - int read() { - if (tokenType == End) - return tokenType; - if (tokenType == Element) { - isEmptyElement = xmlTextReaderIsEmptyElement(xml); - hasAttributes = xmlTextReaderHasAttributes(xml); - return tokenType = Identifier; - } - if (tokenType == Identifier && hasAttributes && xmlTextReaderMoveToFirstAttribute(xml) == 1) - return tokenType = Attribute; - if (tokenType == Attribute && xmlTextReaderMoveToNextAttribute(xml) == 1) - return tokenType = Attribute; - if (isEmptyElement && (tokenType == Identifier || tokenType == Attribute)) - return tokenType = EndElement; - if (!xmlTextReaderRead(xml)) - return tokenType = End; - return tokenType = xmlTextReaderNodeType(xml); - } - - operator xmlTextReaderPtr() const { - return xml; - } - -private: - xmlTextReaderPtr xml; - bool owner; - int tokenType; - bool isEmptyElement; - bool hasValue; - bool hasAttributes; -}; - -/** - * Constants used to tag XML tokens. - */ -const value endElement("<"); -const value startElement(">"); - -/** - * Read an XML identifier. - */ -const value readIdentifier(XMLReader& reader) { - const char* name = (const char*)xmlTextReaderConstName(reader); - return name; -} - -/** - * Read XML text. - */ -const value readText(XMLReader& reader) { - const char *val = (const char*)xmlTextReaderConstValue(reader); - return string(val); -} - -/** - * Read an XML attribute. - */ -const value readAttribute(XMLReader& reader) { - const char *name = (const char*)xmlTextReaderConstName(reader); - const char *val = (const char*)xmlTextReaderConstValue(reader); - return mklist(attribute, name, string(val)); -} - -/** - * Read an XML token. - */ -const value readToken(XMLReader& reader) { - const int tokenType = reader.read(); - if (tokenType == XMLReader::None || tokenType == XMLReader::End) - return value(); - if (tokenType == XMLReader::Element) - return startElement; - if (tokenType == XMLReader::Identifier) - return readIdentifier(reader); - if (tokenType == XMLReader::Attribute) - return readAttribute(reader); - if (tokenType == XMLReader::Text) - return readText(reader); - if (tokenType == XMLReader::EndElement) - return endElement; - return readToken(reader); -} - -/** - * Read a list of values from XML tokens. - */ -const list readList(const list& listSoFar, XMLReader& reader) { - const value token = readToken(reader); - if(isNil(token) || endElement == token) - return reverse(listSoFar); - if(startElement == token) - return readList(cons(readList(mklist(element), reader), listSoFar), reader); - return readList(cons(token, listSoFar), reader); -} - -/** - * Read a list of values from a libxml2 XML reader. - */ -const list read(XMLReader& reader) { - value nextToken = readToken(reader); - if (startElement == nextToken) - return mklist(readList(mklist(element), reader)); - return list(); -} - -/** - * Context passed to the read callback function. - */ -class XMLReadContext { -public: - XMLReadContext(const list& ilist) : ilist(ilist) { - } - list ilist; -}; - -/** - * Callback function called by libxml2 to read XML. - */ -int readCallback(void *context, char* buffer, int len) { - XMLReadContext& rc = *static_cast(context); - if (isNil(rc.ilist)) - return 0; - const list f(fragment(rc.ilist, len)); - const string s(car(f)); - rc.ilist = cdr(f); - memcpy(buffer, c_str(s), length(s)); - return (int)length(s); -} - -/** - * Return true if a list of strings contains an XML document. - */ -const bool isXML(const list& ls) { - if (isNil(ls)) - return false; - return substr(car(ls), 0, 5) == " readXML(const list& ilist) { - debug(ilist, "xml::readXML"); - XMLReadContext cx(ilist); - xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT); - if (xml == NULL) - return list(); - XMLReader reader(xml); - return read(reader); -} - -/** - * Default encoding used to write XML documents. - */ -const char* encoding = "UTF-8"; - - -/** - * Write a list of XML element or attribute tokens. - */ -const list expandElementValues(const value& n, const list& l) { - if (isNil(l)) - return l; - return cons(value(cons(element, cons(n, isList(car(l))? (list)car(l) : mklist(car(l))))), expandElementValues(n, cdr(l))); -} - -const failable writeList(const list& l, const xmlTextWriterPtr xml) { - if (isNil(l)) - return true; - - // Write an attribute - const value token(car(l)); - if (isTaggedList(token, attribute)) { - if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)c_str(string(attributeName(token))), (const xmlChar*)c_str(string(attributeValue(token)))) < 0) - return mkfailure("xmlTextWriterWriteAttribute failed"); - - } else if (isTaggedList(token, element)) { - - // Write an element containing a value - if (elementHasValue(token)) { - const value v = elementValue(token); - if (isList(v)) { - - // Write an element per entry in a list of values - const list e = expandElementValues(elementName(token), v); - writeList(e, xml); - - } else { - - // Write an element with a single value - if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) - return mkfailure("xmlTextWriterStartElement failed"); - - // Write its children - const failable w = writeList(elementChildren(token), xml); - if (!hasContent(w)) - return w; - - if (xmlTextWriterEndElement(xml) < 0) - return mkfailure("xmlTextWriterEndElement failed"); - } - } - else { - - // Write an element - if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) - return mkfailure("xmlTextWriterStartElement failed"); - - // Write its children - const failable w = writeList(elementChildren(token), xml); - if (!hasContent(w)) - return w; - - if (xmlTextWriterEndElement(xml) < 0) - return mkfailure("xmlTextWriterEndElement failed"); - } - } else { - - // Write XML text - if (xmlTextWriterWriteString(xml, (const xmlChar*)c_str(string(token))) < 0) - return mkfailure("xmlTextWriterWriteString failed"); - } - - // Go on - return writeList(cdr(l), xml); -} - -/** - * Write a list of values to a libxml2 XML writer. - */ -const failable write(const list& l, const xmlTextWriterPtr xml, bool xmlTag) { - if (xmlTag) { - if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) - return mkfailure("xmlTextWriterStartDocument failed"); - } - - const failable w = writeList(l, xml); - if (!hasContent(w)) - return w; - - if (xmlTag) { - if (xmlTextWriterEndDocument(xml) < 0) - return mkfailure("xmlTextWriterEndDocument failed"); - } - return true; -} - -/** - * Context passed to the write callback function. - */ -template class XMLWriteContext { -public: - XMLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { - } - const lambda reduce; - R accum; -}; - -/** - * Callback function called by libxml2 to write XML out. - */ -template int writeCallback(void *context, const char* buffer, int len) { - XMLWriteContext& cx = *static_cast*>(context); - cx.accum = cx.reduce(string(buffer, len), cx.accum); - return len; -} - -/** - * Convert a list of values to an XML document. - */ -template const failable writeXML(const lambda& reduce, const R& initial, const list& l, const bool xmlTag) { - XMLWriteContext cx(reduce, initial); - xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback, NULL, &cx, NULL); - if (out == NULL) - return mkfailure("xmlOutputBufferCreateIO failed"); - xmlTextWriterPtr xml = xmlNewTextWriter(out); - if (xml == NULL) - return mkfailure("xmlNewTextWriter failed"); - xmlTextWriterSetIndent(xml, 1); - - const failable w = write(l, xml, xmlTag); - xmlFreeTextWriter(xml); - if (!hasContent(w)) { - return mkfailure(w); - } - return cx.accum; -} - -template const failable writeXML(const lambda& reduce, const R& initial, const list& l) { - return writeXML(reduce, initial, l, true); -} - -/** - * Convert a list of values to a list of strings representing an XML document. - */ -const failable > writeXML(const list& l, const bool xmlTag) { - debug(l, "xml::writeXML"); - const failable > ls = writeXML >(rcons, list(), l, xmlTag); - if (!hasContent(ls)) - return ls; - return reverse(list(content(ls))); -} - -const failable > writeXML(const list& l) { - return writeXML(l, true); -} - -} -#endif /* tuscany_xml_hpp */ diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/kernel/xsd-test.cpp deleted file mode 100644 index fbd2ee6dca..0000000000 --- a/sca-cpp/trunk/kernel/xsd-test.cpp +++ /dev/null @@ -1,107 +0,0 @@ -/* - * 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$ */ - -/** - * Test validation of a composite file against an SCDL schema. - */ - -#include "string.hpp" -#include "fstream.hpp" -#include -#include - -namespace tuscany { - -bool printNode(xmlTextReaderPtr reader) { - const xmlChar* name = xmlTextReaderConstName(reader); - if(name == NULL) - name = (xmlChar *)""; - const xmlChar* value = xmlTextReaderConstValue(reader); - cerr << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " - << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); - if(value == NULL) - cerr << endl; - else - cerr << value << endl; - return true; -} - -int xmlRead(void *context, char* buffer, int len) { - return (int)fread(buffer, 1, len, (FILE*)context); -} - -int xmlClose(void *context) { - fclose((FILE*)context); - return 0; -} - -bool readFile(const char*xsdfilename, const char *filename) { - cout << "Loading schema " << xsdfilename << endl; - const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET); - const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc); - const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx); - const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); - - cout << "Reading file " << filename << endl; - FILE* file = fopen(filename, "r"); - if (file != NULL) { - const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET); - xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1); - xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1); - - if(reader != NULL) { - xmlTextReaderSchemaValidateCtxt(reader, validctx, 0); - - int rc; - while((rc = xmlTextReaderRead(reader)) == 1) { - printNode(reader); - } - if(xmlTextReaderIsValid(reader) != 1) - cout << "Could not validate document" << endl; - xmlFreeTextReader(reader); - if(rc != 0) - cout << "Could not parse document" << endl; - } else - cout << "Could not create parser" << endl; - } else - cout << "Could not open document" << endl; - - xmlSchemaFreeValidCtxt(validctx); - xmlSchemaFree(xsd); - xmlSchemaFreeParserCtxt(xsdctx); - - return true; -} - -} - -int main(int argc, char **argv) { - tuscany::cout << "Testing..." << tuscany::endl; - if(argc != 3) - return 1; - - tuscany::readFile(argv[1], argv[2]); - - xmlCleanupParser(); - - tuscany::cout << "OK" << tuscany::endl; - return 0; -} diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am index 16fe2791f7..95694ffef5 100644 --- a/sca-cpp/trunk/modules/Makefile.am +++ b/sca-cpp/trunk/modules/Makefile.am @@ -15,5 +15,5 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = scheme atom rss js json scdl http server python opencl java openid oauth wsgi +SUBDIRS = xml json scheme atom rss js scdl http server python opencl java openid oauth wsgi diff --git a/sca-cpp/trunk/modules/atom/atom-test.cpp b/sca-cpp/trunk/modules/atom/atom-test.cpp index 479ed64f29..056e9ea965 100644 --- a/sca-cpp/trunk/modules/atom/atom-test.cpp +++ b/sca-cpp/trunk/modules/atom/atom-test.cpp @@ -38,100 +38,100 @@ ostream* writer(const string& s, ostream* os) { const string itemEntry( "\n" - "\n" - " item\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " jane@example.com\n" - " \n" - " Fri Jan 01 08:11:36 PDT 2012\n" - " \n" - " \n" - " Apple\n" - " $2.99\n" - " \n" - " \n" - " \n" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "jane@example.com" + "" + "Fri Jan 01 08:11:36 PDT 2012" + "" + "" + "Apple" + "$2.99" + "" + "" + "" "\n"); const string itemTextEntry("\n" - "\n" - " item\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " jane@example.com\n" - " \n" - " Fri Jan 01 08:11:36 PDT 2012\n" - " Apple\n" - " \n" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "jane@example.com" + "" + "Fri Jan 01 08:11:36 PDT 2012" + "Apple" + "" "\n"); const string itemNoContentEntry("\n" - "\n" - " item\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " jane\n" - " \n" - " Fri Jan 01 08:11:36 PDT 2012\n" - " \n" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "jane" + "" + "Fri Jan 01 08:11:36 PDT 2012" + "" "\n"); const string incompleteEntry("\n" - " item\n" - " \n" - " \n" - " Orange\n" - " 3.55\n" - " \n" - " \n" + "item" + "" + "" + "Orange" + "3.55" + "" + "" "\n"); const string completedEntry("\n" - "\n" - " item\n" - " \n" - " \n" - " \n" - " Orange\n" - " 3.55\n" - " \n" - " \n" - " \n" + "" + "item" + "" + "" + "" + "Orange" + "3.55" + "" + "" + "" "\n"); -bool testEntry() { +const bool testEntry() { { - const list i = list() + element + value("item") - + value(list() + element + value("name") + value(string("Apple"))) - + value(list() + element + value("price") + value(string("$2.99"))); - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("item"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("author") + value(string("jane@example.com"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list() + element + value("content") + value(i))); + const list i = nilListValue + element + value("item") + + value(nilListValue + element + value("name") + value(string("Apple"))) + + value(nilListValue + element + value("price") + value(string("$2.99"))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("item"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("author") + value(string("jane@example.com"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) + + value(nilListValue + element + value("content") + value(i))); ostringstream os; writeATOMEntry(writer, &os, a); assert(str(os) == itemEntry); } { - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("item"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("author") + value(string("jane@example.com"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list() + element + value("content") + value(string("Apple")))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("item"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("author") + value(string("jane@example.com"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) + + value(nilListValue + element + value("content") + value(string("Apple")))); ostringstream os; writeATOMEntry(writer, &os, a); assert(str(os) == itemTextEntry); } { - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("item"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("author") + value(string("jane"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("item"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("author") + value(string("jane"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); ostringstream os; writeATOMEntry(writer, &os, a); assert(str(os) == itemNoContentEntry); @@ -164,54 +164,54 @@ bool testEntry() { } const string emptyFeed("\n" - "\n" - " Feed\n" - " 1234\n" + "" + "Feed" + "1234" "\n"); const string itemFeed("\n" - "\n" - " Feed\n" - " 1234\n" - " \n" - " item\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " jane@example.com\n" - " \n" - " Fri Jan 01 08:11:36 PDT 2012\n" - " \n" - " \n" - " Apple\n" - " $2.99\n" - " \n" - " \n" - " \n" - " \n" - " \n" - " item\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\n" - " \n" - " jane@example.com\n" - " \n" - " Fri Jan 01 08:11:36 PDT 2012\n" - " \n" - " \n" - " Orange\n" - " $3.55\n" - " \n" - " \n" - " \n" - " \n" + "" + "Feed" + "1234" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "jane@example.com" + "" + "Fri Jan 01 08:11:36 PDT 2012" + "" + "" + "Apple" + "$2.99" + "" + "" + "" + "" + "" + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + "" + "jane@example.com" + "" + "Fri Jan 01 08:11:36 PDT 2012" + "" + "" + "Orange" + "$3.55" + "" + "" + "" + "" "\n"); -bool testFeed() { +const bool testFeed() { { - const list a = list() + (list() + element + value("feed") - + value(list() + element + value("title") + value(string("Feed"))) - + value(list() + element + value("id") + value(string("1234"))) - + value(list() + element + value("author") + value(string("jane@example.com"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); + const list a = nilListValue + (nilListValue + element + value("feed") + + value(nilListValue + element + value("title") + value(string("Feed"))) + + value(nilListValue + element + value("id") + value(string("1234"))) + + value(nilListValue + element + value("author") + value(string("jane@example.com"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); ostringstream os; writeATOMFeed(writer, &os, a); assert(str(os) == emptyFeed); @@ -223,31 +223,31 @@ bool testFeed() { assert(str(os) == emptyFeed); } { - const list i1 = list() + element + "item" - + (list() + element + "name" + "Apple") - + (list() + element + "price" + "$2.99"); + const list i1 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Apple") + + (nilListValue + element + "price" + "$2.99"); - const list i2 = list() + element + "item" - + (list() + element + "name" + "Orange") - + (list() + element + "price" + "$3.55"); + const list i2 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Orange") + + (nilListValue + element + "price" + "$3.55"); - const list i = list() - + value(list() + element + value("entry") - + value(list() + element + value("title") + value(string("item"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("author") + value(string("jane@example.com"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list() + element + value("content") + value(i1))) - + value(list() + element + value("entry") - + value(list() + element + value("title") + value(string("item"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) - + value(list() + element + value("author") + value(string("jane@example.com"))) - + value(list() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list() + element + value("content") + value(i2))); + const list i = nilListValue + + value(nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("item"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("author") + value(string("jane@example.com"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) + + value(nilListValue + element + value("content") + value(i1))) + + value(nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("item"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) + + value(nilListValue + element + value("author") + value(string("jane@example.com"))) + + value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) + + value(nilListValue + element + value("content") + value(i2))); - const list a = list() + (append(list() + element + value("feed") - + value(list() + element + value("title") + value(string("Feed"))) - + value(list() + element + value("id") + value("1234")), + const list a = nilListValue + (append(nilListValue + element + value("feed") + + value(nilListValue + element + value("title") + value(string("Feed"))) + + value(nilListValue + element + value("id") + value("1234")), i)); ostringstream os; @@ -273,7 +273,7 @@ bool testFeed() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::atom::testEntry(); diff --git a/sca-cpp/trunk/modules/atom/atom.hpp b/sca-cpp/trunk/modules/atom/atom.hpp index 5de3894214..2f6e688bcb 100644 --- a/sca-cpp/trunk/modules/atom/atom.hpp +++ b/sca-cpp/trunk/modules/atom/atom.hpp @@ -30,7 +30,7 @@ #include "list.hpp" #include "value.hpp" #include "monad.hpp" -#include "xml.hpp" +#include "../xml/xml.hpp" namespace tuscany { namespace atom { @@ -46,24 +46,24 @@ const value entry("entry"); */ const list entryElementValues(const list& e) { const list lt = filter(selector(mklist(element, "title")), e); - const list t = list() + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt))); + const list t = nilListValue + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt))); const list li = filter(selector(mklist(element, "id")), e); - const list i = list() + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li))); + const list i = nilListValue + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li))); const list la = filter(selector(mklist(element, "author")), e); - const list lan = isNil(la)? list() : filter(selector(mklist(element, "name")), car(la)); - const list lae = isNil(la)? list() : filter(selector(mklist(element, "email")), car(la)); + const list lan = isNil(la)? nilListValue : filter(selector(mklist(element, "name")), car(la)); + const list lae = isNil(la)? nilListValue : filter(selector(mklist(element, "email")), car(la)); const list laa = isNil(lan)? lae : lan; - const list a = isNil(laa)? list() : mklist(list() + element + value("author") + elementValue(car(laa))); + const list a = isNil(laa)? nilListValue : mklist(nilListValue + element + value("author") + elementValue(car(laa))); const list lu = filter(selector(mklist(element, "updated")), e); - const list u = isNil(lu)? list() : mklist(list() + element + value("updated") + elementValue(car(lu))); + const list u = isNil(lu)? nilListValue : mklist(nilListValue + element + value("updated") + elementValue(car(lu))); const list lc = filter(selector(mklist(element, "content")), e); - const list c = isNil(lc)? list() : mklist(list() + element + value("content") + elementValue(car(lc))); + const list c = isNil(lc)? nilListValue : mklist(nilListValue + element + value("content") + elementValue(car(lc))); - return append(append(append(list() + element + entry + value(t) + value(i), a), u), c); + return append(append(append(nilListValue + element + entry + value(t) + value(i), a), u), c); } /** @@ -79,7 +79,7 @@ const list entriesElementValues(const list& e) { * Return true if a list of strings contains an ATOM feed. */ const bool isATOMFeed(const list& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "& ls) { * Return true if a list of strings contains an ATOM entry. */ const bool isATOMEntry(const list& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "& ls) { * Convert a list of strings to a list of values representing an ATOM entry. */ const failable > readATOMEntry(const list& ilist) { - const list e = readXML(ilist); + const list e = content(xml::readElements(ilist)); if (isNil(e)) return mkfailure >("Empty entry"); return mklist(entryElementValues(car(e))); @@ -107,32 +107,25 @@ const failable > readATOMEntry(const list& ilist) { * Convert a list of strings to a list of values representing an ATOM feed. */ const failable > readATOMFeed(const list& ilist) { - const list f = readXML(ilist); + const list f = content(xml::readElements(ilist)); if (isNil(f)) return mkfailure >("Empty feed"); const list t = filter(selector(mklist(element, "title")), car(f)); const list i = filter(selector(mklist(element, "id")), car(f)); const list e = filter(selector(mklist(element, entry)), car(f)); - return mklist(append(list() + element + feed - + value(list() + element + value("title") + elementValue(car(t))) - + value(list() + element + value("id") + elementValue(car(i))), + return mklist(append(nilListValue + element + feed + + value(nilListValue + element + value("title") + elementValue(car(t))) + + value(nilListValue + element + value("id") + elementValue(car(i))), entriesElementValues(e))); } /** * Returns children of an ATOM content element. */ -struct filterContentElementChildren { - const value type; - filterContentElementChildren() : type("type") { - } - const bool operator()(const value& v) const { - return !(isAttribute(v) && attributeName((list)v) == type); - } -}; - const list contentElementChildren(const value& content) { - return filter(filterContentElementChildren(), elementChildren(content)); + return filter([](const value& v) { + return !(isAttribute(v) && attributeName((list)v) == "type"); + }, elementChildren(content)); } /** @@ -146,18 +139,18 @@ const list entryElement(const list& l) { const value updated = elementChild("updated", l); const value content = elementChild("content", l); const bool text = isNil(content)? false : elementHasValue(content); - return list() - + element + entry + (list() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") - + (list() + element + "title" + (list() + attribute + "type" + "text") + elementValue(title)) - + (list() + element + "id" + elementValue(id)) - + (isNil(author)? list() : (list() + element + "author" + - (email? (list() + element + "email" + elementValue(author)) : (list() + element + "name" + elementValue(author))))) - + (isNil(updated)? list() : (list() + element + "updated" + elementValue(updated))) + return nilListValue + + element + entry + (nilListValue + attribute + "xmlns" + "http://www.w3.org/2005/Atom") + + (nilListValue + element + "title" + (nilListValue + attribute + "type" + "text") + elementValue(title)) + + (nilListValue + element + "id" + elementValue(id)) + + (isNil(author)? nilListValue : (nilListValue + element + "author" + + (email? (nilListValue + element + "email" + elementValue(author)) : (nilListValue + element + "name" + elementValue(author))))) + + (isNil(updated)? nilListValue : (nilListValue + element + "updated" + elementValue(updated))) + (isNil(content)? - list() : - append(list() + element + "content" + (list() + attribute + "type" + (text? "text" : "application/xml")), + nilListValue : + append(nilListValue + element + "content" + (nilListValue + attribute + "type" + (text? "text" : "application/xml")), text? mklist(elementValue(content)) : contentElementChildren(content))) - + (list() + element + "link" + (list() + attribute + "href" + elementValue(id))); + + (nilListValue + element + "link" + (nilListValue + attribute + "href" + elementValue(id))); } /** @@ -172,9 +165,9 @@ const list entriesElements(const list& l) { /** * Convert a list of element values representing an ATOM entry to an ATOM entry. */ -template const failable writeATOMEntry(const lambda& reduce, const R& initial, const list& ll) { +template const failable writeATOMEntry(const lambda& reduce, const R& initial, const list& ll) { const list l = isNil(ll)? ll : (list)car(ll); - return writeXML(reduce, initial, mklist(entryElement(l))); + return xml::writeElements(reduce, initial, mklist(entryElement(l))); } const failable > writeATOMEntry(const list& l) { @@ -187,31 +180,31 @@ const failable > writeATOMEntry(const list& l) { /** * Convert a list of element values representing an ATOM feed to an ATOM feed. */ -template const failable writeATOMFeed(const lambda& reduce, const R& initial, const list& ll) { +template const failable writeATOMFeed(const lambda& reduce, const R& initial, const list& ll) { const list l = isNil(ll)? ll : (list)car(ll); const list lt = filter(selector(mklist(element, "title")), l); const value t = isNil(lt)? value(emptyString) : elementValue(car(lt)); const list li = filter(selector(mklist(element, "id")), l); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); - const list f = list() - + element + feed + (list() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") - + (list() + element + "title" + (list() + attribute + "type" + "text") + t) - + (list() + element + "id" + i); + const list f = nilListValue + + element + feed + (nilListValue + attribute + "xmlns" + "http://www.w3.org/2005/Atom") + + (nilListValue + element + "title" + (nilListValue + attribute + "type" + "text") + t) + + (nilListValue + element + "id" + i); // Write ATOM entries const list le = filter(selector(mklist(element, entry)), l); if (isNil(le)) - return writeXML(reduce, initial, mklist(f)); + return xml::writeElements(reduce, initial, mklist(f)); // Write a single ATOM entry element with a list of values if (!isNil(le) && !isNil(car(le)) && isList(car(caddr(car(le))))) { const list fe = append(f, entriesElements(caddr(car(le)))); - return writeXML(reduce, initial, mklist(fe)); + return xml::writeElements(reduce, initial, mklist(fe)); } // Write separate ATOM entry elements const list fe = append(f, entriesElements(le)); - return writeXML(reduce, initial, mklist(fe)); + return xml::writeElements(reduce, initial, mklist(fe)); } /** diff --git a/sca-cpp/trunk/modules/rss/rss-test.cpp b/sca-cpp/trunk/modules/rss/rss-test.cpp index be1dcac574..a6de6ed31a 100644 --- a/sca-cpp/trunk/modules/rss/rss-test.cpp +++ b/sca-cpp/trunk/modules/rss/rss-test.cpp @@ -37,78 +37,78 @@ ostream* writer(const string& s, ostream* os) { } const string itemEntry("\n" - "\n" - " fruit\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " \n" - " Apple\n" - " $2.99\n" - " \n" - " \n" + "" + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "" + "Apple" + "$2.99" + "" + "" "\n"); const string itemTextEntry("\n" - "\n" - " fruit\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " Apple\n" + "" + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "Apple" "\n"); const string itemNoDescriptionEntry("\n" - "\n" - " fruit\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" + "" + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" "\n"); const string incompleteEntry("\n" - " fruit\n" - " \n" - " \n" - " Orange\n" - " 3.55\n" - " \n" - " \n" + "fruit" + "" + "" + "Orange" + "3.55" + "" + "" ""); const string completedEntry("\n" - "\n" - " fruit\n" - " \n" - " \n" - " \n" - " Orange\n" - " 3.55\n" - " \n" - " \n" + "" + "fruit" + "" + "" + "" + "Orange" + "3.55" + "" + "" "\n"); -bool testEntry() { +const bool testEntry() { { - const list i = list() + element + value("item") - + value(list() + element + value("name") + value(string("Apple"))) - + value(list() + element + value("price") + value(string("$2.99"))); - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("fruit"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("content") + value(i))); + const list i = nilListValue + element + value("item") + + value(nilListValue + element + value("name") + value(string("Apple"))) + + value(nilListValue + element + value("price") + value(string("$2.99"))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("fruit"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("content") + value(i))); ostringstream os; writeRSSEntry(writer, &os, a); assert(str(os) == itemEntry); } { - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("fruit"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("content") + value(string("Apple")))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("fruit"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("content") + value(string("Apple")))); ostringstream os; writeRSSEntry(writer, &os, a); assert(str(os) == itemTextEntry); } { - const list a = list() + (list() + element + value("entry") - + value(list() + element + value("title") + value(string("fruit"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))); + const list a = nilListValue + (nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("fruit"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))); ostringstream os; writeRSSEntry(writer, &os, a); assert(str(os) == itemNoDescriptionEntry); @@ -141,48 +141,48 @@ bool testEntry() { } const string emptyFeed("\n" - "\n" - " \n" - " Feed\n" - " 1234\n" - " Feed\n" - " \n" + "" + "" + "Feed" + "1234" + "Feed" + "" "\n"); const string itemFeed("\n" - "\n" - " \n" - " Feed\n" - " 1234\n" - " Feed\n" - " \n" - " fruit\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\n" - " \n" - " \n" - " Apple\n" - " $2.99\n" - " \n" - " \n" - " \n" - " \n" - " fruit\n" - " cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\n" - " \n" - " \n" - " Orange\n" - " $3.55\n" - " \n" - " \n" - " \n" - " \n" + "" + "" + "Feed" + "1234" + "Feed" + "" + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + "" + "" + "Apple" + "$2.99" + "" + "" + "" + "" + "fruit" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + "" + "" + "Orange" + "$3.55" + "" + "" + "" + "" "\n"); -bool testFeed() { +const bool testFeed() { { - const list a = list() + (list() + element + value("feed") - + value(list() + element + value("title") + value(string("Feed"))) - + value(list() + element + value("id") + value(string("1234")))); + const list a = nilListValue + (nilListValue + element + value("feed") + + value(nilListValue + element + value("title") + value(string("Feed"))) + + value(nilListValue + element + value("id") + value(string("1234")))); ostringstream os; writeRSSFeed(writer, &os, a); assert(str(os) == emptyFeed); @@ -194,27 +194,27 @@ bool testFeed() { assert(str(os) == emptyFeed); } { - const list i1 = list() + element + "item" - + (list() + element + "name" + "Apple") - + (list() + element + "price" + "$2.99"); - - const list i2 = list() + element + "item" - + (list() + element + "name" + "Orange") - + (list() + element + "price" + "$3.55"); - - const list i = list() - + value(list() + element + value("entry") - + value(list() + element + value("title") + value(string("fruit"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list() + element + value("content") + value(i1))) - + value(list() + element + value("entry") - + value(list() + element + value("title") + value(string("fruit"))) - + value(list() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) - + value(list() + element + value("content") + value(i2))); + const list i1 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Apple") + + (nilListValue + element + "price" + "$2.99"); + + const list i2 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Orange") + + (nilListValue + element + "price" + "$3.55"); + + const list i = nilListValue + + value(nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("fruit"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) + + value(nilListValue + element + value("content") + value(i1))) + + value(nilListValue + element + value("entry") + + value(nilListValue + element + value("title") + value(string("fruit"))) + + value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) + + value(nilListValue + element + value("content") + value(i2))); - const list a = list() + (append(list() + element + value("feed") - + value(list() + element + value("title") + value(string("Feed"))) - + value(list() + element + value("id") + value("1234")), + const list a = nilListValue + (append(nilListValue + element + value("feed") + + value(nilListValue + element + value("title") + value(string("Feed"))) + + value(nilListValue + element + value("id") + value("1234")), i)); ostringstream os; @@ -240,7 +240,7 @@ bool testFeed() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::rss::testEntry(); diff --git a/sca-cpp/trunk/modules/rss/rss.hpp b/sca-cpp/trunk/modules/rss/rss.hpp index c62d137adc..7fba736065 100644 --- a/sca-cpp/trunk/modules/rss/rss.hpp +++ b/sca-cpp/trunk/modules/rss/rss.hpp @@ -30,7 +30,7 @@ #include "list.hpp" #include "value.hpp" #include "monad.hpp" -#include "xml.hpp" +#include "../xml/xml.hpp" namespace tuscany { namespace rss { @@ -50,10 +50,10 @@ const list entryElementValues(const list& e) { const list li = filter(selector(mklist(element, "link")), e); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); const list ld = filter(selector(mklist(element, "description")), e); - return append(list() + element + entry - + value(list() + element + value("title") + t) - + value(list() + element + value("id") + i), - isNil(ld)? list() : mklist(value(list() + element + value("content") + elementValue(car(ld))))); + return append(nilListValue + element + entry + + value(nilListValue + element + value("title") + t) + + value(nilListValue + element + value("id") + i), + isNil(ld)? nilListValue : mklist(value(nilListValue + element + value("content") + elementValue(car(ld))))); } /** @@ -69,7 +69,7 @@ const list entriesElementValues(const list& e) { * Return true if a list of strings contains an RSS feed. */ const bool isRSSFeed(const list& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "& ls) { * Convert a list of strings to a list of values representing an RSS entry. */ const failable > readRSSEntry(const list& ilist) { - const list e = readXML(ilist); + const list e = content(xml::readElements(ilist)); if (isNil(e)) return mkfailure >("Empty entry"); return mklist(entryElementValues(car(e))); @@ -88,16 +88,16 @@ const failable > readRSSEntry(const list& ilist) { * Convert a list of strings to a list of values representing an RSS feed. */ const failable > readRSSFeed(const list& ilist) { - const list f = readXML(ilist); + const list f = content(xml::readElements(ilist)); if (isNil(f)) return mkfailure >("Empty feed"); const list c = filter(selector(mklist(element, "channel")), car(f)); const list t = filter(selector(mklist(element, "title")), car(c)); const list i = filter(selector(mklist(element, "link")), car(c)); const list e = filter(selector(mklist(element, "item")), car(c)); - return mklist(append(list() + element + feed - + value(list() + element + value("title") + elementValue(car(t))) - + value(list() + element + value("id") + elementValue(car(i))), + return mklist(append(nilListValue + element + feed + + value(nilListValue + element + value("title") + elementValue(car(t))) + + value(nilListValue + element + value("id") + elementValue(car(i))), entriesElementValues(e))); } @@ -109,13 +109,13 @@ const list entryElement(const list& l) { const value id = elementValue(elementChild("id", l)); const value content = elementChild("content", l); const bool text = isNil(content)? false : elementHasValue(content); - return append(list() + return append(nilListValue + element + "item" - + (list() + element + "title" + title) - + (list() + element + "link" + id), + + (nilListValue + element + "title" + title) + + (nilListValue + element + "link" + id), isNil(content)? - list() : - mklist(append(list() + element + "description", + nilListValue : + mklist(append(nilListValue + element + "description", text? mklist(elementValue(content)) : elementChildren(content)))); } @@ -132,9 +132,9 @@ const list entriesElements(const list& l) { * Convert a list of values representing an RSS entry to an RSS entry. * The first two values in the list are the entry id and title. */ -template const failable writeRSSEntry(const lambda& reduce, const R& initial, const list& ll) { +template const failable writeRSSEntry(const lambda& reduce, const R& initial, const list& ll) { const list l = isNil(ll)? ll : (list)car(ll); - return writeXML(reduce, initial, mklist(entryElement(l))); + return xml::writeElements(reduce, initial, mklist(entryElement(l))); } const failable > writeRSSEntry(const list& l) { @@ -148,41 +148,41 @@ const failable > writeRSSEntry(const list& l) { * Convert a list of values representing an RSS feed to an RSS feed. * The first two values in the list are the feed id and title. */ -template const failable writeRSSFeed(const lambda& reduce, const R& initial, const list& ll) { +template const failable writeRSSFeed(const lambda& reduce, const R& initial, const list& ll) { const list l = isNil(ll)? ll : (list)car(ll); const list lt = filter(selector(mklist(element, "title")), l); const value t = isNil(lt)? value(emptyString) : elementValue(car(lt)); const list li = filter(selector(mklist(element, "id")), l); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); - const list c = list() - + (list() + element + "title" + t) - + (list() + element + "link" + i) - + (list() + element + "description" + t); + const list c = nilListValue + + (nilListValue + element + "title" + t) + + (nilListValue + element + "link" + i) + + (nilListValue + element + "description" + t); // Write RSS entries const list le = filter(selector(mklist(element, entry)), l); if (isNil(le)) { - const list fe = list() - + element + "rss" + (list() + attribute + "version" + "2.0") - + append(list() + element + "channel", c); - return writeXML(reduce, initial, mklist(fe)); + const list fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", c); + return xml::writeElements(reduce, initial, mklist(fe)); } // Write a single RSS entry element with a list of values if (!isNil(le) && !isNil(car(le)) && isList(car(caddr(car(le))))) { const list ce = append(c, entriesElements(caddr(car(le)))); - const list fe = list() - + element + "rss" + (list() + attribute + "version" + "2.0") - + append(list() + element + "channel", ce); - return writeXML(reduce, initial, mklist(fe)); + const list fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", ce); + return xml::writeElements(reduce, initial, mklist(fe)); } // Write separate RSS entry elements const list ce = append(c, entriesElements(le)); - const list fe = list() - + element + "rss" + (list() + attribute + "version" + "2.0") - + append(list() + element + "channel", ce); - return writeXML(reduce, initial, mklist(fe)); + const list fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", ce); + return xml::writeElements(reduce, initial, mklist(fe)); } /** diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp index 4c10f515df..9daacb5559 100644 --- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp +++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp @@ -33,15 +33,15 @@ namespace tuscany { namespace scdl { -bool testComposite() { +const bool testComposite() { ifstream is("test.composite"); - const list c = readXML(streamList(is)); + const list c = content(xml::readElements(streamList(is))); return true; } -bool testComponents() { +const bool testComponents() { ifstream is("test.composite"); - const list c = components(readXML(streamList(is))); + const list c = components(content(xml::readElements(streamList(is)))); assert(length(c) == 4); const value store = car(c); @@ -58,9 +58,9 @@ bool testComponents() { return true; } -bool testServices() { +const bool testServices() { ifstream is("test.composite"); - const list c = components(readXML(streamList(is))); + const list c = components(content(xml::readElements(streamList(is)))); const value store = car(c); assert(length(services(store)) == 1); @@ -74,9 +74,9 @@ bool testServices() { return true; } -bool testReferences() { +const bool testReferences() { ifstream is("test.composite"); - const list c = components(readXML(streamList(is))); + const list c = components(content(xml::readElements(streamList(is)))); const value store = car(c); assert(length(references(store)) == 3); @@ -86,7 +86,7 @@ bool testReferences() { assert(length(bindings(catalog)) == 1); const value binding = car(bindings(catalog)); - assert(uri(binding) == value()); + assert(uri(binding) == nilValue); assert(bindingType(binding) == "binding.jsonrpc"); const list t = mkbtree(sort(referenceToTargetAssoc(references(store)))); @@ -94,9 +94,9 @@ bool testReferences() { return true; } -bool testProperties() { +const bool testProperties() { ifstream is("test.composite"); - const list c = components(readXML(streamList(is))); + const list c = components(content(xml::readElements(streamList(is)))); const value catalog = named(string("Catalog"), c); assert(length(properties(catalog)) == 1); @@ -110,7 +110,7 @@ bool testProperties() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scdl::testComposite(); diff --git a/sca-cpp/trunk/modules/scdl/scdl.hpp b/sca-cpp/trunk/modules/scdl/scdl.hpp index 7cf43e3b14..35a717d478 100644 --- a/sca-cpp/trunk/modules/scdl/scdl.hpp +++ b/sca-cpp/trunk/modules/scdl/scdl.hpp @@ -30,7 +30,7 @@ #include "list.hpp" #include "value.hpp" #include "monad.hpp" -#include "xml.hpp" +#include "../modules/xml/xml.hpp" namespace tuscany { namespace scdl { @@ -82,33 +82,26 @@ const list nameToElementAssoc(const list& l) { /** * Returns the scdl declaration with the given name. */ -struct filterName { - const value n; - filterName(const value& n) : n(n) { - } - const bool operator()(const value& v) const { +const value named(const value& n, const value& l) { + const vblambda filterName = [n](const value& v) -> const bool { return name(v) == n; - } -}; - -const value named(const value& name, const value& l) { - const list c = filter(filterName(name), l); + }; + const list c = filter(filterName, l); if (isNil(c)) - return value(); + return nilValue; return car(c); } /** * Returns the implementation of a component. */ -const bool filterImplementation(const value& v) { - return isElement(v) && contains(string(cadr(v)), "implementation."); -} - const value implementation(const value& l) { + const vblambda filterImplementation = [](const value& v) -> const bool { + return isElement(v) && contains(string(cadr(v)), "implementation."); + }; const list n = filter(filterImplementation, l); if (isNil(n)) - return value(); + return nilValue; return car(n); } @@ -156,7 +149,7 @@ const list bindings(const value& l) { */ const value bindingsTarget(const list& l) { if (isNil(l)) - return value(); + return nilValue; const value u = uri(car(l)); if (!isNil(u)) return u; diff --git a/sca-cpp/trunk/modules/scheme/Makefile.am b/sca-cpp/trunk/modules/scheme/Makefile.am index 130fe14303..460dbb3f82 100644 --- a/sca-cpp/trunk/modules/scheme/Makefile.am +++ b/sca-cpp/trunk/modules/scheme/Makefile.am @@ -30,18 +30,18 @@ value_element_LDFLAGS = element_value_SOURCES = element-value.cpp element_value_LDFLAGS = -xml_value_SOURCES = xml-value.cpp -xml_value_LDFLAGS = -lxml2 +xml_element_SOURCES = xml-element.cpp +xml_element_LDFLAGS = -lxml2 -value_xml_SOURCES = value-xml.cpp -value_xml_LDFLAGS = -lxml2 +element_xml_SOURCES = element-xml.cpp +element_xml_LDFLAGS = -lxml2 json_value_SOURCES = json-value.cpp -json_value_LDFLAGS = -lmozjs +json_value_LDFLAGS = -ljansson value_json_SOURCES = value-json.cpp -value_json_LDFLAGS = -lmozjs +value_json_LDFLAGS = -ljansson noinst_PROGRAMS = scheme-test -mod_PROGRAMS = scheme-shell element-value value-element xml-value value-xml json-value value-json +mod_PROGRAMS = scheme-shell element-value value-element xml-element element-xml json-value value-json TESTS = scheme-test diff --git a/sca-cpp/trunk/modules/scheme/driver.hpp b/sca-cpp/trunk/modules/scheme/driver.hpp index 112c226ed1..c94af7bbf7 100644 --- a/sca-cpp/trunk/modules/scheme/driver.hpp +++ b/sca-cpp/trunk/modules/scheme/driver.hpp @@ -55,7 +55,7 @@ const bool userPrint(const value val, ostream& out) { const value evalDriverLoop(istream& in, ostream& out, Env& env) { promptForInput(evalInputPrompt, out); - value input = readValue(in); + const value input = content(readValue(in)); if (isNil(input)) return input; const value output = evalExpr(input, env); diff --git a/sca-cpp/trunk/modules/scheme/element-value.cpp b/sca-cpp/trunk/modules/scheme/element-value.cpp index 8a443dbdb2..bce6042615 100644 --- a/sca-cpp/trunk/modules/scheme/element-value.cpp +++ b/sca-cpp/trunk/modules/scheme/element-value.cpp @@ -31,9 +31,9 @@ namespace tuscany { namespace scheme { -int elementValue() { - const value v = elementsToValues(readValue(cin)); - cout << writeValue(v); +const int elementValue() { + const value v = elementsToValues(content(readValue(cin))); + write(content(writeValue(v)), cout); return 0; } diff --git a/sca-cpp/trunk/modules/scheme/element-xml.cpp b/sca-cpp/trunk/modules/scheme/element-xml.cpp new file mode 100644 index 0000000000..c7bc7661ab --- /dev/null +++ b/sca-cpp/trunk/modules/scheme/element-xml.cpp @@ -0,0 +1,51 @@ +/* + * 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$ */ + +/** + * Convert a scheme value to an XML document. + */ + +#include "fstream.hpp" +#include "string.hpp" +#include "element.hpp" +#include "../xml/xml.hpp" +#include "eval.hpp" + +namespace tuscany { +namespace scheme { + +const int valueXML() { + const failable > s = xml::writeElements(content(readValue(cin))); + if (!hasContent(s)) { + cerr << reason(s) << " : " << rcode(s); + return 1; + } + write(content(s), cout); + return 0; +} + +} +} + +int main() { + return tuscany::scheme::valueXML(); +} + diff --git a/sca-cpp/trunk/modules/scheme/environment.hpp b/sca-cpp/trunk/modules/scheme/environment.hpp index 303a37cb3c..1a295c74f4 100644 --- a/sca-cpp/trunk/modules/scheme/environment.hpp +++ b/sca-cpp/trunk/modules/scheme/environment.hpp @@ -45,7 +45,7 @@ const value setSymbol("set!"); const value dotSymbol("."); const Env theEmptyEnvironment() { - return list(); + return nilListValue; } const bool isDefinition(const value& exp) { @@ -68,11 +68,11 @@ const gc_ptr firstFrame(const Env& env) { return car(env); } -list frameVariables(const Frame& frame) { +const list frameVariables(const Frame& frame) { return car((list )frame); } -list frameValues(const Frame& frame) { +const list frameValues(const Frame& frame) { return cdr((list )frame); } @@ -103,8 +103,7 @@ const Frame makeBinding(const Frame& frameSoFar, const list& variables, c } const gc_ptr makeFrame(const list& variables, const list values) { - gc_ptr frame = new (gc_new()) Frame(); - *frame = value(makeBinding(cons(value(list()), list()), variables, values)); + const gc_ptr frame = new (gc_new()) Frame(makeBinding(cons(value(nilListValue), nilListValue), variables, values)); return frame; } @@ -120,7 +119,7 @@ const value definitionValue(const value& exp) { const list exps(exp); if(isSymbol(car(cdr(exps)))) { if (isNil(cdr(cdr(exps)))) - return value(); + return nilValue; return car(cdr(cdr(exps))); } const list lexps(car(cdr(exps))); @@ -140,7 +139,8 @@ const Frame addBindingToFrame(const value& var, const value& val, const Frame& f } const bool defineVariable(const value& var, const value& val, Env& env) { - *firstFrame(env) = addBindingToFrame(var, val, *firstFrame(env)); + const Frame newFrame = addBindingToFrame(var, val, *firstFrame(env)); + setvalue(*firstFrame(env), addBindingToFrame(var, val, *firstFrame(env))); return true; } @@ -168,7 +168,7 @@ const value lookupEnvScan(const value& var, const list& vars, const list< const value lookupEnvLoop(const value& var, const Env& env) { if(env == theEmptyEnvironment()) { logStream() << "Unbound variable " << var << endl; - return value(); + return nilValue; } return lookupEnvScan(var, frameVariables(*firstFrame(env)), frameValues(*firstFrame(env)), env); } diff --git a/sca-cpp/trunk/modules/scheme/eval.hpp b/sca-cpp/trunk/modules/scheme/eval.hpp index 34d1a7bc17..5074471931 100644 --- a/sca-cpp/trunk/modules/scheme/eval.hpp +++ b/sca-cpp/trunk/modules/scheme/eval.hpp @@ -147,7 +147,7 @@ const value applyProcedure(const value& procedure, list& arguments) { return evalSequence(procedureBody(procedure), env); } logStream() << "Unknown procedure type " << procedure << endl; - return value(); + return nilValue; } const value sequenceToExp(const list exps) { @@ -209,16 +209,16 @@ const value expandClauses(const list& clauses) { if(isNil(rest)) return sequenceToExp(condActions(first)); logStream() << "else clause isn't last " << clauses << endl; - return value(); + return nilValue; } return makeIf(condPredicate(first), sequenceToExp(condActions(first)), expandClauses(rest)); } -value condToIf(const value& exp) { +const value condToIf(const value& exp) { return expandClauses(condClauses(exp)); } -value evalIf(const value& exp, Env& env) { +const value evalIf(const value& exp, Env& env) { if(isTrue(evalExpr(ifPredicate(exp), env))) return evalExpr(ifConsequent(exp), env); return evalExpr(ifAlternative(exp), env); @@ -255,7 +255,7 @@ const value evalExpr(const value& exp, Env& env) { return applyProcedure(evalExpr(operat(exp), env), operandValues); } logStream() << "Unknown expression type " << exp << endl; - return value(); + return nilValue; } const list quotedParameters(const list& p) { diff --git a/sca-cpp/trunk/modules/scheme/io.hpp b/sca-cpp/trunk/modules/scheme/io.hpp index 8f9d70e7fe..02f6923c86 100644 --- a/sca-cpp/trunk/modules/scheme/io.hpp +++ b/sca-cpp/trunk/modules/scheme/io.hpp @@ -37,39 +37,38 @@ namespace tuscany { namespace scheme { -const value rightParenthesis(mklist(")")); -const value leftParenthesis(mklist("(")); -const value comment(mklist(";")); +const value rightParenthesis(")"); +const value leftParenthesis("("); -const double stringToNumber(const string& str) { +inline const double stringToNumber(const string& str) { return atof(c_str(str)); } -const bool isWhitespace(const char ch) { +inline const bool isWhitespace(const char ch) { return ch != -1 && isspace(ch); } -const bool isIdentifierStart(const char ch) { +inline const bool isIdentifierStart(const char ch) { return ch != -1 && !isspace(ch) && !isdigit(ch); } -const bool isIdentifierPart(const char ch) { +inline const bool isIdentifierPart(const char ch) { return ch != -1 && !isspace(ch) && ch != '(' && ch != ')'; } -const bool isDigit(const char ch) { +inline const bool isDigit(const char ch) { return isdigit(ch) || ch == '.'; } -const bool isLeftParenthesis(const value& token) { +inline const bool isLeftParenthesis(const value& token) { return leftParenthesis == token; } -const bool isRightParenthesis(const value& token) { +inline const bool isRightParenthesis(const value& token) { return rightParenthesis == token; } -const char readChar(istream& in) { +inline const char readChar(istream& in) { if(in.eof()) { return -1; } @@ -77,14 +76,14 @@ const char readChar(istream& in) { return c; } -const char peekChar(istream& in) { +inline const char peekChar(istream& in) { if(eof(in)) return -1; char c = (char)peek(in); return c; } -const bool isQuote(const value& token) { +inline const bool isQuote(const value& token) { return token == quoteSymbol; } @@ -93,9 +92,9 @@ const value readQuoted(istream& in); const value readIdentifier(const char chr, istream& in); const value readString(istream& in); const value readNumber(const char chr, istream& in); -const value readValue(istream& in); +const failable readValue(istream& in); -const failable readToken(istream& in) { +inline const failable readToken(istream& in) { const char firstChar = readChar(in); if(isWhitespace(firstChar)) return readToken(in); @@ -119,18 +118,19 @@ const failable readToken(istream& in) { return readToken(in); } -const failable skipComment(istream& in) { - const char nextChar = readChar(in); - if (nextChar == '\n') - return readToken(in); - return skipComment(in); +inline const failable skipComment(istream& in) { + while(true) { + const char nextChar = readChar(in); + if (nextChar == '\n') + return readToken(in); + } } -const value readQuoted(istream& in) { - return mklist(quoteSymbol, readValue(in)); +inline const value readQuoted(istream& in) { + return mklist(quoteSymbol, content(readValue(in))); } -const list readList(const list& listSoFar, istream& in) { +inline const list readList(const list& listSoFar, istream& in) { const failable ftoken = readToken(in); if (!hasContent(ftoken)) return reverse(listSoFar); @@ -142,95 +142,97 @@ const list readList(const list& listSoFar, istream& in) { return readList(cons(token, listSoFar), in); } -const string listToString(const list& l) { - if(isNil(l)) - return ""; - const char buf[1] = { car(l) }; - return string(buf, 1) + listToString(cdr(l)); -} - -const list readIdentifierHelper(const list& listSoFar, istream& in) { - const char nextChar = peekChar(in); - if(isIdentifierPart(nextChar)) - return readIdentifierHelper(cons(readChar(in), listSoFar), in); - return reverse(listSoFar); +inline const string readIdentifierHelper(const char chr, istream& in) { + ostringstream buf; + buf << chr; + while(true) { + const char nextChar = peekChar(in); + if(!isIdentifierPart(nextChar)) + return str(buf); + buf << readChar(in); + } } -const value readIdentifier(const char chr, istream& in) { - const value val = c_str(listToString(readIdentifierHelper(mklist(chr), in))); +inline const value readIdentifier(const char chr, istream& in) { + const value val = c_str(readIdentifierHelper(chr, in)); if (val == "false") return value((bool)false); if (val == "true") return value((bool)true); if (val == "nil") - return value(); + return nilValue; return val; } -const list readStringHelper(const list& listSoFar, istream& in) { - const char nextChar = readChar(in); - if(nextChar == -1 || nextChar == '"') - return reverse(listSoFar); - if (nextChar == '\\') { - const char escapedChar = readChar(in); - if (escapedChar == -1) - return reverse(listSoFar); - return readStringHelper(cons(escapedChar, listSoFar), in); +inline const value readString(istream& in) { + ostringstream buf; + while(true) { + const char nextChar = readChar(in); + if(nextChar == -1 || nextChar == '"') + return (value)str(buf); + if (nextChar == '\\') { + const char escapedChar = readChar(in); + if (escapedChar == -1) + return (value)str(buf); + buf << escapedChar; + } + buf << nextChar; } - return readStringHelper(cons(nextChar, listSoFar), in); } -const value readString(istream& in) { - return listToString(readStringHelper(list(), in)); -} - -const list readNumberHelper(const list& listSoFar, istream& in) { - const char nextChar = peekChar(in); - if(isDigit(nextChar)) - return readNumberHelper(cons(readChar(in), listSoFar), in); - return reverse(listSoFar); -} - -const value readNumber(const char chr, istream& in) { - return stringToNumber(listToString(readNumberHelper(mklist(chr), in))); +inline const value readNumber(const char chr, istream& in) { + ostringstream buf; + buf << chr; + while(true) { + const char nextChar = peekChar(in); + if(!isDigit(nextChar)) + return stringToNumber(str(buf)); + buf << readChar(in); + } } -const value readValue(istream& in) { +inline const failable readValue(istream& in) { const failable fnextToken = readToken(in); if (!hasContent(fnextToken)) - return value(); + return nilValue; const value nextToken = content(fnextToken); if(isLeftParenthesis(nextToken)) - return readList(list(), in); + return (value)readList(nilListValue, in); return nextToken; } -const value readValue(const string s) { +inline const failable readValue(const string& s) { istringstream in(s); const failable fnextToken = readToken(in); if (!hasContent(fnextToken)) - return value(); + return nilValue; const value nextToken = content(fnextToken); if(isLeftParenthesis(nextToken)) - return readList(list(), in); + return (value)readList(nilListValue, in); return nextToken; } -const bool writeValue(const value& val, ostream& out) { +inline const failable readValue(const list& l) { + ostringstream os; + write(l, os); + return readValue(str(os)); +} + +inline const failable writeValue(const value& val, ostream& out) { out << val; - return true; + return out; } -const string writeValue(const value& val) { +inline const failable > writeValue(const value& val) { ostringstream out; out << val; - return str(out); + return mklist(str(out)); } -const value readScript(istream& in) { - const value val = readValue(in); +inline const value readScript(istream& in) { + const value val = content(readValue(in)); if (isNil(val)) - return list(); + return nilListValue; return cons(val, (list)readScript(in)); } diff --git a/sca-cpp/trunk/modules/scheme/primitive.hpp b/sca-cpp/trunk/modules/scheme/primitive.hpp index 59aee12073..2e0c4f62dd 100644 --- a/sca-cpp/trunk/modules/scheme/primitive.hpp +++ b/sca-cpp/trunk/modules/scheme/primitive.hpp @@ -40,7 +40,7 @@ const value quoteSymbol("'"); const value lambdaSymbol("lambda"); #ifdef WANT_THREADS -perthread_ptr displayOutStream; +const perthread_ptr displayOutStream; #else ostream* displayOutStream = NULL; #endif @@ -51,49 +51,49 @@ perthread_ptr logOutStream; ostream* logOutStream = NULL; #endif -const bool setupDisplay(ostream& out) { +inline const bool setupDisplay(ostream& out) { displayOutStream = &out; return true; } -ostream& displayStream() { +inline ostream& displayStream() { if (displayOutStream == NULL) return cout; return *displayOutStream; } -const bool setupLog(ostream& out) { +inline const bool setupLog(ostream& out) { logOutStream = &out; return true; } -ostream& logStream() { +inline ostream& logStream() { if (logOutStream == NULL) return cerr; return *logOutStream; } -const value carProc(const list& args) { +inline const value carProc(const list& args) { return car((list )car(args)); } -const value cdrProc(const list& args) { +inline const value cdrProc(const list& args) { return cdr((list )car(args)); } -const value consProc(const list& args) { +inline const value consProc(const list& args) { return cons(car(args), (list )cadr(args)); } -const value listProc(const list& args) { +inline const value listProc(const list& args) { return args; } -const value assocProc(const list& args) { +inline const value assocProc(const list& args) { return assoc(car(args), (list >)cadr(args)); } -const value nulProc(const list& args) { +inline const value nulProc(const list& args) { const value v(car(args)); if (isNil(v)) return true; @@ -102,31 +102,31 @@ const value nulProc(const list& args) { return false; } -const value equalProc(const list& args) { +inline const value equalProc(const list& args) { return (bool)(car(args) == cadr(args)); } -const value addProc(const list& args) { +inline const value addProc(const list& args) { if (isNil(cdr(args))) return (double)car(args); return (double)car(args) + (double)cadr(args); } -const value subProc(const list& args) { +inline const value subProc(const list& args) { if (isNil(cdr(args))) return (double)0 - (double)car(args); return (double)car(args) - (double)cadr(args); } -const value mulProc(const list& args) { +inline const value mulProc(const list& args) { return (double)car(args) * (double)cadr(args); } -const value divProc(const list& args) { +inline const value divProc(const list& args) { return (double)car(args) / (double)cadr(args); } -const value displayProc(const list& args) { +inline const value displayProc(const list& args) { if (isNil(args)) { displayStream() << endl; return true; @@ -135,7 +135,7 @@ const value displayProc(const list& args) { return displayProc(cdr(args)); } -const value logProc(const list& args) { +inline const value logProc(const list& args) { if (isNil(args)) { logStream() << endl; return true; @@ -144,52 +144,52 @@ const value logProc(const list& args) { return logProc(cdr(args)); } -const value uuidProc(unused const list& args) { +inline const value uuidProc(unused const list& args) { return mkuuid(); } -const value cadrProc(const list& args) { +inline const value cadrProc(const list& args) { return cadr((list )car(args)); } -const value caddrProc(const list& args) { +inline const value caddrProc(const list& args) { return caddr((list )car(args)); } -const value cadddrProc(const list& args) { +inline const value cadddrProc(const list& args) { return cadddr((list )car(args)); } -const value cddrProc(const list& args) { +inline const value cddrProc(const list& args) { return cddr((list )car(args)); } -const value cdddrProc(const list& args) { +inline const value cdddrProc(const list& args) { return cdddr((list )car(args)); } -const value appendProc(const list& args) { +inline const value appendProc(const list& args) { return append((list )car(args), (list)cadr(args)); } -const value startProc(unused const list& args) { - return lambda&)>(); +inline const value startProc(unused const list& args) { + return lvvlambda(); } -const value stopProc(unused const list& args) { - return lambda&)>(); +inline const value stopProc(unused const list& args) { + return lvvlambda(); } -const value applyPrimitiveProcedure(const value& proc, list& args) { - const lambda&)> func(cadr((list)proc)); +inline const value applyPrimitiveProcedure(const value& proc, list& args) { + const lvvlambda func(cadr((list)proc)); return func(args); } -const bool isPrimitiveProcedure(const value& proc) { +inline const bool isPrimitiveProcedure(const value& proc) { return isTaggedList(proc, primitiveSymbol); } -const bool isSelfEvaluating(const value& exp) { +inline const bool isSelfEvaluating(const value& exp) { if(isNil(exp)) return true; if(isNumber(exp)) @@ -203,15 +203,15 @@ const bool isSelfEvaluating(const value& exp) { return false; } -const value primitiveImplementation(const list& proc) { +inline const value primitiveImplementation(const list& proc) { return car(cdr(proc)); } -template const value primitiveProcedure(const F& f) { - return mklist(primitiveSymbol, (lambda&)>)f); +template inline const value primitiveProcedure(const F& f) { + return mklist(primitiveSymbol, (lvvlambda)f); } -const list primitiveProcedureNames() { +inline const list primitiveProcedureNames() { return mklist("car") + "cdr" + "cons" @@ -237,7 +237,7 @@ const list primitiveProcedureNames() { + "stop"; } -const list primitiveProcedureObjects() { +inline const list primitiveProcedureObjects() { return mklist(primitiveProcedure(carProc)) + primitiveProcedure(cdrProc) + primitiveProcedure(consProc) @@ -263,23 +263,23 @@ const list primitiveProcedureObjects() { + primitiveProcedure(stopProc); } -const bool isFalse(const value& exp) { +inline const bool isFalse(const value& exp) { return (bool)exp == false; } -const bool isTrue(const value& exp) { +inline const bool isTrue(const value& exp) { return (bool)exp == true; } -const bool isQuoted(const value& exp) { +inline const bool isQuoted(const value& exp) { return isTaggedList(exp, quoteSymbol); } -const value textOfQuotation(const value& exp) { +inline const value textOfQuotation(const value& exp) { return car(cdr((list )exp)); } -const value makeLambda(const list& parameters, const list& body) { +inline const value makeLambda(const list& parameters, const list& body) { return cons(lambdaSymbol, cons(parameters, body)); } diff --git a/sca-cpp/trunk/modules/scheme/scheme-shell.cpp b/sca-cpp/trunk/modules/scheme/scheme-shell.cpp index 4aa67c2375..96ea5e834e 100644 --- a/sca-cpp/trunk/modules/scheme/scheme-shell.cpp +++ b/sca-cpp/trunk/modules/scheme/scheme-shell.cpp @@ -30,7 +30,7 @@ #include "driver.hpp" int main() { - tuscany::gc_scoped_pool pool; + const tuscany::gc_scoped_pool pool; tuscany::scheme::evalDriverRun(tuscany::cin, tuscany::cout); return 0; } diff --git a/sca-cpp/trunk/modules/scheme/scheme-test.cpp b/sca-cpp/trunk/modules/scheme/scheme-test.cpp index 5b69b8e588..e83f99456f 100644 --- a/sca-cpp/trunk/modules/scheme/scheme-test.cpp +++ b/sca-cpp/trunk/modules/scheme/scheme-test.cpp @@ -26,14 +26,16 @@ #include #include "stream.hpp" #include "string.hpp" +#include "perf.hpp" #include "driver.hpp" +#include "scheme-test.hpp" namespace tuscany { namespace scheme { -bool testEnv() { - gc_scoped_pool pool; - Env globalEnv = list(); +const bool testEnv() { + const gc_scoped_pool pool; + Env globalEnv = nilListValue; Env env = extendEnvironment(mklist("a"), mklist(1), globalEnv); defineVariable("x", env, env); assert(lookupVariableValue(value("x"), env) == env); @@ -41,7 +43,7 @@ bool testEnv() { return true; } -bool testEnvGC() { +const bool testEnvGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); @@ -52,49 +54,49 @@ bool testEnvGC() { return true; } -bool testRead() { +const bool testRead() { istringstream is("abcd"); - assert(readValue(is) == "abcd"); + assert(content(readValue(is)) == "abcd"); istringstream is2("123"); - assert(readValue(is2) == value(123)); + assert(content(readValue(is2)) == value(123)); istringstream is3("(abcd)"); - assert(readValue(is3) == mklist(value("abcd"))); + assert(content(readValue(is3)) == mklist(value("abcd"))); istringstream is4("(abcd xyz)"); - assert(readValue(is4) == mklist("abcd", "xyz")); + assert(content(readValue(is4)) == mklist("abcd", "xyz")); istringstream is5("(abcd (xyz tuv))"); - assert(readValue(is5) == mklist("abcd", mklist("xyz", "tuv"))); + assert(content(readValue(is5)) == mklist("abcd", mklist("xyz", "tuv"))); return true; } -bool testWrite() { +const bool testWrite() { { - const list i = list() - + (list() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - + (list() + "item" - + (list() + "name" + "Apple") - + (list() + "price" + "$2.99"))) - + (list() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - + (list() + "item" - + (list() + "name" + "Orange") - + (list() + "price" + "$3.55"))); + const list i = nilListValue + + (nilListValue + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + + (nilListValue + "item" + + (nilListValue + "name" + "Apple") + + (nilListValue + "price" + "$2.99"))) + + (nilListValue + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + + (nilListValue + "item" + + (nilListValue + "name" + "Orange") + + (nilListValue + "price" + "$3.55"))); const list a = cons("Feed", cons("feed-1234", i)); ostringstream os; writeValue(a, os); istringstream is(str(os)); - assert(readValue(is) == a); + assert(content(readValue(is)) == a); } { - const list i = mklist("x", value()); + const list i = mklist("x", nilValue); const list a = mklist(i); ostringstream os; writeValue(a, os); istringstream is(str(os)); - assert(readValue(is) == a); + assert(content(readValue(is)) == a); } return true; } @@ -147,8 +149,8 @@ const string evalOutput(const string& scm) { return str(os); } -bool testEval() { - gc_scoped_pool pool; +const bool testEval() { + const gc_scoped_pool pool; assert(contains(evalOutput(testSchemeNumber), "testNumber ok")); assert(contains(evalOutput(testSchemeString), "testString ok")); assert(contains(evalOutput(testSchemeDefinition), "testDefinition ok")); @@ -161,8 +163,8 @@ bool testEval() { return true; } -bool testEvalExpr() { - gc_scoped_pool pool; +const bool testEvalExpr() { + const gc_scoped_pool pool; const value exp = mklist("+", 2, 3); Env env = setupEnvironment(); const value r = evalExpr(exp, env); @@ -170,8 +172,8 @@ bool testEvalExpr() { return true; } -bool testEvalRun() { - gc_scoped_pool pool; +const bool testEvalRun() { + const gc_scoped_pool pool; evalDriverRun(cin, cout); return true; } @@ -188,8 +190,8 @@ const string testReturnLambda( const string testCallLambda( "(define (testCallLambda l x y) (l x y))"); -bool testEvalLambda() { - gc_scoped_pool pool; +const bool testEvalLambda() { + const gc_scoped_pool pool; Env env = setupEnvironment(); const value trl = mklist("testReturnLambda"); @@ -208,7 +210,18 @@ bool testEvalLambda() { return true; } -bool testEvalGC() { +const bool testEvalScript() { + const gc_scoped_pool pool; + Env env = setupEnvironment(); + ifstream is("test.scm"); + const value script = readScript(is); + const value expr = mklist("echo", string("x")); + const value res = evalScript(expr, script, env); + assert(res == string("x")); + return true; +} + +const bool testEvalGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); @@ -221,11 +234,55 @@ bool testEvalGC() { return true; } +const string testCustomer = "((customer (@name \"jdoe\") (account (id \"1234\") (@balance 1000)) (address (@city \"san francisco\") (@state \"ca\"))))"; + +const bool testReadWrite() { + const gc_scoped_pool pool; + + istringstream is(testCustomer); + const value r = content(readValue(is)); + + ostringstream os; + writeValue(r, os); + //assert(str(os) == testCustomer); + return true; +} + +const bool testReadWritePerf() { + const gc_scoped_pool pool; + + const blambda rwl = blambda(testReadWrite); + cout << "Scheme read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + +const bool testReadWriteBigDoc() { + const gc_scoped_pool pool; + + istringstream is(testBigDoc); + const value r = content(readValue(is)); + + ostringstream os; + writeValue(r, os); + //assert(str(os) == testBigDoc); + return true; +} + +const bool testReadWriteBigDocPerf() { + const gc_scoped_pool pool; + + const blambda rwl = blambda(testReadWriteBigDoc); + cout << "Scheme big doc read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + } } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::scheme::testEnv(); @@ -235,7 +292,10 @@ int main() { tuscany::scheme::testEval(); tuscany::scheme::testEvalExpr(); tuscany::scheme::testEvalLambda(); + tuscany::scheme::testEvalScript(); tuscany::scheme::testEvalGC(); + tuscany::scheme::testReadWritePerf(); + tuscany::scheme::testReadWriteBigDocPerf(); tuscany::cout << "OK" << tuscany::endl; return 0; diff --git a/sca-cpp/trunk/modules/scheme/scheme-test.hpp b/sca-cpp/trunk/modules/scheme/scheme-test.hpp new file mode 100644 index 0000000000..67f32344a8 --- /dev/null +++ b/sca-cpp/trunk/modules/scheme/scheme-test.hpp @@ -0,0 +1,34 @@ +/* + * 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$ */ + +/** + * Test Scheme doc. + */ + +namespace tuscany { +namespace scheme { + +const string testBigDoc = "((feed (title \"Search Results\") (id \"search\") (entry (title \"An empty app template\") (id \"new\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"An empty test app\") (id \"test\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Check my public social data\") (id \"me360\") (author \"admin@example.com\") (updated \"Apr 28, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"nearme\") (id \"nearme\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"nearme2\") (id \"nearme2\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Our photos of an event\") (id \"ourphotos\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"My online store\") (id \"shoppingcart\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Slice\") (id \"slice\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test animation components\") (id \"testanimation\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test database components\") (id \"testdb\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test event components\") (id \"testevents\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTTP components\") (id \"testhttp\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test logic components\") (id \"testlogic\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test search components\") (id \"testsearch\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTTP components\") (id \"testhttp\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test social components\") (id \"testsocial\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test text processing components\") (id \"testtext\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test URL components\") (id \"testurl\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test values and lists\") (id \"testvalues\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test widgets\") (id \"testwidgets\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test more widgets\") (id \"testwidgets2\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTML generator components\") (id \"testwidgets3\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"jsdtest\") (id \"jsdtest\") (author \"jsdelfino\") (updated \"Jul 27, 2012\") (content (stats (description \"Test app\")))) (entry (title \"SMS send service\") (id \"twsms\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"boao\") (id \"boao\") (author \"jsdelfino\") (updated \"2012-10-12T12:06:59+00:00\") (content (stats (description \"Sample app\")))) (entry (title \"An empty test app\") (id \"test\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"An empty app template\") (id \"new\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"nearme\") (id \"nearme\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"nearme2\") (id \"nearme2\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Our photos of an event\") (id \"ourphotos\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"My online store\") (id \"shoppingcart\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Slice\") (id \"slice\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test animation components\") (id \"testanimation\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test database components\") (id \"testdb\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test event components\") (id \"testevents\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test social components\") (id \"testsocial\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTTP components\") (id \"testhttp\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test logic components\") (id \"testlogic\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test search components\") (id \"testsearch\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTTP components\") (id \"testhttp\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test text processing components\") (id \"testtext\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test URL components\") (id \"testurl\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test values and lists\") (id \"testvalues\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test widgets\") (id \"testwidgets\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test more widgets\") (id \"testwidgets2\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Test HTML generator components\") (id \"testwidgets3\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"test9\") (id \"test9\") (author \"jsdelfino\") (updated \"2012-09-25T06:17:18+00:00\") (content (stats (description \"Sample app\")))) (entry (title \"SMS send service\") (id \"twsms\") (author \"admin@example.com\") (updated \"Jan 01, 2012\") (content (stats (description \"Sample app\")))) (entry (title \"Check my public social data\") (id \"me360\") (author \"admin@example.com\") (updated \"Apr 28, 2012\") (content (stats (description \"Sample app\"))))))"; + + +} +} + diff --git a/sca-cpp/trunk/modules/scheme/test.scm b/sca-cpp/trunk/modules/scheme/test.scm new file mode 100644 index 0000000000..4bbff6e5c2 --- /dev/null +++ b/sca-cpp/trunk/modules/scheme/test.scm @@ -0,0 +1,44 @@ +; 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. + +; JSON-RPC test case + +(define (echo x) x) + +; ATOMPub test case + +(define (get id) + (if (nul id) + '((feed (title "Sample Feed") (id "123456789") (entry + (((title "Item") (id "111") (content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99)))) + ((title "Item") (id "222") (content (item (name "Orange") (currencyCode "USD") (currencySymbol "$") (price 3.55)))) + ((title "Item") (id "333") (content (item (name "Pear") (currencyCode "USD") (currencySymbol "$") (price 1.55)))))))) + + (list (list 'entry '(title "Item") (list 'id (car id)) '(content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99)))))) +) + +(define (post collection item) + '("123456789") +) + +(define (put id item) + true +) + +(define (delete id) + true +) diff --git a/sca-cpp/trunk/modules/scheme/value-element.cpp b/sca-cpp/trunk/modules/scheme/value-element.cpp index a4acdaf2d7..af5eac9b57 100644 --- a/sca-cpp/trunk/modules/scheme/value-element.cpp +++ b/sca-cpp/trunk/modules/scheme/value-element.cpp @@ -31,9 +31,9 @@ namespace tuscany { namespace scheme { -int valueElement() { - const value v = valuesToElements(readValue(cin)); - cout << writeValue(v); +const int valueElement() { + const value v = valuesToElements(content(readValue(cin))); + write(content(writeValue(v)), cout); return 0; } diff --git a/sca-cpp/trunk/modules/scheme/value-xml.cpp b/sca-cpp/trunk/modules/scheme/value-xml.cpp deleted file mode 100644 index ff785899c6..0000000000 --- a/sca-cpp/trunk/modules/scheme/value-xml.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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$ */ - -/** - * Convert a scheme value to an XML document. - */ - -#include "fstream.hpp" -#include "string.hpp" -#include "xml.hpp" -#include "element.hpp" -#include "eval.hpp" - -namespace tuscany { -namespace scheme { - -int valueXML() { - failable > s = writeXML(readValue(cin)); - if (!hasContent(s)) { - cerr << reason(s) << " : " << rcode(s); - return 1; - } - write(content(s), cout); - return 0; -} - -} -} - -int main() { - return tuscany::scheme::valueXML(); -} - diff --git a/sca-cpp/trunk/modules/scheme/xml-element.cpp b/sca-cpp/trunk/modules/scheme/xml-element.cpp new file mode 100644 index 0000000000..2050004895 --- /dev/null +++ b/sca-cpp/trunk/modules/scheme/xml-element.cpp @@ -0,0 +1,47 @@ +/* + * 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$ */ + +/** + * Convert an XML document to a scheme value. + */ + +#include "fstream.hpp" +#include "string.hpp" +#include "element.hpp" +#include "../xml/xml.hpp" +#include "eval.hpp" + +namespace tuscany { +namespace scheme { + +const int xmlValue() { + const value v = content(xml::readElements(streamList(cin))); + write(content(writeValue(v)), cout); + return 0; +} + +} +} + +int main() { + return tuscany::scheme::xmlValue(); +} + diff --git a/sca-cpp/trunk/modules/scheme/xml-value.cpp b/sca-cpp/trunk/modules/scheme/xml-value.cpp deleted file mode 100644 index d88f754aa5..0000000000 --- a/sca-cpp/trunk/modules/scheme/xml-value.cpp +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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$ */ - -/** - * Convert an XML document to a scheme value. - */ - -#include "fstream.hpp" -#include "string.hpp" -#include "xml.hpp" -#include "element.hpp" -#include "eval.hpp" - -namespace tuscany { -namespace scheme { - -int xmlValue() { - const value v = readXML(streamList(cin)); - cout << writeValue(v); - return 0; -} - -} -} - -int main() { - return tuscany::scheme::xmlValue(); -} - diff --git a/sca-cpp/trunk/modules/xml/Makefile.am b/sca-cpp/trunk/modules/xml/Makefile.am new file mode 100644 index 0000000000..e99218a736 --- /dev/null +++ b/sca-cpp/trunk/modules/xml/Makefile.am @@ -0,0 +1,29 @@ +# 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. + +incl_HEADERS = *.hpp +incldir = $(prefix)/include/modules/xml + +xml_test_SOURCES = xml-test.cpp +xml_test_LDFLAGS = -lxml2 + +xsd_test_SOURCES = xsd-test.cpp +xsd_test_LDFLAGS = -lxml2 + +noinst_PROGRAMS = xml-test xsd-test +TESTS = xml-test + diff --git a/sca-cpp/trunk/modules/xml/test.xml b/sca-cpp/trunk/modules/xml/test.xml new file mode 100644 index 0000000000..501d9ac477 --- /dev/null +++ b/sca-cpp/trunk/modules/xml/test.xml @@ -0,0 +1,2 @@ + +Search ResultssearchAn empty app templatenewadmin@example.comJan 01, 2012Sample appAn empty test apptestadmin@example.comJan 01, 2012Sample appCheck my public social datame360admin@example.comApr 28, 2012Sample appnearmenearmeadmin@example.comJan 01, 2012Sample appnearme2nearme2admin@example.comJan 01, 2012Sample appOur photos of an eventourphotosadmin@example.comJan 01, 2012Sample appMy online storeshoppingcartadmin@example.comJan 01, 2012Sample appSlicesliceadmin@example.comJan 01, 2012Sample appTest animation componentstestanimationadmin@example.comJan 01, 2012Sample appTest database componentstestdbadmin@example.comJan 01, 2012Sample appTest event componentstesteventsadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest logic componentstestlogicadmin@example.comJan 01, 2012Sample appTest search componentstestsearchadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest social componentstestsocialadmin@example.comJan 01, 2012Sample appTest text processing componentstesttextadmin@example.comJan 01, 2012Sample appTest URL componentstesturladmin@example.comJan 01, 2012Sample appTest values and liststestvaluesadmin@example.comJan 01, 2012Sample appTest widgetstestwidgetsadmin@example.comJan 01, 2012Sample appTest more widgetstestwidgets2admin@example.comJan 01, 2012Sample appTest HTML generator componentstestwidgets3admin@example.comJan 01, 2012Sample appjsdtestjsdtestjsdelfinoJul 27, 2012Test appSMS send servicetwsmsadmin@example.comJan 01, 2012Sample appboaoboaojsdelfino2012-10-12T12:06:59+00:00Sample appAn empty test apptestadmin@example.comJan 01, 2012Sample appAn empty app templatenewadmin@example.comJan 01, 2012Sample appnearmenearmeadmin@example.comJan 01, 2012Sample appnearme2nearme2admin@example.comJan 01, 2012Sample appOur photos of an eventourphotosadmin@example.comJan 01, 2012Sample appMy online storeshoppingcartadmin@example.comJan 01, 2012Sample appSlicesliceadmin@example.comJan 01, 2012Sample appTest animation componentstestanimationadmin@example.comJan 01, 2012Sample appTest database componentstestdbadmin@example.comJan 01, 2012Sample appTest event componentstesteventsadmin@example.comJan 01, 2012Sample appTest social componentstestsocialadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest logic componentstestlogicadmin@example.comJan 01, 2012Sample appTest search componentstestsearchadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest text processing componentstesttextadmin@example.comJan 01, 2012Sample appTest URL componentstesturladmin@example.comJan 01, 2012Sample appTest values and liststestvaluesadmin@example.comJan 01, 2012Sample appTest widgetstestwidgetsadmin@example.comJan 01, 2012Sample appTest more widgetstestwidgets2admin@example.comJan 01, 2012Sample appTest HTML generator componentstestwidgets3admin@example.comJan 01, 2012Sample apptest9test9jsdelfino2012-09-25T06:17:18+00:00Sample appSMS send servicetwsmsadmin@example.comJan 01, 2012Sample appCheck my public social datame360admin@example.comApr 28, 2012Sample app diff --git a/sca-cpp/trunk/modules/xml/xml-test.cpp b/sca-cpp/trunk/modules/xml/xml-test.cpp new file mode 100644 index 0000000000..dd2be2f9c2 --- /dev/null +++ b/sca-cpp/trunk/modules/xml/xml-test.cpp @@ -0,0 +1,373 @@ +/* + * 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$ */ + +/** + * Test XML handling functions. + */ + +#include +#include "stream.hpp" +#include "string.hpp" +#include "list.hpp" +#include "value.hpp" +#include "element.hpp" +#include "perf.hpp" +#include "xml.hpp" +#include "xml-test.hpp" + +namespace tuscany { +namespace xml { + +const string currencyXML = +"\n" +"" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "US" + "" +"\n"; + +const string customerXML = +"\n" +"" + "jdoe" + "
" + "san francisco" + "ca" + "
" + "" + "1234" + "1000" + "" + "" + "6789" + "2000" + "" + "" + "4567" + "3000" + "" +"
\n"; + +const string abcXML = +"\n" +"" + "abc" + "def" + "xyz" + "tuv" +"\n"; + +const string xyzXML = +"\n" +"" + "" + "123" + "abc" + "" + "" + "234" + "def" + "" + "" + "345" + "xyz" + "" + "" + "456" + "tuv" + "" +"\n"; + +const string boolXML = +"\n" +"true\n"; + +const string numberXML = +"\n" +"123.4\n"; + +const bool isName(const value& token) { + return isTaggedList(token, attribute) && attributeName(token) == "name"; +} + +const bool testReadXML() { + { + istringstream is(customerXML); + const list c = content(readElements(streamList(is))); + } + { + istringstream is(currencyXML); + const list c = content(readElements(streamList(is))); + + const value composite = car(c); + assert(isTaggedList(composite, element)); + assert(elementName(composite) == "composite"); + assert(attributeValue(car(filter(isName, elementChildren(composite)))) == string("currency")); + } + { + istringstream is(boolXML); + const list c = content(readElements(streamList(is))); + assert(caddr(car(c)) == value(true)); + } + { + istringstream is(numberXML); + const list c = content(readElements(streamList(is))); + assert(caddr(car(c)) == value(123.4)); + } + return true; +} + +ostream* xmlWriter(const string& s, ostream* os) { + (*os) << s; + return os; +} + +const bool testWriteXML() { + { + istringstream is(customerXML); + const list c = content(readElements(streamList(is))); + ostringstream os; + writeElements(xmlWriter, &os, c); + assert(str(os) == customerXML); + } + { + istringstream is(currencyXML); + const list c = content(readElements(streamList(is))); + ostringstream os; + writeElements(xmlWriter, &os, c); + assert(str(os) == currencyXML); + } + return true; +} + +const bool testElements() { + { + const list ad = mklist(mklist("city", string("san francisco")), mklist("state", string("ca"))); + const list ac1 = mklist(mklist("id", string("1234")), mklist("balance", 1000)); + const list ac2 = mklist(mklist("id", string("6789")), mklist("balance", 2000)); + const list ac3 = mklist(mklist("id", string("4567")), mklist("balance", 3000)); + { + const list c = mklist(mklist("customer", mklist("name", string("jdoe")), cons("address", ad), mklist("account", mklist(ac1, ac2, ac3)))); + const list e = valuesToElements(c); + const list v = elementsToValues(e); + assert(v == c); + + ostringstream os; + writeElements(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + { + const list c = mklist(mklist("customer", mklist("name", string("jdoe")), cons("address", ad), cons("account", ac1), cons("account", ac2), cons("account", ac3))); + const list e = valuesToElements(c); + const list v = elementsToValues(e); + + ostringstream os; + writeElements(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + } + { + istringstream is(abcXML); + const list c = content(readElements(streamList(is))); + const list v = elementsToValues(c); + const list e = valuesToElements(v); + ostringstream os; + writeElements(xmlWriter, &os, e); + assert(str(os) == abcXML); + } + { + istringstream is(xyzXML); + const list c = content(readElements(streamList(is))); + const list v = elementsToValues(c); + const list e = valuesToElements(v); + ostringstream os; + writeElements(xmlWriter, &os, e); + assert(str(os) == xyzXML); + } + { + istringstream is(customerXML); + const list c = content(readElements(streamList(is))); + const list v = elementsToValues(c); + const list e = valuesToElements(v); + ostringstream os; + writeElements(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + return true; +} + +const bool testValues() { + { + const list l = mklist(nilListValue + "ns1:echoString" + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (nilListValue + "text" + string("Hello World!"))); + const list e = valuesToElements(l); + const failable > lx = writeElements(e); + ostringstream os; + write(content(lx), os); + istringstream is(str(os)); + const list x = content(readElements(streamList(is))); + const list v = elementsToValues(x); + assert(v == l); + } + return true; +} + +const bool testReadWrite() { + const gc_scoped_pool pool; + + istringstream is(customerXML); + const list il = streamList(is); + const list r = elementsToValues(content(readElements(il))); + + ostringstream os; + writeElements(xmlWriter, &os, valuesToElements(r)); + //assert(str(os) == customerXML); + return true; +} + +const bool testReadWritePerf() { + const gc_scoped_pool pool; + + const blambda rwl = blambda(testReadWrite); + cout << "XML read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + +const bool testReadWriteBigDoc() { + const gc_scoped_pool pool; + + istringstream is(testBigDoc); + const list il = streamList(is); + const list r = elementsToValues(content(readElements(il))); + + ostringstream os; + writeElements(xmlWriter, &os, valuesToElements(r)); + //assert(str(os) == testBigDoc); + return true; +} + +const bool testReadWriteBigDocPerf() { + const gc_scoped_pool pool; + + const blambda rwl = blambda(testReadWriteBigDoc); + cout << "XML big doc read + write test " << time(rwl, 5, 200) << " ms" << endl; + + return true; +} + +const string customersXML = +"\n" +"" + "" + "jane doe" + "
" + "san francisco" + "ca" + "
" + "" + "1234" + "1000" + "" + "" + "6789" + "4000" + "" + "
" + "" + "john doe" + "
" + "new york" + "ny" + "
" + "" + "5678" + "2000" + "" + "" + "4321" + "1000" + "" + "
" +"
\n"; + +const bool testQuery() { + { + const gc_scoped_pool pool; + + // Read XML doc containing customers + istringstream is(customersXML); + const list c = content(readElements(streamList(is))); + //cout << c << endl; + + // Map list of customers to a list of (customer name, customer balance) pairs + const list nb = map([](value e) -> const value { + + // Map list of accounts to a list of balances + list bals = map([](value e) -> const value { + return (double)elementValue(elementChild("balance", e)); + }, elementChildren("account", e)); + + // Reduce list of balances to compute customer balance + value total = reduce([](value accum, value v) -> const value { + return (double)accum + (double)v; + }, value(0), bals); + + // Return (customer name, customer balance) pair + return mklist(elementValue(elementChild("name", e)), total); + + }, elementChildren("customer", elementChild("customers", c))); + + // The resulting list of (customer name, customer balance) pairs + //cout << nb << endl; + assert(nb == mklist(mklist("jane doe", 5000), mklist("john doe", 3000))); + } + return true; +} + +} +} + +int main() { + const tuscany::gc_scoped_pool p; + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::xml::testReadXML(); + tuscany::xml::testWriteXML(); + tuscany::xml::testElements(); + tuscany::xml::testValues(); + tuscany::xml::testReadWritePerf(); + tuscany::xml::testReadWriteBigDocPerf(); + tuscany::xml::testQuery(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/modules/xml/xml-test.hpp b/sca-cpp/trunk/modules/xml/xml-test.hpp new file mode 100644 index 0000000000..470ba40880 --- /dev/null +++ b/sca-cpp/trunk/modules/xml/xml-test.hpp @@ -0,0 +1,33 @@ +/* + * 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$ */ + +/** + * Test XML doc. + */ + +namespace tuscany { +namespace xml { + +const string testBigDoc = "\nSearch ResultssearchAn empty app templatenewadmin@example.comJan 01, 2012Sample appAn empty test apptestadmin@example.comJan 01, 2012Sample appCheck my public social datame360admin@example.comApr 28, 2012Sample appnearmenearmeadmin@example.comJan 01, 2012Sample appnearme2nearme2admin@example.comJan 01, 2012Sample appOur photos of an eventourphotosadmin@example.comJan 01, 2012Sample appMy online storeshoppingcartadmin@example.comJan 01, 2012Sample appSlicesliceadmin@example.comJan 01, 2012Sample appTest animation componentstestanimationadmin@example.comJan 01, 2012Sample appTest database componentstestdbadmin@example.comJan 01, 2012Sample appTest event componentstesteventsadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest logic componentstestlogicadmin@example.comJan 01, 2012Sample appTest search componentstestsearchadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest social componentstestsocialadmin@example.comJan 01, 2012Sample appTest text processing componentstesttextadmin@example.comJan 01, 2012Sample appTest URL componentstesturladmin@example.comJan 01, 2012Sample appTest values and liststestvaluesadmin@example.comJan 01, 2012Sample appTest widgetstestwidgetsadmin@example.comJan 01, 2012Sample appTest more widgetstestwidgets2admin@example.comJan 01, 2012Sample appTest HTML generator componentstestwidgets3admin@example.comJan 01, 2012Sample appjsdtestjsdtestjsdelfinoJul 27, 2012Test appSMS send servicetwsmsadmin@example.comJan 01, 2012Sample appboaoboaojsdelfino2012-10-12T12:06:59+00:00Sample appAn empty test apptestadmin@example.comJan 01, 2012Sample appAn empty app templatenewadmin@example.comJan 01, 2012Sample appnearmenearmeadmin@example.comJan 01, 2012Sample appnearme2nearme2admin@example.comJan 01, 2012Sample appOur photos of an eventourphotosadmin@example.comJan 01, 2012Sample appMy online storeshoppingcartadmin@example.comJan 01, 2012Sample appSlicesliceadmin@example.comJan 01, 2012Sample appTest animation componentstestanimationadmin@example.comJan 01, 2012Sample appTest database componentstestdbadmin@example.comJan 01, 2012Sample appTest event componentstesteventsadmin@example.comJan 01, 2012Sample appTest social componentstestsocialadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest logic componentstestlogicadmin@example.comJan 01, 2012Sample appTest search componentstestsearchadmin@example.comJan 01, 2012Sample appTest HTTP componentstesthttpadmin@example.comJan 01, 2012Sample appTest text processing componentstesttextadmin@example.comJan 01, 2012Sample appTest URL componentstesturladmin@example.comJan 01, 2012Sample appTest values and liststestvaluesadmin@example.comJan 01, 2012Sample appTest widgetstestwidgetsadmin@example.comJan 01, 2012Sample appTest more widgetstestwidgets2admin@example.comJan 01, 2012Sample appTest HTML generator componentstestwidgets3admin@example.comJan 01, 2012Sample apptest9test9jsdelfino2012-09-25T06:17:18+00:00Sample appSMS send servicetwsmsadmin@example.comJan 01, 2012Sample appCheck my public social datame360admin@example.comApr 28, 2012Sample app\n"; + +} +} + diff --git a/sca-cpp/trunk/modules/xml/xml.hpp b/sca-cpp/trunk/modules/xml/xml.hpp new file mode 100644 index 0000000000..0a04d5f90a --- /dev/null +++ b/sca-cpp/trunk/modules/xml/xml.hpp @@ -0,0 +1,418 @@ +/* + * 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_xml_hpp +#define tuscany_xml_hpp + +/** + * XML read/write functions. + */ + +#include +#include +#include +#include +#include "string.hpp" +#include "list.hpp" +#include "stream.hpp" +#include "value.hpp" +#include "element.hpp" +#include "monad.hpp" + +namespace tuscany { +namespace xml { + +/** + * Initializes the libxml2 library. + */ +class XMLParser { +public: + inline XMLParser() { + debug("xml::XMLParser"); + xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup); + xmlInitParser(); + } + + inline ~XMLParser() { + } +} xmlParser; + +/** + * Encapsulates a libxml2 xmlTextReader and its state. + */ +class XMLReader { +public: + enum TokenType { + None = 0, Element = 1, Attribute = 2, Text = 3, EndElement = 15, Identifier = 100, End = 101 + }; + + inline XMLReader(xmlTextReaderPtr xml) : xml(xml), owner(true), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) { + debug("xml::XMLReader::xml"); + xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1); + xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1); + } + + inline XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) { + debug("xml::XMLReader::copy"); + } + + XMLReader& operator=(const XMLReader& r) = delete; + + inline ~XMLReader() { + if (!owner) + return; + xmlTextReaderClose(xml); + xmlFreeTextReader(xml); + } + + /** + * Read the next XML token and return its type. + */ + inline const int read() { + if (tokenType == End) + return tokenType; + if (tokenType == Element) { + isEmptyElement = xmlTextReaderIsEmptyElement(xml); + hasAttributes = xmlTextReaderHasAttributes(xml); + return tokenType = Identifier; + } + if (tokenType == Identifier && hasAttributes && xmlTextReaderMoveToFirstAttribute(xml) == 1) + return tokenType = Attribute; + if (tokenType == Attribute && xmlTextReaderMoveToNextAttribute(xml) == 1) + return tokenType = Attribute; + if (isEmptyElement && (tokenType == Identifier || tokenType == Attribute)) + return tokenType = EndElement; + if (!xmlTextReaderRead(xml)) + return tokenType = End; + return tokenType = xmlTextReaderNodeType(xml); + } + + inline operator xmlTextReaderPtr() const { + return xml; + } + +private: + const xmlTextReaderPtr xml; + const bool owner; + int tokenType; + bool isEmptyElement; + bool hasValue; + bool hasAttributes; +}; + +/** + * Constants used to tag XML tokens. + */ +const value endElement("<"); +const value startElement(">"); + +/** + * Read a value from a text string, automatically detects a boolean or number value. + */ +const value readTextValue(const char* const val) { + if (!strcmp("true", val)) + return value(true); + if (!strcmp("false", val)) + return value(false); + + char e[2]; + double d; + const int n = sscanf(val, "%lg%1s", &d, e); + if (n == 1) + return value(d); + + return value(string(val)); +} + +/** + * Read an XML identifier. + */ +inline const value readIdentifier(XMLReader& reader) { + const char* const name = (const char*)xmlTextReaderConstName(reader); + return name; +} + +/** + * Read XML text. + */ +inline const value readText(XMLReader& reader) { + const char* const val = (const char*)xmlTextReaderConstValue(reader); + return readTextValue(val); +} + +/** + * Read an XML attribute. + */ +inline const value readAttribute(XMLReader& reader) { + const char* const name = (const char*)xmlTextReaderConstName(reader); + const char* const val = (const char*)xmlTextReaderConstValue(reader); + return mklist(attribute, name, readTextValue(val)); +} + +/** + * Read an XML token. + */ +inline const value readToken(XMLReader& reader) { + const int tokenType = reader.read(); + if (tokenType == XMLReader::None || tokenType == XMLReader::End) + return nilValue; + if (tokenType == XMLReader::Element) + return startElement; + if (tokenType == XMLReader::Identifier) + return readIdentifier(reader); + if (tokenType == XMLReader::Attribute) + return readAttribute(reader); + if (tokenType == XMLReader::Text) + return readText(reader); + if (tokenType == XMLReader::EndElement) + return endElement; + return readToken(reader); +} + +/** + * Read a list of values from XML tokens. + */ +inline const list readList(const list& listSoFar, XMLReader& reader) { + const value token = readToken(reader); + if(isNil(token) || endElement == token) + return reverse(listSoFar); + if(startElement == token) + return readList(cons(readList(mklist(element), reader), listSoFar), reader); + return readList(cons(token, listSoFar), reader); +} + +/** + * Read a list of values from a libxml2 XML reader. + */ +inline const list read(XMLReader& reader) { + const value nextToken = readToken(reader); + if (startElement == nextToken) + return mklist(readList(mklist(element), reader)); + return nilListValue; +} + +/** + * Context passed to the read callback function. + */ +class XMLReadContext { +public: + inline XMLReadContext(const list& ilist) : ilist(ilist) { + } + + gc_mutable_ref > ilist; +}; + +/** + * Callback function called by libxml2 to read XML. + */ +inline int readCallback(void *context, char* buffer, int len) { + XMLReadContext& rc = *(XMLReadContext*)context; + if (isNil((const list)rc.ilist)) + return 0; + const list f(fragment(rc.ilist, len)); + const string s(car(f)); + rc.ilist = cdr(f); + memcpy(buffer, c_str(s), length(s)); + return (int)length(s); +} + +/** + * Return true if a list of strings contains an XML document. + */ +inline const bool isXML(const list& ls) { + if (isNil(ls)) + return false; + return substr(car(ls), 0, 5) == " > readElements(const list& ilist) { + debug(ilist, "xml::readElements"); + XMLReadContext cx(ilist); + const xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT); + if (xml == NULL) + return nilListValue; + XMLReader reader(xml); + return read(reader); +} + +/** + * Default encoding used to write XML documents. + */ +const char* const encoding = "UTF-8"; + + +/** + * Write a list of XML element or attribute tokens. + */ +inline const list expandElementValues(const value& n, const list& l) { + if (isNil(l)) + return l; + return cons(value(cons(element, cons(n, isList(car(l))? (list)car(l) : mklist(car(l))))), expandElementValues(n, cdr(l))); +} + +inline const failable writeList(const list& l, const xmlTextWriterPtr xml) { + if (isNil(l)) + return true; + + // Write an attribute + const value token(car(l)); + if (isTaggedList(token, attribute)) { + if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)c_str(string(attributeName(token))), (const xmlChar*)c_str(string(attributeValue(token)))) < 0) + return mkfailure("xmlTextWriterWriteAttribute failed"); + + } else if (isTaggedList(token, element)) { + + // Write an element containing a value + if (elementHasValue(token)) { + const value v = elementValue(token); + if (isList(v)) { + + // Write an element per entry in a list of values + const list e = expandElementValues(elementName(token), v); + writeList(e, xml); + + } else { + + // Write an element with a single value + if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) + return mkfailure("xmlTextWriterStartElement failed"); + + // Write its children + const failable w = writeList(elementChildren(token), xml); + if (!hasContent(w)) + return w; + + if (xmlTextWriterEndElement(xml) < 0) + return mkfailure("xmlTextWriterEndElement failed"); + } + } + else { + + // Write an element + if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) + return mkfailure("xmlTextWriterStartElement failed"); + + // Write its children + const failable w = writeList(elementChildren(token), xml); + if (!hasContent(w)) + return w; + + if (xmlTextWriterEndElement(xml) < 0) + return mkfailure("xmlTextWriterEndElement failed"); + } + } else { + + // Write XML text + if (xmlTextWriterWriteString(xml, (const xmlChar*)c_str(string(token))) < 0) + return mkfailure("xmlTextWriterWriteString failed"); + } + + // Go on + return writeList(cdr(l), xml); +} + +/** + * Write a list of values to a libxml2 XML writer. + */ +inline const failable write(const list& l, const xmlTextWriterPtr xml, bool xmlTag) { + if (xmlTag) { + if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) + return mkfailure("xmlTextWriterStartDocument failed"); + } + + const failable w = writeList(l, xml); + if (!hasContent(w)) + return w; + + if (xmlTag) { + if (xmlTextWriterEndDocument(xml) < 0) + return mkfailure("xmlTextWriterEndDocument failed"); + } + return true; +} + +/** + * Context passed to the write callback function. + */ +template class XMLWriteContext { +public: + inline XMLWriteContext(const lambda& reduce, const R& accum) : reduce(reduce), accum(accum) { + } + + const lambda reduce; + gc_mutable_ref accum; +}; + +/** + * Callback function called by libxml2 to write XML out. + */ +template inline int writeCallback(void *context, const char* buffer, int len) { + XMLWriteContext& cx = *(XMLWriteContext*)context; + cx.accum = cx.reduce(string(buffer, len), cx.accum); + return len; +} + +/** + * Convert a list of values to an XML document. + */ +template inline const failable writeElements(const lambda& reduce, const R& initial, const list& l, const bool xmlTag) { + XMLWriteContext cx(reduce, initial); + xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback, NULL, &cx, NULL); + if (out == NULL) + return mkfailure("xmlOutputBufferCreateIO failed"); + xmlTextWriterPtr xml = xmlNewTextWriter(out); + if (xml == NULL) + return mkfailure("xmlNewTextWriter failed"); + xmlTextWriterSetIndent(xml, 0); + + const failable w = write(l, xml, xmlTag); + xmlFreeTextWriter(xml); + if (!hasContent(w)) { + return mkfailure(w); + } + return (R)cx.accum; +} + +template inline const failable writeElements(const lambda& reduce, const R& initial, const list& l) { + return writeElements(reduce, initial, l, true); +} + +/** + * Convert a list of values to a list of strings representing an XML document. + */ +inline const failable > writeElements(const list& l, const bool xmlTag) { + debug(l, "xml::writeElements"); + const failable > ls = writeElements >(rcons, list(), l, xmlTag); + if (!hasContent(ls)) + return ls; + return reverse(list(content(ls))); +} + +inline const failable > writeElements(const list& l) { + return writeElements(l, true); +} + +} +} +#endif /* tuscany_xml_hpp */ diff --git a/sca-cpp/trunk/modules/xml/xsd-test.cpp b/sca-cpp/trunk/modules/xml/xsd-test.cpp new file mode 100644 index 0000000000..b10ad27379 --- /dev/null +++ b/sca-cpp/trunk/modules/xml/xsd-test.cpp @@ -0,0 +1,107 @@ +/* + * 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$ */ + +/** + * Test validation of a composite file against an SCDL schema. + */ + +#include "string.hpp" +#include "fstream.hpp" +#include +#include + +namespace tuscany { + +const bool printNode(xmlTextReaderPtr reader) { + const xmlChar* name = xmlTextReaderConstName(reader); + if(name == NULL) + name = (xmlChar *)""; + const xmlChar* const value = xmlTextReaderConstValue(reader); + cerr << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " + << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); + if(value == NULL) + cerr << endl; + else + cerr << value << endl; + return true; +} + +int xmlRead(void *context, char* buffer, int len) { + return (int)fread(buffer, 1, len, (FILE*)context); +} + +int xmlClose(void *context) { + fclose((FILE*)context); + return 0; +} + +const bool readFile(const char* const xsdfilename, const char* const filename) { + cout << "Loading schema " << xsdfilename << endl; + const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET); + const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc); + const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx); + const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); + + cout << "Reading file " << filename << endl; + FILE* const file = fopen(filename, "r"); + if (file != NULL) { + const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET); + xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1); + xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1); + + if(reader != NULL) { + xmlTextReaderSchemaValidateCtxt(reader, validctx, 0); + + int rc; + while((rc = xmlTextReaderRead(reader)) == 1) { + printNode(reader); + } + if(xmlTextReaderIsValid(reader) != 1) + cout << "Could not validate document" << endl; + xmlFreeTextReader(reader); + if(rc != 0) + cout << "Could not parse document" << endl; + } else + cout << "Could not create parser" << endl; + } else + cout << "Could not open document" << endl; + + xmlSchemaFreeValidCtxt(validctx); + xmlSchemaFree(xsd); + xmlSchemaFreeParserCtxt(xsdctx); + + return true; +} + +} + +int main(const int argc, const char** const argv) { + tuscany::cout << "Testing..." << tuscany::endl; + if(argc != 3) + return 1; + + tuscany::readFile(argv[1], argv[2]); + + xmlCleanupParser(); + + tuscany::cout << "OK" << tuscany::endl; + return 0; +} -- cgit v1.2.3