diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 03:51:03 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2012-12-11 03:51:03 +0000 |
commit | ae0b7c0063db6236be2d7cf01ddbf2159f77c98c (patch) | |
tree | 2f64d65d018634b8728623e2ca99514541fab8aa /sca-cpp | |
parent | 1f3796522a078dda5906395ba471d151ad694b6b (diff) |
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
Diffstat (limited to 'sca-cpp')
55 files changed, 2977 insertions, 2270 deletions
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<int(const int)> csquarel() { - return tuscany::lambda<int(const int)>(tuscany::test::cppsquare); + const tuscany::lambda<const int(const int)> csquarel() { + return tuscany::lambda<const int(const int)>(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<void*>(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<void*> open(const string& name) { + void * h = dlopen(c_str(name), RTLD_NOW); + return h != NULL? failable<void*>(h) : mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror()); + } + template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l); - string name; - failable<void*> h; - bool owner; + const string name; + const failable<void*> h; + const bool owner; }; /** * Find a lambda function in a dynamic library. */ -template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) { +template<typename S> inline const failable<lambda<S> > dynlambda(const string& name, const lib& l) { if (!hasContent(l.h)) return mkfailure<lambda<S>>(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<value>(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<value>(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<value>& l) { +inline const value attributeName(const list<value>& l) { return cadr(l); } /** * Returns the value of an attribute. */ -const value attributeValue(const list<value>& l) { +inline const value attributeValue(const list<value>& l) { return caddr(l); } /** * Returns the name of an element. */ -const value elementName(const list<value>& l) { +inline const value elementName(const list<value>& l) { return cadr(l); } /** * Returns true if an element has children. */ -const bool elementHasChildren(const list<value>& l) { +inline const bool elementHasChildren(const list<value>& l) { return !isNil(cddr(l)); } /** * Returns the children of an element. */ -const list<value> elementChildren(const list<value>& l) { +inline const list<value> elementChildren(const list<value>& l) { return cddr(l); } /** * Returns true if an element has a value. */ -const bool elementHasValue(const list<value>& l) { +inline const bool elementHasValue(const list<value>& l) { const list<value> r = reverse(l); if (isSymbol(car(r))) return false; @@ -107,26 +107,26 @@ const bool elementHasValue(const list<value>& l) { /** * Returns the value of an element. */ -const value elementValue(const list<value>& l) { +inline const value elementValue(const list<value>& 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<value> l = v; return (isNil(l) || !isSymbol(car(l))); } -const value elementToValue(const value& t) { +inline const value elementToValue(const value& t) { const list<value> elementsToValues(const list<value>& e); // Convert an attribute if (isTaggedList(t, attribute)) - return mklist<value>(c_str(atsign + attributeName(t)), attributeValue(t)); + return mklist<value>(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<value> l = v; @@ -166,7 +166,7 @@ const bool elementToValueIsSymbol(const value& v) { return true; } -const list<value> elementToValueGroupValues(const value& v, const list<value>& l) { +inline const list<value> elementToValueGroupValues(const value& v, const list<value>& l) { if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) return cons(v, l); if (car<value>(car(l)) != car<value>(v)) @@ -180,7 +180,7 @@ const list<value> elementToValueGroupValues(const value& v, const list<value>& l } -const list<value> elementsToValues(const list<value>& e) { +inline const list<value> elementsToValues(const list<value>& e) { if (isNil(e)) return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); @@ -189,13 +189,13 @@ const list<value> elementsToValues(const list<value>& e) { /** * Convert a value to an element. */ -const value valueToElement(const value& t) { +inline const value valueToElement(const value& t) { const list<value> valuesToElements(const list<value>& l); // Convert a name value pair if (isList(t) && !isNil((list<value>)t) && isSymbol(car<value>(t))) { const value n = car<value>(t); - const value v = isNil(cdr<value>(t))? value() : cadr<value>(t); + const value v = isNil(cdr<value>(t))? nilValue : cadr<value>(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<value> valuesToElements(const list<value>& l) { +inline const list<value> valuesToElements(const list<value>& l) { if (isNil(l)) return l; return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l))); @@ -231,72 +231,51 @@ const list<value> valuesToElements(const list<value>& l) { * Returns a selector lambda function which can be used to filter * elements against the given element pattern. */ -struct selectorLambda { - const list<value> select; - selectorLambda(const list<value>& s) : select(s) { - } - const bool evalSelect(const list<value>& s, const list<value> 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<const bool(const value&)> selector(const list<value>& select) { + return [select](const value& v) -> const bool { + const lambda<const bool(const list<value>&, const list<value>&)> evalSelect = [&evalSelect](const list<value>& s, const list<value>& 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<bool(const value&)> selector(const list<value> 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<value>)v) == name; - } -}; - -const value attributeValue(const value& name, const value& l) { - const list<value> f = filter<value>(filterAttribute(name), list<value>(l)); +inline const value attributeValue(const value& name, const value& l) { + const list<value> f = filter<value>([name](const value& v) { + return isAttribute(v) && attributeName((list<value>)v) == name; + }, list<value>(l)); if (isNil(f)) - return value(); + return nilValue; return caddr<value>(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<value>)v) == name; - } -}; - -const value elementChildren(const value& name, const value& l) { - return filter<value>(filterElement(name), list<value>(l)); +inline const value elementChildren(const value& name, const value& l) { + return filter<value>([name](const value& v) { + return isElement(v) && elementName((list<value>)v) == name; + }, list<value>(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<value> 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<typename V> const bool debugLog(const V& v, const string& msg) { - gc_scoped_pool p; +template<typename V> 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<typename V> const bool debugLog(const V& v, const string& msg) { /** * Log a debug message and two values. */ -template<typename V, typename W> const bool debugLog(const V& v, const W& w, const string& msg) { - gc_scoped_pool p; +template<typename V, typename W> 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 <utility> @@ -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<typename R, typename... P> 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<typename F> class Proxy: public Callable { + template<typename F> class Proxy: public Callable<R, P...> { 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>(p)...); - } - - virtual const size_t size() const { - return sizeof(function); + virtual const R operator() (const P&&... p) const noexcept { + return function(std::forward<const P&&>(p)...); } private: @@ -123,67 +119,68 @@ template<typename S> class lambda; template<typename R, typename... P> class lambda<R(P...)> { public: - lambda() : callable(0) { + inline lambda() noexcept : callable(NULL) { debug_inc(countLambdas); debug_inc(countELambdas); } - template<typename F> lambda(const F f) { + template<typename F> inline lambda(const F f) noexcept : callable(mkproxy<F>(f)) { debug_inc(countLambdas); debug_inc(countFLambdas); + } - typedef typename CallableType::template Proxy<F> ProxyType; - callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f)); + template<typename F> inline lambda(const gc_mutable_ref<F>& r) noexcept : callable(mkproxy<F>(*(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>(p)...); + inline const R operator()(const P&... p) const noexcept { + return (*callable)(std::forward<const P&&>(p)...); } template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&); - template<typename S> friend const bool isNil(const lambda<S>& l); + template<typename S> friend const bool isNil(const lambda<S>& l) noexcept; private: typedef Callable<R,P...> CallableType; - gc_ptr<CallableType> callable; + const gc_ptr<CallableType> callable; + + template<typename F> inline gc_ptr<CallableType> mkproxy(const F& f) noexcept { + typedef typename CallableType::template Proxy<F> ProxyType; + return gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f)); + } }; -template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) { +template<typename S> inline ostream& operator<<(ostream& out, const lambda<S>& l) { return out << "lambda::" << l.callable; } /** * Return true if a lambda is nil. */ -template<typename S> const bool isNil(const lambda<S>& l) { - return ((void*)l.callable) == 0; +template<typename S> inline const bool isNil(const lambda<S>& l) noexcept { + return (const void*)l.callable == NULL; } /** @@ -191,11 +188,11 @@ template<typename S> const bool isNil(const lambda<S>& l) { */ template<typename R, typename T, typename... P> class curried { public: - curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) { + inline curried(const lambda<R(T, P...)>& f, const T& v) noexcept: v(v), f(f) { } - const R operator()(P... p) const { - return f(v, std::forward<P>(p)...); + inline const R operator()(const P&... p) const noexcept { + return f(v, std::forward<const P&>(p)...); } private: @@ -203,36 +200,29 @@ private: const lambda<R(T, P...)>f; }; -template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) { +template<typename R, typename T, typename... P> inline const lambda<const R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) noexcept { return curried<R, T, P...>(f, t); } -template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) { +template<typename R, typename T, typename U, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) noexcept { return curry(curry(f, t), u); } -template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) { +template<typename R, typename T, typename U, typename V, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& 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<typename T> class returnResult { -public: - returnResult(const T& v) : - v(v) { - } - const T operator()() const { - return v; - } -private: - const T v; -}; - -template<typename T> const lambda<T()> result(const T& v) { - return returnResult<T> (v); +template<typename T> inline const lambda<const T()> result(const T& v) { + return [v]()->T { return v; }; } +/** + * Commonly used lambda types. + */ +typedef lambda<const bool()> 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<typename T> using gc_ptr = T*; + +#else + template<typename T> 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<typename T> using gc_mutable_ptr = T*; + +#else + +template<typename T> 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<apr_pool_t*>(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<typename T> apr_status_t gc_pool_cleanup(void* v) { +template<typename T> inline apr_status_t gc_pool_cleanup(void* v) { T* t = (T*)v; t->~T(); return APR_SUCCESS; } -template<typename T> T* gc_new(apr_pool_t* p) { +template<typename T> 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<T>, apr_pool_cleanup_null) ; return (T*)(gc_new_ptr); } -template<typename T> T* gc_new(const gc_pool& p) { +template<typename T> inline T* const gc_new(const gc_pool& p) noexcept { return gc_new<T>(pool(p)); } -template<typename T> T* gc_new() { +template<typename T> inline T* const gc_new() noexcept { return gc_new<T>(gc_current_pool()); } -template<typename T> apr_status_t gc_pool_acleanup(void* v) { - size_t* m = static_cast<size_t*>(v); +template<typename T> 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<typename T> apr_status_t gc_pool_acleanup(void* v) { return APR_SUCCESS; } -template<typename T> T* gc_anew(apr_pool_t* p, size_t n) { - size_t* gc_anew_ptr = static_cast<size_t*>(apr_palloc(p, sizeof(size_t) + sizeof(T) * n)); +template<typename T> 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<T>, apr_pool_cleanup_null) ; return (T*)(gc_anew_ptr + 1); } -template<typename T> T* gc_anew(const gc_pool& p, size_t n) { +template<typename T> inline T* const gc_anew(const gc_pool& p, const size_t n) noexcept { return gc_anew<T>(pool(p), n); } -template<typename T> T* gc_anew(size_t n) { +template<typename T> inline T* const gc_anew(const size_t n) noexcept { return gc_anew<T>(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<char*>(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<typename T> class gc_mutable_ref { +public: + inline gc_mutable_ref() noexcept : ptr(new (gc_new<T>()) 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>()) 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>()) 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<size_t*>(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<size_t*>(ptr) - 1); - size_t* rptr = static_cast<size_t*>(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<char*>(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<size_t*>(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<size_t*>(ptr) - 1); - size_t* rptr = static_cast<size_t*>(mremap(static_cast<size_t*>(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<size_t*>(ptr) - 1); - munmap(static_cast<size_t*>(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<bool()> crc32 = crc32hashTest(key); - cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl; - const lambda<bool()> times33 = times33hashTest(key); - cout << "times33hash test " << time(times33, 5, count) << " ms" << endl; - const lambda<bool()> murmur = murmurhashTest(key); - cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl; - const lambda<bool()> 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 <rse@engelschall.com> */ -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 <functional> #include <assert.h> #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<int> 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<int(const int)> f, int v) { +const int mapLambda(lambda<const int(const int)> f, int v) { return f(v); } -bool testLambda() { - const lambda<int(const int)> sq(square); +const lambda<const int(const int)> mksquare() { + return square; +} + +const bool testSizes() { + const gc_ptr<int> p(NULL); + cout << "sizeof gc_ptr " << sizeof(p) << endl; + const lambda<const int(const int)> sq(square); + cout << "sizeof C function lambda " << sizeof(sq) << endl; + const lambda<const int(const int)> incl(incFunctor(10)); + cout << "sizeof functor lambda " << sizeof(incl) << endl; + const std::function<int(const int)> sqf(square); + cout << "sizeof C function std::function " << sizeof(sqf) << endl; + const std::function<int(const int)> 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<int> li = cons<int>(2, mklist<int>(3, 4)); + cout << "sizeof list<int> " << sizeof(li) << endl; + const list<string> ls = cons<string>("a", mklist<string>("b", "c")); + cout << "sizeof list<string> " << sizeof(ls) << endl; + const list<value> lv = cons<value>("a", mklist<value>("b", "c")); + cout << "sizeof list<value> " << sizeof(lv) << endl; + return true; +} + +const bool testLambda() { + const lambda<const int(const int)> sq(square); assert(sq(2) == 4); + + const lambda<const lambda<const int(const int)>()> mksq(mksquare); + assert(mksq()(2) == 4); + assert(mapLambda(sq, 2) == 4); assert(mapLambda(square, 2) == 4); - const lambda<int(const int)> incf(inc(10)); + const lambda<const int(const int)> 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<const int(const int)> incl(incl11); + assert(incl(1) == 11); + assert(mapLambda(incl, 1) == 11); + assert(mapLambda(incl11, 1) == 11); + + const lambda<const int(const int)> il(incf); + assert(il(1) == 11); + const lambda<const int(const int)> 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<int(const int)> l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); return true; } -bool testLambdaGC() { +const bool testMutable() { + { + gc_mutable_ref<string> s = string("aaa"); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref<string> s; + assert(s == ""); + s = "bbb"; + assert(s == "bbb"); + } + { + gc_mutable_ref<value> 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<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)mult, sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool curryPerf() { + const sint a(2); + const sint b(3); + const lambda<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)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<const int(const sint)> mult2 = multFunctor(sint(2)); + assert(6 == mult2(sint(3))); + return true; +} + +const bool functorPerf() { + const sint a(2); + const sint b(3); + const lambda<const int(const sint)> mult2 = lambda<const int(const sint)>(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<const sint(const sint)> 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<const sint(const sint)> mult2 = multlambda11(a); + for(int i = 0; i < 1000; i++) + mult2(b); + return true; +} + +const std::function<sint(const sint&)> 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<sint(const sint&)> 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<typename T> const list<T> listPerf(const T& v, const long int i) { + if (i == 0) + return list<T>(); + return cons<T>(v, listPerf<T>(v, i -1)); +} + +const bool testListPerf() { + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<int>(0, 1000); + return true; + }; + cout << "List<int> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<string>(string("x"), 1000); + return true; + }; + cout << "List<string> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + { + const gc_scoped_pool gcp; + const blambda lp = []() -> const bool { + listPerf<string>(value("x"), 1000); + return true; + }; + cout << "List<value> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl; + } + return true; +} + +const bool testOut() { ostringstream os1; os1 << list<int> (); assert(str(os1) == "()"); @@ -147,7 +451,7 @@ bool testOut() { return true; } -bool testEquals() { +const bool testEquals() { assert(list<int>() == list<int>()); assert(mklist(1, 2) == mklist(1, 2)); assert(list<int>() != mklist(1, 2)); @@ -156,14 +460,14 @@ bool testEquals() { return true; } -bool testLength() { +const bool testLength() { assert(0 == length(list<int>())); 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<Complex> 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<int, int>(square, list<int>()))); const list<int> m = map<int, int>(square, mklist(2, 3)); @@ -209,26 +515,26 @@ const int add(const int x, const int y) { return x + y; } -bool testReduce() { - const lambda<int(const int, const int)> r(add); +const bool testReduce() { + const lambda<const int(const int, const int)> 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<int>(isPositive, mklist(1, -1, 2, -2))) == 1); assert(cadr(filter<int>(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<int>()))); 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<list<string> > l = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA")); assert(assoc<string>("a", l) == mklist<string>("a", "A")); assert(isNil(assoc<string>("z", l))); @@ -261,10 +567,13 @@ bool testAssoc() { const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); assert(assoc<value>("a", v) == mklist<value>("a", "A")); + + const list<value> v2 = mklist<value>(mklist<value>("x", "X"), "a", mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); + assert(assoc<value>("a", v2) == mklist<value>("a", "A")); return true; } -bool testZip() { +const bool testZip() { const list<string> k = mklist<string>("x", "a", "y", "a"); const list<string> v = mklist<string>("X", "A", "Y", "AA"); const list<list<string> > z = mklist(k, v); @@ -274,7 +583,7 @@ bool testZip() { return true; } -bool testTokenize() { +const bool testTokenize() { assert(tokenize("/", "") == list<string>()); assert(tokenize("/", "aaa") == mklist<string>("aaa")); assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("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<value> x) { +const value valueSquare(const list<value>& 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<value(const list<value>&)> vl(valueSquare); - assert(value(vl) == value(vl)); + lvvlambda vl(valueSquare); + //assert(value(vl) == value(vl)); assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2))); const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("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<value> t = mktree<value>("a", list<value>(), list<value>()); +const bool testTree() { + const list<value> t = mktree<value>("a", nilListValue, nilListValue); const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t))))); const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a")); assert(mt == ct); @@ -371,8 +680,8 @@ const list<value> lta(const string& x) { return mklist<value>(c_str(x), c_str(x + x)); } -bool testTreeAssoc() { - const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>()); +const bool testTreeAssoc() { + const list<value> t = mktree<value>(lta("a"), nilListValue, nilListValue); const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t))))); const list<value> l = flatten<value>(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<double> s = seq(0.0, 999.0); - list<double> r = map<double, double>(fib, s); - assert(1000 == length(r)); - return true; - } -}; - -struct nestedFibMapPerf { - const lambda<double(const double)> fib; - nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) { - } - const bool operator()() const { - list<double> s = seq(0.0, 999.0); - list<double> r = map<double, double>(fib, s); - assert(1000 == length(r)); - return true; - } -}; +const bool fibMapPerf() { + const list<double> s = seq(0.0, 999.0); + const list<double> r = map<double, double>(fib, s); + assert(1000 == length(r)); + return true; +} -bool testCppPerf() { +const bool testCppPerf() { { - const lambda<bool()> 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<const double(const double n)> fib = [](const double n) -> const double { + const lambda<const double(const double, const double, const double)> 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<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib)); + const blambda nfml = [fib]() -> const bool { + const list<double> s = seq(0.0, 999.0); + const list<double> r = map<double, double>(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<int> idH(const int v) { return idF(v) >> idG; } -bool testIdMonad() { +const bool testIdMonad() { const id<int> m(2); assert(m >> idF == idF(2)); assert(m >> unit<int>() == m); @@ -476,7 +773,7 @@ const maybe<int> maybeH(const int v) { return maybeF(v) >> maybeG; } -bool testMaybeMonad() { +const bool testMaybeMonad() { const maybe<int> m(2); assert(m >> maybeF == maybeF(2)); assert((m >> just<int>()) == m); @@ -498,7 +795,7 @@ const failable<int> failableH(const int v) { return failableF(v) >> failableG; } -bool testFailableMonad() { +const bool testFailableMonad() { const failable<int> m(2); assert(m >> failableF == failableF(2)); assert((m >> success<int, string, int>()) == m); @@ -515,23 +812,16 @@ bool testFailableMonad() { assert(rcode(vooops) == 500); const value v = value(vooops); - assert(car<value>(v) == value()); + assert(car<value>(v) == nilValue); assert(cadr<value>(v) == string("test")); assert(caddr<value>(v) == value((double)500)); return true; } -struct tickInc { - const double v; - tickInc(const double v) : v(v) { - } - const scp<int, double> operator()(int s) const { - return scp<int, double>(s + 1, v); - } -}; - const state<int, double> tick(const double v) { - return transformer<int, double>(tickInc(v)); + return transformer<int, double>([v](const int s) { + return scp<int, double>(s + 1, v); + }); } const state<int, double> stateF(const double v) { @@ -546,8 +836,8 @@ const state<int, double> stateH(const double v) { return stateF(v) >> stateG; } -bool testStateMonad() { - const lambda<state<int, double>(const double)> r(result<int, double>); +const bool testStateMonad() { + const lambda<const state<int, double>(const double)> r(result<int, double>); state<int, double> m = result<int, double>(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<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl)); + const failable<lambda<const int(const int)> > sq(dynlambda<const int(const int)>("csquare", dl)); assert(hasContent(sq)); - lambda<int(const int)> l(content(sq)); + lambda<const int(const int)> l(content(sq)); assert(l(2) == 4); - const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl)); + const failable<lambda<const lambda<const int(const int)>()> > sql(dynlambda<const lambda<const int(const int)>()>("csquarel", dl)); assert(hasContent(sql)); - lambda<lambda<int(const int)>()> ll(content(sql)); + lambda<const lambda<const int(const int)>()> 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<const int(const int)> 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<const int(const int)> f, int v) { +const int mapLambda(const lambda<const int(const int)> f, int v) { return f(v); } -bool testLambda() { +const bool testLambda() { const lambda<const int(const int)> 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<int(int)> incf = inc(10); + const lambda<const int(const int)> incf = inc(10); assert(incf(1) == 11); assert(mapLambda(incf, 1) == 11); assert(mapLambda(inc(10), 1) == 11); - lambda<const int(const int)> l; - l = incf; - assert(l(1) == 11); - l = square; - assert(l(2) == 4); + const lambda<const int(const int)> il(incf); + assert(il(1) == 11); + const lambda<const int(const int)> 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<double> s = seq(0.0, 4999.0); - list<double> r = map<double, double>([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s); + const list<double> s = seq(0.0, 4999.0); + const list<double> r = map<double, double>([](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<typename T> class list { public: - list() { + inline list() : car() { debug_inc(countLists); debug_inc(countELists); debug_watchList(); } - list(const T car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) { + inline list(const T& car, const lambda<list<T>()>& 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<T>& operator=(const list<T>& p) { - if(this == &p) - return *this; - car = p.car; - cdr = p.cdr; -#ifdef WANT_MAINTAINER_WATCH - watch = p.watch; -#endif - return *this; - } + list<T>& operator=(const list<T>& p) = delete; - ~list() { + inline ~list() { debug_dec(countLists); } - const bool operator==(const list<T>& p) const { + inline const bool operator==(const list<T>& p) const { if(this == &p) return true; if(isNil(cdr)) @@ -140,7 +131,7 @@ public: return cdr() == p.cdr(); } - const bool operator<(const list<T>& p) const { + inline const bool operator<(const list<T>& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -154,7 +145,7 @@ public: return cdr() < p.cdr(); } - const bool operator>(const list<T>& p) const { + inline const bool operator>(const list<T>& p) const { if(this == &p) return false; if (isNil(cdr)) @@ -168,11 +159,11 @@ public: return cdr() > p.cdr(); } - const bool operator!=(const list<T>& p) const { + inline const bool operator!=(const list<T>& p) const { return !this->operator==(p); } - operator const list<list<T> >() const { + inline operator const list<list<T> >() const { return (list<list<T> >)T(*this); } @@ -185,9 +176,10 @@ private: template<typename X> friend const bool isNil(const list<X>& p); template<typename X> friend const X car(const list<X>& p); template<typename X> friend const list<X> cdr(const list<X>& p); + template<typename X> friend const bool setlist(list<X>& target, const list<X>& l); - T car; - lambda<list<T>()> cdr; + const T car; + const lambda<list<T>()> 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<typename T> const string watchList(const list<T>& p) { +template<typename T> inline const string watchList(const list<T>& p) { if(isNil(p)) return "()"; odebugstream os; @@ -209,21 +201,21 @@ template<typename T> const string watchList(const list<T>& p) { /** * Returns true if the given list is nil. */ -template<typename T> const bool isNil(const list<T>& p) { +template<typename T> inline const bool isNil(const list<T>& p) { return isNil(p.cdr); } /** * Write a list to an output stream. */ -template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) { +template<typename T> inline ostream& writeHelper(ostream& out, const list<T>& l) { if (isNil(l)) return out; out << " " << car(l); return writeHelper(out, cdr(l)); } -template<typename T> ostream& operator<<(ostream& out, const list<T>& l) { +template<typename T> inline ostream& operator<<(ostream& out, const list<T>& l) { if(isNil(l)) return out << "()"; out << "(" << car(l); @@ -234,74 +226,74 @@ template<typename T> ostream& operator<<(ostream& out, const list<T>& l) { /** * Construct a (lazy) list from a value and a lambda function that returns the cdr. */ -template<typename T> const list<T> cons(const T& car, const lambda<list<T>()>& cdr) { +template<typename T> inline const list<T> cons(const T& car, const lambda<const list<T>()>& cdr) { return list<T> (car, cdr); } /** * Construct a list from a value and a cdr list. */ -template<typename T> const list<T> cons(const T& car, const list<T>& cdr) { +template<typename T> inline const list<T> cons(const T& car, const list<T>& cdr) { return list<T> (car, result(cdr)); } /** * Cons variations for use with the reduce and reduceRight functions. */ -template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) { +template<typename T> inline const list<T> lcons(const list<T>& cdr, const T& car) { return cons<T>(car, cdr); } -template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) { +template<typename T> inline const list<T> rcons(const T& car, const list<T>& cdr) { return cons<T>(car, cdr); } /** * Construct a list of one value. */ -template<typename T> const list<T> mklist(const T& car) { +template<typename T> inline const list<T> mklist(const T& car) { return list<T> (car, result(list<T> ())); } /** * Construct a list of two values. */ -template<typename T> const list<T> mklist(const T& a, const T& b) { +template<typename T> inline const list<T> mklist(const T& a, const T& b) { return cons(a, mklist(b)); } /** * Construct a list of three values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c) { +template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c) { return cons(a, cons(b, mklist(c))); } /** * Construct a list of four values. */ -template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d) { +template<typename T> inline const list<T> 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<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) { +template<typename T> inline const list<T> 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<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) { +template<typename T> inline const list<T> 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<typename T> const T car(const list<T>& p) { +template<typename T> inline const T car(const list<T>& p) { // Abort if trying to access the car of a nil list assertOrFail(!isNil(p.cdr)); return p.car; @@ -310,159 +302,144 @@ template<typename T> const T car(const list<T>& p) { /** * Returns the cdr of a list. */ -template<typename T> const list<T> cdr(const list<T>& p) { +template<typename T> inline const list<T> cdr(const list<T>& p) { return p.cdr(); } /** * Returns the car of the cdr (the 2nd element) of a list. */ -template<typename T> const T cadr(const list<T>& p) { +template<typename T> inline const T cadr(const list<T>& p) { return car(cdr(p)); } /** * Returns the 3rd element of a list. */ -template<typename T> const T caddr(const list<T>& p) { +template<typename T> inline const T caddr(const list<T>& p) { return car(cdr(cdr(p))); } /** * Returns the 4th element of a list. */ -template<typename T> const T cadddr(const list<T>& p) { +template<typename T> inline const T cadddr(const list<T>& p) { return car(cdr(cdr(cdr(p)))); } /** * Returns the 5th element of a list. */ -template<typename T> const T caddddr(const list<T>& p) { +template<typename T> inline const T caddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(p))))); } /** * Returns the 6th element of a list. */ -template<typename T> const T cadddddr(const list<T>& p) { +template<typename T> inline const T cadddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns the 7th element of a list. */ -template<typename T> const T caddddddr(const list<T>& p) { +template<typename T> inline const T caddddddr(const list<T>& p) { return car(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the 8th element of a list. */ -template<typename T> const T cadddddddr(const list<T>& p) { +template<typename T> inline const T cadddddddr(const list<T>& 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<typename T> const list<T> cddr(const list<T>& p) { +template<typename T> inline const list<T> cddr(const list<T>& p) { return cdr(cdr(p)); } /** * Returns a list of elements from the 4th to the end of a list. */ -template<typename T> const list<T> cdddr(const list<T>& p) { +template<typename T> inline const list<T> cdddr(const list<T>& p) { return cdr(cdr(cdr(p))); } /** * Returns a list of elements from the 5th to the end of a list. */ -template<typename T> const list<T> cddddr(const list<T>& p) { +template<typename T> inline const list<T> cddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(p)))); } /** * Returns a list of elements from the 6th to the end of a list. */ -template<typename T> const list<T> cdddddr(const list<T>& p) { +template<typename T> inline const list<T> cdddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(p))))); } /** * Returns a list of elements from the 7th to the end of a list. */ -template<typename T> const list<T> cddddddr(const list<T>& p) { +template<typename T> inline const list<T> cddddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(cdr(p)))))); } /** * Returns a list of elements from the 8th to the end of a list. */ -template<typename T> const list<T> cdddddddr(const list<T>& p) { +template<typename T> inline const list<T> cdddddddr(const list<T>& p) { return cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))); } /** * Returns the length of a list. */ -template<typename T> struct lengthRef { - const size_t operator()(const size_t c, const list<T>& p) { +template<typename T> inline const size_t length(const list<T>& p) { + const lambda<size_t(const size_t, const list<T>&)> lengthRef = [&lengthRef](const size_t c, const list<T>& p) -> const size_t { if(isNil(p)) return c; - return (*this)(c + 1, cdr(p)); - } -}; - -template<typename T> const size_t length(const list<T>& p) { - return lengthRef<T> ()(0, p); + return lengthRef(c + 1, cdr(p)); + }; + return lengthRef(0, p); } /** * Appends a list and a lambda function returning a list. */ -template<typename T> struct appendCdr { - const list<T> a; - const lambda<list<T>()> fb; - appendCdr(const list<T>& a, const lambda<list<T>()>& fb) : - a(a), fb(fb) { - } - const list<T> operator()() const { - return append(a, fb); - } -}; - -template<typename T> const list<T> append(const list<T>&a, const lambda<list<T>()>& fb) { +template<typename T> inline const list<T> append(const list<T>&a, const lambda<const list<T>()>& fb) { if(isNil(a)) return fb(); - - return cons<T>(car(a), appendCdr<T> (cdr(a), fb)); + return cons<T>(car(a), [a, fb]() { return append(cdr(a), fb); }); } /** * Appends two lists. */ -template<typename T> const list<T> append(const list<T>&a, const list<T>& b) { +template<typename T> inline const list<T> append(const list<T>&a, const list<T>& b) { return append(a, result(b)); } /** * Append a value to a list. */ -template<typename T> const list<T> operator+(const list<T>& l, const T& v) { +template<typename T> inline const list<T> operator+(const list<T>& l, const T& v) { return append(l, mklist(v)); } -template<typename T, typename V> const list<T> operator+(const list<T>& l, const V& v) { +template<typename T, typename V> const list<T> inline operator+(const list<T>& l, const V& v) { return append(l, mklist<T>(v)); } /** * Map a lambda function on a list. */ -template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, const list<T>& p) { +template<typename T, typename R> inline const list<R> map(const lambda<const R(const T)>& f, const list<T>& p) { if(isNil(p)) return list<R> (); return cons(f(car(p)), map(f, cdr(p))); @@ -471,46 +448,32 @@ template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, /** * Run a reduce lambda function on a list. */ -template<typename T, typename R> struct reduceAccumulate { - const lambda<R(const R&, const T&)> f; - reduceAccumulate(const lambda<R(const R, const T)>& f) : - f(f) { - } - R operator()(const R& acc, const list<T>& p) const { +template<typename T, typename R> inline const R reduce(const lambda<const R(const R, const T)>& f, const R& initial, const list<T>& p) { + const lambda<const R(const R&, const list<T>&p)> reduceAccumulate = [f, &reduceAccumulate](const R& acc, const list<T>& p) -> R { if(isNil(p)) return acc; - return (*this)(f(acc, car(p)), cdr(p)); - } -}; - -template<typename T, typename R> const R reduce(const lambda<R(const R, const T)>& f, const R& initial, const list<T>& p) { - return reduceAccumulate<T, R> (f)(initial, p); + return reduceAccumulate(f(acc, car(p)), cdr(p)); + }; + return reduceAccumulate(initial, p); } -template<typename T, typename R> struct reduceRightAccumulate { - const lambda<R(const T&, const R&)> f; - reduceRightAccumulate(const lambda<R(const T, const R)>& f) : - f(f) { - } - R operator()(const list<T>& p, const R& acc) const { +template<typename T, typename R> inline const R reduceRight(const lambda<const R(const T, const R)>& f, const R& initial, const list<T>& p) { + const lambda<const R(const list<T>&p, const R&)> reduceRightAccumulate = [f, &reduceRightAccumulate](const list<T>& p, const R& acc) -> R { if(isNil(p)) return acc; - return (*this)(cdr(p), f(car(p), acc)); - } -}; - -template<typename T, typename R> const R reduceRight(const lambda<R(const T, const R)>& f, const R& initial, const list<T>& p) { - return reduceRightAccumulate<T, R> (f)(p, initial); + return reduceRightAccumulate(cdr(p), f(car(p), acc)); + }; + return reduceRightAccumulate(p, initial); } /** * Run a filter lambda function on a list. */ -template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const list<T>& p) { +template<typename T> inline const list<T> filter(const lambda<const bool(const T)>& f, const list<T>& p) { if(isNil(p)) return list<T> (); if(f(car(p))) { - const lambda<list<T>(const lambda<bool(const T)>, const list<T>)> ff(filter<T>); + const lambda<const list<T>(const lambda<const bool(const T)>, const list<T>)> ff(filter<T>); return cons(car(p), curry(ff, f, cdr(p))); } return filter(f, cdr(p)); @@ -519,7 +482,7 @@ template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const /** * Returns a list pointing to a member of a list. */ -template<typename T> const list<T> member(const T& t, const list<T>& p) { +template<typename T> inline const list<T> member(const T& t, const list<T>& p) { if(isNil(p)) return list<T> (); if(t == car(p)) @@ -530,44 +493,31 @@ template<typename T> const list<T> member(const T& t, const list<T>& p) { /** * Reverse a list. */ -template<typename T> const list<T> reverseIter(const list<T>& acc, const list<T>& p) { +template<typename T> inline const list<T> reverseIter(const list<T>& acc, const list<T>& p) { if(isNil(p)) return acc; return reverseIter(cons(car(p), acc), cdr(p)); } -template<typename T> const list<T> reverse(const list<T>& p) { +template<typename T> inline const list<T> reverse(const list<T>& p) { return reverseIter(list<T> (), p); } -template<typename T> const list<T> seq(const T& start, const T& end); - -template<typename T> struct seqGenerate { - const T start; - const T end; - seqGenerate(const T& start, const T&end) : - start(start), end(end) { - } - const list<T> operator()() const { - return seq<T> (start, end); - } -}; - /** * Returns a sequence of values between the given bounds. */ -template<typename T> const list<T> seq(const T& start, const T& end) { +template<typename T> inline const list<T> seq(const T& start, const T& end) { if(start == end) return mklist(start); if(start < end) - return cons<T>(start, seqGenerate<T> (start + 1, end)); - return cons<T>(start, seqGenerate<T> (start - 1, end)); + return cons<T>(start, [start, end] { return seq<T> (start + 1, end); }); + return cons<T>(start, [start, end] { return seq<T> (start - 1, end); }); } /** * Returns the i-th element of a list. */ -template<typename T> const T listRef(const list<T>& l, const size_t i) { +template<typename T> inline const T listRef(const list<T>& l, const size_t i) { if (i == 0) return car(l); return listRef(cdr(l), i - 1); @@ -576,7 +526,7 @@ template<typename T> const T listRef(const list<T>& l, const size_t i) { /** * Returns the first pair matching a key from a list of key value pairs. */ -template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) { +template<typename T> inline const list<T> assoc(const T& k, const list<list<T> >& p) { if(isNil(p)) return list<T> (); if(k == car(car(p))) @@ -587,7 +537,7 @@ template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) { /** * Returns a list of lists containing elements from two input lists. */ -template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b) { +template<typename T> inline const list<list<T> > zip(const list<T>& a, const list<T>& b) { if (isNil(a) || isNil(b)) return list<list<T> >(); return cons<list<T> >(mklist<T>(car(a), car(b)), zip(cdr(a), cdr(b))); @@ -596,19 +546,19 @@ template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b /** * Converts a list of key value pairs to a list containing the list of keys and the list of values. */ -template<typename T> const list<T> unzipKeys(const list<list<T> >& l) { +template<typename T> inline const list<T> unzipKeys(const list<list<T> >& l) { if (isNil(l)) return list<T>(); return cons(car(car(l)), unzipKeys(cdr(l))); } -template<typename T> const list<T> unzipValues(const list<list<T> >& l) { +template<typename T> inline const list<T> unzipValues(const list<list<T> >& l) { if (isNil(l)) return list<T>(); return cons(cadr(car(l)), unzipValues(cdr(l))); } -template<typename T> const list<list<T> > unzip(const list<list<T> >& l) { +template<typename T> inline const list<list<T> > unzip(const list<list<T> >& l) { return mklist<list<T> >(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>()) 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<bool()> 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<bool()> 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 <execinfo.h> #include <cxxabi.h> +#endif + #include "function.hpp" #include "string.hpp" #include "stream.hpp" @@ -43,21 +46,16 @@ namespace tuscany */ template<typename V> class id { public: - id(const V& v) : v(v) { + inline id(const V& v) : v(v) { } - const id<V>& operator=(const id<V>& m) { - if(this == &m) - return *this; - v = m.v; - return *this; - } + id<V>& operator=(const id<V>& m) = delete; - const bool operator!=(const id<V>& m) const { + inline const bool operator!=(const id<V>& m) const { return !this->operator==(m); } - const bool operator==(const id<V>& m) const { + inline const bool operator==(const id<V>& m) const { if (&m == this) return true; return v == m.v; @@ -72,7 +70,7 @@ private: /** * Write an identity monad to a stream. */ -template<typename V> ostream& operator<<(ostream& out, const id<V>& m) { +template<typename V> inline ostream& operator<<(ostream& out, const id<V>& m) { out << content(m); return out; } @@ -80,29 +78,29 @@ template<typename V> ostream& operator<<(ostream& out, const id<V>& m) { /** * Returns the content of an identity monad. */ -template<typename V> const V content(const id<V>& m) { +template<typename V> inline const V content(const id<V>& m) { return m.v; } /** * Return an identity monad from a value. */ -template<typename V> const id<V> mkunit(const V& v) { +template<typename V> inline const id<V> mkunit(const V& v) { return id<V>(v); } -template<typename V> const lambda<id<V>(const V)> unit() { +template<typename V> inline const lambda<const id<V>(const V)> unit() { return mkunit<V>; } /** * Bind a function to an identity monad. Pass the value in the monad to the function. */ -template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(const V)>& f) { +template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const lambda<const id<R>(const V)>& f) { return f(content(m)); } -template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) { +template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) { return f(content(m)); } @@ -112,26 +110,22 @@ template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id */ template<typename V> 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<V>& operator=(const maybe<V>& m) { - if(this == &m) - return *this; - hasv = m.hasv; - if (hasv) - v = m.v; - return *this; + inline maybe(const maybe<V>& m) : hasv(m.hasv), v(m.v) { } - const bool operator!=(const maybe<V>& m) const { + maybe<V>& operator=(const maybe<V>& m) = delete; + + inline const bool operator!=(const maybe<V>& m) const { return !this->operator==(m); } - const bool operator==(const maybe<V>& m) const { + inline const bool operator==(const maybe<V>& m) const { if (this == &m) return true; if (!hasv) @@ -141,7 +135,7 @@ public: private: const bool hasv; - V v; + const V v; template<typename X> friend const bool hasContent(const maybe<X>& m); template<typename X> friend const X content(const maybe<X>& m); @@ -150,7 +144,7 @@ private: /** * Write a maybe monad to a stream. */ -template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) { +template<typename V> inline ostream& operator<<(ostream& out, const maybe<V>& m) { if (!hasContent(m)) { out << "nothing"; return out; @@ -162,25 +156,25 @@ template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) { /** * Return a maybe monad with a value in it. */ -template<typename V> const maybe<V> mkjust(const V& v) { +template<typename V> inline const maybe<V> mkjust(const V& v) { return maybe<V>(v); } -template<typename V> const lambda<maybe<V>(const V)> just() { +template<typename V> inline const lambda<const maybe<V>(const V)> just() { return mkjust<V>; } /** * Returns true if a maybe monad contains a content. */ -template<typename V> const bool hasContent(const maybe<V>& m) { +template<typename V> inline const bool hasContent(const maybe<V>& m) { return m.hasv; } /** * Returns the content of a maybe monad. */ -template<typename V> const V content(const maybe<V>& m) { +template<typename V> inline const V content(const maybe<V>& m) { return m.v; } @@ -188,13 +182,13 @@ template<typename V> const V content(const maybe<V>& 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<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(const V)>& f) { +template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const lambda<const maybe<R>(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } -template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) { +template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -207,30 +201,22 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co */ template<typename V, typename F = string, typename C = int> 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<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { + inline failable(const failable<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) { } - const failable<V, F, C>& operator=(const failable<V, F, C>& m) { - if (&m == this) - return *this; - hasv = m.hasv; - v = m.v; - f = m.f; - c = m.c; - return *this; - } + failable<V, F, C>& operator=(const failable<V, F, C>& m) = delete; - const bool operator!=(const failable<V, F, C>& m) const { + inline const bool operator!=(const failable<V, F, C>& m) const { return !this->operator==(m); } - const bool operator==(const failable<V, F, C>& m) const { + inline const bool operator==(const failable<V, F, C>& 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<typename A, typename B, typename R> friend const bool hasContent(const failable<A, B, R>& m); @@ -250,16 +236,16 @@ private: template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f, const int c, const bool log); template<typename A> friend const failable<A> 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<typename V, typename F, typename C> ostream& operator<<(ostream& out, const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline ostream& operator<<(ostream& out, const failable<V, F, C>& m) { if (!hasContent(m)) { out << reason(m) << " : " << rcode(m); return out; @@ -271,20 +257,22 @@ template<typename V, typename F, typename C> ostream& operator<<(ostream& out, c /** * Returns a failable monad with a success value in it. */ -template<typename V, typename F, typename C> const failable<V, F, C> mksuccess(const V& v) { +template<typename V, typename F, typename C> inline const failable<V, F, C> mksuccess(const V& v) { return failable<V, F, C>(v); } -template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> success() { +template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> success() { return mksuccess<V, F, C>; } +#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<typename V, typename F, typename C> const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) { +template<typename V, typename F, typename C> inline const failable<V, F, C> 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<typename V, typename F, typename C> const failable<V, F, C> 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<V, F, C>(false, f, c); } -template<typename V, typename F> const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) { +template<typename V, typename F> inline const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) { return mkfailure<V, F, int>(f, c, log); } -template<typename V> const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) { +template<typename V> inline const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) { return mkfailure<V, string, int>(string(f), c, log); } -template<typename V> const failable<V> mkfailure() { +template<typename V> inline const failable<V> mkfailure() { return failable<V, string>(false, string(), -1); } -template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> failure() { +template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> failure() { return mkfailure<V, F, C>; } /** * Convert a failable of a given type to a failable of another type. */ -template<typename V, typename F, typename C, typename X> const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = true) { +template<typename V, typename F, typename C, typename X> inline const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = false) { return mkfailure<V, F, C>(reason(f), rcode(f), log); } /** * Returns true if the monad contains a content. */ -template<typename V, typename F, typename C> const bool hasContent(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const bool hasContent(const failable<V, F, C>& m) { return m.hasv; } /** * Returns the content of a failable monad. */ -template<typename V, typename F, typename C> const V content(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const V content(const failable<V, F, C>& m) { return m.v; } /** * Returns the reason for failure of a failable monad. */ -template<typename V, typename F, typename C> const F reason(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const F reason(const failable<V, F, C>& m) { return m.f; } /** * Returns the reason code for failure of a failable monad. */ -template<typename V, typename F, typename C> const C rcode(const failable<V, F, C>& m) { +template<typename V, typename F, typename C> inline const C rcode(const failable<V, F, C>& m) { return m.c; } @@ -458,14 +452,14 @@ template<typename V, typename F, typename C> const C rcode(const failable<V, F, * if present, or does nothing if there's no value and a failure instead. */ template<typename R, typename FR, typename XR, typename V, typename FV, typename XV> -const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<failable<R, FR, XR>(const V)>& f) { +inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<const failable<R, FR, XR>(const V)>& f) { if (!hasContent(m)) return m; return f(content(m)); } template<typename R, typename FR, typename XR, typename V, typename FV, typename XV> -const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) { +inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) { if (!hasContent(m)) return m; return f(content(m)); @@ -476,30 +470,27 @@ const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failabl */ template<typename S, typename V> 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<S, V>& operator=(const scp<S, V>& p) { - if(this == &p) - return *this; - s = p.s; - v = p.v; - return *this; + inline scp(const scp<S, V>& p) : s(p.s), v(p.v) { } - const bool operator!=(const scp<S, V>& p) const { + scp<S, V>& operator=(const scp<S, V>& p) = delete; + + inline const bool operator!=(const scp<S, V>& p) const { return !this->operator==(p); } - const bool operator==(const scp<S, V>& p) const { + inline const bool operator==(const scp<S, V>& 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<typename S, typename V> const S scpstate(const scp<S, V>& m) { +template<typename S, typename V> inline const S scpstate(const scp<S, V>& m) { return m.s; } /** * Returns the content of a state-content pair. */ -template<typename S, typename V> const S content(const scp<S, V>& m) { +template<typename S, typename V> inline const S content(const scp<S, V>& m) { return m.v; } @@ -532,38 +523,36 @@ template<typename S, typename V> const S content(const scp<S, V>& m) { */ template<typename S, typename V> class state { public: - state(const lambda<scp<S, V>(const S)>& f) : f(f) { + inline state(const lambda<const scp<S, V>(const S)>& f) : f(f) { } - const scp<S, V> operator()(const S& s) const { + inline const scp<S, V> operator()(const S& s) const { return f(s); } - const state<S, V>& operator=(const state<S, V>& m) { - if(this == &m) - return *this; - f = m.f; - return *this; + inline state(const state<S, V>& m) : f(m.f) { } - const bool operator!=(const state<S, V>& m) const { + state<S, V>& operator=(const state<S, V>& m) = delete; + + inline const bool operator!=(const state<S, V>& m) const { return !this->operator==(m); } - const bool operator==(const state<S, V>& m) const { + inline const bool operator==(const state<S, V>& m) const { if (this == &m) return true; return f == m.f; } private: - const lambda<scp<S, V>(const S)> f; + const lambda<const scp<S, V>(const S)> f; }; /** * Write a state monad to a stream. */ -template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) { +template<typename S, typename V> inline ostream& operator<<(ostream& out, const state<S, V>& m) { const S s = m; const V v = m; out << '(' << s << ' ' << v << ')'; @@ -573,17 +562,10 @@ template<typename S, typename V> ostream& operator<<(ostream& out, const state<S /** * Return a state monad carrying a result content. */ -template<typename S, typename V> struct returnState { - const V v; - returnState(const V& v) : v(v) { - } - const scp<S, V> operator()(const S& s) const { +template<typename S, typename V> inline const state<S, V> result(const V& v) { + return state<S, V>([v](const S& s) -> const scp<S, V> { return scp<S, V>(s, v); - } -}; - -template<typename S, typename V> const state<S, V> result(const V& v) { - return state<S, V>(returnState<S, V>(v)); + }); } /** @@ -591,7 +573,7 @@ template<typename S, typename V> const state<S, V> result(const V& v) { * A transformer function takes a state and returns an scp pair carrying a content and a * new (transformed) state. */ -template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(const S)>& f) { +template<typename S, typename V> inline const state<S, V> transformer(const lambda<const scp<S, V>(const S)>& f) { return state<S, V>(f); } @@ -599,28 +581,19 @@ template<typename S, typename V> const state<S, V> transformer(const lambda<scp< * Bind a function to a state monad. The function takes a content and returns a state * monad carrying a return content. */ -template<typename S, typename A, typename B> struct stateBind { - const state<S, A> st; - const lambda<state<S, B>(const A)>f; - - stateBind(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) : st(st), f(f) { - } - - const scp<S, B> operator()(const S& is) const { +template<typename S, typename A, typename B> +inline const state<S, B> operator>>(const state<S, A>& st, const lambda<const state<S, B>(const A)>& f) { + const lambda<const scp<S, B>(const S&)> stateBind = [st, f](const S& is) -> const scp<S, B> { const scp<S, A> iscp = st(is); const state<S, B> m = f((A)iscp); return m((S)iscp); - } -}; - -template<typename S, typename A, typename B> -const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) { - return state<S, B>(stateBind<S, A , B>(st, f)); + }; + return state<S, B>(stateBind); } template<typename S, typename A, typename B> -const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) { - return state<S, B>(stateBind<S, A , B>(st, f)); +inline const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) { + return st >> lambda<const state<S, B>(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<int> tlsic() { - gc_ptr<int> i = new (gc_new<int>()) int(); + const gc_ptr<int> i = new (gc_new<int>()) int(); *i = 0; return i; } const perthread_ptr<int> 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<bool()> 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<bool()> 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<bool()> 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<bool()> 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<future<int> > submitSquares(worker& w, const int max, const int i) { if (i == max) return list<future<int> >(); - const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), i); + const lambda<const int()> func = curry(lambda<const int(const int)> (mtsquare), i); return cons(submit(w, func), submitSquares(w, max, i + 1)); } @@ -143,7 +117,7 @@ bool checkSquareResults(const list<future<int> > r, int i) { } const gc_ptr<unsigned long> tlsvc() { - gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long(); + const gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long(); *i = 0l; return i; } @@ -181,11 +155,11 @@ const bool unblockWorkers(wqueue<bool>& wq, const int n) { const list<future<long int> > submitTLSSets(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) { if (i == max) return list<future<long int> >(); - const lambda<long int()> func = curry(lambda<long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); + const lambda<const long int()> func = curry(lambda<const long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); return cons(submit(w, func), submitTLSSets(w, wq, xq, max, i + 1)); } -bool checkTLSSets(const list<future<long int> > s) { +const bool checkTLSSets(const list<future<long int> > s) { if (isNil(s)) return true; assert(car(s) == 0); @@ -195,22 +169,22 @@ bool checkTLSSets(const list<future<long int> > s) { const list<future<bool> > submitTLSChecks(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) { if (i == max) return list<future<bool> >(); - const lambda<bool()> func = curry(lambda<bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); + const blambda func = curry(lambda<const bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq); return cons(submit(w, func), submitTLSChecks(w, wq, xq, max, i + 1)); } -bool checkTLSResults(const list<future<bool> > r) { +const bool checkTLSResults(const list<future<bool> > 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<int()> func = curry(lambda<int(const int)> (mtsquare), 2); + const lambda<const int()> func = curry(lambda<const int(const int)> (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<typename T> class future { private: template<typename X> 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<X> value; }; - gc_ptr<futureValue<T> > fvalue; + const gc_ptr<futureValue<T> > fvalue; - template<typename X> friend const X get(const future<X>& f); - template<typename X> friend bool set(const future<X>& f, const X& v); + template<typename X> friend const X get(const future<X>& f) noexcept; + template<typename X> friend bool set(const future<X>& f, const X& v) noexcept; public: - future() : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) { + inline future() noexcept : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) { } - ~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<typename T> class wqueue { public: - wqueue(size_t max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) { + inline wqueue(size_t max) noexcept : max(max), size(0), tail(0), head(0), values(new (gc_anew<gc_mutable_ref<T> >(max)) gc_mutable_ref<T>[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<T> values; + gc_ptr<gc_mutable_ref<T> > values; - template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v); - template<typename X> friend const X dequeue(wqueue<X>& q); + template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v) noexcept; + template<typename X> friend const X dequeue(wqueue<X>& q) noexcept; }; /** * Adds an element to the tail of the queue. */ -template<typename T> const size_t enqueue(wqueue<T>&q, const T& v) { +template<typename T> inline const size_t enqueue(wqueue<T>&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<typename T> const size_t enqueue(wqueue<T>&q, const T& v) { /** * Returns the element at the head of the queue. */ -template<typename T> const T dequeue(wqueue<T>& q) { +template<typename T> inline const T dequeue(wqueue<T>& q) noexcept { pthread_mutex_lock(&q.mutex); while(q.size == 0) pthread_cond_wait(&q.empty, &q.mutex); @@ -202,13 +197,13 @@ template<typename T> const T dequeue(wqueue<T>& 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<lambda<bool()> >* work = reinterpret_cast<wqueue<lambda<bool()> >*>(arg); + wqueue<blambda >* work = reinterpret_cast<wqueue<blambda >*>(arg); while(dequeue(*work)()) ; return NULL; @@ -217,7 +212,7 @@ void *workerThreadFunc(void *arg) { /** * Returns a list of worker threads. */ -const list<pthread_t> workerThreads(wqueue<lambda<bool()> >& wqueue, const size_t count) { +inline const list<pthread_t> workerThreads(wqueue<blambda >& wqueue, const size_t count) noexcept { if (count == 0) return list<pthread_t>(); 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<lambda<bool()> >(max)), threads(workerThreads(work, max)) { + inline sharedWorker(size_t max) noexcept : work(wqueue<blambda >(max)), threads(workerThreads(work, max)) { } - wqueue<lambda<bool()> > work; + wqueue<blambda > work; const list<pthread_t> threads; }; public: - worker(size_t max) : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) { + inline worker(size_t max) noexcept : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) { } - worker(const worker& wk) : w(wk.w) { + inline worker(const worker& wk) noexcept : w(wk.w) { } private: sharedWorker& w; - template<typename X> friend const future<X> submit(worker& w, const lambda<X()>& func); - friend const bool shutdown(worker& w); - friend const bool cancel(worker& w); + template<typename X> friend const future<X> submit(const worker& w, const lambda<const X()>& 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<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& fut) { +template<typename R> inline const bool submitFunc(const lambda<const R()>& func, const future<R>& fut) noexcept { fut = func(); return true; } @@ -268,9 +263,9 @@ template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& f /** * Submits work to a worker. */ -template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) { +template<typename R> inline const future<R> submit(const worker& w, const lambda<const R()>& func) noexcept { const future<R> fut; - const lambda<bool()> f = curry(lambda<bool(const lambda<R()>, future<R>)>(submitFunc<R>), func, fut); + const blambda f = curry(lambda<const bool(const lambda<const R()>, future<R>)>(submitFunc<R>), func, fut); enqueue(w.w.work, f); return fut; } @@ -278,7 +273,7 @@ template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) /** * Enqueues shutdown requests. */ -const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> >& work) { +inline const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<blambda>& work) noexcept { if (isNil(threads)) return true; enqueue(work, result(false)); @@ -288,7 +283,7 @@ const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> /** * Waits for shut down threads to terminate. */ -const bool shutdownJoin(const list<pthread_t>& threads) { +inline const bool shutdownJoin(const list<pthread_t>& threads) noexcept { if (isNil(threads)) return true; pthread_join(car(threads), NULL); @@ -298,7 +293,7 @@ const bool shutdownJoin(const list<pthread_t>& 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<pthread_t>& threads) { +inline const bool cancel(const list<pthread_t>& 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<typename T> class perthread_ptr { public: - perthread_ptr() : key(createkey()), owner(true), cl(lambda<gc_ptr<T>()>()), managed(false) { + inline perthread_ptr() noexcept : key(createkey()), owner(true), cl(lambda<const gc_ptr<T>()>()), managed(false) { } - perthread_ptr(const lambda<gc_ptr<T>()>& cl) : key(createkey()), owner(true), cl(cl), managed(true) { + inline perthread_ptr(const lambda<const gc_ptr<T>()>& 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<T>& v) { + inline const perthread_ptr& operator=(const gc_ptr<T>& 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<T>& r) const throw() { + inline const bool operator==(const gc_ptr<T>& 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<T>& r) const throw() { + inline const bool operator!=(const gc_ptr<T>& 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<T>() const { + inline operator gc_ptr<T>() 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<T>& v) { + inline const bool set(const gc_ptr<T>& v) const noexcept { pthread_setspecific(key, (T*)v); return true; } - gc_ptr<T> get() const { - const gc_ptr<T> v = static_cast<T*>(pthread_getspecific(key)); + inline const gc_ptr<T> get() const noexcept { + const gc_ptr<T> v = (T*)(pthread_getspecific(key)); if (v != NULL || !managed) return v; const gc_ptr<T> nv = cl(); - pthread_setspecific(key, nv); + pthread_setspecific(key, (T*)nv); return nv; } #else - gc_ptr<gc_ptr<T> > createkey() { + inline const gc_ptr<gc_ptr<T> > createkey() noexcept { return new (gc_new<gc_ptr<T> >()) gc_ptr<T>(); } - bool deletekey(unused gc_ptr<gc_ptr<T> > k) { + inline const bool deletekey(unused gc_ptr<gc_ptr<T> > k) noexcept { return true; } - bool set(const gc_ptr<T>& v) { + inline const bool set(const gc_ptr<T>& v) const noexcept { *key = v; return true; } - gc_ptr<T> get() const { + inline const gc_ptr<T> 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<gc_ptr<T> >key; + const gc_ptr<gc_ptr<T> >key; #endif - bool owner; - lambda<const gc_ptr<T>()> cl; - bool managed; + const bool owner; + const lambda<const gc_ptr<T>()> 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<bool()> f; - timeLambda(const lambda<bool()>& 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<const bool(const long)> tl = [f](const long count) -> const bool { for (long i = 0; i < count; i++) f(); return true; - } -}; - -const double time(const lambda<bool()>& f, const long warmup, const long count) { - const lambda<bool(long)> tl = timeLambda(f); - struct timeval start; - struct timeval end; + }; tl(warmup); gettimeofday(&start, NULL); @@ -62,13 +56,13 @@ const double time(const lambda<bool()>& 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<string>& l, char* buf) { +const bool writeList(const list<string>& l, char* const buf) { if (isNil(l)) return true; const string c = car(l); @@ -59,63 +59,108 @@ const bool writeList(const list<string>& 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<string>)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<string>)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<string>)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<string>)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<string>)buf); + accumbuf = NULL; + accumlen = 0; + return true; } friend const string str(ostringstream& os); size_t len; - list<string> buf; + char* accumbuf; + size_t accumlen; + gc_mutable_ref<list<string> > 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<string> tokenize(const char* sep, const string& str) { - struct nested { - static const list<string> tokenize(const char* sep, const size_t slen, const string& str, const size_t start) { - if (start >= length(str)) - return list<string>(); - 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<string> tokenize(const char* const sep, const string& str) { + const lambda<const list<string>(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<string> { + if (start >= length(str)) + return list<string>(); + 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<string>& l) { - struct nested { - static ostringstream& join(const char* sep, const list<string>& 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<string>& l) { ostringstream os; - return str(nested::join(sep, l, os)); + const lambda<ostringstream&(const char* const, const list<string>&, ostringstream&)> join = [&join](const char* const sep, const list<string>& 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<string> operator()() { +inline const list<string> streamList(istream& is) { + const lambda<const list<string>()> ilistRead = [&is, &ilistRead]() -> const list<string> { char buffer[1024]; const size_t n = read(is, buffer, sizeof(buffer)); if (n ==0) return list<string>(); - return cons(string(buffer, n), (*this)()); - } -}; - -const list<string> 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<string> fragment(list<string> l, size_t max) { +inline const list<string> fragment(const list<string>& l, const size_t max) { const string s = car(l); if (length(s) <= max) return l; @@ -250,13 +276,26 @@ const list<string> fragment(list<string> l, size_t max) { /** * Write a list of strings to an output stream. */ -ostream& write(const list<string>& l, ostream& os) { +inline ostream& write(const list<string>& 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<string>& 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<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { - return out << p.ptr; +#ifndef WANT_RAW_PTR + +/** + * Write a pointer. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_ptr<T>& p) { + return out << (T*)p; +} + +/** + * Write a mutable pointer. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ptr<T>& p) { + return out << (T*)p; +} + +#endif + +/** + * Write a mutable reference. + */ +template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ref<T>& r) { + return out << (T)r; } #ifdef WANT_MAINTAINER_LOG @@ -159,35 +181,40 @@ template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& 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<string> 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<string> pl = list<string>() + "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<bool()> a16 = addStrings(16); + const lambda<const blambda(const size_t size)> 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<bool()> a32 =addStrings(32); + const blambda a32 =addStrings(32); cout << "string test " << time(a32, 5, count) << " ms" << endl; - const lambda<bool()> a256 =addStrings(256); + const blambda a256 =addStrings(256); cout << "string test " << time(a256, 5, count) << " ms" << endl; - const lambda<bool()> a1024 =addStrings(1024); + const blambda a1024 =addStrings(1024); cout << "string test " << time(a1024, 5, count) << " ms" << endl; - const lambda<bool()> a4096 =addStrings(4096); + const blambda a4096 =addStrings(4096); cout << "string test " << time(a4096, 5, count) << " ms" << endl; } { - const lambda<bool()> a16 =addStdStrings(16); + const lambda<const blambda(const size_t size)> 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<bool()> a32 =addStdStrings(32); + const blambda a32 =addStdStrings(32); cout << "Std string test " << time(a32, 5, count) << " ms" << endl; - const lambda<bool()> a256 =addStdStrings(256); + const blambda a256 =addStdStrings(256); cout << "Std string test " << time(a256, 5, count) << " ms" << endl; - const lambda<bool()> a1024 =addStdStrings(1024); + const blambda a1024 =addStdStrings(1024); cout << "Std string test " << time(a1024, 5, count) << " ms" << endl; - const lambda<bool()> 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<typename T> const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) { +template<typename T> inline const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) { return mklist<T>(e, left, right); } /** * Find a leaf with the given key in a tree. */ -template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) { +template<typename T> inline const list<T> assoctree(const T& k, const list<T>& tree) { if (isNil(tree)) return tree; if (k == car<T>(car(tree))) @@ -58,7 +58,7 @@ template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) { /** * Construct a new tree from a leaf and a tree. */ -template<typename T> const list<T> constree(const T& e, const list<T>& tree) { +template<typename T> inline const list<T> constree(const T& e, const list<T>& tree) { if (isNil(tree)) return mktree(e, list<T>(), list<T>()); if (e == car(tree)) @@ -71,7 +71,7 @@ template<typename T> const list<T> constree(const T& e, const list<T>& tree) { /** * Make a tree from an unordered list of leaves. */ -template<typename T> const list<T> mktree(const list<T>& l) { +template<typename T> inline const list<T> mktree(const list<T>& l) { if (isNil(l)) return l; return constree(car(l), mktree(cdr(l))); @@ -80,7 +80,7 @@ template<typename T> const list<T> mktree(const list<T>& l) { /** * Convert a tree to an ordered list of leaves. */ -template<typename T> const list<T> flatten(const list<T>& tree) { +template<typename T> inline const list<T> flatten(const list<T>& tree) { if (isNil(tree)) return tree; return append<T>(flatten<T>(cadr(tree)), cons<T>(car(tree), flatten<T>(caddr(tree)))); @@ -89,14 +89,14 @@ template<typename T> const list<T> flatten(const list<T>& tree) { /** * Sort a list. */ -template<typename T> const list<T> sort(const list<T>& l) { +template<typename T> inline const list<T> sort(const list<T>& l) { return flatten(mktree(l)); } /** * Make a balanced tree from an ordered list of leaves. */ -template<typename T> const list<T> btreeHelper(const list<T>& elements, const size_t n) { +template<typename T> inline const list<T> btreeHelper(const list<T>& elements, const size_t n) { if (n == 0) return cons<T>(list<T>(), elements); const size_t leftSize = (n - 1) / 2; { @@ -116,7 +116,7 @@ template<typename T> const list<T> btreeHelper(const list<T>& elements, const si } } -template<typename T> const list<T> mkbtree(const list<T>& elements) { +template<typename T> inline const list<T> mkbtree(const list<T>& elements) { return car(btreeHelper<T>(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<value> nilListValue; +extern const list<value> nilPairValue; +extern const value emptyStringValue; +extern const value trueValue; +extern const value falseValue; + +/** + * Common value-based lambda types. + */ +typedef lambda<const value(const list<value>&)> lvvlambda; +typedef lambda<const value(const value&)> vvlambda; +typedef lambda<const bool(const value&)> vblambda; +typedef lambda<const value()> 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<list<value> > lst; + const string str; + const lvvlambda func; + const gc_ptr<value> 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<value>& 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<value(const list<value>&)>& 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<value>& lst) : type(value::List), data(vdata(result(lst))) { + inline value(const list<value>& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(l)) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const list<list<value> >& l) : type(value::List), data(vdata(result(listOfValues(l)))) { + inline value(const list<list<value> >& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(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<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) { + inline value(const gc_ptr<value> p) noexcept : type(value::Ptr), ptr(p) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const failable<value>& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist<value>(content(m)) : rcode(m) == 1? mklist<value>(value(), reason(m)) : mklist<value>(value(), reason(m), rcode(m))))) { + inline value(const failable<value>& m) noexcept : type(value::List), + lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(content(m)) : + rcode(m) == 1? mklist<value>(nilValue, reason(m)) : mklist<value>(nilValue, reason(m), rcode(m)))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const maybe<value>& m) : type(value::List), - data(vdata(result(hasContent(m)? mklist<value>(content(m)) : list<value>()))) { + inline value(const maybe<value>& m) noexcept : type(value::List), + lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(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<value>& args) const { - return func()(args); + inline const value operator()(const list<value>& 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<value>() const { - return ptr()(); + inline operator const gc_ptr<value>() const noexcept { + return ptr; } - operator const list<value>() const { - return lst()(); + inline operator const list<value>() const noexcept { + return *lst; } - operator const list<list<value> >() const { - return listOfListOfValues(lst()()); + inline operator const list<list<value> >() const noexcept { + return listOfListOfValues(*lst); } - operator const lambda<value(const list<value>&)>() const { - return func(); + inline operator const lvvlambda() const noexcept { + return func; } private: - template<typename T> lambda<T>& vdata() const { - return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data)); - } - - template<typename T> const lambda<char()>& vdata(const T& v) const { - return *reinterpret_cast<const lambda<char()> *> (&v); - } - - lambda<double()>& num() const { - return vdata<double()> (); - } - - lambda<bool()>& boo() const { - return vdata<bool()> (); - } - - lambda<gc_ptr<value>()>& ptr() const { - return vdata<gc_ptr<value>()> (); - } - - lambda<string()>& str() const { - return vdata<string()> (); - } - - lambda<list<value>()>& lst() const { - return vdata<list<value>()> (); - } - - lambda<value(const list<value>&)>& func() const { - return vdata<value(const list<value>&)> (); - } - - const list<value> listOfValues(const list<list<value> >& l) const { + inline const list<value> listOfValues(const list<list<value> >& l) const noexcept { if (isNil(l)) - return list<value>(); + return nilListValue; return cons<value>(car(l), listOfValues(cdr(l))); } - const list<list<value> > listOfListOfValues(const list<value>& l) const { + inline const list<list<value> > listOfListOfValues(const list<value>& l) const noexcept { if (isNil(l)) return list<list<value> >(); - return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l))); + return cons<list<value> >(car(l).type == value::List? list<value>(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<char()> data; + const ValueType type; + union { + void* mix; + const gc_ptr<list<value> > lst; + const string str; + const lvvlambda func; + const gc_ptr<value> ptr; + const double num; + const bool boo; + }; }; +/** + * Common value constants. + */ +const value nilValue; +const list<value> nilListValue = list<value>(); +const list<value> nilPairValue = mklist<value>(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<value>(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<value> p = v.ptr()(); - if (p == gc_ptr<value>(NULL)) + if (v.ptr == gc_ptr<value>(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<value>)exp)) return car((list<value>)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<typename T> const list<value> mkvalues(const list<T>& l) { +template<typename T> inline const list<value> mkvalues(const list<T>& l) noexcept { if (isNil(l)) - return list<value>(); + return nilListValue; return cons<value>(car(l), mkvalues(cdr(l))); } /** * Convert a list of values to a list of other things. */ -template<typename T> const list<T> convertValues(const list<value>& l) { +template<typename T> inline const list<T> convertValues(const list<value>& l) noexcept { if (isNil(l)) return list<T>(); return cons<T>(car(l), convertValues<T>(cdr(l))); @@ -603,7 +586,7 @@ template<typename T> const list<T> convertValues(const list<value>& l) { /** * Convert a path string value to a list of values. */ -const list<string> pathTokens(const char* p) { +inline const list<string> pathTokens(const char* const p) noexcept { if (p == NULL || p[0] == '\0') return list<string>(); if (p[0] == '/') @@ -611,23 +594,23 @@ const list<string> pathTokens(const char* p) { return tokenize("/", p); } -const list<value> pathValues(const value& p) { +inline const list<value> 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<value>& p) { +inline const value path(const list<value>& 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 <assert.h> -#include "stream.hpp" -#include "string.hpp" -#include "list.hpp" -#include "value.hpp" -#include "element.hpp" -#include "xml.hpp" - -namespace tuscany { - -const string currencyXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" targetNamespace=\"http://services\" name=\"currency\">\n" -" <component name=\"CurrencyConverterWebService\">\n" -" <implementation.java class=\"services.CurrencyConverterImpl\"/>\n" -" <service name=\"CurrencyConverter\">\n" -" <binding.ws/>\n" -" </service>\n" -" </component>\n" -" <component name=\"CurrencyConverterWebService2\">\n" -" <implementation.java class=\"services.CurrencyConverterImpl2\"/>\n" -" <service name=\"CurrencyConverter2\">\n" -" <binding.atom/>\n" -" </service>\n" -" <property name=\"currency\">US</property>\n" -" </component>\n" -"</composite>\n"; - -const string customerXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<customer>\n" -" <name>jdoe</name>\n" -" <address>\n" -" <city>san francisco</city>\n" -" <state>ca</state>\n" -" </address>\n" -" <account>\n" -" <id>1234</id>\n" -" <balance>1000</balance>\n" -" </account>\n" -" <account>\n" -" <id>6789</id>\n" -" <balance>2000</balance>\n" -" </account>\n" -" <account>\n" -" <id>4567</id>\n" -" <balance>3000</balance>\n" -" </account>\n" -"</customer>\n"; - -const string abcXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<a>\n" -" <m>abc</m>\n" -" <m>def</m>\n" -" <m>xyz</m>\n" -" <m>tuv</m>\n" -"</a>\n"; - -const string xyzXML = -"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" -"<a>\n" -" <m>\n" -" <id>123</id>\n" -" <name>abc</name>\n" -" </m>\n" -" <m>\n" -" <id>234</id>\n" -" <name>def</name>\n" -" </m>\n" -" <m>\n" -" <id>345</id>\n" -" <name>xyz</name>\n" -" </m>\n" -" <m>\n" -" <id>456</id>\n" -" <name>tuv</name>\n" -" </m>\n" -"</a>\n"; - -const bool isName(const value& token) { - return isTaggedList(token, attribute) && attributeName(token) == "name"; -} - -bool testReadXML() { - { - istringstream is(customerXML); - const list<value> c = readXML(streamList(is)); - } - { - istringstream is(currencyXML); - const list<value> c = readXML(streamList(is)); - - const value composite = car(c); - assert(isTaggedList(composite, element)); - assert(elementName(composite) == "composite"); - assert(attributeValue(car(filter<value>(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<value> c = readXML(streamList(is)); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, c); - assert(str(os) == customerXML); - } - { - istringstream is(currencyXML); - const list<value> c = readXML(streamList(is)); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, c); - assert(str(os) == currencyXML); - } - return true; -} - -bool testElements() { - { - const list<value> ad = mklist<value>(mklist<value>("city", string("san francisco")), mklist<value>("state", string("ca"))); - const list<value> ac1 = mklist<value>(mklist<value>("id", string("1234")), mklist<value>("balance", 1000)); - const list<value> ac2 = mklist<value>(mklist<value>("id", string("6789")), mklist<value>("balance", 2000)); - const list<value> ac3 = mklist<value>(mklist<value>("id", string("4567")), mklist<value>("balance", 3000)); - { - const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3)))); - const list<value> e = valuesToElements(c); - const list<value> v = elementsToValues(e); - assert(v == c); - - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - { - const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3))); - const list<value> e = valuesToElements(c); - const list<value> v = elementsToValues(e); - - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - } - { - istringstream is(abcXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == abcXML); - } - { - istringstream is(xyzXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == xyzXML); - } - { - istringstream is(customerXML); - const list<value> c = readXML(streamList(is)); - const list<value> v = elementsToValues(c); - const list<value> e = valuesToElements(v); - ostringstream os; - writeXML<ostream*>(xmlWriter, &os, e); - assert(str(os) == customerXML); - } - return true; -} - -bool testValues() { - { - const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!"))); - const list<value> e = valuesToElements(l); - const failable<list<string> > lx = writeXML(e); - ostringstream os; - write(content(lx), os); - istringstream is(str(os)); - const list<value> x = readXML(streamList(is)); - const list<value> 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/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( "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n" - " <author>\n" - " <email>jane@example.com</email>\n" - " </author>\n" - " <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n" - " <content type=\"application/xml\">\n" - " <item>\n" - " <name>Apple</name>\n" - " <price>$2.99</price>\n" - " </item>\n" - " </content>\n" - " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<author>" + "<email>jane@example.com</email>" + "</author>" + "<updated>Fri Jan 01 08:11:36 PDT 2012</updated>" + "<content type=\"application/xml\">" + "<item>" + "<name>Apple</name>" + "<price>$2.99</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" "</entry>\n"); const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n" - " <author>\n" - " <email>jane@example.com</email>\n" - " </author>\n" - " <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n" - " <content type=\"text\">Apple</content>\n" - " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<author>" + "<email>jane@example.com</email>" + "</author>" + "<updated>Fri Jan 01 08:11:36 PDT 2012</updated>" + "<content type=\"text\">Apple</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" "</entry>\n"); const string itemNoContentEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n" - " <author>\n" - " <name>jane</name>\n" - " </author>\n" - " <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n" - " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<author>" + "<name>jane</name>" + "</author>" + "<updated>Fri Jan 01 08:11:36 PDT 2012</updated>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" "</entry>\n"); const string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title>item</title>\n" - " <content type=\"text/xml\">\n" - " <Item xmlns=\"http://services/\">\n" - " <name xmlns=\"\">Orange</name>\n" - " <price xmlns=\"\">3.55</price>\n" - " </Item>\n" - " </content>\n" + "<title>item</title>" + "<content type=\"text/xml\">" + "<Item xmlns=\"http://services/\">" + "<name xmlns=\"\">Orange</name>" + "<price xmlns=\"\">3.55</price>" + "</Item>" + "</content>" "</entry>\n"); const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id></id>\n" - " <content type=\"application/xml\">\n" - " <Item xmlns=\"http://services/\">\n" - " <name xmlns=\"\">Orange</name>\n" - " <price xmlns=\"\">3.55</price>\n" - " </Item>\n" - " </content>\n" - " <link href=\"\"/>\n" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id></id>" + "<content type=\"application/xml\">" + "<Item xmlns=\"http://services/\">" + "<name xmlns=\"\">Orange</name>" + "<price xmlns=\"\">3.55</price>" + "</Item>" + "</content>" + "<link href=\"\"/>" "</entry>\n"); -bool testEntry() { +const bool testEntry() { { - const list<value> i = list<value>() + element + value("item") - + value(list<value>() + element + value("name") + value(string("Apple"))) - + value(list<value>() + element + value("price") + value(string("$2.99"))); - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("item"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("author") + value(string("jane@example.com"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list<value>() + element + value("content") + value(i))); + const list<value> i = nilListValue + element + value("item") + + value(nilListValue + element + value("name") + value(string("Apple"))) + + value(nilListValue + element + value("price") + value(string("$2.99"))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemEntry); } { - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("item"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("author") + value(string("jane@example.com"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list<value>() + element + value("content") + value(string("Apple")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemTextEntry); } { - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("item"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("author") + value(string("jane"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemNoContentEntry); @@ -164,54 +164,54 @@ bool testEntry() { } const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">Feed</title>\n" - " <id>1234</id>\n" + "<feed xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">Feed</title>" + "<id>1234</id>" "</feed>\n"); const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<feed xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">Feed</title>\n" - " <id>1234</id>\n" - " <entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n" - " <author>\n" - " <email>jane@example.com</email>\n" - " </author>\n" - " <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n" - " <content type=\"application/xml\">\n" - " <item>\n" - " <name>Apple</name>\n" - " <price>$2.99</price>\n" - " </item>\n" - " </content>\n" - " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n" - " </entry>\n" - " <entry xmlns=\"http://www.w3.org/2005/Atom\">\n" - " <title type=\"text\">item</title>\n" - " <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>\n" - " <author>\n" - " <email>jane@example.com</email>\n" - " </author>\n" - " <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n" - " <content type=\"application/xml\">\n" - " <item>\n" - " <name>Orange</name>\n" - " <price>$3.55</price>\n" - " </item>\n" - " </content>\n" - " <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>\n" - " </entry>\n" + "<feed xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">Feed</title>" + "<id>1234</id>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" + "<author>" + "<email>jane@example.com</email>" + "</author>" + "<updated>Fri Jan 01 08:11:36 PDT 2012</updated>" + "<content type=\"application/xml\">" + "<item>" + "<name>Apple</name>" + "<price>$2.99</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" + "</entry>" + "<entry xmlns=\"http://www.w3.org/2005/Atom\">" + "<title type=\"text\">item</title>" + "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>" + "<author>" + "<email>jane@example.com</email>" + "</author>" + "<updated>Fri Jan 01 08:11:36 PDT 2012</updated>" + "<content type=\"application/xml\">" + "<item>" + "<name>Orange</name>" + "<price>$3.55</price>" + "</item>" + "</content>" + "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>" + "</entry>" "</feed>\n"); -bool testFeed() { +const bool testFeed() { { - const list<value> a = list<value>() + (list<value>() + element + value("feed") - + value(list<value>() + element + value("title") + value(string("Feed"))) - + value(list<value>() + element + value("id") + value(string("1234"))) - + value(list<value>() + element + value("author") + value(string("jane@example.com"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == emptyFeed); @@ -223,31 +223,31 @@ bool testFeed() { assert(str(os) == emptyFeed); } { - const list<value> i1 = list<value>() + element + "item" - + (list<value>() + element + "name" + "Apple") - + (list<value>() + element + "price" + "$2.99"); + const list<value> i1 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Apple") + + (nilListValue + element + "price" + "$2.99"); - const list<value> i2 = list<value>() + element + "item" - + (list<value>() + element + "name" + "Orange") - + (list<value>() + element + "price" + "$3.55"); + const list<value> i2 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Orange") + + (nilListValue + element + "price" + "$3.55"); - const list<value> i = list<value>() - + value(list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("item"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("author") + value(string("jane@example.com"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list<value>() + element + value("content") + value(i1))) - + value(list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("item"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) - + value(list<value>() + element + value("author") + value(string("jane@example.com"))) - + value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))) - + value(list<value>() + element + value("content") + value(i2))); + const list<value> 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<value> a = list<value>() + (append<value>(list<value>() + element + value("feed") - + value(list<value>() + element + value("title") + value(string("Feed"))) - + value(list<value>() + element + value("id") + value("1234")), + const list<value> a = nilListValue + (append<value>(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<value> entryElementValues(const list<value>& e) { const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e); - const list<value> t = list<value>() + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt))); + const list<value> t = nilListValue + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt))); const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e); - const list<value> i = list<value>() + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li))); + const list<value> i = nilListValue + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li))); const list<value> la = filter<value>(selector(mklist<value>(element, "author")), e); - const list<value> lan = isNil(la)? list<value>() : filter<value>(selector(mklist<value>(element, "name")), car(la)); - const list<value> lae = isNil(la)? list<value>() : filter<value>(selector(mklist<value>(element, "email")), car(la)); + const list<value> lan = isNil(la)? nilListValue : filter<value>(selector(mklist<value>(element, "name")), car(la)); + const list<value> lae = isNil(la)? nilListValue : filter<value>(selector(mklist<value>(element, "email")), car(la)); const list<value> laa = isNil(lan)? lae : lan; - const list<value> a = isNil(laa)? list<value>() : mklist<value>(list<value>() + element + value("author") + elementValue(car(laa))); + const list<value> a = isNil(laa)? nilListValue : mklist<value>(nilListValue + element + value("author") + elementValue(car(laa))); const list<value> lu = filter<value>(selector(mklist<value>(element, "updated")), e); - const list<value> u = isNil(lu)? list<value>() : mklist<value>(list<value>() + element + value("updated") + elementValue(car(lu))); + const list<value> u = isNil(lu)? nilListValue : mklist<value>(nilListValue + element + value("updated") + elementValue(car(lu))); const list<value> lc = filter<value>(selector(mklist<value>(element, "content")), e); - const list<value> c = isNil(lc)? list<value>() : mklist<value>(list<value>() + element + value("content") + elementValue(car(lc))); + const list<value> c = isNil(lc)? nilListValue : mklist<value>(nilListValue + element + value("content") + elementValue(car(lc))); - return append<value>(append<value>(append<value>(list<value>() + element + entry + value(t) + value(i), a), u), c); + return append<value>(append<value>(append<value>(nilListValue + element + entry + value(t) + value(i), a), u), c); } /** @@ -79,7 +79,7 @@ const list<value> entriesElementValues(const list<value>& e) { * Return true if a list of strings contains an ATOM feed. */ const bool isATOMFeed(const list<string>& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "<feed") && contains(car(ls), "=\"http://www.w3.org/2005/Atom\""); } @@ -88,7 +88,7 @@ const bool isATOMFeed(const list<string>& ls) { * Return true if a list of strings contains an ATOM entry. */ const bool isATOMEntry(const list<string>& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "<entry") && !contains(car(ls), "<feed") && contains(car(ls), "=\"http://www.w3.org/2005/Atom\""); } @@ -97,7 +97,7 @@ const bool isATOMEntry(const list<string>& ls) { * Convert a list of strings to a list of values representing an ATOM entry. */ const failable<list<value> > readATOMEntry(const list<string>& ilist) { - const list<value> e = readXML(ilist); + const list<value> e = content(xml::readElements(ilist)); if (isNil(e)) return mkfailure<list<value> >("Empty entry"); return mklist<value>(entryElementValues(car(e))); @@ -107,32 +107,25 @@ const failable<list<value> > readATOMEntry(const list<string>& ilist) { * Convert a list of strings to a list of values representing an ATOM feed. */ const failable<list<value> > readATOMFeed(const list<string>& ilist) { - const list<value> f = readXML(ilist); + const list<value> f = content(xml::readElements(ilist)); if (isNil(f)) return mkfailure<list<value> >("Empty feed"); const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(f)); const list<value> i = filter<value>(selector(mklist<value>(element, "id")), car(f)); const list<value> e = filter<value>(selector(mklist<value>(element, entry)), car(f)); - return mklist<value>(append<value>(list<value>() + element + feed - + value(list<value>() + element + value("title") + elementValue(car(t))) - + value(list<value>() + element + value("id") + elementValue(car(i))), + return mklist<value>(append<value>(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<value>)v) == type); - } -}; - const list<value> contentElementChildren(const value& content) { - return filter<value>(filterContentElementChildren(), elementChildren(content)); + return filter<value>([](const value& v) { + return !(isAttribute(v) && attributeName((list<value>)v) == "type"); + }, elementChildren(content)); } /** @@ -146,18 +139,18 @@ const list<value> entryElement(const list<value>& l) { const value updated = elementChild("updated", l); const value content = elementChild("content", l); const bool text = isNil(content)? false : elementHasValue(content); - return list<value>() - + element + entry + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") - + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + elementValue(title)) - + (list<value>() + element + "id" + elementValue(id)) - + (isNil(author)? list<value>() : (list<value>() + element + "author" + - (email? (list<value>() + element + "email" + elementValue(author)) : (list<value>() + element + "name" + elementValue(author))))) - + (isNil(updated)? list<value>() : (list<value>() + 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<value>() : - append<value>(list<value>() + element + "content" + (list<value>() + attribute + "type" + (text? "text" : "application/xml")), + nilListValue : + append<value>(nilListValue + element + "content" + (nilListValue + attribute + "type" + (text? "text" : "application/xml")), text? mklist<value>(elementValue(content)) : contentElementChildren(content))) - + (list<value>() + element + "link" + (list<value>() + attribute + "href" + elementValue(id))); + + (nilListValue + element + "link" + (nilListValue + attribute + "href" + elementValue(id))); } /** @@ -172,9 +165,9 @@ const list<value> entriesElements(const list<value>& l) { /** * Convert a list of element values representing an ATOM entry to an ATOM entry. */ -template<typename R> const failable<R> writeATOMEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { +template<typename R> const failable<R> writeATOMEntry(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { const list<value> l = isNil(ll)? ll : (list<value>)car(ll); - return writeXML<R>(reduce, initial, mklist<value>(entryElement(l))); + return xml::writeElements<R>(reduce, initial, mklist<value>(entryElement(l))); } const failable<list<string> > writeATOMEntry(const list<value>& l) { @@ -187,31 +180,31 @@ const failable<list<string> > writeATOMEntry(const list<value>& l) { /** * Convert a list of element values representing an ATOM feed to an ATOM feed. */ -template<typename R> const failable<R> writeATOMFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { +template<typename R> const failable<R> writeATOMFeed(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { const list<value> l = isNil(ll)? ll : (list<value>)car(ll); const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l); const value t = isNil(lt)? value(emptyString) : elementValue(car(lt)); const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); - const list<value> f = list<value>() - + element + feed + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") - + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + t) - + (list<value>() + element + "id" + i); + const list<value> 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<value> le = filter<value>(selector(mklist<value>(element, entry)), l); if (isNil(le)) - return writeXML<R>(reduce, initial, mklist<value>(f)); + return xml::writeElements<R>(reduce, initial, mklist<value>(f)); // Write a single ATOM entry element with a list of values if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) { const list<value> fe = append(f, entriesElements(caddr<value>(car(le)))); - return writeXML<R>(reduce, initial, mklist<value>(fe)); + return xml::writeElements<R>(reduce, initial, mklist<value>(fe)); } // Write separate ATOM entry elements const list<value> fe = append(f, entriesElements(le)); - return writeXML<R>(reduce, initial, mklist<value>(fe)); + return xml::writeElements<R>(reduce, initial, mklist<value>(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("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<item>\n" - " <title>fruit</title>\n" - " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n" - " <description>\n" - " <item>\n" - " <name>Apple</name>\n" - " <price>$2.99</price>\n" - " </item>\n" - " </description>\n" + "<item>" + "<title>fruit</title>" + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" + "<description>" + "<item>" + "<name>Apple</name>" + "<price>$2.99</price>" + "</item>" + "</description>" "</item>\n"); const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<item>\n" - " <title>fruit</title>\n" - " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n" - " <description>Apple</description>\n" + "<item>" + "<title>fruit</title>" + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" + "<description>Apple</description>" "</item>\n"); const string itemNoDescriptionEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<item>\n" - " <title>fruit</title>\n" - " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n" + "<item>" + "<title>fruit</title>" + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" "</item>\n"); const string incompleteEntry("<item>\n" - " <title>fruit</title>\n" - " <description>\n" - " <Item xmlns=\"http://services/\">\n" - " <name xmlns=\"\">Orange</name>\n" - " <price xmlns=\"\">3.55</price>\n" - " </Item>\n" - " </description>\n" + "<title>fruit</title>" + "<description>" + "<Item xmlns=\"http://services/\">" + "<name xmlns=\"\">Orange</name>" + "<price xmlns=\"\">3.55</price>" + "</Item>" + "</description>" "</item>"); const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<item>\n" - " <title>fruit</title>\n" - " <link></link>\n" - " <description>\n" - " <Item xmlns=\"http://services/\">\n" - " <name xmlns=\"\">Orange</name>\n" - " <price xmlns=\"\">3.55</price>\n" - " </Item>\n" - " </description>\n" + "<item>" + "<title>fruit</title>" + "<link></link>" + "<description>" + "<Item xmlns=\"http://services/\">" + "<name xmlns=\"\">Orange</name>" + "<price xmlns=\"\">3.55</price>" + "</Item>" + "</description>" "</item>\n"); -bool testEntry() { +const bool testEntry() { { - const list<value> i = list<value>() + element + value("item") - + value(list<value>() + element + value("name") + value(string("Apple"))) - + value(list<value>() + element + value("price") + value(string("$2.99"))); - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("fruit"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("content") + value(i))); + const list<value> i = nilListValue + element + value("item") + + value(nilListValue + element + value("name") + value(string("Apple"))) + + value(nilListValue + element + value("price") + value(string("$2.99"))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemEntry); } { - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("fruit"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("content") + value(string("Apple")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemTextEntry); } { - const list<value> a = list<value>() + (list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("fruit"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == itemNoDescriptionEntry); @@ -141,48 +141,48 @@ bool testEntry() { } const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<rss version=\"2.0\">\n" - " <channel>\n" - " <title>Feed</title>\n" - " <link>1234</link>\n" - " <description>Feed</description>\n" - " </channel>\n" + "<rss version=\"2.0\">" + "<channel>" + "<title>Feed</title>" + "<link>1234</link>" + "<description>Feed</description>" + "</channel>" "</rss>\n"); const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<rss version=\"2.0\">\n" - " <channel>\n" - " <title>Feed</title>\n" - " <link>1234</link>\n" - " <description>Feed</description>\n" - " <item>\n" - " <title>fruit</title>\n" - " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n" - " <description>\n" - " <item>\n" - " <name>Apple</name>\n" - " <price>$2.99</price>\n" - " </item>\n" - " </description>\n" - " </item>\n" - " <item>\n" - " <title>fruit</title>\n" - " <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>\n" - " <description>\n" - " <item>\n" - " <name>Orange</name>\n" - " <price>$3.55</price>\n" - " </item>\n" - " </description>\n" - " </item>\n" - " </channel>\n" + "<rss version=\"2.0\">" + "<channel>" + "<title>Feed</title>" + "<link>1234</link>" + "<description>Feed</description>" + "<item>" + "<title>fruit</title>" + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>" + "<description>" + "<item>" + "<name>Apple</name>" + "<price>$2.99</price>" + "</item>" + "</description>" + "</item>" + "<item>" + "<title>fruit</title>" + "<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>" + "<description>" + "<item>" + "<name>Orange</name>" + "<price>$3.55</price>" + "</item>" + "</description>" + "</item>" + "</channel>" "</rss>\n"); -bool testFeed() { +const bool testFeed() { { - const list<value> a = list<value>() + (list<value>() + element + value("feed") - + value(list<value>() + element + value("title") + value(string("Feed"))) - + value(list<value>() + element + value("id") + value(string("1234")))); + const list<value> 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<ostream*>(writer, &os, a); assert(str(os) == emptyFeed); @@ -194,27 +194,27 @@ bool testFeed() { assert(str(os) == emptyFeed); } { - const list<value> i1 = list<value>() + element + "item" - + (list<value>() + element + "name" + "Apple") - + (list<value>() + element + "price" + "$2.99"); - - const list<value> i2 = list<value>() + element + "item" - + (list<value>() + element + "name" + "Orange") - + (list<value>() + element + "price" + "$3.55"); - - const list<value> i = list<value>() - + value(list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("fruit"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))) - + value(list<value>() + element + value("content") + value(i1))) - + value(list<value>() + element + value("entry") - + value(list<value>() + element + value("title") + value(string("fruit"))) - + value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"))) - + value(list<value>() + element + value("content") + value(i2))); + const list<value> i1 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Apple") + + (nilListValue + element + "price" + "$2.99"); + + const list<value> i2 = nilListValue + element + "item" + + (nilListValue + element + "name" + "Orange") + + (nilListValue + element + "price" + "$3.55"); + + const list<value> 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<value> a = list<value>() + (append<value>(list<value>() + element + value("feed") - + value(list<value>() + element + value("title") + value(string("Feed"))) - + value(list<value>() + element + value("id") + value("1234")), + const list<value> a = nilListValue + (append<value>(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<value> entryElementValues(const list<value>& e) { const list<value> li = filter<value>(selector(mklist<value>(element, "link")), e); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); const list<value> ld = filter<value>(selector(mklist<value>(element, "description")), e); - return append<value>(list<value>() + element + entry - + value(list<value>() + element + value("title") + t) - + value(list<value>() + element + value("id") + i), - isNil(ld)? list<value>() : mklist<value>(value(list<value>() + element + value("content") + elementValue(car(ld))))); + return append<value>(nilListValue + element + entry + + value(nilListValue + element + value("title") + t) + + value(nilListValue + element + value("id") + i), + isNil(ld)? nilListValue : mklist<value>(value(nilListValue + element + value("content") + elementValue(car(ld))))); } /** @@ -69,7 +69,7 @@ const list<value> entriesElementValues(const list<value>& e) { * Return true if a list of strings contains an RSS feed. */ const bool isRSSFeed(const list<string>& ls) { - if (!isXML(ls)) + if (!xml::isXML(ls)) return false; return contains(car(ls), "<rss"); } @@ -78,7 +78,7 @@ const bool isRSSFeed(const list<string>& ls) { * Convert a list of strings to a list of values representing an RSS entry. */ const failable<list<value> > readRSSEntry(const list<string>& ilist) { - const list<value> e = readXML(ilist); + const list<value> e = content(xml::readElements(ilist)); if (isNil(e)) return mkfailure<list<value> >("Empty entry"); return mklist<value>(entryElementValues(car(e))); @@ -88,16 +88,16 @@ const failable<list<value> > readRSSEntry(const list<string>& ilist) { * Convert a list of strings to a list of values representing an RSS feed. */ const failable<list<value> > readRSSFeed(const list<string>& ilist) { - const list<value> f = readXML(ilist); + const list<value> f = content(xml::readElements(ilist)); if (isNil(f)) return mkfailure<list<value> >("Empty feed"); const list<value> c = filter<value>(selector(mklist<value>(element, "channel")), car(f)); const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(c)); const list<value> i = filter<value>(selector(mklist<value>(element, "link")), car(c)); const list<value> e = filter<value>(selector(mklist<value>(element, "item")), car(c)); - return mklist<value>(append<value>(list<value>() + element + feed - + value(list<value>() + element + value("title") + elementValue(car(t))) - + value(list<value>() + element + value("id") + elementValue(car(i))), + return mklist<value>(append<value>(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<value> entryElement(const list<value>& l) { const value id = elementValue(elementChild("id", l)); const value content = elementChild("content", l); const bool text = isNil(content)? false : elementHasValue(content); - return append<value>(list<value>() + return append<value>(nilListValue + element + "item" - + (list<value>() + element + "title" + title) - + (list<value>() + element + "link" + id), + + (nilListValue + element + "title" + title) + + (nilListValue + element + "link" + id), isNil(content)? - list<value>() : - mklist<value>(append<value>(list<value>() + element + "description", + nilListValue : + mklist<value>(append<value>(nilListValue + element + "description", text? mklist<value>(elementValue(content)) : elementChildren(content)))); } @@ -132,9 +132,9 @@ const list<value> entriesElements(const list<value>& 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<typename R> const failable<R> writeRSSEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { +template<typename R> const failable<R> writeRSSEntry(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { const list<value> l = isNil(ll)? ll : (list<value>)car(ll); - return writeXML<R>(reduce, initial, mklist<value>(entryElement(l))); + return xml::writeElements<R>(reduce, initial, mklist<value>(entryElement(l))); } const failable<list<string> > writeRSSEntry(const list<value>& l) { @@ -148,41 +148,41 @@ const failable<list<string> > writeRSSEntry(const list<value>& 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<typename R> const failable<R> writeRSSFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { +template<typename R> const failable<R> writeRSSFeed(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) { const list<value> l = isNil(ll)? ll : (list<value>)car(ll); const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l); const value t = isNil(lt)? value(emptyString) : elementValue(car(lt)); const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l); const value i = isNil(li)? value(emptyString) : elementValue(car(li)); - const list<value> c = list<value>() - + (list<value>() + element + "title" + t) - + (list<value>() + element + "link" + i) - + (list<value>() + element + "description" + t); + const list<value> c = nilListValue + + (nilListValue + element + "title" + t) + + (nilListValue + element + "link" + i) + + (nilListValue + element + "description" + t); // Write RSS entries const list<value> le = filter<value>(selector(mklist<value>(element, entry)), l); if (isNil(le)) { - const list<value> fe = list<value>() - + element + "rss" + (list<value>() + attribute + "version" + "2.0") - + append(list<value>() + element + "channel", c); - return writeXML<R>(reduce, initial, mklist<value>(fe)); + const list<value> fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", c); + return xml::writeElements<R>(reduce, initial, mklist<value>(fe)); } // Write a single RSS entry element with a list of values if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) { const list<value> ce = append(c, entriesElements(caddr<value>(car(le)))); - const list<value> fe = list<value>() - + element + "rss" + (list<value>() + attribute + "version" + "2.0") - + append(list<value>() + element + "channel", ce); - return writeXML<R>(reduce, initial, mklist<value>(fe)); + const list<value> fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", ce); + return xml::writeElements<R>(reduce, initial, mklist<value>(fe)); } // Write separate RSS entry elements const list<value> ce = append(c, entriesElements(le)); - const list<value> fe = list<value>() - + element + "rss" + (list<value>() + attribute + "version" + "2.0") - + append(list<value>() + element + "channel", ce); - return writeXML<R>(reduce, initial, mklist<value>(fe)); + const list<value> fe = nilListValue + + element + "rss" + (nilListValue + attribute + "version" + "2.0") + + append(nilListValue + element + "channel", ce); + return xml::writeElements<R>(reduce, initial, mklist<value>(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<value> c = readXML(streamList(is)); + const list<value> c = content(xml::readElements(streamList(is))); return true; } -bool testComponents() { +const bool testComponents() { ifstream is("test.composite"); - const list<value> c = components(readXML(streamList(is))); + const list<value> 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<value> c = components(readXML(streamList(is))); + const list<value> 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<value> c = components(readXML(streamList(is))); + const list<value> 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<value> 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<value> c = components(readXML(streamList(is))); + const list<value> 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<value> nameToElementAssoc(const list<value>& 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<value> c = filter<value>(filterName(name), l); + }; + const list<value> c = filter<value>(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<value>(v)), "implementation."); -} - const value implementation(const value& l) { + const vblambda filterImplementation = [](const value& v) -> const bool { + return isElement(v) && contains(string(cadr<value>(v)), "implementation."); + }; const list<value> n = filter<value>(filterImplementation, l); if (isNil(n)) - return value(); + return nilValue; return car(n); } @@ -156,7 +149,7 @@ const list<value> bindings(const value& l) { */ const value bindingsTarget(const list<value>& 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/value-xml.cpp b/sca-cpp/trunk/modules/scheme/element-xml.cpp index ff785899c6..c7bc7661ab 100644 --- a/sca-cpp/trunk/modules/scheme/value-xml.cpp +++ b/sca-cpp/trunk/modules/scheme/element-xml.cpp @@ -25,15 +25,15 @@ #include "fstream.hpp" #include "string.hpp" -#include "xml.hpp" #include "element.hpp" +#include "../xml/xml.hpp" #include "eval.hpp" namespace tuscany { namespace scheme { -int valueXML() { - failable<list<string> > s = writeXML(readValue(cin)); +const int valueXML() { + const failable<list<string> > s = xml::writeElements(content(readValue(cin))); if (!hasContent(s)) { cerr << reason(s) << " : " << rcode(s); return 1; 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<value>(); + return nilListValue; } const bool isDefinition(const value& exp) { @@ -68,11 +68,11 @@ const gc_ptr<Frame> firstFrame(const Env& env) { return car(env); } -list<value> frameVariables(const Frame& frame) { +const list<value> frameVariables(const Frame& frame) { return car((list<value> )frame); } -list<value> frameValues(const Frame& frame) { +const list<value> frameValues(const Frame& frame) { return cdr((list<value> )frame); } @@ -103,8 +103,7 @@ const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, c } const gc_ptr<Frame> makeFrame(const list<value>& variables, const list<value> values) { - gc_ptr<Frame> frame = new (gc_new<Frame>()) Frame(); - *frame = value(makeBinding(cons(value(list<value>()), list<value>()), variables, values)); + const gc_ptr<Frame> frame = new (gc_new<Frame>()) Frame(makeBinding(cons(value(nilListValue), nilListValue), variables, values)); return frame; } @@ -120,7 +119,7 @@ const value definitionValue(const value& exp) { const list<value> exps(exp); if(isSymbol(car(cdr(exps)))) { if (isNil(cdr(cdr(exps)))) - return value(); + return nilValue; return car(cdr(cdr(exps))); } const list<value> 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<value>& 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<value>& arguments) { return evalSequence(procedureBody(procedure), env); } logStream() << "Unknown procedure type " << procedure << endl; - return value(); + return nilValue; } const value sequenceToExp(const list<value> exps) { @@ -209,16 +209,16 @@ const value expandClauses(const list<value>& 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<value> quotedParameters(const list<value>& 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<value>(")")); -const value leftParenthesis(mklist<value>("(")); -const value comment(mklist<value>(";")); +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<value> readValue(istream& in); -const failable<value> readToken(istream& in) { +inline const failable<value> readToken(istream& in) { const char firstChar = readChar(in); if(isWhitespace(firstChar)) return readToken(in); @@ -119,18 +118,19 @@ const failable<value> readToken(istream& in) { return readToken(in); } -const failable<value> skipComment(istream& in) { - const char nextChar = readChar(in); - if (nextChar == '\n') - return readToken(in); - return skipComment(in); +inline const failable<value> 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<value> readList(const list<value>& listSoFar, istream& in) { +inline const list<value> readList(const list<value>& listSoFar, istream& in) { const failable<value> ftoken = readToken(in); if (!hasContent(ftoken)) return reverse(listSoFar); @@ -142,95 +142,97 @@ const list<value> readList(const list<value>& listSoFar, istream& in) { return readList(cons(token, listSoFar), in); } -const string listToString(const list<char>& l) { - if(isNil(l)) - return ""; - const char buf[1] = { car(l) }; - return string(buf, 1) + listToString(cdr(l)); -} - -const list<char> readIdentifierHelper(const list<char>& 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<char> readStringHelper(const list<char>& 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<char>(), in)); -} - -const list<char> readNumberHelper(const list<char>& 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<value> readValue(istream& in) { const failable<value> fnextToken = readToken(in); if (!hasContent(fnextToken)) - return value(); + return nilValue; const value nextToken = content(fnextToken); if(isLeftParenthesis(nextToken)) - return readList(list<value>(), in); + return (value)readList(nilListValue, in); return nextToken; } -const value readValue(const string s) { +inline const failable<value> readValue(const string& s) { istringstream in(s); const failable<value> fnextToken = readToken(in); if (!hasContent(fnextToken)) - return value(); + return nilValue; const value nextToken = content(fnextToken); if(isLeftParenthesis(nextToken)) - return readList(list<value>(), in); + return (value)readList(nilListValue, in); return nextToken; } -const bool writeValue(const value& val, ostream& out) { +inline const failable<value> readValue(const list<string>& l) { + ostringstream os; + write(l, os); + return readValue(str(os)); +} + +inline const failable<ostream&> writeValue(const value& val, ostream& out) { out << val; - return true; + return out; } -const string writeValue(const value& val) { +inline const failable<list<string> > writeValue(const value& val) { ostringstream out; out << val; - return str(out); + return mklist<string>(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<value>(); + return nilListValue; return cons(val, (list<value>)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<ostream> displayOutStream; +const perthread_ptr<ostream> displayOutStream; #else ostream* displayOutStream = NULL; #endif @@ -51,49 +51,49 @@ perthread_ptr<ostream> 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<value>& args) { +inline const value carProc(const list<value>& args) { return car((list<value> )car(args)); } -const value cdrProc(const list<value>& args) { +inline const value cdrProc(const list<value>& args) { return cdr((list<value> )car(args)); } -const value consProc(const list<value>& args) { +inline const value consProc(const list<value>& args) { return cons(car(args), (list<value> )cadr(args)); } -const value listProc(const list<value>& args) { +inline const value listProc(const list<value>& args) { return args; } -const value assocProc(const list<value>& args) { +inline const value assocProc(const list<value>& args) { return assoc(car(args), (list<list<value> >)cadr(args)); } -const value nulProc(const list<value>& args) { +inline const value nulProc(const list<value>& args) { const value v(car(args)); if (isNil(v)) return true; @@ -102,31 +102,31 @@ const value nulProc(const list<value>& args) { return false; } -const value equalProc(const list<value>& args) { +inline const value equalProc(const list<value>& args) { return (bool)(car(args) == cadr(args)); } -const value addProc(const list<value>& args) { +inline const value addProc(const list<value>& args) { if (isNil(cdr(args))) return (double)car(args); return (double)car(args) + (double)cadr(args); } -const value subProc(const list<value>& args) { +inline const value subProc(const list<value>& args) { if (isNil(cdr(args))) return (double)0 - (double)car(args); return (double)car(args) - (double)cadr(args); } -const value mulProc(const list<value>& args) { +inline const value mulProc(const list<value>& args) { return (double)car(args) * (double)cadr(args); } -const value divProc(const list<value>& args) { +inline const value divProc(const list<value>& args) { return (double)car(args) / (double)cadr(args); } -const value displayProc(const list<value>& args) { +inline const value displayProc(const list<value>& args) { if (isNil(args)) { displayStream() << endl; return true; @@ -135,7 +135,7 @@ const value displayProc(const list<value>& args) { return displayProc(cdr(args)); } -const value logProc(const list<value>& args) { +inline const value logProc(const list<value>& args) { if (isNil(args)) { logStream() << endl; return true; @@ -144,52 +144,52 @@ const value logProc(const list<value>& args) { return logProc(cdr(args)); } -const value uuidProc(unused const list<value>& args) { +inline const value uuidProc(unused const list<value>& args) { return mkuuid(); } -const value cadrProc(const list<value>& args) { +inline const value cadrProc(const list<value>& args) { return cadr((list<value> )car(args)); } -const value caddrProc(const list<value>& args) { +inline const value caddrProc(const list<value>& args) { return caddr((list<value> )car(args)); } -const value cadddrProc(const list<value>& args) { +inline const value cadddrProc(const list<value>& args) { return cadddr((list<value> )car(args)); } -const value cddrProc(const list<value>& args) { +inline const value cddrProc(const list<value>& args) { return cddr((list<value> )car(args)); } -const value cdddrProc(const list<value>& args) { +inline const value cdddrProc(const list<value>& args) { return cdddr((list<value> )car(args)); } -const value appendProc(const list<value>& args) { +inline const value appendProc(const list<value>& args) { return append((list<value> )car(args), (list<value>)cadr(args)); } -const value startProc(unused const list<value>& args) { - return lambda<value(const list<value>&)>(); +inline const value startProc(unused const list<value>& args) { + return lvvlambda(); } -const value stopProc(unused const list<value>& args) { - return lambda<value(const list<value>&)>(); +inline const value stopProc(unused const list<value>& args) { + return lvvlambda(); } -const value applyPrimitiveProcedure(const value& proc, list<value>& args) { - const lambda<value(const list<value>&)> func(cadr((list<value>)proc)); +inline const value applyPrimitiveProcedure(const value& proc, list<value>& args) { + const lvvlambda func(cadr((list<value>)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<value>& proc) { +inline const value primitiveImplementation(const list<value>& proc) { return car(cdr(proc)); } -template<typename F> const value primitiveProcedure(const F& f) { - return mklist<value>(primitiveSymbol, (lambda<value(const list<value>&)>)f); +template<typename F> inline const value primitiveProcedure(const F& f) { + return mklist<value>(primitiveSymbol, (lvvlambda)f); } -const list<value> primitiveProcedureNames() { +inline const list<value> primitiveProcedureNames() { return mklist<value>("car") + "cdr" + "cons" @@ -237,7 +237,7 @@ const list<value> primitiveProcedureNames() { + "stop"; } -const list<value> primitiveProcedureObjects() { +inline const list<value> primitiveProcedureObjects() { return mklist(primitiveProcedure(carProc)) + primitiveProcedure(cdrProc) + primitiveProcedure(consProc) @@ -263,23 +263,23 @@ const list<value> 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<value> )exp)); } -const value makeLambda(const list<value>& parameters, const list<value>& body) { +inline const value makeLambda(const list<value>& parameters, const list<value>& body) { return cons(lambdaSymbol, cons<value>(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 <assert.h> #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<value>(); +const bool testEnv() { + const gc_scoped_pool pool; + Env globalEnv = nilListValue; Env env = extendEnvironment(mklist<value>("a"), mklist<value>(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<value>("abcd", "xyz")); + assert(content(readValue(is4)) == mklist<value>("abcd", "xyz")); istringstream is5("(abcd (xyz tuv))"); - assert(readValue(is5) == mklist<value>("abcd", mklist<value>("xyz", "tuv"))); + assert(content(readValue(is5)) == mklist<value>("abcd", mklist<value>("xyz", "tuv"))); return true; } -bool testWrite() { +const bool testWrite() { { - const list<value> i = list<value>() - + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - + (list<value>() + "item" - + (list<value>() + "name" + "Apple") - + (list<value>() + "price" + "$2.99"))) - + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - + (list<value>() + "item" - + (list<value>() + "name" + "Orange") - + (list<value>() + "price" + "$3.55"))); + const list<value> 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<value> a = cons<value>("Feed", cons<value>("feed-1234", i)); ostringstream os; writeValue(a, os); istringstream is(str(os)); - assert(readValue(is) == a); + assert(content(readValue(is)) == a); } { - const list<value> i = mklist<value>("x", value()); + const list<value> i = mklist<value>("x", nilValue); const list<value> a = mklist<value>(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<value>("+", 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<value>("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<value>("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/xml-value.cpp b/sca-cpp/trunk/modules/scheme/xml-element.cpp index d88f754aa5..2050004895 100644 --- a/sca-cpp/trunk/modules/scheme/xml-value.cpp +++ b/sca-cpp/trunk/modules/scheme/xml-element.cpp @@ -25,16 +25,16 @@ #include "fstream.hpp" #include "string.hpp" -#include "xml.hpp" #include "element.hpp" +#include "../xml/xml.hpp" #include "eval.hpp" namespace tuscany { namespace scheme { -int xmlValue() { - const value v = readXML(streamList(cin)); - cout << writeValue(v); +const int xmlValue() { + const value v = content(xml::readElements(streamList(cin))); + write(content(writeValue(v)), cout); return 0; } 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 @@ +<?xml version="1.0" encoding="UTF-8"?> +<feed><title>Search Results</title><id>search</id><entry><title>An empty app template</title><id>new</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty test app</title><id>test</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Check my public social data</title><id>me360</id><author>admin@example.com</author><updated>Apr 28, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme</title><id>nearme</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme2</title><id>nearme2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Our photos of an event</title><id>ourphotos</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>My online store</title><id>shoppingcart</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Slice</title><id>slice</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test animation components</title><id>testanimation</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test database components</title><id>testdb</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test event components</title><id>testevents</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test logic components</title><id>testlogic</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test search components</title><id>testsearch</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test social components</title><id>testsocial</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test text processing components</title><id>testtext</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test URL components</title><id>testurl</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test values and lists</title><id>testvalues</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test widgets</title><id>testwidgets</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test more widgets</title><id>testwidgets2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTML generator components</title><id>testwidgets3</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>jsdtest</title><id>jsdtest</id><author>jsdelfino</author><updated>Jul 27, 2012</updated><content><stats><description>Test app</description></stats></content></entry><entry><title>SMS send service</title><id>twsms</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>boao</title><id>boao</id><author>jsdelfino</author><updated>2012-10-12T12:06:59+00:00</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty test app</title><id>test</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty app template</title><id>new</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme</title><id>nearme</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme2</title><id>nearme2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Our photos of an event</title><id>ourphotos</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>My online store</title><id>shoppingcart</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Slice</title><id>slice</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test animation components</title><id>testanimation</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test database components</title><id>testdb</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test event components</title><id>testevents</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test social components</title><id>testsocial</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test logic components</title><id>testlogic</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test search components</title><id>testsearch</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test text processing components</title><id>testtext</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test URL components</title><id>testurl</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test values and lists</title><id>testvalues</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test widgets</title><id>testwidgets</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test more widgets</title><id>testwidgets2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTML generator components</title><id>testwidgets3</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>test9</title><id>test9</id><author>jsdelfino</author><updated>2012-09-25T06:17:18+00:00</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>SMS send service</title><id>twsms</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Check my public social data</title><id>me360</id><author>admin@example.com</author><updated>Apr 28, 2012</updated><content><stats><description>Sample app</description></stats></content></entry></feed> 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 <assert.h> +#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 = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" targetNamespace=\"http://services\" name=\"currency\">" + "<component name=\"CurrencyConverterWebService\">" + "<implementation.java class=\"services.CurrencyConverterImpl\"/>" + "<service name=\"CurrencyConverter\">" + "<binding.ws/>" + "</service>" + "</component>" + "<component name=\"CurrencyConverterWebService2\">" + "<implementation.java class=\"services.CurrencyConverterImpl2\"/>" + "<service name=\"CurrencyConverter2\">" + "<binding.atom/>" + "</service>" + "<property name=\"currency\">US</property>" + "</component>" +"</composite>\n"; + +const string customerXML = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<customer>" + "<name>jdoe</name>" + "<address>" + "<city>san francisco</city>" + "<state>ca</state>" + "</address>" + "<account>" + "<id>1234</id>" + "<balance>1000</balance>" + "</account>" + "<account>" + "<id>6789</id>" + "<balance>2000</balance>" + "</account>" + "<account>" + "<id>4567</id>" + "<balance>3000</balance>" + "</account>" +"</customer>\n"; + +const string abcXML = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<a>" + "<m>abc</m>" + "<m>def</m>" + "<m>xyz</m>" + "<m>tuv</m>" +"</a>\n"; + +const string xyzXML = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<a>" + "<m>" + "<id>123</id>" + "<name>abc</name>" + "</m>" + "<m>" + "<id>234</id>" + "<name>def</name>" + "</m>" + "<m>" + "<id>345</id>" + "<name>xyz</name>" + "</m>" + "<m>" + "<id>456</id>" + "<name>tuv</name>" + "</m>" +"</a>\n"; + +const string boolXML = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<x>true</x>\n"; + +const string numberXML = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<x>123.4</x>\n"; + +const bool isName(const value& token) { + return isTaggedList(token, attribute) && attributeName(token) == "name"; +} + +const bool testReadXML() { + { + istringstream is(customerXML); + const list<value> c = content(readElements(streamList(is))); + } + { + istringstream is(currencyXML); + const list<value> c = content(readElements(streamList(is))); + + const value composite = car(c); + assert(isTaggedList(composite, element)); + assert(elementName(composite) == "composite"); + assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency")); + } + { + istringstream is(boolXML); + const list<value> c = content(readElements(streamList(is))); + assert(caddr<value>(car(c)) == value(true)); + } + { + istringstream is(numberXML); + const list<value> c = content(readElements(streamList(is))); + assert(caddr<value>(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<value> c = content(readElements(streamList(is))); + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, c); + assert(str(os) == customerXML); + } + { + istringstream is(currencyXML); + const list<value> c = content(readElements(streamList(is))); + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, c); + assert(str(os) == currencyXML); + } + return true; +} + +const bool testElements() { + { + const list<value> ad = mklist<value>(mklist<value>("city", string("san francisco")), mklist<value>("state", string("ca"))); + const list<value> ac1 = mklist<value>(mklist<value>("id", string("1234")), mklist<value>("balance", 1000)); + const list<value> ac2 = mklist<value>(mklist<value>("id", string("6789")), mklist<value>("balance", 2000)); + const list<value> ac3 = mklist<value>(mklist<value>("id", string("4567")), mklist<value>("balance", 3000)); + { + const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3)))); + const list<value> e = valuesToElements(c); + const list<value> v = elementsToValues(e); + assert(v == c); + + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + { + const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3))); + const list<value> e = valuesToElements(c); + const list<value> v = elementsToValues(e); + + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + } + { + istringstream is(abcXML); + const list<value> c = content(readElements(streamList(is))); + const list<value> v = elementsToValues(c); + const list<value> e = valuesToElements(v); + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, e); + assert(str(os) == abcXML); + } + { + istringstream is(xyzXML); + const list<value> c = content(readElements(streamList(is))); + const list<value> v = elementsToValues(c); + const list<value> e = valuesToElements(v); + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, e); + assert(str(os) == xyzXML); + } + { + istringstream is(customerXML); + const list<value> c = content(readElements(streamList(is))); + const list<value> v = elementsToValues(c); + const list<value> e = valuesToElements(v); + ostringstream os; + writeElements<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); + } + return true; +} + +const bool testValues() { + { + const list<value> l = mklist<value>(nilListValue + "ns1:echoString" + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (nilListValue + "text" + string("Hello World!"))); + const list<value> e = valuesToElements(l); + const failable<list<string> > lx = writeElements(e); + ostringstream os; + write(content(lx), os); + istringstream is(str(os)); + const list<value> x = content(readElements(streamList(is))); + const list<value> v = elementsToValues(x); + assert(v == l); + } + return true; +} + +const bool testReadWrite() { + const gc_scoped_pool pool; + + istringstream is(customerXML); + const list<string> il = streamList(is); + const list<value> r = elementsToValues(content(readElements(il))); + + ostringstream os; + writeElements<ostream*>(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<string> il = streamList(is); + const list<value> r = elementsToValues(content(readElements(il))); + + ostringstream os; + writeElements<ostream*>(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 = +"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +"<customers>" + "<customer>" + "<name>jane doe</name>" + "<address>" + "<city>san francisco</city>" + "<state>ca</state>" + "</address>" + "<account>" + "<id>1234</id>" + "<balance>1000</balance>" + "</account>" + "<account>" + "<id>6789</id>" + "<balance>4000</balance>" + "</account>" + "</customer>" + "<customer>" + "<name>john doe</name>" + "<address>" + "<city>new york</city>" + "<state>ny</state>" + "</address>" + "<account>" + "<id>5678</id>" + "<balance>2000</balance>" + "</account>" + "<account>" + "<id>4321</id>" + "<balance>1000</balance>" + "</account>" + "</customer>" +"</customers>\n"; + +const bool testQuery() { + { + const gc_scoped_pool pool; + + // Read XML doc containing customers + istringstream is(customersXML); + const list<value> c = content(readElements(streamList(is))); + //cout << c << endl; + + // Map list of customers to a list of (customer name, customer balance) pairs + const list<value> nb = map<value, value>([](value e) -> const value { + + // Map list of accounts to a list of balances + list<value> bals = map<value, value>([](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, value>([](value accum, value v) -> const value { + return (double)accum + (double)v; + }, value(0), bals); + + // Return (customer name, customer balance) pair + return mklist<value>(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<value>(mklist<value>("jane doe", 5000), mklist<value>("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 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<feed><title>Search Results</title><id>search</id><entry><title>An empty app template</title><id>new</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty test app</title><id>test</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Check my public social data</title><id>me360</id><author>admin@example.com</author><updated>Apr 28, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme</title><id>nearme</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme2</title><id>nearme2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Our photos of an event</title><id>ourphotos</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>My online store</title><id>shoppingcart</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Slice</title><id>slice</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test animation components</title><id>testanimation</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test database components</title><id>testdb</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test event components</title><id>testevents</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test logic components</title><id>testlogic</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test search components</title><id>testsearch</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test social components</title><id>testsocial</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test text processing components</title><id>testtext</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test URL components</title><id>testurl</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test values and lists</title><id>testvalues</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test widgets</title><id>testwidgets</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test more widgets</title><id>testwidgets2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTML generator components</title><id>testwidgets3</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>jsdtest</title><id>jsdtest</id><author>jsdelfino</author><updated>Jul 27, 2012</updated><content><stats><description>Test app</description></stats></content></entry><entry><title>SMS send service</title><id>twsms</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>boao</title><id>boao</id><author>jsdelfino</author><updated>2012-10-12T12:06:59+00:00</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty test app</title><id>test</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>An empty app template</title><id>new</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme</title><id>nearme</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>nearme2</title><id>nearme2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Our photos of an event</title><id>ourphotos</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>My online store</title><id>shoppingcart</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Slice</title><id>slice</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test animation components</title><id>testanimation</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test database components</title><id>testdb</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test event components</title><id>testevents</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test social components</title><id>testsocial</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test logic components</title><id>testlogic</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test search components</title><id>testsearch</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTTP components</title><id>testhttp</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test text processing components</title><id>testtext</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test URL components</title><id>testurl</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test values and lists</title><id>testvalues</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test widgets</title><id>testwidgets</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test more widgets</title><id>testwidgets2</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Test HTML generator components</title><id>testwidgets3</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>test9</title><id>test9</id><author>jsdelfino</author><updated>2012-09-25T06:17:18+00:00</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>SMS send service</title><id>twsms</id><author>admin@example.com</author><updated>Jan 01, 2012</updated><content><stats><description>Sample app</description></stats></content></entry><entry><title>Check my public social data</title><id>me360</id><author>admin@example.com</author><updated>Apr 28, 2012</updated><content><stats><description>Sample app</description></stats></content></entry></feed>\n"; + +} +} + diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/modules/xml/xml.hpp index d00a2905fb..0a04d5f90a 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/modules/xml/xml.hpp @@ -38,24 +38,20 @@ #include "monad.hpp" namespace tuscany { - -/** - * APR-based memory management functions. - */ - +namespace xml { /** * Initializes the libxml2 library. */ class XMLParser { public: - XMLParser() { + inline XMLParser() { debug("xml::XMLParser"); xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup); xmlInitParser(); } - ~XMLParser() { + inline ~XMLParser() { } } xmlParser; @@ -68,30 +64,19 @@ public: 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) { + 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); } - XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) { + 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"); } - 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& operator=(const XMLReader& r) = delete; - ~XMLReader() { + inline ~XMLReader() { if (!owner) return; xmlTextReaderClose(xml); @@ -101,7 +86,7 @@ public: /** * Read the next XML token and return its type. */ - int read() { + inline const int read() { if (tokenType == End) return tokenType; if (tokenType == Element) { @@ -120,13 +105,13 @@ public: return tokenType = xmlTextReaderNodeType(xml); } - operator xmlTextReaderPtr() const { + inline operator xmlTextReaderPtr() const { return xml; } private: - xmlTextReaderPtr xml; - bool owner; + const xmlTextReaderPtr xml; + const bool owner; int tokenType; bool isEmptyElement; bool hasValue; @@ -140,37 +125,55 @@ 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. */ -const value readIdentifier(XMLReader& reader) { - const char* name = (const char*)xmlTextReaderConstName(reader); +inline const value readIdentifier(XMLReader& reader) { + const char* const 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); +inline const value readText(XMLReader& reader) { + const char* const val = (const char*)xmlTextReaderConstValue(reader); + return readTextValue(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<value>(attribute, name, string(val)); +inline const value readAttribute(XMLReader& reader) { + const char* const name = (const char*)xmlTextReaderConstName(reader); + const char* const val = (const char*)xmlTextReaderConstValue(reader); + return mklist<value>(attribute, name, readTextValue(val)); } /** * Read an XML token. */ -const value readToken(XMLReader& reader) { +inline const value readToken(XMLReader& reader) { const int tokenType = reader.read(); if (tokenType == XMLReader::None || tokenType == XMLReader::End) - return value(); + return nilValue; if (tokenType == XMLReader::Element) return startElement; if (tokenType == XMLReader::Identifier) @@ -187,7 +190,7 @@ const value readToken(XMLReader& reader) { /** * Read a list of values from XML tokens. */ -const list<value> readList(const list<value>& listSoFar, XMLReader& reader) { +inline const list<value> readList(const list<value>& listSoFar, XMLReader& reader) { const value token = readToken(reader); if(isNil(token) || endElement == token) return reverse(listSoFar); @@ -199,11 +202,11 @@ const list<value> readList(const list<value>& listSoFar, XMLReader& reader) { /** * Read a list of values from a libxml2 XML reader. */ -const list<value> read(XMLReader& reader) { - value nextToken = readToken(reader); +inline const list<value> read(XMLReader& reader) { + const value nextToken = readToken(reader); if (startElement == nextToken) return mklist<value>(readList(mklist(element), reader)); - return list<value>(); + return nilListValue; } /** @@ -211,17 +214,18 @@ const list<value> read(XMLReader& reader) { */ class XMLReadContext { public: - XMLReadContext(const list<string>& ilist) : ilist(ilist) { + inline XMLReadContext(const list<string>& ilist) : ilist(ilist) { } - list<string> ilist; + + gc_mutable_ref<list<string> > ilist; }; /** * Callback function called by libxml2 to read XML. */ -int readCallback(void *context, char* buffer, int len) { - XMLReadContext& rc = *static_cast<XMLReadContext*>(context); - if (isNil(rc.ilist)) +inline int readCallback(void *context, char* buffer, int len) { + XMLReadContext& rc = *(XMLReadContext*)context; + if (isNil((const list<string>)rc.ilist)) return 0; const list<string> f(fragment(rc.ilist, len)); const string s(car(f)); @@ -233,7 +237,7 @@ int readCallback(void *context, char* buffer, int len) { /** * Return true if a list of strings contains an XML document. */ -const bool isXML(const list<string>& ls) { +inline const bool isXML(const list<string>& ls) { if (isNil(ls)) return false; return substr(car(ls), 0, 5) == "<?xml"; @@ -242,12 +246,12 @@ const bool isXML(const list<string>& ls) { /** * Read a list of values from a list of strings representing an XML document. */ -const list<value> readXML(const list<string>& ilist) { - debug(ilist, "xml::readXML"); +inline const failable<list<value> > readElements(const list<string>& ilist) { + debug(ilist, "xml::readElements"); XMLReadContext cx(ilist); - xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT); + const xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT); if (xml == NULL) - return list<value>(); + return nilListValue; XMLReader reader(xml); return read(reader); } @@ -255,19 +259,19 @@ const list<value> readXML(const list<string>& ilist) { /** * Default encoding used to write XML documents. */ -const char* encoding = "UTF-8"; +const char* const encoding = "UTF-8"; /** * Write a list of XML element or attribute tokens. */ -const list<value> expandElementValues(const value& n, const list<value>& l) { +inline const list<value> expandElementValues(const value& n, const list<value>& l) { if (isNil(l)) return l; return cons<value>(value(cons<value>(element, cons<value>(n, isList(car(l))? (list<value>)car(l) : mklist(car(l))))), expandElementValues(n, cdr(l))); } -const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) { +inline const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) { if (isNil(l)) return true; @@ -331,7 +335,7 @@ const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) /** * Write a list of values to a libxml2 XML writer. */ -const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, bool xmlTag) { +inline const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, bool xmlTag) { if (xmlTag) { if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) return mkfailure<bool>("xmlTextWriterStartDocument failed"); @@ -353,17 +357,18 @@ const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, boo */ template<typename R> class XMLWriteContext { public: - XMLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + inline XMLWriteContext(const lambda<const R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda<R(const string&, const R)> reduce; - R accum; + + const lambda<const R(const string&, const R)> reduce; + gc_mutable_ref<R> accum; }; /** * Callback function called by libxml2 to write XML out. */ -template<typename R> int writeCallback(void *context, const char* buffer, int len) { - XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context); +template<typename R> inline int writeCallback(void *context, const char* buffer, int len) { + XMLWriteContext<R>& cx = *(XMLWriteContext<R>*)context; cx.accum = cx.reduce(string(buffer, len), cx.accum); return len; } @@ -371,7 +376,7 @@ template<typename R> int writeCallback(void *context, const char* buffer, int le /** * Convert a list of values to an XML document. */ -template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const bool xmlTag) { +template<typename R> inline const failable<R> writeElements(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const bool xmlTag) { XMLWriteContext<R> cx(reduce, initial); xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL); if (out == NULL) @@ -379,34 +384,35 @@ template<typename R> const failable<R> writeXML(const lambda<R(const string&, co xmlTextWriterPtr xml = xmlNewTextWriter(out); if (xml == NULL) return mkfailure<R>("xmlNewTextWriter failed"); - xmlTextWriterSetIndent(xml, 1); + xmlTextWriterSetIndent(xml, 0); const failable<bool> w = write(l, xml, xmlTag); xmlFreeTextWriter(xml); if (!hasContent(w)) { return mkfailure<R>(w); } - return cx.accum; + return (R)cx.accum; } -template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { - return writeXML(reduce, initial, l, true); +template<typename R> inline const failable<R> writeElements(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { + return writeElements(reduce, initial, l, true); } /** * Convert a list of values to a list of strings representing an XML document. */ -const failable<list<string> > writeXML(const list<value>& l, const bool xmlTag) { - debug(l, "xml::writeXML"); - const failable<list<string> > ls = writeXML<list<string> >(rcons<string>, list<string>(), l, xmlTag); +inline const failable<list<string> > writeElements(const list<value>& l, const bool xmlTag) { + debug(l, "xml::writeElements"); + const failable<list<string> > ls = writeElements<list<string> >(rcons<string>, list<string>(), l, xmlTag); if (!hasContent(ls)) return ls; return reverse(list<string>(content(ls))); } -const failable<list<string> > writeXML(const list<value>& l) { - return writeXML(l, true); +inline const failable<list<string> > writeElements(const list<value>& l) { + return writeElements(l, true); } } +} #endif /* tuscany_xml_hpp */ diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/modules/xml/xsd-test.cpp index fbd2ee6dca..b10ad27379 100644 --- a/sca-cpp/trunk/kernel/xsd-test.cpp +++ b/sca-cpp/trunk/modules/xml/xsd-test.cpp @@ -30,11 +30,11 @@ namespace tuscany { -bool printNode(xmlTextReaderPtr reader) { +const bool printNode(xmlTextReaderPtr reader) { const xmlChar* name = xmlTextReaderConstName(reader); if(name == NULL) name = (xmlChar *)"<unknown>"; - const xmlChar* value = xmlTextReaderConstValue(reader); + const xmlChar* const value = xmlTextReaderConstValue(reader); cerr << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); if(value == NULL) @@ -53,7 +53,7 @@ int xmlClose(void *context) { return 0; } -bool readFile(const char*xsdfilename, const char *filename) { +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); @@ -61,7 +61,7 @@ bool readFile(const char*xsdfilename, const char *filename) { const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); cout << "Reading file " << filename << endl; - FILE* file = fopen(filename, "r"); + 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); @@ -93,7 +93,7 @@ bool readFile(const char*xsdfilename, const char *filename) { } -int main(int argc, char **argv) { +int main(const int argc, const char** const argv) { tuscany::cout << "Testing..." << tuscany::endl; if(argc != 3) return 1; |