diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-02 10:27:26 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2010-01-02 10:27:26 +0000 |
commit | 95fa76f5f3208d913320c13a05171ecdcd7134c2 (patch) | |
tree | 872e101cd2fb1505baf313940e48c6b615fd6725 /sca-cpp | |
parent | 1d04916fda43146fb62488c20ba03b7b3006c8e9 (diff) |
Performance improvements when running both in multi-threaded and pre-forked HTTPD. Changed memory management to use Apache APR pools instead of ref counting pointers as it's much faster and easier to integrate with the Python and Ruby interpreters. Changed to use simple pool-based string and stream implementations instead of the STL ones, which cause a lots of mutex locks in a multi-threaded environment. Added build options to compile with threading and profiling.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@895165 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp')
55 files changed, 2649 insertions, 1685 deletions
diff --git a/sca-cpp/trunk/components/cache/mcache-client-test.cpp b/sca-cpp/trunk/components/cache/mcache-client-test.cpp index 2e444250c7..e3bf5f7a2e 100644 --- a/sca-cpp/trunk/components/cache/mcache-client-test.cpp +++ b/sca-cpp/trunk/components/cache/mcache-client-test.cpp @@ -24,8 +24,8 @@ */ #include <assert.h> -#include <iostream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "list.hpp" #include "value.hpp" @@ -36,46 +36,46 @@ namespace tuscany { namespace cache { -const std::string url("http://localhost:8090/mcache"); +const string url("http://localhost:8090/mcache"); bool testCache() { http::CURLSession cs; const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$2.99")); - const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - const failable<value, std::string> id = http::post(a, url, cs); + const failable<value> id = http::post(a, url, cs); assert(hasContent(id)); { - const failable<value, std::string> val = http::get(url + "/" + std::string(content(id)), cs); + const failable<value> val = http::get(url + "/" + content(id), cs); assert(hasContent(val)); assert(content(val) == a); } const list<value> j = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$3.55")); - const list<value> b = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$3.55")); + const list<value> b = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), j); { - const failable<value, std::string> r = http::put(b, url + "/" + std::string(content(id)), cs); + const failable<value> r = http::put(b, url + "/" + content(id), cs); assert(hasContent(r)); assert(content(r) == value(true)); } { - const failable<value, std::string> val = http::get(url + "/" + std::string(content(id)), cs); + const failable<value> val = http::get(url + "/" + content(id), cs); assert(hasContent(val)); assert(content(val) == b); } { - const failable<value, std::string> r = http::del(url + "/" + std::string(content(id)), cs); + const failable<value> r = http::del(url + "/" + content(id), cs); assert(hasContent(r)); assert(content(r) == value(true)); } { - const failable<value, std::string> val = http::get(url + "/" + std::string(content(id)), cs); + const failable<value> val = http::get(url + "/" + content(id), cs); assert(!hasContent(val)); } @@ -89,7 +89,7 @@ struct getLoop { getLoop(const value& id, const value& entry, http::CURLSession cs) : id(id), entry(entry), cs(cs) { } const bool operator()() const { - const failable<value, std::string> val = http::get(url + "/" + std::string(id), cs); + const failable<value> val = http::get(url + "/" + id, cs); assert(hasContent(val)); assert(content(val) == entry); return true; @@ -98,16 +98,16 @@ struct getLoop { bool testGetPerf() { const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$4.55")); - const value a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$4.55")); + const value a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); http::CURLSession cs; - const failable<value, std::string> id = http::post(a, url, cs); + const failable<value> id = http::post(a, url, cs); assert(hasContent(id)); const lambda<bool()> gl = getLoop(content(id), a, cs); - std::cout << "Cache get test " << time(gl, 5, 200) << " ms" << std::endl; + cout << "Cache get test " << time(gl, 5, 200) << " ms" << endl; return true; } @@ -116,12 +116,12 @@ bool testGetPerf() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::cache::testCache(); tuscany::cache::testGetPerf(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/components/cache/mcache-test.cpp b/sca-cpp/trunk/components/cache/mcache-test.cpp index dc286687c0..90f17ffd48 100644 --- a/sca-cpp/trunk/components/cache/mcache-test.cpp +++ b/sca-cpp/trunk/components/cache/mcache-test.cpp @@ -24,8 +24,8 @@ */ #include <assert.h> -#include <iostream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "perf.hpp" #include "mcache.hpp" @@ -35,10 +35,10 @@ namespace cache { bool testMemCached() { MemCached ch; - assert(hasContent(post("a", std::string("AAA"), ch))); - assert(get("a", ch) == value(std::string("AAA"))); - assert(hasContent(put("a", std::string("aaa"), ch))); - assert(get("a", ch) == value(std::string("aaa"))); + assert(hasContent(post("a", string("AAA"), ch))); + assert((get("a", ch)) == value(string("AAA"))); + assert(hasContent(put("a", string("aaa"), ch))); + assert((get("a", ch)) == value(string("aaa"))); assert(hasContent(del("a", ch))); assert(!hasContent(get("a", ch))); @@ -50,18 +50,17 @@ struct getLoop { getLoop(MemCached& ch) : ch(ch) { } const bool operator()() const { - assert(get("c", ch) == value(std::string("CCC"))); + assert((get("c", ch)) == value(string("CCC"))); return true; } }; bool testGetPerf() { MemCached ch; - assert(hasContent(post("c", std::string("CCC"), ch))); + assert(hasContent(post("c", string("CCC"), ch))); const lambda<bool()> gl = getLoop(ch); - std::cout << "Memcached get test " << time(gl, 5, 200) << " ms" << std::endl; - + cout << "Memcached get test " << time(gl, 5, 200) << " ms" << endl; return true; } @@ -69,12 +68,12 @@ bool testGetPerf() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::cache::testMemCached(); tuscany::cache::testGetPerf(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/components/cache/mcache.cpp b/sca-cpp/trunk/components/cache/mcache.cpp index 926fb66674..3e8fdeb294 100644 --- a/sca-cpp/trunk/components/cache/mcache.cpp +++ b/sca-cpp/trunk/components/cache/mcache.cpp @@ -25,7 +25,7 @@ #include <apr_uuid.h> -#include <string> +#include "string.hpp" #include "function.hpp" #include "list.hpp" @@ -41,7 +41,7 @@ cache::MemCached ch; /** * Get an item from the cache. */ -const failable<value, std::string> get(const list<value>& params) { +const failable<value> get(const list<value>& params) { return cache::get(car(params), ch); } @@ -53,34 +53,34 @@ const value uuidValue() { apr_uuid_get(&uuid); char buf[APR_UUID_FORMATTED_LENGTH]; apr_uuid_format(buf, &uuid); - return value(std::string(buf, APR_UUID_FORMATTED_LENGTH)); + return value(string(buf, APR_UUID_FORMATTED_LENGTH)); } -const failable<value, std::string> post(const list<value>& params) { +const failable<value> post(const list<value>& params) { const value id = uuidValue(); - const failable<bool, std::string> val = cache::post(id, car(params), ch); + const failable<bool> val = cache::post(id, car(params), ch); if (!hasContent(val)) - return mkfailure<value, std::string>(reason(val)); + return mkfailure<value>(reason(val)); return id; } /** * Put an item into the cache. */ -const failable<value, std::string> put(const list<value>& params) { - const failable<bool, std::string> val = cache::put(car(params), cadr(params), ch); +const failable<value> put(const list<value>& params) { + const failable<bool> val = cache::put(car(params), cadr(params), ch); if (!hasContent(val)) - return mkfailure<value, std::string>(reason(val)); + return mkfailure<value>(reason(val)); return value(content(val)); } /** * Delete an item from the cache. */ -const failable<value, std::string> del(const list<value>& params) { - const failable<bool, std::string> val = cache::del(car(params), ch); +const failable<value> del(const list<value>& params) { + const failable<bool> val = cache::del(car(params), ch); if (!hasContent(val)) - return mkfailure<value, std::string>(reason(val)); + return mkfailure<value>(reason(val)); return value(content(val)); } @@ -99,7 +99,7 @@ const tuscany::value eval(const tuscany::list<tuscany::value>& params) { return tuscany::cache::put(cdr(params)); if (func == "delete") return tuscany::cache::del(cdr(params)); - return tuscany::mkfailure<tuscany::value, std::string>(std::string("Function not supported: ") + std::string(func)); + return tuscany::mkfailure<tuscany::value>(tuscany::string("Function not supported: ") + func); } } diff --git a/sca-cpp/trunk/components/cache/mcache.hpp b/sca-cpp/trunk/components/cache/mcache.hpp index d1fe182946..3f32a47964 100644 --- a/sca-cpp/trunk/components/cache/mcache.hpp +++ b/sca-cpp/trunk/components/cache/mcache.hpp @@ -34,8 +34,7 @@ #include "apr_memcache.h" #include "apr_network_io.h" -#include <string> -#include <sstream> +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "monad.hpp" @@ -56,7 +55,7 @@ public: init("localhost", 11211); } - MemCached(const std::string host, const int port) { + MemCached(const string host, const int port) { apr_pool_create(&pool, NULL); apr_memcache_create(pool, 1, 0, &mc); init(host, port); @@ -70,22 +69,22 @@ private: apr_pool_t* pool; apr_memcache_t* mc; - friend const failable<bool, std::string> post(const value& key, const value& val, const MemCached& cache); - friend const failable<bool, std::string> put(const value& key, const value& val, const MemCached& cache); - friend const failable<value, std::string> get(const value& key, const MemCached& cache); - friend const failable<bool, std::string> del(const value& key, const MemCached& cache); + friend const failable<bool> post(const value& key, const value& val, const MemCached& cache); + friend const failable<bool> put(const value& key, const value& val, const MemCached& cache); + friend const failable<value> get(const value& key, const MemCached& cache); + friend const failable<bool> del(const value& key, const MemCached& cache); /** * Initialize the memcached context. */ - const failable<bool, std::string> init(const std::string& host, const int port) { + const failable<bool> init(const string& host, const int port) { apr_memcache_server_t *server; - const apr_status_t sc = apr_memcache_server_create(pool, host.c_str(), (apr_port_t)port, 0, 1, 1, 60, &server); + const apr_status_t sc = apr_memcache_server_create(pool, c_str(host), (apr_port_t)port, 0, 1, 1, 60, &server); if (sc != APR_SUCCESS) - return mkfailure<bool, std::string>("Could not create server"); + return mkfailure<bool>("Could not create server"); const apr_status_t as = apr_memcache_add_server(mc, server); if (as != APR_SUCCESS) - return mkfailure<bool, std::string>("Could not add server"); + return mkfailure<bool>("Could not add server"); return true; } @@ -94,15 +93,15 @@ private: /** * Post a new item to the cache. */ -const failable<bool, std::string> post(const value& key, const value& val, const MemCached& cache) { +const failable<bool> post(const value& key, const value& val, const MemCached& cache) { debug(key, "cache::post::key"); debug(val, "cache::post::value"); - const std::string ks(eval::writeValue(key)); - const std::string vs(eval::writeValue(val)); - const apr_status_t rc = apr_memcache_add(cache.mc, ks.c_str(), const_cast<char*>(vs.c_str()), vs.size(), 0, 27); + const string ks(eval::writeValue(key)); + const string vs(eval::writeValue(val)); + const apr_status_t rc = apr_memcache_add(cache.mc, c_str(ks), const_cast<char*>(c_str(vs)), length(vs), 0, 27); if (rc != APR_SUCCESS) - return mkfailure<bool, std::string>("Could not add entry"); + return mkfailure<bool>("Could not add entry"); debug(true, "cache::post::result"); return true; @@ -111,15 +110,15 @@ const failable<bool, std::string> post(const value& key, const value& val, const /** * Update an item in the cache. If the item doesn't exist it is added. */ -const failable<bool, std::string> put(const value& key, const value& val, const MemCached& cache) { +const failable<bool> put(const value& key, const value& val, const MemCached& cache) { debug(key, "cache::put::key"); debug(val, "cache::put::value"); - const std::string ks(eval::writeValue(key)); - const std::string vs(eval::writeValue(val)); - const apr_status_t rc = apr_memcache_set(cache.mc, ks.c_str(), const_cast<char*>(vs.c_str()), vs.size(), 0, 27); + const string ks(eval::writeValue(key)); + const string vs(eval::writeValue(val)); + const apr_status_t rc = apr_memcache_set(cache.mc, c_str(ks), const_cast<char*>(c_str(vs)), length(vs), 0, 27); if (rc != APR_SUCCESS) - return mkfailure<bool, std::string>("Could not add entry"); + return mkfailure<bool>("Could not add entry"); debug(true, "cache::put::result"); return true; @@ -128,25 +127,24 @@ const failable<bool, std::string> put(const value& key, const value& val, const /** * Get an item from the cache. */ -const failable<value, std::string> get(const value& key, const MemCached& cache) { +const failable<value> get(const value& key, const MemCached& cache) { debug(key, "cache::get::key"); - const std::string ks(eval::writeValue(key)); - + const string ks(eval::writeValue(key)); apr_pool_t* vpool; const apr_status_t pc = apr_pool_create(&vpool, cache.pool); if (pc != APR_SUCCESS) - return mkfailure<value, std::string>("Could not allocate memory"); + return mkfailure<value>("Could not allocate memory"); char *data; apr_size_t size; - const apr_status_t rc = apr_memcache_getp(cache.mc, cache.pool, ks.c_str(), &data, &size, NULL); + const apr_status_t rc = apr_memcache_getp(cache.mc, cache.pool, c_str(ks), &data, &size, NULL); if (rc != APR_SUCCESS) { apr_pool_destroy(vpool); - return mkfailure<value, std::string>("Could not get entry"); + return mkfailure<value>("Could not get entry"); } - const value val(eval::readValue(std::string(data, size))); + const value val(eval::readValue(string(data, size))); apr_pool_destroy(vpool); debug(val, "cache::get::result"); @@ -156,14 +154,13 @@ const failable<value, std::string> get(const value& key, const MemCached& cache) /** * Delete an item from the cache */ -const failable<bool, std::string> del(const value& key, const MemCached& cache) { +const failable<bool> del(const value& key, const MemCached& cache) { debug(key, "cache::delete::key"); - std::ostringstream kos; - kos << key; - const apr_status_t rc = apr_memcache_delete(cache.mc, kos.str().c_str(), 0); + const string ks(eval::writeValue(key)); + const apr_status_t rc = apr_memcache_delete(cache.mc, c_str(ks), 0); if (rc != APR_SUCCESS) - return mkfailure<bool, std::string>("Could not delete entry"); + return mkfailure<bool>("Could not delete entry"); debug(true, "cache::delete::result"); return true; diff --git a/sca-cpp/trunk/components/cache/memcached-server-test b/sca-cpp/trunk/components/cache/memcached-server-test index 0dc32f6613..f3c4287dc8 100755 --- a/sca-cpp/trunk/components/cache/memcached-server-test +++ b/sca-cpp/trunk/components/cache/memcached-server-test @@ -35,7 +35,7 @@ $mc & sleep 2 # Test -./mcache-client-test 2>/dev/null +./mcache-client-test rc=$? # Cleanup diff --git a/sca-cpp/trunk/components/cache/memcached-test b/sca-cpp/trunk/components/cache/memcached-test index 0160188f65..df21d32a57 100755 --- a/sca-cpp/trunk/components/cache/memcached-test +++ b/sca-cpp/trunk/components/cache/memcached-test @@ -23,7 +23,7 @@ $mc & sleep 1 # Test -./mcache-test 2>/dev/null +./mcache-test rc=$? # Cleanup diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index af2dcf4df6..99650734c3 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -39,7 +39,7 @@ AC_PROG_LIBTOOL # Check for running on Darwin AC_MSG_CHECKING([if running on Darwin]) UNAME=`uname -s` -if test "x$UNAME" = "xDarwin"; then +if test "${UNAME}" = "Darwin"; then AC_DEFINE([IS_DARWIN], [1], [Set to 1 when running on Darwin - Mac OSX]) AC_MSG_RESULT(yes) AC_SUBST([libsuffix],[".dylib"]) @@ -49,14 +49,14 @@ else AC_SUBST([libsuffix],[".so"]) is_darwin=false fi -AM_CONDITIONAL([DARWIN], [test x$is_darmin = xtrue]) +AM_CONDITIONAL([DARWIN], [test "${is_darmin}" = "true"]) # Configure CURL_INCLUDE and CURL_LIB AC_MSG_CHECKING([for curl]) AC_ARG_WITH([curl], [AC_HELP_STRING([--with-curl=PATH], [path to installed curl [default=/usr]])], [ - CURL_INCLUDE="$withval/include" - CURL_LIB="$withval/lib" - AC_MSG_RESULT("$withval") + CURL_INCLUDE="${withval}/include" + CURL_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") ], [ CURL_INCLUDE="/usr/include" CURL_LIB="/usr/lib" @@ -68,9 +68,9 @@ AC_SUBST(CURL_LIB) # Configure LIBXML2_INCLUDE and LIBXML2_LIB AC_MSG_CHECKING([for libxml2]) AC_ARG_WITH([libxml2], [AC_HELP_STRING([--with-libxml2=PATH], [path to installed libxml2 [default=/usr]])], [ - LIBXML2_INCLUDE="$withval/include/libxml2" - LIBXML2_LIB="$withval/lib" - AC_MSG_RESULT("$withval") + LIBXML2_INCLUDE="${withval}/include/libxml2" + LIBXML2_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") ], [ LIBXML2_INCLUDE="/usr/include/libxml2" LIBXML2_LIB="/usr/lib" @@ -83,16 +83,16 @@ AC_SUBST(LIBXML2_LIB) AC_MSG_CHECKING([for js-include]) AC_ARG_WITH([js-include], [AC_HELP_STRING([--with-js-include=PATH], [path to installed SpiderMonkey include dir [default=/usr/include/xulrunner-1.9.1.5/unstable]])], [ - JS_INCLUDE="$withval" - AC_MSG_RESULT("$withval") + JS_INCLUDE="${withval}" + AC_MSG_RESULT("${withval}") ], [ JS_INCLUDE="/usr/include/xulrunner-1.9.1.5/unstable" AC_MSG_RESULT(/usr/include/xulrunner-1.9.1.5/unstable) ]) AC_MSG_CHECKING([for js-lib]) AC_ARG_WITH([js-lib], [AC_HELP_STRING([--with-js-lib=PATH], [path to installed SpiderMonkey lib dir [default=/usr/lib/xulrunner-1.9.1.5]])], [ - JS_LIB="$withval" - AC_MSG_RESULT("$withval") + JS_LIB="${withval}" + AC_MSG_RESULT("${withval}") ], [ JS_LIB="/usr/lib/xulrunner-1.9.1.5" AC_MSG_RESULT(/usr/lib/xulrunner-1.9.1.5) @@ -103,9 +103,9 @@ AC_SUBST(JS_LIB) # Configure APR and HTTPD AC_MSG_CHECKING([for apr]) AC_ARG_WITH([apr], [AC_HELP_STRING([--with-apr=PATH], [path to installed apr [default=/usr/local/apache2]])], [ - APR_INCLUDE="$withval/include" - APR_LIB="$withval/lib" - AC_MSG_RESULT("$withval") + APR_INCLUDE="${withval}/include" + APR_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") ], [ APR_INCLUDE="/usr/local/apache2/include" APR_LIB="/usr/local/apache2/lib" @@ -116,8 +116,8 @@ AC_SUBST(APR_LIB) AC_MSG_CHECKING([for httpd]) AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed httpd [default=/usr/local/apache2]])], [ - HTTPD_INCLUDE="$withval/include" - AC_MSG_RESULT("$withval") + HTTPD_INCLUDE="${withval}/include" + AC_MSG_RESULT("${withval}") ], [ HTTPD_INCLUDE="/usr/local/apache2/include" AC_MSG_RESULT(/usr/local/apache2/lib) @@ -125,20 +125,20 @@ AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed htt AC_SUBST(HTTPD_INCLUDE) # Checks for libraries. -original_LIBS="$LIBS" +original_LIBS="${LIBS}" AC_MSG_NOTICE([checking for libraries]) -LIBS="-L$CURL_LIB $original_LIBS" +LIBS="-L${CURL_LIB} ${original_LIBS}" AC_CHECK_LIB([curl], [curl_global_init], [], [AC_MSG_ERROR([couldn't find a suitable libcurl, use --with-curl=PATH])]) -LIBS="-L$JS_LIB $original_LIBS" +LIBS="-L${JS_LIB} ${original_LIBS}" AC_CHECK_LIB([mozjs], [JS_NewContext], [], [AC_MSG_ERROR([couldn't find a suitable libmozjs, use --with-js-lib=PATH])]) -LIBS="$original_LIBS" +LIBS="${original_LIBS}" AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([couldn't find a suitable libpthread])]) -LIBS="-L$LIBXML2_LIB $original_LIBS" +LIBS="-L${LIBXML2_LIB} ${original_LIBS}" AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitable libxml2, use --with-libxml2=PATH])]) -LIBS="-L$APR_LIB $original_LIBS" +LIBS="-L${APR_LIB} ${original_LIBS}" AC_CHECK_LIB([apr-1], [apr_pool_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])]) AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])]) -LIBS="$original_LIBS" +LIBS="${original_LIBS}" # Checks for header files. AC_MSG_NOTICE([checking for header files]) @@ -158,9 +158,12 @@ AC_MSG_NOTICE([checking for library functions]) AC_CHECK_FUNCS([gettimeofday select]) # Configure GCC C++ compile options -# Configure debugging, profiling and compile-time warnings -AC_MSG_CHECKING([whether to compile for debugging and profiling]) -AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [compile for debugging and profiling [default=no]])], +cxxflags="" +ldflags="${LDFLAGS}" + +# Configure debugging and compile-time warnings +AC_MSG_CHECKING([whether to compile with debugging and compile-time warnings]) +AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [compile with debugging and compile-time warnings [default=no]])], [ case "${enableval}" in no) AC_MSG_RESULT(no) @@ -171,23 +174,63 @@ AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [comp ;; esac ], [ AC_MSG_RESULT(no)]) -if test "$want_maintainer_mode" = "true"; then - AC_SUBST([CXXFLAGS], [" -D_REENTRANT -D_DEBUG -O0 -g3 -pg -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0"]) - AC_SUBST([LDFLAGS], ["${LDFLAGS} -lpthread -pg"]) +if test "${want_maintainer_mode}" = "true"; then + cxxflags="${cxxflags} -D_DEBUG -O0 -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0" + ldflags="${ldflags} -pg" else - AC_SUBST([CXXFLAGS], [" -D_REENTRANT -O3 -std=c++0x -fmessage-length=0"]) - AC_SUBST([LDFLAGS], ["${LDFLAGS} -lpthread"]) + cxxflags="${cxxflags} -O3 -std=c++0x -fmessage-length=0" +fi + +# Configure profiling +AC_MSG_CHECKING([whether to compile with profiling]) +AC_ARG_ENABLE(profiling, [AS_HELP_STRING([--enable-profiling], [compile with profiling [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_profiling=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_profiling}" = "true"; then + cxxflags="${cxxflags} -pg" + ldflags="${ldflags} -pg" +fi + +# Configure multi-threading support +AC_MSG_CHECKING([whether to compile for multi-threaded execution]) +AC_ARG_ENABLE(threads, [AS_HELP_STRING([--enable-threads], [compile for multi-threaded execution [default=no]])], +[ case "${enableval}" in + no) + AC_MSG_RESULT(no) + ;; + *) + AC_MSG_RESULT(yes) + want_threads=true + ;; + esac ], +[ AC_MSG_RESULT(no)]) +if test "${want_threads}" = "true"; then + LIBS="${original_LIBS}" + AC_CHECK_LIB([pthread], [pthread_create], [], [AC_MSG_ERROR([couldn't find a suitable libpthread])]) + LIBS="${original_LIBS}" + cxxflags="${cxxflags} -D_REENTRANT" + ldflags="${ldflags} -lpthread" fi +AC_SUBST([CXXFLAGS], ["${cxxflags}"]) +AC_SUBST([LDFLAGS], ["${ldflags}"]) # Configure exuberant ctags TAGSFILE="`pwd`/tags" -AC_SUBST([CTAGSFLAGS], ["${CTAGSFLAGS} --c++-kinds=+p --fields=+iaS --extra=+q --append --tag-relative=yes -f $TAGSFILE"]) +AC_SUBST([CTAGSFLAGS], ["${CTAGSFLAGS} --c++-kinds=+p --fields=+iaS --extra=+q --append --tag-relative=yes -f ${TAGSFILE}"]) # Configure TUSCANY_SCACPP -TUSCANY_SCACPP=`echo "$TUSCANY_SCACPP"` -if test "$TUSCANY_SCACPP" = ""; then +TUSCANY_SCACPP=`echo "${TUSCANY_SCACPP}"` +if test "${TUSCANY_SCACPP}" = ""; then SCAPWD=`pwd` - AC_SUBST([TUSCANY_SCACPP], ["$SCAPWD"]) + AC_SUBST([TUSCANY_SCACPP], ["${SCAPWD}"]) fi # Configure Doxygen build @@ -199,15 +242,15 @@ AC_ARG_ENABLE(doxygen, [AS_HELP_STRING([--enable-doxygen], [build Doxygen docume ;; *) AC_MSG_RESULT(yes) - AC_PATH_PROG(DOXYGEN, doxygen, , $PATH) - if test "$DOXYGEN" = ""; then + AC_PATH_PROG(DOXYGEN, doxygen, , ${PATH}) + if test "${DOXYGEN}" = ""; then AC_MSG_ERROR([could not find doxygen]) fi want_doxygen=true ;; esac ], [ AC_MSG_RESULT(no)]) -AM_CONDITIONAL([WANT_DOXYGEN], [test "$want_doxygen" = "true"]) +AM_CONDITIONAL([WANT_DOXYGEN], [test "${want_doxygen}" = "true"]) AC_CONFIG_FILES([Makefile kernel/Makefile diff --git a/sca-cpp/trunk/etc/git-exclude b/sca-cpp/trunk/etc/git-exclude index 2e5c4821d0..d71d8e428b 100644 --- a/sca-cpp/trunk/etc/git-exclude +++ b/sca-cpp/trunk/etc/git-exclude @@ -61,17 +61,21 @@ doxygen # Specific ignores kernel-test -xsd-test -parallel-test +string-test +mem-test xml-test +xsd-test atom-test eval-test eval-shell json-test +cache-test client-test mcache-test mcache-client-test curl-test scdl-test +store-function-test +store-object-test store-script-test diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am index 4dfc285e90..507454439a 100644 --- a/sca-cpp/trunk/kernel/Makefile.am +++ b/sca-cpp/trunk/kernel/Makefile.am @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -noinst_PROGRAMS = kernel-test parallel-test xml-test xsd-test +noinst_PROGRAMS = string-test kernel-test mem-test parallel-test xml-test xsd-test testdir=$(prefix)/test test_LTLIBRARIES = libdynlib-test.la @@ -25,12 +25,18 @@ include_HEADERS = *.hpp INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -kernel_test_SOURCES = kernel-test.cpp -kernel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 +string_test_SOURCES = string-test.cpp +string_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 libdynlib_test_la_SOURCES = dynlib-test.cpp libdynlib_test_la_LIBADD = -L${APR_LIB} -lapr-1 -laprutil-1 +kernel_test_SOURCES = kernel-test.cpp +kernel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 + +mem_test_SOURCES = mem-test.cpp +mem_test_LDADD = -L${APR_LIB} -lapr-1 -laprutil-1 + parallel_test_SOURCES = parallel-test.cpp parallel_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 @@ -40,4 +46,4 @@ xml_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 xsd_test_SOURCES = xsd-test.cpp xsd_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -TESTS = kernel-test parallel-test xml-test +TESTS = string-test kernel-test mem-test parallel-test xml-test diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/debug.hpp index c06fe55f4a..c51ee6c974 100644 --- a/sca-cpp/trunk/kernel/debug.hpp +++ b/sca-cpp/trunk/kernel/debug.hpp @@ -23,24 +23,15 @@ #define tuscany_debug_hpp /** - * Functions to help log and debug. + * Debug functions and macros. */ -#include <string> -#include <ostream> - namespace tuscany { #ifdef _DEBUG -/** - * Debug log. - */ -template<typename V> const bool debug(const V& v, const std::string& msg) { - std::cerr << msg << ": " << v << std::endl; - return true; -} +//#define _DEBUG_WATCH /** * Increment / decrement a debug counter. @@ -55,20 +46,18 @@ bool debug_dec(long int& c) { return true; } -/** - * Attribute used to mark unused parameters. - */ -#define unused __attribute__ ((unused)) - #else -#define debug(v, msg) - #define debug_inc(c) #define debug_dec(c) -#define unused +#endif +/** + * Attribute used to mark unused parameters. + */ +#ifndef unused +#define unused __attribute__ ((unused)) #endif } diff --git a/sca-cpp/trunk/kernel/dynlib.hpp b/sca-cpp/trunk/kernel/dynlib.hpp index 10a5a030cb..a000653455 100644 --- a/sca-cpp/trunk/kernel/dynlib.hpp +++ b/sca-cpp/trunk/kernel/dynlib.hpp @@ -38,9 +38,9 @@ namespace tuscany { * OS specific dynamic library file extension. */ #ifdef IS_DARWIN -const std::string dynlibExt(".dylib"); +const string dynlibExt(".dylib"); #else -const std::string dynlibExt(".so"); +const string dynlibExt(".so"); #endif /** @@ -51,7 +51,7 @@ public: lib() : dl(NULL) { } - lib(const std::string& name) : dl(new DynLib(name)) { + lib(const string& name) : dl(new (gc_new<DynLib>()) DynLib(name)) { } ~lib() { @@ -60,41 +60,42 @@ public: private: class DynLib { public: - DynLib(const std::string& name) : name(name), h(dlopen(name.c_str(), RTLD_NOW)) { + DynLib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)) { } + ~DynLib() { if (h == NULL) return; dlclose(h); } - const std::string name; + const string name; void* h; }; gc_ptr<DynLib> dl; - friend const failable<lib, std::string> dynlib(const std::string& name); - template<typename S> friend const failable<lambda<S>, std::string> dynlambda(const std::string& name, const lib& l); + friend const failable<lib> dynlib(const string& name); + template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l); }; /** * Load a dynamic library. */ -const failable<lib, std::string> dynlib(const std::string& name) { +const failable<lib> dynlib(const string& name) { const lib l(name); if (l.dl->h == NULL) - return mkfailure<lib, std::string>("Could not load library: " + name + ": " + dlerror()); + return mkfailure<lib>(string("Could not load library: ") + name + ": " + dlerror()); return l; } /** * Find a lambda function in a dynamic library. */ -template<typename S> const failable<lambda<S>, std::string> dynlambda(const std::string& name, const lib& l) { - const void* s = dlsym(l.dl->h, name.c_str()); +template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) { + const void* s = dlsym(l.dl->h, c_str(name)); if (s == NULL) - return mkfailure<lambda<S>, std::string>(std::string("Could not load symbol: " + name)); + return mkfailure<lambda<S> >(string("Could not load symbol: ") + name); return lambda<S>((S*)s); } diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp index 612752d1df..4570110e96 100644 --- a/sca-cpp/trunk/kernel/element.hpp +++ b/sca-cpp/trunk/kernel/element.hpp @@ -98,7 +98,7 @@ const value elementHasValue(const list<value>& l) { const list<value> r = reverse(l); if (isSymbol(car(r))) return false; - if(isList(car(r)) && isSymbol(car<value>(car(r)))) + if(isList(car(r)) && !isNil((list<value>)car(r)) && isSymbol(car<value>(car(r)))) return false; return true; } @@ -201,7 +201,7 @@ const value valueToElement(const value& t) { return mklist(element, n, v); // Convert a list value - if (!isSymbol(car<value>(v))) + if (isNil((list<value>)v) || !isSymbol(car<value>(v))) return cons(element, cons(n, mklist<value>(valuesToElements(v)))); // Convert a nested name value pair value diff --git a/sca-cpp/trunk/kernel/fstream.hpp b/sca-cpp/trunk/kernel/fstream.hpp new file mode 100644 index 0000000000..3d6b1edade --- /dev/null +++ b/sca-cpp/trunk/kernel/fstream.hpp @@ -0,0 +1,152 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_fstream_hpp +#define tuscany_fstream_hpp + +/** + * File based streams. + */ + +#include <stdio.h> +#include <stdarg.h> +#include "string.hpp" +#include "stream.hpp" + +namespace tuscany { + +/* + * Output stream backed by a FILE. + */ +class ofstream : public ostream { +public: + ofstream(const string& path) : file(fopen(c_str(path), "wb")), owned(true) { + } + + ofstream(FILE* file) : file(file), owned(false) { + } + + ofstream(const ofstream& os) : file(os.file), owned(false) { + } + + ~ofstream() { + if (!owned) + return; + if (file == NULL) + return; + fclose(file); + } + + ofstream& vprintf(const char* fmt, ...) { + va_list args; + va_start (args, fmt); + vfprintf (file, fmt, args); + va_end (args); + return *this; + } + + ofstream& flush() { + fflush(file); + return *this; + } + +private: + FILE* file; + bool owned; +}; + +/* + * Input stream backed by a FILE. + */ +class ifstream : public istream { +public: + ifstream(const string& path) : file(fopen(c_str(path), "rb")), owned(true) { + } + + ifstream(FILE* file) : file(file), owned(false) { + } + + ifstream(const ifstream& is) : file(is.file), owned(false) { + } + + ~ifstream() { + if (!owned) + return; + if (file == NULL) + return; + fclose(file); + } + + const int read(void* buf, int size) { + return fread(buf, 1, size, file); + } + + const bool eof() { + return feof(file); + } + + const bool fail() { + return file == NULL; + } + + const int get() { + return fgetc(file); + } + + const int peek() { + int c = fgetc(file); + if (c == -1) + return c; + ungetc(c, file); + return c; + } + +private: + FILE* file; + bool owned; +}; + +/** + * Standard streams. + */ +ofstream cout(stdout); +ofstream cerr(stderr); +ifstream cin(stdin); + +/** + * Debug log stream. + */ +#ifdef _DEBUG + +template<typename V> const bool debug(const V& v, const string& msg) { + cerr << msg << ": " << v << endl; + return true; +} + +#else + +#define debug(v, msg) + +#endif + +} + +#endif /* tuscany_fstream_hpp */ diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp index 54784b5549..26f566fde6 100644 --- a/sca-cpp/trunk/kernel/function.hpp +++ b/sca-cpp/trunk/kernel/function.hpp @@ -26,7 +26,8 @@ * Lambda function type. */ -#include <iostream> +#include <bits/move.h> +#include "fstream.hpp" #include "gc.hpp" #include "debug.hpp" @@ -55,13 +56,13 @@ bool checkLambdaCounters() { } bool printLambdaCounters() { - std::cout << "countLambdas " << countLambdas << std::endl; - std::cout << "countELambdas " << countELambdas << std::endl; - std::cout << "countFLambdas " << countFLambdas << std::endl; - std::cout << "countCLambdas " << countCLambdas << std::endl; - std::cout << "countProxies " << countProxies << std::endl; - std::cout << "countFProxies " << countFProxies << std::endl; - std::cout << "countCProxies " << countCProxies << std::endl; + cout << "countLambdas " << countLambdas << endl; + cout << "countELambdas " << countELambdas << endl; + cout << "countFLambdas " << countFLambdas << endl; + cout << "countCLambdas " << countCLambdas << endl; + cout << "countProxies " << countProxies << endl; + cout << "countFProxies " << countFProxies << endl; + cout << "countCProxies " << countCProxies << endl; return true; } @@ -79,7 +80,7 @@ bool printLambdaCounters() { template<typename R, typename... P> class Callable { public: - Callable() : refCount(0) { + Callable() { } virtual const int size() const = 0; @@ -116,19 +117,6 @@ public: private: const F function; }; - -private: - friend class gc_counting_ptr<Callable>; - - unsigned int refCount; - - unsigned int acquire() { - return gc_add_and_fetch(refCount, (unsigned int)1); - } - - unsigned int release() { - return gc_sub_and_fetch(refCount, (unsigned int)1); - } }; template<typename S> class lambda; @@ -145,7 +133,7 @@ public: debug_inc(countFLambdas); typedef typename CallableType::template Proxy<F> ProxyType; - callable = gc_counting_ptr<CallableType>(new ProxyType(f)); + callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f)); } lambda(const lambda& l) { @@ -179,15 +167,15 @@ public: return (*callable)(std::forward<P>(p)...); } - template<typename S> friend std::ostream& operator<<(std::ostream&, const lambda<S>&); + template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&); template<typename S> friend const bool isNil(const lambda<S>& l); private: typedef Callable<R,P...> CallableType; - gc_counting_ptr<CallableType> callable; + gc_ptr<CallableType> callable; }; -template<typename S> std::ostream& operator<<(std::ostream& out, const lambda<S>& l) { +template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) { return out << "lambda::" << l.callable; } diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp index c9a1a35756..3d20245c69 100644 --- a/sca-cpp/trunk/kernel/gc.hpp +++ b/sca-cpp/trunk/kernel/gc.hpp @@ -23,399 +23,236 @@ #define tuscany_gc_hpp /** - * Garbage collected pointer. + * Garbage collected memory management, using APR memory pools. */ +#include <stdlib.h> #include <apr_general.h> #include <apr_pools.h> -#include <iostream> +#include <assert.h> +#include <new> +#include "debug.hpp" namespace tuscany { /** - * Macros used to add or subtract values to reference counters. - * In a multithreaded environment, use the GCC __sync_add_and_fetch - * and __sync_sub_and_fetch built in functions. + * Pointer to a value. */ -#ifdef _REENTRANT - -#define gc_add_and_fetch(t, v) __sync_add_and_fetch(&(t), v) -#define gc_sub_and_fetch(t, v) __sync_sub_and_fetch(&(t), v) - -#else - -#define gc_add_and_fetch(t, v) ((t) = (t) + (v)) -#define gc_sub_and_fetch(t, v) ((t) = (t) - (v)) - -#endif - template<typename T> class gc_ptr { public: - gc_ptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) { + gc_ptr(T* ptr = NULL) throw() : ptr(ptr) { } ~gc_ptr() throw() { - release(); } - gc_ptr(const gc_ptr& r) throw() : countingRef(r.countingRef) { - acquire(r.countingRef); + gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) { } gc_ptr& operator=(const gc_ptr& r) throw() { if(this == &r) return *this; - acquire(r.countingRef); - release(); - countingRef = r.countingRef; + ptr = r.ptr; return *this; } const bool operator==(const gc_ptr& r) const throw() { if (this == &r) return true; - if (countingRef == NULL) - return r.countingRef == NULL; - if (r.countingRef == NULL) - return false; - return countingRef-> ptr == r.countingRef->ptr; + return ptr == r.ptr; } const bool operator!=(const gc_ptr& r) const throw() { - return !this->operator ==(r); + return !this->operator==(r); } T& operator*() const throw() { - return *countingRef->ptr; + return *ptr; } T* operator->() const throw() { - return countingRef->ptr; + return ptr; } operator T*() const throw() { - return countingRef->ptr; - } - - template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_ptr<X>&); - -private: - struct CountingRef { - T* ptr; - unsigned count; - - CountingRef(T* p) throw() : - ptr(p), count(1) { - } - }* countingRef; - - void acquire(CountingRef* ref) throw() { - if(ref) - gc_add_and_fetch(ref->count, (unsigned int)1); + return ptr; } - void release() throw() { - if(countingRef) { - unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1); - if(rc == 0) { - delete countingRef->ptr; - delete countingRef; - } - } - } + T* ptr; }; -template<typename T> std::ostream& operator<<(std::ostream& out, const gc_ptr<T>& p) { - return out << p.countingRef->ptr; -} - /** - * Garbage collected pointer to an array. + * Garbage collected APR memory pool. */ -template<typename T> class gc_aptr { +class gc_pool { public: - gc_aptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) { + gc_pool() : p(NULL) { } - ~gc_aptr() throw() { - release(); + gc_pool(apr_pool_t* p) : p(p) { } - gc_aptr(const gc_aptr& r) throw() : countingRef(r.countingRef) { - acquire(r.countingRef); + gc_pool(const gc_pool& pool) : p(pool.p) { } - gc_aptr& operator=(const gc_aptr& r) throw() { - if(this == &r) + gc_pool& operator=(const gc_pool& pool) { + if (this == &pool) return *this; - acquire(r.countingRef); - release(); - countingRef = r.countingRef; + p = pool.p; return *this; } - const bool operator==(const gc_aptr& r) const throw() { - if (this == &r) - return true; - if (countingRef == NULL) - return r.countingRef == NULL; - if (r.countingRef == NULL) - return false; - return countingRef-> ptr == r.countingRef->ptr; - } - - const bool operator!=(const gc_aptr& r) const throw() { - return !this->operator ==(r); - } - - T& operator*() const throw() { - return *countingRef->ptr; - } - - T* operator->() const throw() { - return countingRef->ptr; - } - - operator T*() const throw() { - return countingRef->ptr; + operator apr_pool_t*() const { + return p; } - template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_aptr<X>&); - private: - struct CountingRef { - T* ptr; - unsigned count; - - CountingRef(T* p) throw() : - ptr(p), count(1) { - } - }* countingRef; - - void acquire(CountingRef* ref) throw() { - if(ref) - gc_add_and_fetch(ref->count, (unsigned int)1); - } + friend const bool destroy(gc_pool& pool); + friend class gc_global_pool_t; + friend class gc_scoped_pool; - void release() throw() { - if(countingRef) { - unsigned rc = gc_sub_and_fetch(countingRef->count, (unsigned int)1); - if(rc == 0) { - delete[] countingRef->ptr; - delete countingRef; - } - } - } + apr_pool_t* p; }; -template<typename T> std::ostream& operator<<(std::ostream& out, const gc_aptr<T>& p) { - return out << p.countingRef->ptr; -} - /** - * Garbage collected pointer to a reference counting object. + * Destroy a memory pool. */ -template<typename T> class gc_counting_ptr { -public: - gc_counting_ptr(T* p = 0) throw() : ptr(p) { - acquire(p); - } - - ~gc_counting_ptr() throw() { - release(); - } - - gc_counting_ptr(const gc_counting_ptr& r) throw() : ptr(r.ptr) { - acquire(ptr); - } - - gc_counting_ptr& operator=(const gc_counting_ptr& r) throw() { - if(this == &r) - return *this; - acquire(r.ptr); - release(); - ptr = r.ptr; - return *this; - } - - const bool operator==(const gc_counting_ptr& r) const throw() { - if (this == &r) - return true; - return ptr == r.ptr; - } - - const bool operator!=(const gc_counting_ptr& r) const throw() { - return !this->operator ==(r); - } - - T& operator*() const throw() { - return *ptr; - } - - T* operator->() const throw() { - return ptr; - } - - operator T*() const throw() { - return ptr; - } - - template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_counting_ptr<X>&); - -private: - T* ptr; - - void acquire(T* p) throw() { - if(p) - p->acquire(); - } - - void release() throw() { - if(ptr) { - if(ptr->release() == 0) { - delete ptr; - } - } - } -}; - -template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counting_ptr<T>& p) { - return out << p.ptr; +const bool destroy(gc_pool& pool) { + apr_pool_destroy(pool.p); + return true; } /** - * Apache Portable Runtime library context + * Default global memory pool. */ -class APRContext { +class gc_apr_context_t { public: - APRContext() { + gc_apr_context_t() { apr_initialize(); } - ~APRContext() { - apr_terminate(); + ~gc_apr_context_t() { + //apr_terminate(); } }; -APRContext aprContext; +gc_apr_context_t gc_apr_context; -/** - * Garbage collected memory pool, using an APR pool. - */ -class gc_pool { +class gc_global_pool_t : public gc_pool { public: - gc_pool() : aprPool(new APRPool) { + gc_global_pool_t() { + apr_pool_create(&p, NULL); } - operator apr_pool_t*() const { - return aprPool->p; + ~gc_global_pool_t() { + //apr_pool_destroy(p); } +}; -private: - class APRPool { - friend class gc_pool; - friend class gc_counting_ptr<APRPool>; - - unsigned int refCount; - apr_pool_t* p; - - APRPool() : refCount(0) { - apr_pool_create(&p, NULL); - } - - ~APRPool() { - apr_pool_destroy(p); - } - - unsigned int acquire() { - return gc_add_and_fetch(refCount, (unsigned int)1); - } +gc_global_pool_t gc_global_pool; - unsigned int release() { - return gc_sub_and_fetch(refCount, (unsigned int)1); - } - }; +/** + * Maintain a stack of memory pools. + */ +#ifdef _REENTRANT +__thread +#endif +apr_pool_t* gc_pool_stack = NULL; - const gc_counting_ptr<APRPool> aprPool; -}; +/** + * Return the current memory pool. + */ +apr_pool_t* gc_current_pool() { + apr_pool_t* p = gc_pool_stack; + if (p != NULL) + return p; + apr_pool_t* g = gc_global_pool; + gc_pool_stack = g; + return g; +} /** - * Garbage collected pointer to pooled memory. + * A memory pool scope, used to setup a scope in which a particular pool + * will be used for all allocations. */ -template<typename T> class gc_pool_ptr { +class gc_scoped_pool : public gc_pool { public: - gc_pool_ptr(T* ptr = 0) throw() : ptr(ptr) { - } - - ~gc_pool_ptr() throw() { - } - - gc_pool_ptr(const gc_pool_ptr& r) throw() : ptr(r.ptr) { - } - - gc_pool_ptr& operator=(const gc_pool_ptr& r) throw() { - if(this == &r) - return *this; - ptr = r.ptr; - return *this; - } - const bool operator==(const gc_pool_ptr& r) const throw() { - if (this == &r) - return true; - return ptr == r.ptr; - } - - const bool operator!=(const gc_pool_ptr& r) const throw() { - return !this->operator ==(r); + gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owned(true) { + apr_pool_create(&p, NULL); + gc_pool_stack = p; } - T& operator*() const throw() { - return *ptr; + gc_scoped_pool(apr_pool_t* pool) : gc_pool(pool), prev(gc_current_pool()), owned(false) { + gc_pool_stack = p; } - T* operator->() const throw() { - return ptr; + ~gc_scoped_pool() { + if (owned) + apr_pool_destroy(p); + if (prev != NULL) + gc_pool_stack = prev; } - operator T*() const throw() { - return ptr; +private: + gc_scoped_pool(const unused gc_scoped_pool& pool) : gc_pool(pool.p), prev(NULL), owned(false) { } - template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_pool_ptr<X>&); - -private: - T* ptr; + apr_pool_t* prev; + bool owned; }; -template<typename T> std::ostream& operator<<(std::ostream& out, const gc_pool_ptr<T>& p) { - return out << p.ptr; -} - /** - * Cleanup function, called by the APR pool to cleanup registered resources. - * Calls the allocated object's destructor. + * 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_cleanupCallback(void* v) { +template<typename T> apr_status_t gc_pool_cleanup(void* v) { T* t = static_cast<T*>(v); t->~T(); return APR_SUCCESS; } -/** - * Returns a pointer to an object allocated from a memory pool. - */ -template<typename T> gc_pool_ptr<T> gc_pool_new(const gc_pool& mp) { +template<typename T> T* gc_new(apr_pool_t* p) { + void* m = apr_palloc(p, sizeof(T)); + apr_pool_cleanup_register(p, m, gc_pool_cleanup<T>, apr_pool_cleanup_null) ; + return static_cast<T*>(m); +} + +template<typename T> T* gc_new() { + return gc_new<T>(gc_current_pool()); +} + +template<typename T> apr_status_t gc_pool_acleanup(void* v) { + int* m = static_cast<int*>(v); + int n = *m; + T* t = static_cast<T*>(m + 1); + for (int i = 0; i < n; i++, t++) + t->~T(); + return APR_SUCCESS; +} - // Allocate memory from the pool - void* m = apr_palloc(mp, sizeof(T)); +template<typename T> T* gc_anew(apr_pool_t* p, int n) { + int* m = static_cast<int*>(apr_palloc(p, sizeof(int) + sizeof(T[n]))); + *m = n; + apr_pool_cleanup_register(p, m, gc_pool_acleanup<T>, apr_pool_cleanup_null) ; + return static_cast<T*>(m + 1); +} - // Register a cleanup callback - apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback<T>, apr_pool_cleanup_null) ; +template<typename T> T* gc_anew(int n) { + return gc_anew<T>(gc_current_pool(), n); +} - // Run the requested type's constructor over the allocated memory - return new (m) T(); +/** + * Allocate an array of chars. + */ +char* gc_cnew(apr_pool_t* p, int n) { + return static_cast<char*>(apr_palloc(p, n)); +} + +char* gc_cnew(int n) { + return gc_cnew(gc_current_pool(), n); } } + #endif /* tuscany_gc_hpp */ diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp index 8a5e4a704d..c4f76c13c9 100644 --- a/sca-cpp/trunk/kernel/kernel-test.cpp +++ b/sca-cpp/trunk/kernel/kernel-test.cpp @@ -24,12 +24,10 @@ */ #include <assert.h> -#include <iostream> -#include <string> -#include <sstream> +#include "string.hpp" +#include "sstream.hpp" #include "function.hpp" #include "list.hpp" -#include "slist.hpp" #include "tree.hpp" #include "value.hpp" #include "monad.hpp" @@ -77,7 +75,10 @@ bool testLambda() { bool testLambdaGC() { resetLambdaCounters(); - testLambda(); + { + gc_scoped_pool gc; + testLambda(); + } assert(checkLambdaCounters()); return true; } @@ -87,18 +88,15 @@ int countElements = 0; struct Element { int i; - Element() : - i(0) { + Element() : i(0) { countElements++; } - Element(int i) : - i(i) { + Element(int i) : i(i) { countElements++; } - Element(const Element& o) : - i(o.i) { + Element(const Element& o) : i(o.i) { countElements++; } @@ -110,7 +108,7 @@ struct Element { return o.i == i; } }; -std::ostream& operator<<(std::ostream& out, const Element& v) { +ostream& operator<<(ostream& out, const Element& v) { out << v.i ; return out; } @@ -124,23 +122,14 @@ bool testCons() { return true; } -bool testSet() { - list<int> l = mklist(1, 2, 3); - setCar(l, 4); - setCdr(l, mklist(5, 6)); - assert(car(l) == 4); - assert(cadr(l) == 5); - assert(caddr(l) == 6); - assert(isNil(cdddr(l))); - return true; -} - bool testListGC() { resetLambdaCounters(); resetListCounters(); countElements = 0; - testCons(); - testSet(); + { + gc_scoped_pool gc; + testCons(); + } assert(checkLambdaCounters()); assert(checkListCounters()); assert(countElements == 0); @@ -148,13 +137,13 @@ bool testListGC() { } bool testOut() { - std::ostringstream os1; + ostringstream os1; os1 << list<int> (); - assert(os1.str() == "()"); + assert(str(os1) == "()"); - std::ostringstream os2; + ostringstream os2; os2 << mklist(1, 2, 3); - assert(os2.str() == "(1 2 3)"); + assert(str(os2) == "(1 2 3)"); return true; } @@ -180,10 +169,7 @@ bool testAppend() { assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3); assert(isNil(cdr(cdr(cdr(append(mklist(1), mklist(2, 3))))))); - list<int> l; - l << 1 << 2 << 3; - assert(l == mklist(1, 2, 3)); - assert(list<int>() << 1 << 2 << 3 == mklist(1, 2, 3)); + assert(list<int>() + 1 + 2 + 3 == mklist(1, 2, 3)); return true; } @@ -196,7 +182,7 @@ struct Complex { x(x), y(y) { } }; -std::ostream& operator<<(std::ostream& out, const Complex& v) { +ostream& operator<<(ostream& out, const Complex& v) { out << "[" << v.x << ":" << v.y << "]"; return out; } @@ -266,9 +252,9 @@ bool testListRef() { } bool testAssoc() { - const list<list<std::string> > l = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA")); - assert(assoc<std::string>("a", l) == mklist<std::string>("a", "A")); - assert(isNil(assoc<std::string>("z", l))); + 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))); const list<list<value> > u = mklist(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA")); assert(assoc<value>("a", u) == mklist<value>("a", "A")); @@ -279,21 +265,21 @@ bool testAssoc() { } bool testZip() { - const list<std::string> k = mklist<std::string>("x", "a", "y", "a"); - const list<std::string> v = mklist<std::string>("X", "A", "Y", "AA"); - const list<list<std::string> > z = mklist(k, v); - const list<list<std::string> > u = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA")); + 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); + const list<list<string> > u = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA")); assert(zip(k, v) == u); assert(unzip(u) == z); return true; } bool testTokenize() { - assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<std::string>("aaa", "bbb", "ccc", "ddd")); - assert(tokenize("/", "/bbb/ccc/ddd") == mklist<std::string>("", "bbb", "ccc", "ddd")); - assert(tokenize("/", "/bbb/ccc/") == mklist<std::string>("", "bbb", "ccc")); - assert(tokenize("/", "/bbb//ccc/") == mklist<std::string>("", "bbb", "", "ccc")); - assert(tokenize("/", "abc/def/") == mklist<std::string>("abc", "def")); + assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd")); + assert(tokenize("/", "/bbb/ccc/ddd") == mklist<string>("", "bbb", "ccc", "ddd")); + assert(tokenize("/", "/bbb/ccc/") == mklist<string>("", "bbb", "ccc")); + assert(tokenize("/", "/bbb//ccc/") == mklist<string>("", "bbb", "", "ccc")); + assert(tokenize("/", "abc/def/") == mklist<string>("abc", "def")); return true; } @@ -336,13 +322,11 @@ bool testValue() { const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y")); assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A")); - const value pv(gc_ptr<value>(new value(1))); + const value pv(gc_ptr<value>(new (gc_new<value>()) value(1))); assert(*(gc_ptr<value>)pv == value(1)); - const list<value> lpv = mklist<value>(gc_ptr<value>(new value(1)), gc_ptr<value>(new value(2))); + const list<value> lpv = mklist<value>(gc_ptr<value>(new (gc_new<value>()) value(1)), gc_ptr<value>(new (gc_new<value>()) value(2))); assert(*(gc_ptr<value>)car(lpv) == value(1)); - *(gc_ptr<value>)cadr(lpv) = value(3); - assert(*(gc_ptr<value>)cadr(lpv) == value(3)); return true; } @@ -350,7 +334,10 @@ bool testValueGC() { resetLambdaCounters(); resetListCounters(); resetValueCounters(); - testValue(); + { + gc_scoped_pool gc; + testValue(); + } assert(checkValueCounters()); assert(checkLambdaCounters()); assert(checkListCounters()); @@ -371,8 +358,8 @@ bool testTree() { return true; } -const list<value> lta(const std::string& x) { - return mklist<value>(x.c_str(), (x + x).c_str()); +const list<value> lta(const string& x) { + return mklist<value>(c_str(x), c_str(x + x)); } bool testTreeAssoc() { @@ -425,7 +412,7 @@ struct nestedFibMapPerf { bool testCppPerf() { { const lambda<bool()> fml = fibMapPerf(); - std::cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << std::endl; + cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl; } { @@ -443,7 +430,7 @@ bool testCppPerf() { }; const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib)); - std::cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << std::endl; + cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl; } return true; } @@ -490,26 +477,26 @@ bool testMaybeMonad() { return true; } -const failable<int, std::string> failableF(const int v) { +const failable<int> failableF(const int v) { return v * 2; } -const failable<int, std::string> failableG(const int v) { +const failable<int> failableG(const int v) { return v * 3; } -const failable<int, std::string> failableH(const int v) { +const failable<int> failableH(const int v) { return failableF(v) >> failableG; } bool testFailableMonad() { - const failable<int, std::string> m(2); + const failable<int> m(2); assert(m >> failableF == failableF(2)); - assert((m >> success<int, std::string>()) == m); + assert((m >> success<int, string>()) == m); assert(m >> failableF >> failableG == m >> failableH); - std::cout << "Failable monad test... "; - failable<int, std::string> ooops = mkfailure<int, std::string>("test"); + cout << "Failable monad test... " << endl; + failable<int> ooops = mkfailure<int>("test"); assert(reason(ooops) == "test"); assert(ooops >> failableF >> failableG == ooops); return true; @@ -553,14 +540,14 @@ bool testStateMonad() { } bool testDynLib() { - const failable<lib, std::string> dl(dynlib(".libs/libdynlib-test" + dynlibExt)); + const failable<lib> dl(dynlib(string(".libs/libdynlib-test") + dynlibExt)); assert(hasContent(dl)); - const failable<lambda<int(const int)>, std::string> sq(dynlambda<int(const int)>("csquare", content(dl))); + const failable<lambda<int(const int)>> sq(dynlambda<int(const int)>("csquare", content(dl))); assert(hasContent(sq)); lambda<int(const int)> l(content(sq)); assert(l(2) == 4); - const failable<lambda<lambda<int(const int)>()>, std::string> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl))); + const failable<lambda<lambda<int(const int)>()>> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl))); assert(hasContent(sql)); lambda<lambda<int(const int)>()> ll(content(sql)); assert(ll()(3) == 9); @@ -570,12 +557,11 @@ bool testDynLib() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::testLambda(); tuscany::testLambdaGC(); tuscany::testCons(); - tuscany::testSet(); tuscany::testListGC(); tuscany::testOut(); tuscany::testEquals(); @@ -603,7 +589,7 @@ int main() { tuscany::testStateMonad(); tuscany::testDynLib(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp index 88163e63d2..653f49dfe5 100644 --- a/sca-cpp/trunk/kernel/list.hpp +++ b/sca-cpp/trunk/kernel/list.hpp @@ -26,9 +26,9 @@ * Simple list functions. */ -#include <string> -#include <sstream> -#include <iostream> +#include <assert.h> +#include "string.hpp" +#include "fstream.hpp" #include "function.hpp" #include "debug.hpp" @@ -56,28 +56,33 @@ bool checkListCounters() { } bool printListCounters() { - std::cout << "countLists " << countLists << std::endl; - std::cout << "countELists " << countELists << std::endl; - std::cout << "countILists " << countILists << std::endl; - std::cout << "countCLists " << countCLists << std::endl; + cout << "countLists " << countLists << endl; + cout << "countELists " << countELists << endl; + cout << "countILists " << countILists << endl; + cout << "countCLists " << countCLists << endl; return true; } -#define debug_watchList() do { \ - this->watch = watchList(*this); \ - } while (0) - #else #define resetListCounters() #define checkListCounters() true #define printListCounters() +#endif + +#ifdef _DEBUG_WATCH + +#define debug_watchList() do { \ + this->watch = watchList(*this); \ + } while (0) + +#else + #define debug_watchList(); #endif - /** * A car/cdr lisp-like pair, base structure to construct lists. */ @@ -91,28 +96,26 @@ public: debug_watchList(); } - list(const T car, const lambda<list<T>()>& cdr) : - car(car), cdr(cdr) { + 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) { + list(const list& p) : car(p.car), cdr(p.cdr) { debug_inc(countLists); debug_inc(countCLists); -#ifdef _DEBUG +#ifdef _DEBUG_WATCH watch = p.watch; #endif } - const list& operator=(const list<T>& p) { + const list<T>& operator=(const list<T>& p) { if(this == &p) return *this; car = p.car; cdr = p.cdr; -#ifdef _DEBUG +#ifdef _DEBUG_WATCH watch = p.watch; #endif return *this; @@ -172,41 +175,34 @@ public: return (list<list<T> >)T(*this); } - list<T>& operator<<(const T& v) { - *this = append(*this, mklist(v)); - return *this; - } +private: +#ifdef _DEBUG_WATCH + template<typename X> friend const string watchList(const list<X>& p); + string watch; +#endif 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 setCar(list<X>& p, const X& car); - template<typename X> friend const bool setCdr(list<X>& p, const list<X>& cdr); - template<typename X> friend const bool setCdr(list<X>& p, const lambda<list<X>()>& cdr); - -private: -#ifdef _DEBUG - template<typename X> friend const std::string watchList(const list<X>& p); - std::string watch; -#endif T car; lambda<list<T>()> cdr; }; -#ifdef _DEBUG +#ifdef _DEBUG_WATCH /** * 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 std::string watchList(const list<T>& p) { +template<typename T> const string watchList(const list<T>& p) { if(isNil(p)) return "()"; - std::ostringstream os; + ostringstream<string::npos> os; os << "(" << car(p) << " ...)"; - return os.str(); + return str(os); } + #endif /** @@ -219,14 +215,14 @@ template<typename T> const bool isNil(const list<T>& p) { /** * Write a list to an output stream. */ -template<typename T> std::ostream& writeHelper(std::ostream& out, const list<T>& l) { +template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) { if (isNil(l)) return out; out << " " << car(l); return writeHelper(out, cdr(l)); } -template<typename T> std::ostream& operator<<(std::ostream& out, const list<T>& l) { +template<typename T> ostream& operator<<(ostream& out, const list<T>& l) { if(isNil(l)) return out << "()"; out << "(" << car(l); @@ -305,6 +301,8 @@ template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, co * Returns the car of a list. */ template<typename T> const T car(const list<T>& p) { + // Abort if trying to access the car of a nil list + assert(!isNil(p.cdr)); return p.car; } @@ -316,31 +314,6 @@ template<typename T> const list<T> cdr(const list<T>& p) { } /** - * Sets the car of a list. - */ -template<typename T> const bool setCar(list<T>& p, const T& car) { - p.car = car; - return true; -} - -/** - * Sets the cdr of a list. - */ -template<typename T> const bool setCdr(list<T>& p, const list<T>& c) { - p.cdr = result(c); - return true; -} - -/** - * Sets the cdr of a list to a lambda function. - */ -template<typename T> const bool setCdr(list<T>& p, const lambda<list<T>()>& cdr) { - p.cdr = cdr; - return true; -} - - -/** * Returns the car of the cdr of a list. */ template<typename T> const T cadr(const list<T>& p) { @@ -419,6 +392,17 @@ template<typename T> const list<T> append(const list<T>&a, const list<T>& b) { } /** + * Append a value to a list. + */ +template<typename T> 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) { + 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) { diff --git a/sca-cpp/trunk/kernel/mem-test.cpp b/sca-cpp/trunk/kernel/mem-test.cpp new file mode 100644 index 0000000000..b1164a5a36 --- /dev/null +++ b/sca-cpp/trunk/kernel/mem-test.cpp @@ -0,0 +1,162 @@ +/* + * 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 memory allocation functions. + */ + +#include <assert.h> +#include "stream.hpp" +#include "string.hpp" +#include "gc.hpp" +#include "function.hpp" +#include "perf.hpp" + +namespace tuscany { + +int countElements = 0; +int maxElements = 0; + +class Element { +public: + Element() : i(0) { + countElements++; + if (countElements > maxElements) + maxElements = countElements; + } + + Element(int i) : i(i) { + countElements++; + if (countElements > maxElements) + maxElements = countElements; + } + + Element(const Element& o) : i(o.i) { + countElements++; + if (countElements > maxElements) + maxElements = countElements; + } + + ~Element() { + countElements--; + } + + const bool operator==(const Element& o) const { + return o.i == i; + } + +private: + friend ostream& operator<<(ostream& out, const Element& v); + + int i; + char c[20]; +}; + +ostream& operator<<(ostream& out, const Element& v) { + out << v.i ; + return out; +} + +bool poolAlloc(Element** 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) { + if (count == 0) + return true; + // Do nothing to free the element, but cycle through them just + // to get a fair comparison with the other memory alloc tests + 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 int count = 100000; + const lambda<bool()> pl = poolAllocPerf(count); + maxElements = 0; + cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl; + assert(countElements == 0); + assert(maxElements == count); + return true; +} + +bool stdAlloc(Element** 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) { + 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 int count = 100000; + const lambda<bool()> sl = stdAllocPerf(count); + maxElements = 0; + cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl; + assert(countElements == 0); + assert(maxElements == count); + return true; +} + +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::testPoolAllocPerf(); + tuscany::testStdAllocPerf(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp index 5449aa38fd..d2057cf367 100644 --- a/sca-cpp/trunk/kernel/monad.hpp +++ b/sca-cpp/trunk/kernel/monad.hpp @@ -26,11 +26,10 @@ * Simple monad implementations. */ -#include <string> -#include <iostream> - #include "function.hpp" #include "debug.hpp" +#include "string.hpp" +#include "stream.hpp" namespace tuscany { @@ -70,7 +69,7 @@ private: /** * Write an identity monad to a stream. */ -template<typename V> std::ostream& operator<<(std::ostream& out, const id<V>& m) { +template<typename V> ostream& operator<<(ostream& out, const id<V>& m) { out << content(m); return out; } @@ -148,7 +147,7 @@ private: /** * Write a maybe monad to a stream. */ -template<typename V> std::ostream& operator<<(std::ostream& out, const maybe<V>& m) { +template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) { if (!hasContent(m)) { out << "nothing"; return out; @@ -203,7 +202,7 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co * To get the value in the monad, just cast it to the value type. * To get the failure in the monad, cast it to the failure type. */ -template<typename V, typename F> class failable { +template<typename V, typename F = string> class failable { public: failable() : hasv(false) { } @@ -211,22 +210,7 @@ public: failable(const V& v) : hasv(true), v(v) { } - failable(const failable<V, F>& m) : hasv(m.hasv) { - if (hasv) - v = m.v; - else - f = m.f; - } - - const failable<V, F>& operator=(const failable<V, F>& m) { - if(this == &m) - return *this; - hasv = m.hasv; - if (hasv) - v = m.v; - else - f = m.f; - return *this; + failable(const failable<V, F>& m) : hasv(m.hasv), v(m.v), f(m.f) { } const bool operator!=(const failable<V, F>& m) const { @@ -242,23 +226,28 @@ public: } private: - bool hasv; - V v; - F f; - failable(const bool hasv, const F& f) : hasv(hasv), f(f) { } + // Prevent mutation + const failable<V, F>& operator=(const failable<V, F>& m) { + return *this; + } + template<typename A, typename B> friend const bool hasContent(const failable<A, B>& m); template<typename A, typename B> friend const A content(const failable<A, B>& m); template<typename A, typename B> friend const B reason(const failable<A, B>& m); template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f); + + bool hasv; + V v; + F f; }; /** * Write a failable monad to a stream. */ -template<typename V, typename F> std::ostream& operator<<(std::ostream& out, const failable<V, F>& m) { +template<typename V, typename F> ostream& operator<<(ostream& out, const failable<V, F>& m) { if (!hasContent(m)) { out << reason(m); return out; @@ -286,6 +275,10 @@ template<typename V, typename F> const failable<V, F> mkfailure(const F& f) { return failable<V, F>(false, f); } +template<typename V> const failable<V> mkfailure(const char* f) { + return mkfailure<V, string>(string(f)); +} + template<typename V, typename F> const lambda<failable<V, F>(const V)> failure() { return mkfailure<V, F>; } @@ -421,7 +414,7 @@ private: /** * Write a state monad to a stream. */ -template<typename S, typename V> std::ostream& operator<<(std::ostream& out, const state<S, V>& m) { +template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) { const S s = m; const V v = m; out << '(' << s << ' ' << v << ')'; diff --git a/sca-cpp/trunk/kernel/parallel-test.cpp b/sca-cpp/trunk/kernel/parallel-test.cpp index 8ae2eeed2c..b47501a58d 100644 --- a/sca-cpp/trunk/kernel/parallel-test.cpp +++ b/sca-cpp/trunk/kernel/parallel-test.cpp @@ -24,8 +24,8 @@ */ #include <assert.h> -#include <iostream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "function.hpp" #include "list.hpp" #include "perf.hpp" @@ -33,6 +33,8 @@ namespace tuscany { +#ifdef _REENTRANT + int inci = 0; struct incPerf { @@ -84,25 +86,25 @@ bool testAtomicPerf() { const int count = 100000; { const lambda<bool()> l = incPerf(); - std::cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << std::endl; + cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl; assert(inci == count + 1000); } { const lambda<bool()> l = addAndFetchPerf(); - std::cout << "Atomic inc test " << time(l, 1000, count) << " ms" << std::endl; + 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); - std::cout << "Locked inc test " << time(l, 1000, count) << " ms" << std::endl; + cout << "Locked inc test " << time(l, 1000, count) << " ms" << endl; assert(muxi == count + 1000); pthread_mutex_destroy(&mutex); } { const lambda<bool()> l = tlsPerf(); - std::cout << "Thread local inc test " << time(l, 1000, count) << " ms" << std::endl; + cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl; assert(tlsi == count + 1000); } return true; @@ -114,38 +116,51 @@ const int mtsquare(const int x) { return x * x; } +bool checkResults(const list<future<int> > r, int i) { + if (isNil(r)) + return true; + assert(car(r) == i * i); + checkResults(cdr(r), i + 1); + return true; +} + +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); + return cons(submit(w, func), submitSquares(w, max, i + 1)); +} + bool testWorker() { - worker w(10); + worker w(20); { const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), 2); assert(submit(w, func) == 4); } { - const int max = 10; - - list<future<int> > r; - for(int i = 0; i < max; i++) { - const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), i); - r = cons(submit(w, func), r); - } - for(int i = max - 1; i >= 0; i--) { - assert(car(r) == i * i); - r = cdr(r); - } + const int max = 20; + const list<future<int> > r(submitSquares(w, max, 0)); + checkResults(r, 0); } shutdown(w); return true; } +#endif + } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; +#ifdef _REENTRANT tuscany::testAtomicPerf(); tuscany::testWorker(); +#else + tuscany::cout << "Skipped multi-thread tests" << tuscany::endl; +#endif - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp index a94764763a..33cb735b84 100644 --- a/sca-cpp/trunk/kernel/parallel.hpp +++ b/sca-cpp/trunk/kernel/parallel.hpp @@ -26,13 +26,18 @@ * Simple parallel work execution functions. */ +#ifdef _REENTRANT #include <pthread.h> #include <sys/syscall.h> +#include <unistd.h> +#endif #include "function.hpp" namespace tuscany { +#ifdef _REENTRANT + /** * Returns the current thread id. */ @@ -48,8 +53,7 @@ template<typename T> class future { private: template<typename X> class futureValue { public: - futureValue() : - refCount(0), hasValue(false) { + futureValue() : hasValue(false) { pthread_mutex_init(&valueMutex, NULL); pthread_cond_init(&valueCond, NULL); } @@ -59,14 +63,6 @@ private: pthread_cond_destroy(&valueCond); } - unsigned int acquire() { - return __sync_add_and_fetch(&refCount, (unsigned int)1); - } - - unsigned int release() { - return __sync_sub_and_fetch(&refCount, (unsigned int)1); - } - bool set(const T& v) { pthread_mutex_lock(&valueMutex); if(hasValue) { @@ -91,33 +87,28 @@ private: } private: - unsigned refCount; pthread_mutex_t valueMutex; pthread_cond_t valueCond; bool hasValue; X value; }; - gc_counting_ptr<futureValue<T> > fvalue; + 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); public: - future() : fvalue(new futureValue<T>()) { - //std::cout << "future() threadId " << threadId() << "\n"; + future() : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) { } ~future() { - //std::cout << "~future() threadId " << threadId() << "\n"; } future(const future& f) : fvalue(f.fvalue) { - //std::cout << "future(const future& f) threadId " << threadId() << "\n"; } const future& operator=(const future& f) { - //std::cout << "future::operator=(const future& f) threadId " << threadId() << "\n"; if (&f == this) return *this; fvalue = f.fvalue; @@ -132,7 +123,6 @@ public: operator const T() const { return fvalue->get(); } - }; /** @@ -140,7 +130,7 @@ public: */ template<typename T> class queue { public: - queue(int max) : max(max), size(0), tail(0), head(0), values(new T[max]) { + queue(int max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) { pthread_mutex_init(&mutex, NULL); pthread_cond_init(&full, NULL); pthread_cond_init(&empty, NULL); @@ -160,7 +150,7 @@ private: pthread_mutex_t mutex; pthread_cond_t full; pthread_cond_t empty; - gc_aptr<T> values; + gc_ptr<T> values; template<typename X> friend const int enqueue(queue<X>& q, const X& v); template<typename X> friend const X dequeue(queue<X>& q); @@ -280,5 +270,7 @@ const bool shutdown(worker& w) { return true; } +#endif + } #endif /* tuscany_parallel_hpp */ diff --git a/sca-cpp/trunk/kernel/slist.hpp b/sca-cpp/trunk/kernel/slist.hpp deleted file mode 100644 index 705152cb29..0000000000 --- a/sca-cpp/trunk/kernel/slist.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -/* $Rev$ $Date$ */ - -#ifndef tuscany_slist_hpp -#define tuscany_slist_hpp - -/** - * Useful functions to work with lists of strings and character streams. - */ - -#include <iostream> -#include <string> -#include "function.hpp" -#include "list.hpp" - -namespace tuscany { - -/** - * Tokenize a string into a list of strings. - */ -const list<std::string> tokenize(const std::string& sep, const std::string& str) { - struct nested { - static const list<std::string> tokenize(const std::string& sep, const std::string& str, const unsigned int start = 0) { - if (start >= str.length()) - return list<std::string>(); - const unsigned int i = str.find_first_of(sep, start); - if (i == std::string::npos) - return mklist(str.substr(start)); - return cons(str.substr(start, i - start), tokenize(sep, str, i + 1)); - } - }; - return nested::tokenize(sep, str, 0); -} - -/** - * Returns a lazy list view of an input stream. - */ -struct ilistRead{ - std::istream &is; - ilistRead(std::istream& is) : is(is) { - } - const list<std::string> operator()() { - char buffer[1024]; - is.read(buffer, 1024); - const int n = is.gcount(); - if (n ==0) - return list<std::string>(); - return cons(std::string(buffer, n), (*this)()); - } -}; - -const list<std::string> streamList(std::istream& is) { - return ilistRead(is)(); -} - -/** - * Fragment the first element of a list of strings to fit the given max length. - */ -const list<std::string> fragment(list<std::string> l, unsigned int max) { - const std::string s = car(l); - if (s.length() <= max) - return l; - return cons(s.substr(0, max), cons(s.substr(max), cdr(l))); -} - -/** - * Write a list of strings to an output stream. - */ -std::ostream& write(const list<std::string>& l, std::ostream& os) { - if(isNil(l)) - return os; - os << car(l); - return write(cdr(l), os); -} - -} - -#endif /* tuscany_slist_hpp */ diff --git a/sca-cpp/trunk/kernel/sstream.hpp b/sca-cpp/trunk/kernel/sstream.hpp new file mode 100644 index 0000000000..5fcdb0c22b --- /dev/null +++ b/sca-cpp/trunk/kernel/sstream.hpp @@ -0,0 +1,234 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_sstream_hpp +#define tuscany_sstream_hpp + +/** + * Char buffer based streams. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <memory.h> +#include "string.hpp" +#include "stream.hpp" +#include "list.hpp" + +namespace tuscany { + +/** + * Instrumentable memcpy. + */ +void* stream_memcpy(void* t, const void* s, const size_t n) { + return memcpy(t, s, n); +} + +/** + * Output stream backed by a char buffer. + */ +class ostringstream : public ostream { +public: + ostringstream() : len(0) { + } + + ~ostringstream() { + } + + ostringstream(const ostringstream& os) { + len = os.len; + buf = os.buf; + } + + ostringstream& vprintf(const char* fmt, ...) { + va_list args; + va_start (args, fmt); + string s; + s.len = vsnprintf(NULL, 0, fmt, args); + s.buf = gc_cnew(s.len + 1); + vsnprintf(s.buf, s.len + 1, fmt, args); + buf = cons(s, buf); + len += s.len; + va_end (args); + return *this; + } + + ostringstream& flush() { + return *this; + } + +private: + static const bool strHelper(const list<string> l, char* buf) { + if (isNil(l)) + return true; + const string c = car(l); + char* b = buf - length(c); + memcpy(b, c_str(c), length(c)); + return strHelper(cdr(l), b); + } + + const string str() { + if (isNil(buf)) + return string(); + string s; + s.len = len; + s.buf = gc_cnew(s.len + 1); + strHelper(buf, s.buf + len); + s.buf[s.len] = '\0'; + return s; + } + + friend const string str(ostringstream& os); + + int len; + list<string> buf; +}; + +/** + * Return a string representation of a stream. + */ +const string str(ostringstream& os) { + return os.str(); +} + +/** + * Input stream backed by a char buffer + */ +class istringstream : public istream { +public: + istringstream(const string& s) { + cur = 0; + const int slen = length(s); + len = slen; + buf = c_str(s); + } + + ~istringstream() { + } + + istringstream(const istringstream& is) { + len = is.len; + cur = is.cur; + buf = is.buf; + } + + const int read(void* b, int size) { + const int n = len - cur; + if (n == 0) + return 0; + if (n > size) { + stream_memcpy(b, buf + cur, size); + cur = cur + size; + return size; + } + stream_memcpy(b, buf + cur, n); + cur = cur + n; + return n; + } + + const bool eof() { + return cur == len; + } + + const bool fail() { + return false; + } + + const int get() { + if (eof()) + return -1; + const int c = buf[cur]; + cur += 1; + return c; + } + + const int peek() { + if (eof()) + return -1; + return buf[cur]; + } + +private: + int len; + int cur; + const char* buf; +}; + +/** + * 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 string& str, const int start = 0) { + if (start >= length(str)) + return list<string>(); + const int 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, str, i + 1)); + } + }; + return nested::tokenize(sep, str, 0); +} + +/** + * Returns a lazy list view of an input stream. + */ +struct ilistRead{ + istream &is; + ilistRead(istream& is) : is(is) { + } + const list<string> operator()() { + char buffer[1024]; + const int 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)(); +} + +/** + * Fragment the first element of a list of strings to fit the given max length. + */ +const list<string> fragment(list<string> l, int max) { + const string s = car(l); + if (length(s) <= max) + return l; + return cons(substr(s, 0, max), cons(substr(s, max), cdr(l))); +} + +/** + * Write a list of strings to an output stream. + */ +ostream& write(const list<string>& l, ostream& os) { + if(isNil(l)) + return os; + os << car(l); + return write(cdr(l), os); +} + +} + +#endif /* tuscany_sstream_hpp */ diff --git a/sca-cpp/trunk/kernel/stream.hpp b/sca-cpp/trunk/kernel/stream.hpp new file mode 100644 index 0000000000..a3e532c4ce --- /dev/null +++ b/sca-cpp/trunk/kernel/stream.hpp @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_stream_hpp +#define tuscany_stream_hpp + +/** + * Basic stream type and functions. + */ + +#include <stdarg.h> +#include "debug.hpp" +#include "gc.hpp" +#include "string.hpp" + +namespace tuscany { + +/** + * Base output stream. + */ +class ostream { +public: + virtual ostream& vprintf(const char* fmt, ...) = 0; + virtual ostream& flush() = 0; +}; + +/** + * Flush a stream. + */ +ostream& flush(ostream& os) { + return os.flush(); +} + +/** + * Write simple values to a stream. + */ +ostream& operator<<(ostream& os, const char* v) { + return os.vprintf("%s", v); +} + +ostream& operator<<(ostream& os, const unsigned char* v) { + return os.vprintf("%s", v); +} + +ostream& operator<<(ostream& os, const char v) { + return os.vprintf("%c", v); +} + +ostream& operator<<(ostream& os, const int v) { + return os.vprintf("%d", v); +} + +ostream& operator<<(ostream& os, const long int v) { + return os.vprintf("%ld", v); +} + +ostream& operator<<(ostream& os, const double v) { + return os.vprintf("%g", v); +} + +ostream& operator<<(ostream& os, const void* v) { + return os.vprintf("%p", v); +} + +ostream& operator<<(ostream& os, const string& v) { + return os.vprintf("%s", c_str(v)); +} + +class stream_endl { +} endl; + +ostream& operator<<(ostream& os, unused const stream_endl e) { + os.vprintf("%s", "\n"); + return os.flush(); +} + +/* + * Input stream. + */ +class istream { +public: + virtual const int read(void* buf, int size) = 0; + virtual const bool eof() = 0; + virtual const bool fail() = 0; + virtual const int get() = 0; + virtual const int peek() = 0; +}; + +/** + * Read from an input stream. + */ +const int read(istream& is, void * buf, int size) { + return is.read(buf, size); +} + +/** + * Return true if the end of an input stream has been reached. + */ +const bool eof(istream& is) { + return is.eof(); +} + +/** + * Return true if an input stream can't be accessed. + */ +const bool fail(istream& is) { + return is.fail(); +} + +/** + * Read a character from a stream. + */ +const int get(istream& is) { + return is.get(); +} + +/** + * Peek a character from a stream. + */ +const int peek(istream& is) { + return is.peek(); +} + +template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) { + return out << p.ptr; +} + +} + +#endif /* tuscany_stream_hpp */ diff --git a/sca-cpp/trunk/kernel/string-test.cpp b/sca-cpp/trunk/kernel/string-test.cpp new file mode 100644 index 0000000000..323756c7e4 --- /dev/null +++ b/sca-cpp/trunk/kernel/string-test.cpp @@ -0,0 +1,196 @@ +/* + * 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 string functions. + */ + +#include <assert.h> +#include <string> +#include "sstream.hpp" +#include "string.hpp" +#include "list.hpp" +#include "perf.hpp" + +namespace tuscany { + +bool testCopies() { + resetStringCopyCounters(); + string x("abcd"); + assert(checkStringCopyCounters(1)); + resetStringCopyCounters(); + string y = string("abcd"); + assert(checkStringCopyCounters(1)); + resetStringCopyCounters(); + string z = y; + assert(checkStringCopyCounters(0)); + resetStringCopyCounters(); + const list<string> pl = list<string>() + "abcd" + "efgh"; + printStringCopyCounters(); + resetStringCopyCounters(); + const list<string> cl = cons<string>("efgh", mklist<string>("abcd")); + printStringCopyCounters(); + return true; +} + +bool testString() { + const string s("abcd"); + assert(length(s) == 4); + assert(!strcmp(c_str(s), "abcd")); + + assert(s == "abcd"); + assert(s == string("abcd")); + assert(s != "zbcd"); + + assert(s < "zbcd"); + assert(s < "zbc"); + assert(s < "abzd"); + assert(s < "abcdz"); + + assert(s > "Abcd"); + assert(s > "Abc"); + assert(s > "abCd"); + assert(s > "Abcdz"); + + const string x = "abcd"; + assert(!strcmp(c_str(x), "abcd")); + + const string y = string("abcd"); + assert(!strcmp(c_str(y), "abcd")); + + assert(string("ab") + "cd" == "abcd"); + + assert(find("abcd", "cd") == 2); + assert(find("abcd", "xy") == length("abcd")); + assert(substr("abcdef", 4) == "ef"); + assert(substr("abcdef", 4, 2) == "ef"); + assert(substr("abcdef", 4, 3) == "ef"); + assert(substr("abcdef", 6, 3) == ""); + return true; +} + +bool testStream() { + ostringstream os; + os << "ab" << "cd"; + cout << str(os) << endl; + assert(str(os) == "abcd"); + + ostringstream cs; + cs << "\'"; + assert(str(cs) == "\'"); + cs << '\''; + assert(str(cs) == "\'\'"); + + istringstream is("abcd"); + char b[2]; + assert(read(is, b, 2) == 2); + assert(string("ab") == string(b, 2)); + assert(eof(is) == false); + assert(read(is, b, 2) == 2); + assert(string("cd") == string(b, 2)); + assert(eof(is) == true); + assert(read(is, b, 2) == 0); + return true; +} + +std::string stdAdd(std::string& x, std::string& y) { + return x + y; +} + +string add(string& x, string& y) { + return x + y; +} + +char charBuffer[16384]; + +struct addStrings{ + const int size; + addStrings(const int size) : size(size) { + } + bool operator()() const { + const int sz = size / 4; + string x(charBuffer, sz); + string y(charBuffer, sz); + assert(length(add(x, y)) == sz * 2); + return true; + } +}; + +struct addStdStrings{ + const int size; + addStdStrings(const int size) : size(size) { + } + bool operator()() const { + const int 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() { + memset(charBuffer, 'A', 16384); + charBuffer[16384] = '\0'; + + const int count = 100000; + { + const lambda<bool()> a16 = addStrings(16); + cout << "string test " << time(a16, 5, count) << " ms" << endl; + const lambda<bool()> a32 =addStrings(32); + cout << "string test " << time(a32, 5, count) << " ms" << endl; + const lambda<bool()> a256 =addStrings(256); + cout << "string test " << time(a256, 5, count) << " ms" << endl; + const lambda<bool()> a1024 =addStrings(1024); + cout << "string test " << time(a1024, 5, count) << " ms" << endl; + const lambda<bool()> a4096 =addStrings(4096); + cout << "string test " << time(a4096, 5, count) << " ms" << endl; + } + { + const lambda<bool()> a16 =addStdStrings(16); + cout << "Std string test " << time(a16, 5, count) << " ms" << endl; + const lambda<bool()> a32 =addStdStrings(32); + cout << "Std string test " << time(a32, 5, count) << " ms" << endl; + const lambda<bool()> a256 =addStdStrings(256); + cout << "Std string test " << time(a256, 5, count) << " ms" << endl; + const lambda<bool()> a1024 =addStdStrings(1024); + cout << "Std string test " << time(a1024, 5, count) << " ms" << endl; + const lambda<bool()> a4096 =addStdStrings(4096); + cout << "Std string test " << time(a4096, 5, count) << " ms" << endl; + } + + return true; +} + +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::testCopies(); + tuscany::testString(); + tuscany::testStream(); + tuscany::testStringPerf(); + + tuscany::cout << "OK" << tuscany::endl; + + return 0; +} diff --git a/sca-cpp/trunk/kernel/string.hpp b/sca-cpp/trunk/kernel/string.hpp new file mode 100644 index 0000000000..f065bcc9a4 --- /dev/null +++ b/sca-cpp/trunk/kernel/string.hpp @@ -0,0 +1,288 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_string_hpp +#define tuscany_string_hpp + +/** + * Simple and fast string type backed by a char buffer + */ + +#include <assert.h> +#include <string.h> +#include <memory.h> +#include <stdio.h> +#include "gc.hpp" + +namespace tuscany { + +#ifdef _DEBUG + +/** + * Debug utilities. Counters used to track string copies. + */ +long countStringCopies = 0; + +bool resetStringCopyCounters() { + countStringCopies = 0; + return true; +} + +bool checkStringCopyCounters(long c) { + return countStringCopies == c; +} + +bool printStringCopyCounters() { + printf("countStringCopies %ld\n", countStringCopies); + return true; +} + +#else + +#define resetStringCopyCounters() +#define checkStringCopyCounters(c) true +#define printStringCopyCounters() + +#endif + +/** + * Instrumented memcpy. + */ +void* string_memcpy(void* t, const void* s, const size_t n) { +#ifdef _DEBUG + countStringCopies += 1; +#endif + return memcpy(t, s, n); +} + +char stringEmptyBuffer[1] = { '\0' }; + +/** + * String class. The maximum string size is specified as a template parameter. + */ +class string { +public: + string() : 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); + } + + string(const char* s, const int n) { + len = n; + if (len == 0) { + buf = stringEmptyBuffer; + return; + } + buf = gc_cnew(len + 1); + string_memcpy(buf, s, len); + buf[len] = '\0'; + } + + string(const int n, const char c) { + len = n; + if (len == 0) { + buf = stringEmptyBuffer; + return; + } + buf = gc_cnew(len + 1); + memset(buf, c, n); + buf[len] = '\0'; + } + + string(const string& s) { + len = s.len; + buf = s.buf; + } + + const string& operator=(const string& s) { + if (&s == this) + return *this; + len = s.len; + buf = s.buf; + return *this; + } + + const bool operator==(const string& s) const { + if (len != s.len) + return false; + if (buf == s.buf) + return true; + return memcmp(buf, s.buf, len) == 0; + } + + const bool operator!=(const string& s) const { + return !(*this == s); + } + + const bool operator==(const char* s) const { + if (buf == s) + return true; + return strcmp(buf, s) == 0; + } + + const bool operator!=(const char* s) const { + return !(*this == s); + } + + const bool operator<(const string& s) const { + const int n = len < s.len? len : s.len; + const int c = memcmp(buf, s.buf, n); + if (c < 0) + return true; + if (c == 0) + return len < s.len; + return false; + } + + const bool operator>(const string& s) const { + const int n = len < s.len? len : s.len; + int c = memcmp(buf, s.buf, n); + if (c > 0) + return true; + if (c == 0) + return len > s.len; + return false; + } + +private: + 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 int length(const string& s); + friend const char* c_str(const string& s); + friend const int find(const string& s1, const char* s2, const int start); + friend const string substr(const string& s, const int pos, const int n); + + int len; + char* buf; +}; + +/** + * 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; +} + +const string operator+(const string& a, const char* b) { + string s; + const int 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; +} + +/** + * Returns the length of a string. + */ +const int length(const string& s) { + return s.len; +} + +/** + * Returns a string as a C zero terminated string. + */ +const char* c_str(const string& s) { + return s.buf; +} + +/** + * Find the first occurrence of string s2 in s1, starting at the given position. + */ +const int find(const string& s1, const char* s2, const int start) { + if (start >= s1.len) + return s1.len; + const char *f = strstr(s1.buf + start, s2); + if (f == NULL) + return s1.len; + return f - s1.buf; +} + +const int find(const string& s1, const char* s2) { + return find(s1, s2, 0); +} + +const bool contains(const string& s1, const char* s2) { + return find(s1, s2) != length(s1); +} + +/** + * Find the first occurence of any character from a string in a string. + */ +const int find_first_of(const string& s1, const string& s2) { + return strcspn(c_str(s1), c_str(s2)); +} + +/** + * Find the last occurence of a character in a string. + */ +const int find_last(const string& s, const char c) { + const char* cs = c_str(s); + const char* f = strrchr(cs, c); + if (f == NULL) + return length(s); + return f - cs; +} + +/** + * Return a substring of a string. + */ +const string substr(const string& s, const int pos, const int n) { + if (pos >= s.len) + return string(); + if (pos + n > s.len) + return string(s.buf + pos, s.len - pos); + return string(s.buf + pos, n); +} + +const string substr(const string& s, const int pos) { + return substr(s, pos, length(s)); +} + +/** + * Common string constants. + */ + +string trueString("true"); +string falseString("false"); +string emptyString(""); + +} + +#endif /* tuscany_string_hpp */ diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp index f0c85ff403..436385aa1b 100644 --- a/sca-cpp/trunk/kernel/tree.hpp +++ b/sca-cpp/trunk/kernel/tree.hpp @@ -26,8 +26,8 @@ * Functions to work with trees. */ -#include <iostream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "function.hpp" #include "list.hpp" #include "monad.hpp" diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp index e767ead74b..d2c5f12e95 100644 --- a/sca-cpp/trunk/kernel/value.hpp +++ b/sca-cpp/trunk/kernel/value.hpp @@ -26,9 +26,9 @@ * Generic value type. */ -#include <string> -#include <iostream> -#include <sstream> +#include <stdlib.h> +#include "string.hpp" +#include "sstream.hpp" #include "gc.hpp" #include "function.hpp" #include "list.hpp" @@ -60,23 +60,29 @@ bool checkValueCounters() { } bool printValueCounters() { - std::cout << "countValues " << countValues << std::endl; - std::cout << "countEValues " << countEValues << std::endl; - std::cout << "countCValues " << countCValues << std::endl; - std::cout << "countVValues " << countVValues << std::endl; + cout << "countValues " << countValues << endl; + cout << "countEValues " << countEValues << endl; + cout << "countCValues " << countCValues << endl; + cout << "countVValues " << countVValues << endl; return true; } -#define debug_watchValue() do { \ - this->watch = watchValue(*this); \ - } while (0) - #else #define resetValueCounters() #define checkValueCounters() true #define printValueCounters() +#endif + +#ifdef _DEBUG_WATCH + +#define debug_watchValue() do { \ + this->watch = watchValue(*this); \ + } while (0) + +#else + #define debug_watchValue() #endif @@ -90,8 +96,7 @@ public: Undefined, Symbol, String, List, Number, Bool, Char, Lambda, Ptr, PoolPtr }; - value() : - type(value::Undefined) { + value() : type(value::Undefined) { debug_inc(countValues); debug_inc(countEValues); debug_watchValue(); @@ -123,43 +128,11 @@ public: default: break; } -#ifdef _DEBUG +#ifdef _DEBUG_WATCH watch = v.watch; #endif } - 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::Char: - chr() = v.chr(); - case value::Ptr: - ptr() = v.ptr(); - case value::PoolPtr: - poolptr() = v.poolptr(); - default: - break; - } -#ifdef _DEBUG - watch = v.watch; -#endif - return *this; - } - virtual ~value() { debug_dec(countValues); } @@ -170,13 +143,13 @@ public: debug_watchValue(); } - value(const std::string& str) : type(value::String), data(vdata(result(str))) { + value(const string& str) : type(value::String), data(vdata(result(str))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const char* str) : type(value::Symbol), data(vdata(result(std::string(str)))) { + value(const char* str) : type(value::Symbol), data(vdata(result(string(str)))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); @@ -218,19 +191,21 @@ public: debug_watchValue(); } +#ifdef _GC_REFCOUNT value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } +#endif - value(const gc_pool_ptr<value> ptr) : type(value::PoolPtr), data(vdata(result(ptr))) { + value(const gc_ptr<value> ptr) : type(value::PoolPtr), data(vdata(result(ptr))) { debug_inc(countValues); debug_inc(countVValues); debug_watchValue(); } - value(const failable<value, std::string>& m) : type(value::List), + value(const failable<value>& m) : type(value::List), data(vdata(result(hasContent(m)? mklist<value>(content(m)) : mklist<value>(value(), reason(m))))) { debug_inc(countValues); debug_inc(countVValues); @@ -244,6 +219,38 @@ public: 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::Char: + chr() = v.chr(); + case value::Ptr: + ptr() = v.ptr(); + case value::PoolPtr: + poolptr() = v.poolptr(); + default: + break; + } +#ifdef _DEBUG_WATCH + watch = v.watch; +#endif + return *this; + } + const bool operator!=(const value& v) const { return !this->operator==(v); } @@ -259,9 +266,8 @@ public: case value::Lambda: return v.type == value::Lambda && func() == v.func(); case value::Symbol: - return str()() == (std::string)v; case value::String: - return str()() == (std::string)v; + return str()() == (string)v; case value::Number: return num()() == (double)v; case value::Bool: @@ -285,8 +291,7 @@ public: return v.type == value::List && lst()() < v.lst()(); case value::Symbol: case value::String: - return str()() < (std::string)v; - return str()() < (std::string)v; + return str()() < (string)v; case value::Bool: return boo()() < (bool)v; case value::Number: @@ -306,8 +311,7 @@ public: return v.type == value::List && lst()() > v.lst()(); case value::Symbol: case value::String: - return str()() > (std::string)v; - return str()() > (std::string)v; + return str()() > (string)v; case value::Bool: return boo()() > (bool)v; case value::Number: @@ -323,25 +327,25 @@ public: return func()(args); } - operator const std::string() const { + operator const string() const { switch(type) { case value::Symbol: case value::String: return str()(); case value::Number: { - std::ostringstream sos; - sos << num()(); - return sos.str(); + ostringstream os; + os << num()(); + return tuscany::str(os); } case value::Bool: - return boo()()? "true" : "false"; + return boo()()? trueString : falseString; case value::Char: { - std::ostringstream sos; - sos << chr()(); - return sos.str(); + ostringstream os; + os << chr()(); + return tuscany::str(os); } default: - return ""; + return emptyString; } } @@ -349,7 +353,7 @@ public: switch(type) { case value::Symbol: case value::String: - return atof(str()().c_str()); + return atof(c_str(str()())); case value::Number: return (double)num()(); case value::Bool: @@ -365,7 +369,7 @@ public: switch(type) { case value::Symbol: case value::String: - return atoi(str()().c_str()); + return atoi(c_str(str()())); case value::Number: return (int)num()(); case value::Bool: @@ -381,7 +385,7 @@ public: switch(type) { case value::Symbol: case value::String: - return str()() == "true"; + return str()() == string("true"); case value::Number: return (int)num()() != 0; case value::Bool: @@ -409,11 +413,13 @@ public: } } +#ifdef _GC_REFCOUNT operator const gc_ptr<value>() const { return ptr()(); } +#endif - operator const gc_pool_ptr<value>() const { + operator const gc_ptr<value>() const { return poolptr()(); } @@ -454,12 +460,12 @@ private: return vdata<gc_ptr<value>()> (); } - lambda<gc_pool_ptr<value>()>& poolptr() const { - return vdata<gc_pool_ptr<value>()> (); + lambda<gc_ptr<value>()>& poolptr() const { + return vdata<gc_ptr<value>()> (); } - lambda<std::string()>& str() const { - return vdata<std::string()> (); + lambda<string()>& str() const { + return vdata<string()> (); } lambda<list<value>()>& lst() const { @@ -482,37 +488,38 @@ private: return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l))); } - friend std::ostream& operator<<(std::ostream&, const value&); + friend ostream& operator<<(ostream&, const value&); friend const value::ValueType type(const value& v); -#ifdef _DEBUG - friend const std::string watchValue(const value& v); - std::string watch; +#ifdef _DEBUG_WATCH + friend const string watchValue(const value& v); + string watch; #endif ValueType type; lambda<char()> data; }; -#ifdef _DEBUG +#ifdef _DEBUG_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 std::string watchValue(const value& v) { +const string watchValue(const value& v) { if (v.type == value::List) return watchList<value>(v); - std::ostringstream os; + ostringstream<string::npos> os; os << v; - return os.str(); + return str(os); } + #endif /** * Write a value to a stream. */ -std::ostream& operator<<(std::ostream& out, const value& v) { +ostream& operator<<(ostream& out, const value& v) { switch(v.type) { case value::List: return out << v.lst()(); @@ -538,8 +545,8 @@ std::ostream& operator<<(std::ostream& out, const value& v) { return out << "gc_ptr::" << p; } case value::PoolPtr: { - const gc_pool_ptr<value> p = v.poolptr()(); - if (p == gc_pool_ptr<value>(NULL)) + const gc_ptr<value> p = v.poolptr()(); + if (p == gc_ptr<value>(NULL)) return out << "pool_ptr::null"; return out << "pool_ptr::" << p; } @@ -634,5 +641,14 @@ const bool isTaggedList(const value& exp, value tag) { return false; } +/** + * Make a list of values from a list of other things. + */ +template<typename T> const list<value> mkvalues(const list<T>& l) { + if (isNil(l)) + return list<value>(); + return cons<value>(car(l), mkvalues(cdr(l))); +} + } #endif /* tuscany_value_hpp */ diff --git a/sca-cpp/trunk/kernel/xml-test.cpp b/sca-cpp/trunk/kernel/xml-test.cpp index 88c476ffef..585a2e519d 100644 --- a/sca-cpp/trunk/kernel/xml-test.cpp +++ b/sca-cpp/trunk/kernel/xml-test.cpp @@ -24,9 +24,8 @@ */ #include <assert.h> -#include <iostream> -#include <string> -#include <sstream> +#include "stream.hpp" +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "element.hpp" @@ -34,7 +33,7 @@ namespace tuscany { -const std::string currencyXML = +const string currencyXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" " "xmlns:t=\"http://tuscany.apache.org/xmlns/sca/1.1\" " @@ -56,7 +55,7 @@ const std::string currencyXML = "</composite>" "\n"; -const std::string customerXML = +const string customerXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<customer>" "<name>jdoe</name>" @@ -74,78 +73,78 @@ const bool isName(const value& token) { bool testReadXML() { { - std::istringstream is(customerXML); + istringstream is(customerXML); const list<value> c = readXML(streamList(is)); } { - std::istringstream is(currencyXML); + 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)))) == std::string("currency")); + assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency")); } return true; } -std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) { +ostream* xmlWriter(const string& s, ostream* os) { (*os) << s; return os; } bool testWriteXML() { { - std::istringstream is(customerXML); + istringstream is(customerXML); const list<value> c = readXML(streamList(is)); - std::ostringstream os; - writeXML<std::ostringstream*>(xmlWriter, &os, c); - assert(os.str() == customerXML); + ostringstream os; + writeXML<ostream*>(xmlWriter, &os, c); + assert(str(os) == customerXML); } { - std::istringstream is(currencyXML); + istringstream is(currencyXML); const list<value> c = readXML(streamList(is)); - std::ostringstream os; - writeXML<std::ostringstream*>(xmlWriter, &os, c); - assert(os.str() == currencyXML); + ostringstream os; + writeXML<ostream*>(xmlWriter, &os, c); + assert(str(os) == currencyXML); } return true; } bool testElement() { { - const list<value> ad = mklist<value>(mklist<value>("city", std::string("san francisco")), mklist<value>("state", std::string("ca"))); - const list<value> ac1 = mklist<value>(mklist<value>("id", std::string("1234")), mklist<value>("balance", 1000)); - const list<value> ac2 = mklist<value>(mklist<value>("id", std::string("6789")), mklist<value>("balance", 2000)); - const list<value> ac3 = mklist<value>(mklist<value>("id", std::string("4567")), mklist<value>("balance", 3000)); + 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", std::string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3)))); + 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); - std::ostringstream os; - writeXML<std::ostringstream*>(xmlWriter, &os, e); - assert(os.str() == customerXML); + ostringstream os; + writeXML<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); } { - const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", std::string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3))); + 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); - std::ostringstream os; - writeXML<std::ostringstream*>(xmlWriter, &os, e); - assert(os.str() == customerXML); + ostringstream os; + writeXML<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); } } { - std::istringstream is(customerXML); + istringstream is(customerXML); const list<value> c = readXML(streamList(is)); const list<value> v = elementsToValues(c); const list<value> e = valuesToElements(v); - std::ostringstream os; - writeXML<std::ostringstream*>(xmlWriter, &os, e); - assert(os.str() == customerXML); + ostringstream os; + writeXML<ostream*>(xmlWriter, &os, e); + assert(str(os) == customerXML); } return true; } @@ -153,13 +152,13 @@ bool testElement() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::testReadXML(); tuscany::testWriteXML(); tuscany::testElement(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp index eee6e290d8..84cfc30475 100644 --- a/sca-cpp/trunk/kernel/xml.hpp +++ b/sca-cpp/trunk/kernel/xml.hpp @@ -30,9 +30,9 @@ #include <libxml/xmlwriter.h> #include <libxml/xmlschemas.h> #include <libxml/globals.h> -#include <string> +#include "string.hpp" #include "list.hpp" -#include "slist.hpp" +#include "stream.hpp" #include "value.hpp" #include "element.hpp" #include "monad.hpp" @@ -127,7 +127,7 @@ const value readIdentifier(XMLReader& reader) { */ const value readText(XMLReader& reader) { const char *val = (const char*)xmlTextReaderConstValue(reader); - return std::string(val); + return string(val); } /** @@ -136,7 +136,7 @@ const value readText(XMLReader& reader) { const value readAttribute(XMLReader& reader) { const char *name = (const char*)xmlTextReaderConstName(reader); const char *val = (const char*)xmlTextReaderConstValue(reader); - return mklist<value>(attribute, name, std::string(val)); + return mklist<value>(attribute, name, string(val)); } /** @@ -186,9 +186,9 @@ const list<value> read(XMLReader& reader) { */ class XMLReadContext { public: - XMLReadContext(const list<std::string>& ilist) : ilist(ilist) { + XMLReadContext(const list<string>& ilist) : ilist(ilist) { } - list<std::string> ilist; + list<string> ilist; }; /** @@ -198,17 +198,17 @@ int readCallback(void *context, char* buffer, int len) { XMLReadContext& rc = *static_cast<XMLReadContext*>(context); if (isNil(rc.ilist)) return 0; - rc.ilist = fragment(rc.ilist, len); - std::string s = car(rc.ilist); - rc.ilist = cdr(rc.ilist); - s.copy(buffer, s.length()); - return s.length(); + const list<string> f(fragment(rc.ilist, len)); + const string s(car(f)); + rc.ilist = cdr(f); + memcpy(buffer, c_str(s), length(s)); + return length(s); } /** - * Read a list values from a list of strings representing an XML document. + * Read a list of values from a list of strings representing an XML document. */ -const list<value> readXML(const list<std::string>& ilist) { +const list<value> readXML(const list<string>& ilist) { XMLReadContext cx(ilist); xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET); if (xml == NULL) @@ -232,15 +232,15 @@ const list<value> expandElementValues(const value& n, const list<value>& l) { return cons<value>(value(cons<value>(element, cons<value>(n, (list<value>)car(l)))), expandElementValues(n, cdr(l))); } -const failable<bool, std::string> writeList(const list<value>& l, const xmlTextWriterPtr xml) { +const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) { if (isNil(l)) return true; // Write an attribute const value token(car(l)); if (isTaggedList(token, attribute)) { - if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)std::string(attributeName(token)).c_str(), (const xmlChar*)std::string(attributeValue(token)).c_str()) < 0) - return mkfailure<bool, std::string>("xmlTextWriterWriteAttribute failed"); + if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)c_str(string(attributeName(token))), (const xmlChar*)c_str(string(attributeValue(token)))) < 0) + return mkfailure<bool>("xmlTextWriterWriteAttribute failed"); } else if (isTaggedList(token, element)) { @@ -256,38 +256,37 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW } else { // Write an element with a single value - if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0) - return mkfailure<bool, std::string>("xmlTextWriterStartElement failed"); + if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) + return mkfailure<bool>("xmlTextWriterStartElement failed"); // Write its children - const failable<bool, std::string> w = writeList(elementChildren(token), xml); + const failable<bool> w = writeList(elementChildren(token), xml); if (!hasContent(w)) return w; if (xmlTextWriterEndElement(xml) < 0) - return mkfailure<bool, std::string>("xmlTextWriterEndElement failed"); + return mkfailure<bool>("xmlTextWriterEndElement failed"); } } else { // Write an element - if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0) - return mkfailure<bool, std::string>("xmlTextWriterStartElement failed"); + if (xmlTextWriterStartElement(xml, (const xmlChar*)c_str(string(elementName(token)))) < 0) + return mkfailure<bool>("xmlTextWriterStartElement failed"); // Write its children - const failable<bool, std::string> w = writeList(elementChildren(token), xml); + const failable<bool> w = writeList(elementChildren(token), xml); if (!hasContent(w)) return w; if (xmlTextWriterEndElement(xml) < 0) - return mkfailure<bool, std::string>("xmlTextWriterEndElement failed"); + return mkfailure<bool>("xmlTextWriterEndElement failed"); } } else { // Write XML text - if (xmlTextWriterWriteString(xml, (const xmlChar*)std::string(token).c_str()) < 0) - return mkfailure<bool, std::string>("xmlTextWriterWriteString failed"); - + if (xmlTextWriterWriteString(xml, (const xmlChar*)c_str(string(token))) < 0) + return mkfailure<bool>("xmlTextWriterWriteString failed"); } // Go on @@ -297,16 +296,16 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW /** * Write a list of values to a libxml2 XML writer. */ -const failable<bool, std::string> write(const list<value>& l, const xmlTextWriterPtr xml) { +const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml) { if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) - return mkfailure<bool, std::string>("xmlTextWriterStartDocument failed"); + return mkfailure<bool>(string("xmlTextWriterStartDocument failed")); - const failable<bool, std::string> w = writeList(l, xml); + const failable<bool> w = writeList(l, xml); if (!hasContent(w)) return w; if (xmlTextWriterEndDocument(xml) < 0) - return mkfailure<bool, std::string>("xmlTextWriterEndDocument failed"); + return mkfailure<bool>("xmlTextWriterEndDocument failed"); return true; } @@ -315,9 +314,9 @@ const failable<bool, std::string> write(const list<value>& l, const xmlTextWrite */ template<typename R> class XMLWriteContext { public: - XMLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + XMLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda<R(const std::string&, const R)> reduce; + const lambda<R(const string&, const R)> reduce; R accum; }; @@ -326,26 +325,26 @@ public: */ template<typename R> int writeCallback(void *context, const char* buffer, int len) { XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context); - cx.accum = cx.reduce(std::string(buffer, len), cx.accum); + cx.accum = cx.reduce(string(buffer, len), cx.accum); return len; } /** * Convert a list of values to an XML document. */ -template<typename R> const failable<R, std::string> writeXML(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) { +template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { XMLWriteContext<R> cx(reduce, initial); xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL); if (out == NULL) - return mkfailure<R, std::string>("xmlOutputBufferCreateIO failed"); + return mkfailure<R>("xmlOutputBufferCreateIO failed"); xmlTextWriterPtr xml = xmlNewTextWriter(out); if (xml == NULL) - return mkfailure<R, std::string>("xmlNewTextWriter failed"); + return mkfailure<R>("xmlNewTextWriter failed"); - const failable<bool, std::string> w = write(l, xml); + const failable<bool> w = write(l, xml); xmlFreeTextWriter(xml); if (!hasContent(w)) { - return mkfailure<R, std::string>(reason(w)); + return mkfailure<R>(reason(w)); } return cx.accum; } @@ -353,11 +352,11 @@ template<typename R> const failable<R, std::string> writeXML(const lambda<R(cons /** * Convert a list of values to a list of strings representing an XML document. */ -const failable<list<std::string>, std::string> writeXML(const list<value>& l) { - const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(rcons<std::string>, list<std::string>(), l); +const failable<list<string> > writeXML(const list<value>& l) { + const failable<list<string> > ls = writeXML<list<string> >(rcons<string>, list<string>(), l); if (!hasContent(ls)) return ls; - return reverse(list<std::string>(content(ls))); + return reverse(list<string>(content(ls))); } } diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/kernel/xsd-test.cpp index 818c03ba68..0fc432c649 100644 --- a/sca-cpp/trunk/kernel/xsd-test.cpp +++ b/sca-cpp/trunk/kernel/xsd-test.cpp @@ -23,8 +23,8 @@ * Test validation of a composite file against an SCDL schema. */ -#include <iostream> -#include <string> +#include "string.hpp" +#include "fstream.hpp" #include <libxml/xmlreader.h> #include <libxml/xmlschemas.h> @@ -35,12 +35,12 @@ bool printNode(xmlTextReaderPtr reader) { if(name == NULL) name = (xmlChar *)"<unknown>"; const xmlChar* value = xmlTextReaderConstValue(reader); - std::cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " + cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " " << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader); if(value == NULL) - std::cout << std::endl; + cout << endl; else - std::cout << value << std::endl; + cout << value << endl; return true; } @@ -54,13 +54,13 @@ int xmlClose(void *context) { } bool readFile(const char*xsdfilename, const char *filename) { - std::cout << "Loading schemas...\n"; + cout << "Loading schemas...\n"; const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET); const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc); const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx); const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd); - std::cout << "Reading file...\n"; + cout << "Reading file...\n"; FILE* file = fopen(filename, "r"); if (file != NULL) { const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET); @@ -75,14 +75,14 @@ bool readFile(const char*xsdfilename, const char *filename) { printNode(reader); } if(xmlTextReaderIsValid(reader) != 1) - std::cout << "Could not validate document" << std::endl; + cout << "Could not validate document" << endl; xmlFreeTextReader(reader); if(rc != 0) - std::cout << "Could not parse document" << std::endl; + cout << "Could not parse document" << endl; } else - std::cout << "Could not create parser" << std::endl; + cout << "Could not create parser" << endl; } else - std::cout << "Could not open document" << std::endl; + cout << "Could not open document" << endl; xmlSchemaFreeValidCtxt(validctx); xmlSchemaFree(xsd); @@ -94,7 +94,7 @@ bool readFile(const char*xsdfilename, const char *filename) { } int main(int argc, char **argv) { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; if(argc != 3) return 1; @@ -102,6 +102,6 @@ int main(int argc, char **argv) { xmlCleanupParser(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/Makefile.am b/sca-cpp/trunk/modules/Makefile.am index 44ddf85de4..3b2d60b93a 100644 --- a/sca-cpp/trunk/modules/Makefile.am +++ b/sca-cpp/trunk/modules/Makefile.am @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -SUBDIRS = atom eval http json scdl server +SUBDIRS = atom eval json scdl http server includedir = $(prefix)/include/modules nobase_include_HEADERS = */*.hpp diff --git a/sca-cpp/trunk/modules/atom/atom-test.cpp b/sca-cpp/trunk/modules/atom/atom-test.cpp index ba651e8eb2..560c383a23 100644 --- a/sca-cpp/trunk/modules/atom/atom-test.cpp +++ b/sca-cpp/trunk/modules/atom/atom-test.cpp @@ -24,21 +24,19 @@ */ #include <assert.h> -#include <iostream> -#include <sstream> -#include <string> -#include "slist.hpp" +#include "stream.hpp" +#include "string.hpp" #include "atom.hpp" namespace tuscany { namespace atom { -std::ostringstream* writer(const std::string& s, std::ostringstream* os) { +ostream* writer(const string& s, ostream* os) { (*os) << s; return os; } -std::string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<entry xmlns=\"http://www.w3.org/2005/Atom\">" "<title type=\"text\">item</title>" "<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>" @@ -50,7 +48,7 @@ std::string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>" "</entry>\n"); -std::string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">" +string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">" "<title>item</title><content type=\"text/xml\">" "<Item xmlns=\"http://services/\">" "<name xmlns=\"\">Orange</name>" @@ -59,7 +57,7 @@ std::string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">" "</content>" "</entry>"); -std::string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<entry xmlns=\"http://www.w3.org/2005/Atom\">" "<title type=\"text\">item</title>" "<id></id>" @@ -73,36 +71,36 @@ std::string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" bool testEntry() { { - const list<value> i = list<value>() << element << "item" - << (list<value>() << element << "name" << std::string("Apple")) - << (list<value>() << element << "price" << std::string("$2.99")); - const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); - std::ostringstream os; - writeATOMEntry<std::ostringstream*>(writer, &os, a); - assert(os.str() == itemEntry); + 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 = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + ostringstream os; + writeATOMEntry<ostream*>(writer, &os, a); + assert(str(os) == itemEntry); } { const list<value> a = content(readEntry(mklist(itemEntry))); - std::ostringstream os; - writeATOMEntry<std::ostringstream*>(writer, &os, a); - assert(os.str() == itemEntry); + ostringstream os; + writeATOMEntry<ostream*>(writer, &os, a); + assert(str(os) == itemEntry); } { const list<value> a = content(readEntry(mklist(incompleteEntry))); - std::ostringstream os; - writeATOMEntry<std::ostringstream*>(writer, &os, a); - assert(os.str() == completedEntry); + ostringstream os; + writeATOMEntry<ostream*>(writer, &os, a); + assert(str(os) == completedEntry); } return true; } -std::string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<feed xmlns=\"http://www.w3.org/2005/Atom\">" "<title type=\"text\">Feed</title>" "<id>1234</id>" "</feed>\n"); -std::string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<feed xmlns=\"http://www.w3.org/2005/Atom\">" "<title type=\"text\">Feed</title>" "<id>1234</id>" @@ -130,51 +128,51 @@ std::string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" bool testFeed() { { - std::ostringstream os; - writeATOMFeed<std::ostringstream*>(writer, &os, mklist<value>("Feed", "1234")); - assert(os.str() == emptyFeed); + ostringstream os; + writeATOMFeed<ostream*>(writer, &os, mklist<value>("Feed", "1234")); + assert(str(os) == emptyFeed); } { const list<value> a = content(readFeed(mklist(emptyFeed))); - std::ostringstream os; - writeATOMFeed<std::ostringstream*>(writer, &os, a); - assert(os.str() == emptyFeed); + ostringstream os; + writeATOMFeed<ostream*>(writer, &os, a); + assert(str(os) == emptyFeed); } { const list<value> i = list<value>() - << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - << (list<value>() << element << "item" - << (list<value>() << element << "name" << "Apple") - << (list<value>() << element << "price" << "$2.99"))) - << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - << (list<value>() << element << "item" - << (list<value>() << element << "name" << "Orange") - << (list<value>() << element << "price" << "$3.55"))); + + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + + (list<value>() + element + "item" + + (list<value>() + element + "name" + "Apple") + + (list<value>() + element + "price" + "$2.99"))) + + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + + (list<value>() + element + "item" + + (list<value>() + element + "name" + "Orange") + + (list<value>() + element + "price" + "$3.55"))); const list<value> a = cons<value>("Feed", cons<value>("1234", i)); - std::ostringstream os; - writeATOMFeed<std::ostringstream*>(writer, &os, a); - assert(os.str() == itemFeed); + ostringstream os; + writeATOMFeed<ostream*>(writer, &os, a); + assert(str(os) == itemFeed); } { const list<value> i = list<value>() - << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" - << valueToElement(list<value>() << "item" - << (list<value>() << "name" << "Apple") - << (list<value>() << "price" << "$2.99"))) - << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" - << valueToElement(list<value>() << "item" - << (list<value>() << "name" << "Orange") - << (list<value>() << "price" << "$3.55"))); + + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b" + + valueToElement(list<value>() + "item" + + (list<value>() + "name" + "Apple") + + (list<value>() + "price" + "$2.99"))) + + (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c" + + valueToElement(list<value>() + "item" + + (list<value>() + "name" + "Orange") + + (list<value>() + "price" + "$3.55"))); const list<value> a = cons<value>("Feed", cons<value>("1234", i)); - std::ostringstream os; - writeATOMFeed<std::ostringstream*>(writer, &os, a); - assert(os.str() == itemFeed); + ostringstream os; + writeATOMFeed<ostream*>(writer, &os, a); + assert(str(os) == itemFeed); } { const list<value> a = content(readFeed(mklist(itemFeed))); - std::ostringstream os; - writeATOMFeed<std::ostringstream*>(writer, &os, a); - assert(os.str() == itemFeed); + ostringstream os; + writeATOMFeed<ostream*>(writer, &os, a); + assert(str(os) == itemFeed); } return true; } @@ -183,12 +181,12 @@ bool testFeed() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::atom::testEntry(); tuscany::atom::testFeed(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/atom/atom.hpp b/sca-cpp/trunk/modules/atom/atom.hpp index 7e2eb66cd2..4dbf7c7728 100644 --- a/sca-cpp/trunk/modules/atom/atom.hpp +++ b/sca-cpp/trunk/modules/atom/atom.hpp @@ -26,7 +26,7 @@ * ATOM data conversion functions. */ -#include <string> +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "monad.hpp" @@ -40,9 +40,9 @@ namespace atom { */ const list<value> entryValues(const list<value>& e) { const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e); - const value t = isNil(lt)? value(std::string("")) : elementValue(car(lt)); + const value t = isNil(lt)? value(emptyString) : elementValue(car(lt)); const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e); - const value i = isNil(li)? value(std::string("")) : elementValue(car(li)); + const value i = isNil(li)? value(emptyString) : elementValue(car(li)); const list<value> lc = filter<value>(selector(mklist<value>(element, "content")), e); return mklist<value>(t, i, cadr(elementChildren(car(lc)))); } @@ -59,10 +59,10 @@ const list<value> entriesValues(const list<value>& e) { /** * Convert a list of strings to a list of values representing an ATOM entry. */ -const failable<list<value>, std::string> readEntry(const list<std::string>& ilist) { +const failable<list<value> > readEntry(const list<string>& ilist) { const list<value> e = readXML(ilist); if (isNil(e)) - return mkfailure<list<value>, std::string>("Empty entry"); + return mkfailure<list<value> >("Empty entry"); return entryValues(car(e)); } @@ -77,10 +77,10 @@ const value entryValue(const list<value>& e) { /** * Convert a list of strings to a list of values representing an ATOM feed. */ -const failable<list<value>, std::string> readFeed(const list<std::string>& ilist) { +const failable<list<value> > readFeed(const list<string>& ilist) { const list<value> f = readXML(ilist); if (isNil(f)) - return mkfailure<list<value>, std::string>("Empty feed"); + 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)); @@ -95,11 +95,11 @@ const failable<list<value>, std::string> readFeed(const list<std::string>& ilist */ const list<value> entryElement(const list<value>& l) { return list<value>() - << element << "entry" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom") - << (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l)) - << (list<value>() << element << "id" << cadr(l)) - << (list<value>() << element << "content" << (list<value>() << attribute << "type" << "application/xml") << caddr(l)) - << (list<value>() << element << "link" << (list<value>() << attribute << "href" << cadr(l))); + + element + "entry" + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") + + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + car(l)) + + (list<value>() + element + "id" + cadr(l)) + + (list<value>() + element + "content" + (list<value>() + attribute + "type" + "application/xml") + caddr(l)) + + (list<value>() + element + "link" + (list<value>() + attribute + "href" + cadr(l))); } /** @@ -115,26 +115,26 @@ const list<value> entriesElements(const list<value>& l) { * Convert a list of values representing an ATOM entry to an ATOM entry. * The first two values in the list are the entry id and title. */ -template<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) { +template<typename R> const failable<R> writeATOMEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { return writeXML<R>(reduce, initial, mklist<value>(entryElement(l))); } -const failable<list<std::string>, std::string> writeATOMEntry(const list<value>& l) { - const failable<list<std::string>, std::string> ls = writeATOMEntry<list<std::string> >(rcons<std::string>, list<std::string>(), l); +const failable<list<string> > writeATOMEntry(const list<value>& l) { + const failable<list<string> > ls = writeATOMEntry<list<string> >(rcons<string>, list<string>(), l); if (!hasContent(ls)) return ls; - return reverse(list<std::string>(content(ls))); + return reverse(list<string>(content(ls))); } /** * Convert a list of values representing an ATOM feed to an ATOM feed. * The first two values in the list are the feed id and title. */ -template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) { +template<typename R> const failable<R> writeATOMFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) { 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") << car(l)) - << (list<value>() << element << "id" << cadr(l)); + + element + "feed" + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom") + + (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + car(l)) + + (list<value>() + element + "id" + cadr(l)); if (isNil(cddr(l))) return writeXML<R>(reduce, initial, mklist<value>(f)); const list<value> fe = append(f, entriesElements(cddr(l))); @@ -145,11 +145,11 @@ template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R * Convert a list of values representing an ATOM feed to a list of strings. * The first two values in the list are the feed id and title. */ -const failable<list<std::string>, std::string> writeATOMFeed(const list<value>& l) { - const failable<list<std::string>, std::string> ls = writeATOMFeed<list<std::string> >(rcons<std::string>, list<std::string>(), l); +const failable<list<string> > writeATOMFeed(const list<value>& l) { + const failable<list<string> > ls = writeATOMFeed<list<string>>(rcons<string>, list<string>(), l); if (!hasContent(ls)) return ls; - return reverse(list<std::string>(content(ls))); + return reverse(list<string>(content(ls))); } /** diff --git a/sca-cpp/trunk/modules/eval/driver.hpp b/sca-cpp/trunk/modules/eval/driver.hpp index 3076e677c4..2d1badf501 100644 --- a/sca-cpp/trunk/modules/eval/driver.hpp +++ b/sca-cpp/trunk/modules/eval/driver.hpp @@ -26,34 +26,34 @@ * Script evaluator main driver loop. */ -#include <string> -#include <iostream> +#include "string.hpp" +#include "stream.hpp" #include "eval.hpp" namespace tuscany { namespace eval { -const std::string evalOutputPrompt("; "); -const std::string evalInputPrompt("=> "); +const string evalOutputPrompt("; "); +const string evalInputPrompt("=> "); -const bool promptForInput(const std::string str, std::ostream& out) { - out << std::endl << std::endl << str; +const bool promptForInput(const string& str, ostream& out) { + out << endl << endl << str; return true; } -const bool announceOutput(const std::string str, std::ostream& out) { - out << std::endl << str; +const bool announceOutput(const string str, ostream& out) { + out << endl << str; return true; } -const bool userPrint(const value val, std::ostream& out) { +const bool userPrint(const value val, ostream& out) { if(isCompoundProcedure(val)) writeValue(mklist<value>(compoundProcedureSymbol, procedureParameters(val), procedureBody(val), "<procedure-env>"), out); writeValue(val, out); return true; } -const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv, const gc_pool& pool) { +const value evalDriverLoop(istream& in, ostream& out, Env& globalEnv, const gc_pool& pool) { promptForInput(evalInputPrompt, out); value input = readValue(in); if (isNil(input)) @@ -64,8 +64,7 @@ const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv, return evalDriverLoop(in, out, globalEnv, pool); } -const bool evalDriverRun(std::istream& in, std::ostream& out) { - gc_pool pool; +const bool evalDriverRun(istream& in, ostream& out, const gc_pool& pool) { setupDisplay(out); Env globalEnv = setupEnvironment(pool); evalDriverLoop(in, out, globalEnv, pool); diff --git a/sca-cpp/trunk/modules/eval/environment.hpp b/sca-cpp/trunk/modules/eval/environment.hpp index 3a19c01deb..29bb3b64da 100644 --- a/sca-cpp/trunk/modules/eval/environment.hpp +++ b/sca-cpp/trunk/modules/eval/environment.hpp @@ -26,10 +26,11 @@ * Script evaluator environment implementation. */ -#include <string> +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "primitive.hpp" +#include <string> namespace tuscany { namespace eval { @@ -63,7 +64,7 @@ const Env enclosingEnvironment(const Env& env) { return cdr(env); } -const gc_pool_ptr<Frame> firstFrame(const Env& env) { +const gc_ptr<Frame> firstFrame(const Env& env) { return car(env); } @@ -82,7 +83,7 @@ const bool isDotVariable(const value& var) { const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, const list<value> values) { if (isNil(variables)) { if (!isNil(values)) - logStream() << "Too many arguments supplied " << values << std::endl; + logStream() << "Too many arguments supplied " << values << endl; return frameSoFar; } if (isDotVariable(car(variables))) @@ -90,7 +91,7 @@ const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, c if (isNil(values)) { if (!isNil(variables)) - logStream() << "Too few arguments supplied " << variables << std::endl; + logStream() << "Too few arguments supplied " << variables << endl; return frameSoFar; } @@ -101,8 +102,8 @@ const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, c return makeBinding(newFrame, cdr(variables), cdr(values)); } -const gc_pool_ptr<Frame> makeFrame(const list<value>& variables, const list<value> values, const gc_pool& pool) { - gc_pool_ptr<Frame> frame = gc_pool_new<Frame>(pool); +const gc_ptr<Frame> makeFrame(const list<value>& variables, const list<value> values, const gc_pool& pool) { + gc_ptr<Frame> frame = new (gc_new<Frame>(pool)) Frame(); *frame = value(makeBinding(cons(value(list<value>()), list<value>()), variables, values)); return frame; } @@ -163,7 +164,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 << std::endl; + logStream() << "Unbound variable " << var << endl; return value(); } return lookupEnvScan(var, frameVariables(*firstFrame(env)), frameValues(*firstFrame(env)), env); diff --git a/sca-cpp/trunk/modules/eval/eval-shell.cpp b/sca-cpp/trunk/modules/eval/eval-shell.cpp index e1c90101da..f73ac61250 100644 --- a/sca-cpp/trunk/modules/eval/eval-shell.cpp +++ b/sca-cpp/trunk/modules/eval/eval-shell.cpp @@ -24,12 +24,13 @@ */ #include <assert.h> -#include <iostream> -#include <string> -#include <sstream> +#include "gc.hpp" +#include "stream.hpp" +#include "string.hpp" #include "driver.hpp" int main() { - tuscany::eval::evalDriverRun(std::cin, std::cout); + tuscany::gc_scoped_pool pool; + tuscany::eval::evalDriverRun(tuscany::cin, tuscany::cout, pool); return 0; } diff --git a/sca-cpp/trunk/modules/eval/eval-test.cpp b/sca-cpp/trunk/modules/eval/eval-test.cpp index fb755b9077..3cf16f602f 100644 --- a/sca-cpp/trunk/modules/eval/eval-test.cpp +++ b/sca-cpp/trunk/modules/eval/eval-test.cpp @@ -24,16 +24,15 @@ */ #include <assert.h> -#include <iostream> -#include <string> -#include <sstream> +#include "stream.hpp" +#include "string.hpp" #include "driver.hpp" namespace tuscany { namespace eval { bool testEnv() { - gc_pool pool; + gc_scoped_pool pool; Env globalEnv = list<value>(); Env env = extendEnvironment(mklist<value>("a"), mklist<value>(1), globalEnv, pool); defineVariable("x", env, env); @@ -50,26 +49,23 @@ bool testEnvGC() { assert(checkValueCounters()); assert(checkLambdaCounters()); assert(checkListCounters()); - //printLambdaCounters(); - //printListCounters(); - //printValueCounters(); return true; } bool testRead() { - std::istringstream is("abcd"); + istringstream is("abcd"); assert(readValue(is) == "abcd"); - std::istringstream is2("123"); + istringstream is2("123"); assert(readValue(is2) == value(123)); - std::istringstream is3("(abcd)"); + istringstream is3("(abcd)"); assert(readValue(is3) == mklist(value("abcd"))); - std::istringstream is4("(abcd xyz)"); + istringstream is4("(abcd xyz)"); assert(readValue(is4) == mklist<value>("abcd", "xyz")); - std::istringstream is5("(abcd (xyz tuv))"); + istringstream is5("(abcd (xyz tuv))"); assert(readValue(is5) == mklist<value>("abcd", mklist<value>("xyz", "tuv"))); return true; @@ -77,43 +73,43 @@ bool testRead() { 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"))); + + (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> a = cons<value>("Feed", cons<value>("feed-1234", i)); - std::ostringstream os; + ostringstream os; writeValue(a, os); - std::istringstream is(os.str()); + istringstream is(str(os)); assert(readValue(is) == a); return true; } -const std::string testSchemeNumber( +const string testSchemeNumber( "(define (testNumber) (if (= 1 1) (display \"testNumber ok\") (error \"testNumber\"))) " "(testNumber)"); -const std::string testSchemeString( +const string testSchemeString( "(define (testString) (if (= \"abc\" \"abc\") (display \"testString ok\") (error \"testString\"))) " "(testString)"); -const std::string testSchemeDefinition( +const string testSchemeDefinition( "(define a \"abc\") (define (testDefinition) (if (= a \"abc\") (display \"testDefinition ok\") (error \"testDefinition\"))) " "(testDefinition)"); -const std::string testSchemeIf( +const string testSchemeIf( "(define (testIf) (if (= \"abc\" \"abc\") (if (= \"xyz\" \"xyz\") (display \"testIf ok\") (error \"testNestedIf\")) (error \"testIf\"))) " "(testIf)"); -const std::string testSchemeCond( +const string testSchemeCond( "(define (testCond) (cond ((= \"abc\" \"abc\") (display \"testCond ok\")) (else (error \"testIf\"))))" "(testCond)"); -const std::string testSchemeBegin( +const string testSchemeBegin( "(define (testBegin) " "(begin " "(define a \"abc\") " @@ -124,42 +120,39 @@ const std::string testSchemeBegin( ") " "(testBegin)"); -const std::string testSchemeLambda( +const string testSchemeLambda( "(define sqrt (lambda (x) (* x x))) " "(define (testLambda) (if (= 4 (sqrt 2)) (display \"testLambda ok\") (error \"testLambda\"))) " "(testLambda)"); -const std::string testSchemeForward( +const string testSchemeForward( "(define (testLambda) (if (= 4 (sqrt 2)) (display \"testForward ok\") (error \"testForward\"))) " "(define sqrt (lambda (x) (* x x))) " "(testLambda)"); -bool contains(const std::string& str, const std::string& pattern) { - return str.find(pattern) != str.npos; -} - -const std::string evalOutput(const std::string& scm) { - std::istringstream is(scm); - std::ostringstream os; - evalDriverRun(is, os); - return os.str(); +const string evalOutput(const string& scm, const gc_pool& pool) { + istringstream is(scm); + ostringstream os; + evalDriverRun(is, os, pool); + return str(os); } bool testEval() { - assert(contains(evalOutput(testSchemeNumber), "testNumber ok")); - assert(contains(evalOutput(testSchemeString), "testString ok")); - assert(contains(evalOutput(testSchemeDefinition), "testDefinition ok")); - assert(contains(evalOutput(testSchemeIf), "testIf ok")); - assert(contains(evalOutput(testSchemeCond), "testCond ok")); - assert(contains(evalOutput(testSchemeBegin), "testBegin1 ok")); - assert(contains(evalOutput(testSchemeBegin), "testBegin2 ok")); - assert(contains(evalOutput(testSchemeLambda), "testLambda ok")); - assert(contains(evalOutput(testSchemeForward), "testForward ok")); + gc_scoped_pool pool; + assert(contains(evalOutput(testSchemeNumber, pool), "testNumber ok")); + assert(contains(evalOutput(testSchemeString, pool), "testString ok")); + assert(contains(evalOutput(testSchemeDefinition, pool), "testDefinition ok")); + assert(contains(evalOutput(testSchemeIf, pool), "testIf ok")); + assert(contains(evalOutput(testSchemeCond, pool), "testCond ok")); + assert(contains(evalOutput(testSchemeBegin, pool), "testBegin1 ok")); + assert(contains(evalOutput(testSchemeBegin, pool), "testBegin2 ok")); + assert(contains(evalOutput(testSchemeLambda, pool), "testLambda ok")); + assert(contains(evalOutput(testSchemeForward, pool), "testForward ok")); return true; } bool testEvalExpr() { - gc_pool pool; + gc_scoped_pool pool; const value exp = mklist<value>("+", 2, 3); Env env = setupEnvironment(pool); const value r = evalExpr(exp, env, pool); @@ -168,7 +161,8 @@ bool testEvalExpr() { } bool testEvalRun() { - evalDriverRun(std::cin, std::cout); + gc_scoped_pool pool; + evalDriverRun(cin, cout, pool); return true; } @@ -178,26 +172,26 @@ const value mult(const list<value>& args) { return x * y; } -const std::string testReturnLambda( +const string testReturnLambda( "(define (testReturnLambda) * )"); -const std::string testCallLambda( +const string testCallLambda( "(define (testCallLambda l x y) (l x y))"); bool testEvalLambda() { - gc_pool pool; + gc_scoped_pool pool; Env env = setupEnvironment(pool); const value trl = mklist<value>("testReturnLambda"); - std::istringstream trlis(testReturnLambda); + istringstream trlis(testReturnLambda); const value trlv = evalScript(trl, trlis, env, pool); - std::istringstream tclis(testCallLambda); + istringstream tclis(testCallLambda); const value tcl = cons<value>("testCallLambda", quotedParameters(mklist<value>(trlv, 2, 3))); const value tclv = evalScript(tcl, tclis, env, pool); assert(tclv == value(6)); - std::istringstream tcelis(testCallLambda); + istringstream tcelis(testCallLambda); const value tcel = cons<value>("testCallLambda", quotedParameters(mklist<value>(primitiveProcedure(mult), 3, 4))); const value tcelv = evalScript(tcel, tcelis, env, pool); assert(tcelv == value(12)); @@ -214,9 +208,6 @@ bool testEvalGC() { assert(checkValueCounters()); assert(checkLambdaCounters()); assert(checkListCounters()); - //printLambdaCounters(); - //printListCounters(); - //printValueCounters(); return true; } @@ -224,7 +215,7 @@ bool testEvalGC() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::eval::testEnv(); tuscany::eval::testEnvGC(); @@ -235,6 +226,6 @@ int main() { tuscany::eval::testEvalLambda(); tuscany::eval::testEvalGC(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/eval/eval.hpp b/sca-cpp/trunk/modules/eval/eval.hpp index 1b4d94c631..ea6e2da13a 100644 --- a/sca-cpp/trunk/modules/eval/eval.hpp +++ b/sca-cpp/trunk/modules/eval/eval.hpp @@ -146,7 +146,7 @@ const value applyProcedure(const value& procedure, list<value>& arguments, const Env env = extendEnvironment(procedureParameters(procedure), arguments, procedureEnvironment(procedure), pool); return evalSequence(procedureBody(procedure), env, pool); } - logStream() << "Unknown procedure type " << procedure << std::endl; + logStream() << "Unknown procedure type " << procedure << endl; return value(); } @@ -208,7 +208,7 @@ const value expandClauses(const list<value>& clauses) { if(isCondElseClause(first)) { if(isNil(rest)) return sequenceToExp(condActions(first)); - logStream() << "else clause isn't last " << clauses << std::endl; + logStream() << "else clause isn't last " << clauses << endl; return value(); } return makeIf(condPredicate(first), sequenceToExp(condActions(first)), expandClauses(rest)); @@ -254,7 +254,7 @@ const value evalExpr(const value& exp, Env& env, const gc_pool& pool) { list<value> operandValues = listOfValues(operands(exp), env, pool); return applyProcedure(evalExpr(operat(exp), env, pool), operandValues, pool); } - logStream() << "Unknown expression type " << exp << std::endl; + logStream() << "Unknown expression type " << exp << endl; return value(); } @@ -281,7 +281,7 @@ const value evalScript(const value& expr, const value& script, Env& env, const g /** * Evaluate an expression against a script provided as an input stream. */ -const value evalScript(const value& expr, std::istream& is, Env& env, const gc_pool& pool) { +const value evalScript(const value& expr, istream& is, Env& env, const gc_pool& pool) { return evalScript(expr, readScript(is), env, pool); } diff --git a/sca-cpp/trunk/modules/eval/io.hpp b/sca-cpp/trunk/modules/eval/io.hpp index 53657ce055..0c2abb3af9 100644 --- a/sca-cpp/trunk/modules/eval/io.hpp +++ b/sca-cpp/trunk/modules/eval/io.hpp @@ -26,10 +26,9 @@ * Script evaluator IO functions. */ -#include <iostream> -#include <string> -#include <sstream> #include <ctype.h> +#include "stream.hpp" +#include "string.hpp" #include "list.hpp" #include "value.hpp" @@ -42,11 +41,8 @@ const value rightParenthesis(mklist<value>(")")); const value leftParenthesis(mklist<value>("(")); const value comment(mklist<value>(";")); -const double stringToNumber(const std::string& str) { - double d; - std::istringstream is(str); - is >> d; - return d; +const double stringToNumber(const string& str) { + return atof(c_str(str)); } const bool isWhitespace(const char ch) { @@ -73,18 +69,18 @@ const bool isRightParenthesis(const value& token) { return rightParenthesis == token; } -const char readChar(std::istream& in) { +const char readChar(istream& in) { if(in.eof()) { return -1; } - char c = (char)in.get(); + char c = (char)get(in); return c; } -const char peekChar(std::istream& in) { - if(in.eof()) +const char peekChar(istream& in) { + if(eof(in)) return -1; - char c = (char)in.peek(); + char c = (char)peek(in); return c; } @@ -92,14 +88,14 @@ const bool isQuote(const value& token) { return token == quoteSymbol; } -const value skipComment(std::istream& in); -const value readQuoted(std::istream& in); -const value readIdentifier(const char chr, std::istream& in); -const value readString(std::istream& in); -const value readNumber(const char chr, std::istream& in); -const value readValue(std::istream& in); +const value skipComment(istream& in); +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 value readToken(std::istream& in) { +const value readToken(istream& in) { const char firstChar = readChar(in); if(isWhitespace(firstChar)) return readToken(in); @@ -119,22 +115,22 @@ const value readToken(std::istream& in) { return readNumber(firstChar, in); if(firstChar == -1) return value(); - logStream() << "Illegal lexical syntax '" << firstChar << "'" << std::endl; + logStream() << "Illegal lexical syntax '" << firstChar << "'" << endl; return readToken(in); } -const value skipComment(std::istream& in) { +const value skipComment(istream& in) { const char nextChar = readChar(in); if (nextChar == '\n') return readToken(in); return skipComment(in); } -const value readQuoted(std::istream& in) { +const value readQuoted(istream& in) { return mklist(quoteSymbol, readValue(in)); } -const list<value> readList(const list<value>& listSoFar, std::istream& in) { +const list<value> readList(const list<value>& listSoFar, istream& in) { const value token = readToken(in); if(isNil(token) || isRightParenthesis(token)) return reverse(listSoFar); @@ -143,72 +139,73 @@ const list<value> readList(const list<value>& listSoFar, std::istream& in) { return readList(cons(token, listSoFar), in); } -const std::string listToString(const list<char>& l) { +const string listToString(const list<char>& l) { if(isNil(l)) return ""; - return car(l) + listToString(cdr(l)); + const char buf[1] = { car(l) }; + return string(buf, 1) + listToString(cdr(l)); } -const list<char> readIdentifierHelper(const list<char>& listSoFar, std::istream& in) { +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); } -const value readIdentifier(const char chr, std::istream& in) { - return listToString(readIdentifierHelper(mklist(chr), in)).c_str(); +const value readIdentifier(const char chr, istream& in) { + return c_str(listToString(readIdentifierHelper(mklist(chr), in))); } -const list<char> readStringHelper(const list<char>& listSoFar, std::istream& in) { +const list<char> readStringHelper(const list<char>& listSoFar, istream& in) { const char nextChar = readChar(in); if(nextChar != -1 && nextChar != '"') return readStringHelper(cons(nextChar, listSoFar), in); return reverse(listSoFar); } -const value readString(std::istream& in) { +const value readString(istream& in) { return listToString(readStringHelper(list<char>(), in)); } -const list<char> readNumberHelper(const list<char>& listSoFar, std::istream& 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, std::istream& in) { +const value readNumber(const char chr, istream& in) { return stringToNumber(listToString(readNumberHelper(mklist(chr), in))); } -const value readValue(std::istream& in) { +const value readValue(istream& in) { const value nextToken = readToken(in); if(isLeftParenthesis(nextToken)) return readList(list<value> (), in); return nextToken; } -const value readValue(const std::string s) { - std::istringstream in(s); +const value readValue(const string s) { + istringstream in(s); const value nextToken = readToken(in); if(isLeftParenthesis(nextToken)) return readList(list<value> (), in); return nextToken; } -const bool writeValue(const value& val, std::ostream& out) { +const bool writeValue(const value& val, ostream& out) { out << val; return true; } -const std::string writeValue(const value& val) { - std::ostringstream out; +const string writeValue(const value& val) { + ostringstream out; out << val; - return out.str(); + return str(out); } -const value readScript(std::istream& in) { +const value readScript(istream& in) { const value val = readValue(in); if (isNil(val)) return list<value>(); diff --git a/sca-cpp/trunk/modules/eval/primitive.hpp b/sca-cpp/trunk/modules/eval/primitive.hpp index 37c53fdd0b..75d691c4ac 100644 --- a/sca-cpp/trunk/modules/eval/primitive.hpp +++ b/sca-cpp/trunk/modules/eval/primitive.hpp @@ -28,7 +28,7 @@ #include <apr_general.h> #include <apr_uuid.h> -#include <iostream> +#include "stream.hpp" #include "function.hpp" #include "list.hpp" #include "value.hpp" @@ -40,24 +40,24 @@ const value primitiveSymbol("primitive"); const value quoteSymbol("'"); const value lambdaSymbol("lambda"); -std::ostream* displayOutStream = &std::cout; -std::ostream* logOutStream = &std::cerr; +ostream* displayOutStream = &cout; +ostream* logOutStream = &cerr; -const bool setupDisplay(std::ostream& out) { +const bool setupDisplay(ostream& out) { displayOutStream = &out; return true; } -std::ostream& displayStream() { +ostream& displayStream() { return *displayOutStream; } -const bool setupLog(std::ostream& out) { +const bool setupLog(ostream& out) { logOutStream = &out; return true; } -std::ostream& logStream() { +ostream& logStream() { return *logOutStream; } @@ -116,7 +116,7 @@ const value divProc(const list<value>& args) { const value displayProc(const list<value>& args) { if (isNil(args)) { - displayStream() << std::endl; + displayStream() << endl; return true; } displayStream() << car(args); @@ -125,7 +125,7 @@ const value displayProc(const list<value>& args) { const value logProc(const list<value>& args) { if (isNil(args)) { - logStream() << std::endl; + logStream() << endl; return true; } logStream() << car(args); @@ -137,7 +137,7 @@ const value uuidProc(unused const list<value>& args) { apr_uuid_get(&uuid); char buf[APR_UUID_FORMATTED_LENGTH]; apr_uuid_format(buf, &uuid); - return std::string(buf, APR_UUID_FORMATTED_LENGTH); + return string(buf, APR_UUID_FORMATTED_LENGTH); } const value cadrProc(unused const list<value>& args) { @@ -194,51 +194,49 @@ template<typename F> const value primitiveProcedure(const F& f) { } const list<value> primitiveProcedureNames() { - list<value> l = mklist<value>("car"); - l = cons<value>("cdr", l); - l = cons<value>("cons", l); - l = cons<value>("list", l); - l = cons<value>("nul", l); - l = cons<value>("=", l); - l = cons<value>("equal?", l); - l = cons<value>("+", l); - l = cons<value>("-", l); - l = cons<value>("*", l); - l = cons<value>("/", l); - l = cons<value>("assoc", l); - l = cons<value>("cadr", l); - l = cons<value>("caddr", l); - l = cons<value>("cadddr", l); - l = cons<value>("cddr", l); - l = cons<value>("cdddr", l); - l = cons<value>("display", l); - l = cons<value>("log", l); - l = cons<value>("uuid", l); - return l; + return mklist<value>("car") + + "cdr" + + "cons" + + "list" + + "nul" + + "=" + + "equal?" + + "+" + + "-" + + "*" + + "/" + + "assoc" + + "cadr" + + "caddr" + + "cadddr" + + "cddr" + + "cdddr" + + "display" + + "log" + + "uuid"; } const list<value> primitiveProcedureObjects() { - list<value> l = mklist(primitiveProcedure(carProc)); - l = cons(primitiveProcedure(cdrProc), l); - l = cons(primitiveProcedure(consProc), l); - l = cons(primitiveProcedure(listProc), l); - l = cons(primitiveProcedure(nulProc), l); - l = cons(primitiveProcedure(equalProc), l); - l = cons(primitiveProcedure(equalProc), l); - l = cons(primitiveProcedure(addProc), l); - l = cons(primitiveProcedure(subProc), l); - l = cons(primitiveProcedure(mulProc), l); - l = cons(primitiveProcedure(divProc), l); - l = cons(primitiveProcedure(assocProc), l); - l = cons(primitiveProcedure(cadrProc), l); - l = cons(primitiveProcedure(caddrProc), l); - l = cons(primitiveProcedure(cadddrProc), l); - l = cons(primitiveProcedure(cddrProc), l); - l = cons(primitiveProcedure(cdddrProc), l); - l = cons(primitiveProcedure(displayProc), l); - l = cons(primitiveProcedure(logProc), l); - l = cons(primitiveProcedure(uuidProc), l); - return l; + return mklist(primitiveProcedure(carProc)) + + primitiveProcedure(cdrProc) + + primitiveProcedure(consProc) + + primitiveProcedure(listProc) + + primitiveProcedure(nulProc) + + primitiveProcedure(equalProc) + + primitiveProcedure(equalProc) + + primitiveProcedure(addProc) + + primitiveProcedure(subProc) + + primitiveProcedure(mulProc) + + primitiveProcedure(divProc) + + primitiveProcedure(assocProc) + + primitiveProcedure(cadrProc) + + primitiveProcedure(caddrProc) + + primitiveProcedure(cadddrProc) + + primitiveProcedure(cddrProc) + + primitiveProcedure(cdddrProc) + + primitiveProcedure(displayProc) + + primitiveProcedure(logProc) + + primitiveProcedure(uuidProc); } const bool isFalse(const value& exp) { diff --git a/sca-cpp/trunk/modules/http/curl-test.cpp b/sca-cpp/trunk/modules/http/curl-test.cpp index 01355dd429..4305d2ac38 100644 --- a/sca-cpp/trunk/modules/http/curl-test.cpp +++ b/sca-cpp/trunk/modules/http/curl-test.cpp @@ -24,21 +24,15 @@ */ #include <assert.h> -#include <iostream> -#include <sstream> -#include <string> -#include "slist.hpp" +#include "stream.hpp" +#include "string.hpp" #include "perf.hpp" #include "curl.hpp" namespace tuscany { namespace http { -const bool contains(const std::string& str, const std::string& pattern) { - return str.find(pattern) != str.npos; -} - -std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { +ostream* curlWriter(const string& s, ostream* os) { (*os) << s; return os; } @@ -46,16 +40,16 @@ std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { const bool testGet() { CURLSession ch; { - std::ostringstream os; - const failable<list<std::ostringstream*>, std::string> r = get<std::ostringstream*>(curlWriter, &os, "http://localhost:8090", ch); + ostringstream os; + const failable<list<ostream*> > r = get<ostream*>(curlWriter, &os, "http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(os.str(), "HTTP/1.1 200 OK")); - assert(contains(os.str(), "It works")); + assert(contains(str(os), "HTTP/1.1 200 OK")); + assert(contains(str(os), "It works")); } { - const failable<value, std::string> r = get("http://localhost:8090", ch); + const failable<value> r = getcontent("http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(content(r), "It works")); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); } return true; } @@ -65,9 +59,9 @@ struct getLoop { getLoop(CURLSession& ch) : ch(ch) { } const bool operator()() const { - const failable<value, std::string> r = get("http://localhost:8090", ch); + const failable<value> r = getcontent("http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(content(r), "It works")); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); return true; } }; @@ -75,7 +69,7 @@ struct getLoop { const bool testGetPerf() { CURLSession ch; lambda<bool()> gl = getLoop(ch); - std::cout << "Static GET test " << time(gl, 5, 200) << " ms" << std::endl; + cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; } @@ -83,12 +77,12 @@ const bool testGetPerf() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::http::testGet(); tuscany::http::testGetPerf(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp index 85665c2785..3478a590fd 100644 --- a/sca-cpp/trunk/modules/http/curl.hpp +++ b/sca-cpp/trunk/modules/http/curl.hpp @@ -29,7 +29,7 @@ #include <curl/curl.h> #include <curl/types.h> #include <curl/easy.h> -#include <string> +#include "string.hpp" #include "gc.hpp" #include "list.hpp" #include "value.hpp" @@ -62,7 +62,7 @@ CURLContext curlContext; */ class CURLSession { public: - CURLSession() : ch(new CURLHandle()) { + CURLSession() : ch(new (gc_new<CURLHandle>()) CURLHandle()) { } ~CURLSession() { @@ -103,9 +103,9 @@ CURL* handle(const CURLSession& c) { */ class CURLReadContext { public: - CURLReadContext(const list<std::string>& ilist) : ilist(ilist) { + CURLReadContext(const list<string>& ilist) : ilist(ilist) { } - list<std::string> ilist; + list<string> ilist; }; /** @@ -115,11 +115,11 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) { CURLReadContext& rcx = *static_cast<CURLReadContext*>(data); if (isNil(rcx.ilist)) return 0; - rcx.ilist = fragment(rcx.ilist, size * nmemb); - const std::string s = car(rcx.ilist); - rcx.ilist = cdr(rcx.ilist); - s.copy((char*)ptr, s.length()); - return s.length(); + const list<string> f(fragment(rcx.ilist, size * nmemb)); + const string s = car(f); + rcx.ilist = cdr(f); + memcpy(ptr, c_str(s), length(s)); + return length(s); } /** @@ -127,9 +127,9 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) { */ template<typename R> class CURLWriteContext { public: - CURLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { + CURLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) { } - const lambda<R(const std::string&, const R)> reduce; + const lambda<R(const string&, const R)> reduce; R accum; }; @@ -137,33 +137,23 @@ public: * Called by CURL to write received data. */ template<typename R> size_t writeCallback(void *ptr, size_t size, size_t nmemb, void *data) { - CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); - const size_t realsize = size * nmemb; - wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum); - return realsize; -} - -/** - * Called by CURL to write received header data. - */ -template<typename R> size_t headerCallback(void *ptr, size_t size, size_t nmemb, void *data) { - CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); - const size_t realsize = size * nmemb; - wcx.accum = wcx.reduce(std::string((const char*)ptr, realsize), wcx.accum); - return realsize; + CURLWriteContext<R>& wcx = *(static_cast<CURLWriteContext<R>*> (data)); + const size_t realsize = size * nmemb; + wcx.accum = wcx.reduce(string((const char*)ptr, realsize), wcx.accum); + return realsize; } /** * Apply an HTTP verb to a list containing a list of headers and a list of content, and * a reduce function used to process the response. */ -curl_slist* headers(curl_slist* cl, const list<std::string>& h) { +curl_slist* headers(curl_slist* cl, const list<string>& h) { if (isNil(h)) return cl; - return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h)); + return headers(curl_slist_append(cl, c_str(string(car(h)))), cdr(h)); } -template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) { +template<typename R> const failable<list<R> > apply(const list<list<string> >& hdr, const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const string& verb, const CURLSession& cs) { // Init the curl session CURL* ch = handle(cs); @@ -171,30 +161,30 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< curl_easy_setopt(ch, CURLOPT_USERAGENT, "libcurl/1.0"); //TODO use HTTP chunking, for now just convert request to a single string - std::ostringstream os; - write(cadr(req), os); - const std::string s = os.str(); - const int sz = s.length(); + ostringstream os; + write(cadr(hdr), os); + const string s = str(os); + const int sz = length(s); // Setup the read, header and write callbacks CURLReadContext rcx(mklist(s)); curl_easy_setopt(ch, CURLOPT_READFUNCTION, (size_t (*)(void*, size_t, size_t, void*))readCallback); curl_easy_setopt(ch, CURLOPT_READDATA, &rcx); CURLWriteContext<R> hcx(reduce, initial); - curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))headerCallback<R>); + curl_easy_setopt(ch, CURLOPT_HEADERFUNCTION, (size_t (*)(void*, size_t, size_t, void*))(writeCallback<R>)); curl_easy_setopt(ch, CURLOPT_HEADERDATA, &hcx); CURLWriteContext<R> wcx(reduce, initial); - curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))writeCallback<R>); + curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))(writeCallback<R>)); curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx); curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true); // Set the request headers - curl_slist* hl = headers(NULL, car(req)); + curl_slist* hl = headers(NULL, car(hdr)); if (hl != NULL) curl_easy_setopt(ch, CURLOPT_HTTPHEADER, hl); // Apply the HTTP verb - curl_easy_setopt(ch, CURLOPT_URL, url.c_str()); + curl_easy_setopt(ch, CURLOPT_URL, c_str(url)); if (verb == "POST") { curl_easy_setopt(ch, CURLOPT_POST, true); curl_easy_setopt(ch, CURLOPT_POSTFIELDSIZE, sz); @@ -210,13 +200,13 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< // Return the HTTP return code or content if (rc) - return mkfailure<list<R>, std::string>(curl_easy_strerror(rc)); + return mkfailure<list<R> >(string(curl_easy_strerror(rc))); long httprc; curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc); if (httprc != 200 && httprc != 201) { - std::ostringstream es; + ostringstream es; es << "HTTP code " << httprc; - return mkfailure<list<R>, std::string>(es.str()); + return mkfailure<list<R> >(str(es)); } return mklist<R>(hcx.accum, wcx.accum); } @@ -224,26 +214,26 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< /** * Evaluate an expression remotely, at the given URL. */ -const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLSession& ch) { +const failable<value> evalExpr(const value& expr, const string& url, const CURLSession& ch) { debug(url, "http::evalExpr::url"); debug(expr, "http::evalExpr::input"); // Convert expression to a JSON-RPC request json::JSONContext cx; - const failable<list<std::string>, std::string> jsreq = jsonRequest(1, car<value>(expr), cdr<value>(expr), cx); + const failable<list<string> > jsreq = json::jsonRequest(1, car<value>(expr), cdr<value>(expr), cx); if (!hasContent(jsreq)) - return mkfailure<value, std::string>(reason(jsreq)); + return mkfailure<value>(reason(jsreq)); // POST it to the URL - const list<std::string> h = mklist<std::string>("Content-Type: application/json-rpc"); - const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(mklist<list<std::string> >(h, content(jsreq)), rcons<std::string>, list<std::string>(), url, "POST", ch); + const list<string> h = mklist<string>("Content-Type: application/json-rpc"); + const failable<list<list<string> > > res = apply<list<string> >(mklist<list<string> >(h, content(jsreq)), rcons<string>, list<string>(), url, "POST", ch); if (!hasContent(res)) - return mkfailure<value, std::string>(reason(res)); + return mkfailure<value>(reason(res)); // Return result - failable<list<value>, std::string> jsres = json::readJSON(cadr<list<std::string> >(content(res)), cx); + failable<list<value> > jsres = json::readJSON(cadr<list<string> >(content(res)), cx); if (!hasContent(jsres)) - return mkfailure<value, std::string>(reason(jsres)); + return mkfailure<value>(reason(jsres)); const list<value> val = elementsToValues(content(jsres)); const value rval(cadr<value>(cadr<value>(val))); @@ -254,72 +244,88 @@ const failable<value, std::string> evalExpr(const value& expr, const std::string /** * Find and return a header. */ -const failable<std::string, std::string> header(const std::string& prefix, const list<std::string>& h) { +const failable<string> header(const char* prefix, const list<string>& h) { if (isNil(h)) - return mkfailure<std::string, std::string>(std::string("Couldn't find header: ") + prefix); - const std::string s = car(h); - if (s.find(prefix) != 0) + return mkfailure<string>(string("Couldn't find header: ") + prefix); + const string s = car(h); + if (find(s, prefix) != 0) return header(prefix, cdr(h)); - const std::string l(s.substr(prefix.length())); - return l.substr(0, l.find_first_of("\r\n")); + const string l(substr(s, length(prefix))); + return substr(l, 0, find_first_of(l, "\r\n")); } /** * Find and return a location header. */ -const failable<std::string, std::string> location(const list<std::string>& h) { +const failable<string> location(const list<string>& h) { return header("Location: ", h); } /** * Convert a location to an entry id. */ -const failable<value, std::string> entryId(const failable<std::string, std::string> l) { +const failable<value> entryId(const failable<string> l) { if (!hasContent(l)) - return mkfailure<value, std::string>(reason(l)); - const std::string ls(content(l)); - return value(ls.substr(ls.find_last_of("/") + 1)); + return mkfailure<value>(reason(l)); + const string ls(content(l)); + return value(string(substr(ls, find_last(ls, '/') + 1))); } /** * Find and return a content-type header. */ -const failable<std::string, std::string> contentType(const list<std::string>& h) { +const failable<string> contentType(const list<string>& h) { return header("Content-Type: ", h); } /** * HTTP GET, return the resource at the given URL. */ -template<typename R> const failable<list<R>, std::string> get(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) { +template<typename R> const failable<list<R> > get(const lambda<R(const string&, const R)>& reduce, const R& initial, const string& url, const CURLSession& ch) { debug(url, "http::get::url"); - const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); + const list<list<string> > req = mklist(list<string>(), list<string>()); return apply(req, reduce, initial, url, "GET", ch); } /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value, std::string> get(const std::string& url, const CURLSession& ch) { +const failable<value> getcontent(const string& url, const CURLSession& ch) { + debug(url, "http::get::url"); + + // Get the contents of the resource at the given URL + const failable<list<list<string> > > res = get<list<string>>(rcons<string>, list<string>(), url, ch); + if (!hasContent(res)) + return mkfailure<value>(reason(res)); + const list<string> ls(reverse(cadr(content(res)))); + + // Return the content as a list of values + const value val(mkvalues(ls)); + debug(val, "http::get::result"); + return val; +} + +/** + * HTTP GET, return a list of values representing the resource at the given URL. + */ +const failable<value> get(const string& url, const CURLSession& ch) { debug(url, "http::get::url"); // Get the contents of the resource at the given URL - const failable<list<list<std::string> >, std::string> res = get<list<std::string> >(rcons<std::string>, list<std::string>(), url, ch); + const failable<list<list<string> > > res = get<list<string> >(rcons<string>, list<string>(), url, ch); if (!hasContent(res)) - return mkfailure<value, std::string>(reason(res)); - const list<std::string> ls(reverse(cadr(content(res)))); + return mkfailure<value>(reason(res)); + const list<string> ls(reverse(cadr(content(res)))); - const std::string ct(content(contentType(car(content(res))))); + const string ct(content(contentType(car(content(res))))); if (ct == "application/atom+xml;type=entry") { const value val(atom::entryValue(content(atom::readEntry(ls)))); debug(val, "http::get::result"); return val; } - // Return the content as a string value - std::ostringstream os; - write(ls, os); - const value val(os.str()); + // Return the content as a list of values + const value val(mkvalues(ls)); debug(val, "http::get::result"); return val; } @@ -327,24 +333,24 @@ const failable<value, std::string> get(const std::string& url, const CURLSession /** * HTTP POST. */ -const failable<value, std::string> post(const value& val, const std::string& url, const CURLSession& ch) { +const failable<value> post(const value& val, const string& url, const CURLSession& ch) { // Convert value to an ATOM entry - const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); + const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) - return mkfailure<value, std::string>(reason(entry)); + return mkfailure<value>(reason(entry)); debug(url, "http::post::url"); debug(content(entry), "http::post::input"); // POST it to the URL - const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); - const list<list<std::string> > req = mklist<list<std::string> >(h, content(entry)); - const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch); + const list<string> h = mklist<string>("Content-Type: application/atom+xml"); + const list<list<string> > req = mklist<list<string> >(h, content(entry)); + const failable<list<list<string> > > res = apply<list<string>>(req, rcons<string>, list<string>(), url, "POST", ch); if (!hasContent(res)) - return mkfailure<value, std::string>(reason(res)); + return mkfailure<value>(reason(res)); // Return the new entry id from the HTTP location header - const failable<value, std::string> eid(entryId(location(car(content(res))))); + const failable<value> eid(entryId(location(car(content(res))))); debug(eid, "http::post::result"); return eid; } @@ -352,21 +358,21 @@ const failable<value, std::string> post(const value& val, const std::string& url /** * HTTP PUT. */ -const failable<value, std::string> put(const value& val, const std::string& url, const CURLSession& ch) { +const failable<value> put(const value& val, const string& url, const CURLSession& ch) { // Convert value to an ATOM entry - const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); + const failable<list<string> > entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasContent(entry)) - return mkfailure<value, std::string>(reason(entry)); + return mkfailure<value>(reason(entry)); debug(url, "http::put::url"); debug(content(entry), "http::put::input"); // PUT it to the URL - const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); - const list<list<std::string> > req = mklist<list<std::string> >(h, content(entry)); - const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch); + const list<string> h = mklist<string>("Content-Type: application/atom+xml"); + const list<list<string> > req = mklist<list<string> >(h, content(entry)); + const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "PUT", ch); if (!hasContent(res)) - return mkfailure<value, std::string>(reason(res)); + return mkfailure<value>(reason(res)); debug(true, "http::put::result"); return value(true); @@ -375,13 +381,13 @@ const failable<value, std::string> put(const value& val, const std::string& url, /** * HTTP DELETE. */ -const failable<value, std::string> del(const std::string& url, const CURLSession& ch) { +const failable<value, string> del(const string& url, const CURLSession& ch) { debug(url, "http::delete::url"); - const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); - const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "DELETE", ch); + const list<list<string> > req = mklist(list<string>(), list<string>()); + const failable<list<list<string> > > res = apply<list<string> >(req, rcons<string>, list<string>(), url, "DELETE", ch); if (!hasContent(res)) - return mkfailure<value, std::string>(reason(res)); + return mkfailure<value>(reason(res)); debug(true, "http::delete::result"); return value(true); @@ -391,18 +397,18 @@ const failable<value, std::string> del(const std::string& url, const CURLSession * HTTP client proxy function. */ struct proxy { - proxy(const std::string& url) : url(url) { + proxy(const string& url) : url(url) { } const value operator()(const list<value>& args) const { CURLSession cs; - failable<value, std::string> val = evalExpr(args, url, cs); + failable<value> val = evalExpr(args, url, cs); if (!hasContent(val)) return value(); return content(val); } - const std::string url; + const string url; }; } diff --git a/sca-cpp/trunk/modules/http/httpd.hpp b/sca-cpp/trunk/modules/http/httpd.hpp index 890fee8f01..e0c5d110c4 100644 --- a/sca-cpp/trunk/modules/http/httpd.hpp +++ b/sca-cpp/trunk/modules/http/httpd.hpp @@ -26,8 +26,8 @@ * HTTPD module implementation functions. */ -#include <string> -#include <iostream> +#include "string.hpp" +#include "stream.hpp" #include "apr_strings.h" #include "apr_fnmatch.h" @@ -60,9 +60,7 @@ namespace httpd { * Returns a server-scoped module configuration. */ template<typename C> void* makeServerConf(apr_pool_t *p, server_rec *s) { - C* c = new (apr_palloc(p, sizeof(C))) C(s); - apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback<C>, apr_pool_cleanup_null) ; - return c; + return new (gc_new<C>(p)) C(s); } template<typename C> const C& serverConf(const request_rec* r, const module* mod) { @@ -78,9 +76,7 @@ template<typename C> C& serverConf(const cmd_parms *cmd, const module* mod) { * Returns a directory-scoped module configuration. */ template<typename C> void *makeDirConf(apr_pool_t *p, char *dirspec) { - C* c = new (apr_palloc(p, sizeof(C))) C(dirspec); - apr_pool_cleanup_register(p, c, gc_pool_cleanupCallback<C>, apr_pool_cleanup_null) ; - return c; + return new (gc_new<C>(p)) C(dirspec); } template<typename C> C& dirConf(const request_rec* r, const module* mod) { @@ -90,31 +86,25 @@ template<typename C> C& dirConf(const request_rec* r, const module* mod) { /** * Convert a path string to a list of values. */ -const list<std::string> pathTokens(const char* p) { +const list<string> pathTokens(const char* p) { if (p == NULL || p[0] == '\0') - return list<std::string>(); + return list<string>(); if (p[0] == '/') return tokenize("/", p + 1); return tokenize("/", p); } -const list<value> pathValues(const list<std::string>& l) { - if (isNil(l)) - return list<value>(); - return cons<value>(car(l), pathValues(cdr(l))); -} - -const list<value> path(const char* p) { - return pathValues(pathTokens(p)); +const list<value> pathValues(const char* p) { + return mkvalues(pathTokens(p)); } /** * Convert a path represented as a list of values to a string. */ -const std::string path(const list<value>& p) { +const string path(const list<value>& p) { if (isNil(p)) return ""; - return std::string("/") + std::string(car(p)) + path(cdr(p)); + return string("/") + car(p) + path(cdr(p)); } /** @@ -126,7 +116,7 @@ const char* optional(const char* s) { return s; } -const std::string contentType(const request_rec* r) { +const string contentType(const request_rec* r) { return optional(apr_table_get(r->headers_in, "Content-Type")); } @@ -136,24 +126,24 @@ const std::string contentType(const request_rec* r) { * Debug log. */ int debugHeader(unused void* r, const char* key, const char* value) { - std::cerr << " header key: " << key << ", value: " << value << std::endl; + cerr << " header key: " << key << ", value: " << value << endl; return 1; } -const bool debugRequest(request_rec* r, const std::string& msg) { - std::cerr << msg << ":" << std::endl; - std::cerr << " protocol: " << optional(r->protocol) << std::endl; - std::cerr << " method: " << optional(r->method) << std::endl; - std::cerr << " method number: " << r->method_number << std::endl; - std::cerr << " content type: " << contentType(r) << std::endl; - std::cerr << " content encoding: " << optional(r->content_encoding) << std::endl; +const bool debugRequest(request_rec* r, const string& msg) { + cerr << msg << ":" << endl; + cerr << " protocol: " << optional(r->protocol) << endl; + cerr << " method: " << optional(r->method) << endl; + cerr << " method number: " << r->method_number << endl; + cerr << " content type: " << contentType(r) << endl; + cerr << " content encoding: " << optional(r->content_encoding) << endl; apr_table_do(debugHeader, r, r->headers_in, NULL); - std::cerr << " unparsed uri: " << optional(r->unparsed_uri) << std::endl; - std::cerr << " uri: " << optional(r->uri) << std::endl; - std::cerr << " path info: " << optional(r->path_info) << std::endl; - std::cerr << " filename: " << optional(r->filename) << std::endl; - std::cerr << " uri tokens: " << pathTokens(r->uri) << std::endl; - std::cerr << " args: " << optional(r->args) << std::endl; + cerr << " unparsed uri: " << optional(r->unparsed_uri) << endl; + cerr << " uri: " << optional(r->uri) << endl; + cerr << " path info: " << optional(r->path_info) << endl; + cerr << " filename: " << optional(r->filename) << endl; + cerr << " uri tokens: " << pathTokens(r->uri) << endl; + cerr << " args: " << optional(r->args) << endl; return true; } @@ -177,16 +167,16 @@ const list<value> pathInfo(const list<value>& uri, const list<value>& path) { /** * Returns a list of key value pairs from the args in a query string. */ -const list<value> queryArg(const std::string& s) { - const list<std::string> t = tokenize("=", s); - return mklist<value>(car(t).c_str(), cadr(t)); +const list<value> queryArg(const string& s) { + const list<string> t = tokenize("=", s); + return mklist<value>(c_str(car(t)), cadr(t)); } const list<list<value> > queryArgs(const request_rec* r) { const char* a = r->args; if (a == NULL) return list<list<value> >(); - return map<std::string, list<value>>(queryArg, tokenize("&", a)); + return map<string, list<value>>(queryArg, tokenize("&", a)); } /** @@ -229,50 +219,49 @@ const int setupReadPolicy(request_rec* r) { /** * Read the content of a POST or PUT. */ -const list<std::string> read(request_rec* r) { - char b[2048]; - const int n = ap_get_client_block(r, b, 2048); +const list<string> read(request_rec* r) { + char b[1024]; + const int n = ap_get_client_block(r, b, sizeof(b)); if (n <= 0) - return list<std::string>(); - return cons(std::string(b, n), read(r)); + return list<string>(); + return cons(string(b, n), read(r)); } /** * Convert a URI value to an absolute URL. */ const char* url(const value& v, request_rec* r) { - std::string u = r->uri; - u.append("/"); - u.append(v); - return ap_construct_url(r->pool, u.c_str(), r); + const string u = string(r->uri) + "/" + v; + return ap_construct_url(r->pool, c_str(u), r); } /** * Write an HTTP result. */ -const failable<int, std::string> writeResult(const failable<list<std::string>, std::string>& ls, const std::string& ct, request_rec* r) { +const failable<int> writeResult(const failable<list<string> >& ls, const string& ct, request_rec* r) { if (!hasContent(ls)) - return mkfailure<int, std::string>(reason(ls)); - std::ostringstream os; + return mkfailure<int>(reason(ls)); + ostringstream os; write(content(ls), os); - debug(os.str(), "httpd::result"); + const string ob(str(os)); + debug(ob, "httpd::result"); - const std::string etag(ap_md5(r->pool, (const unsigned char*)std::string(os.str()).c_str())); + const string etag(ap_md5(r->pool, (const unsigned char*)c_str(ob))); const char* match = apr_table_get(r->headers_in, "If-None-Match"); - apr_table_setn(r->headers_out, "ETag", apr_pstrdup(r->pool, etag.c_str())); + apr_table_setn(r->headers_out, "ETag", apr_pstrdup(r->pool, c_str(etag))); if (match != NULL && etag == match) { r->status = HTTP_NOT_MODIFIED; return OK; } - ap_set_content_type(r, apr_pstrdup(r->pool, ct.c_str())); - ap_rputs(std::string(os.str()).c_str(), r); + ap_set_content_type(r, apr_pstrdup(r->pool, c_str(ct))); + ap_rputs(c_str(ob), r); return OK; } /** * Report request execution status. */ -const int reportStatus(const failable<int, std::string>& rc) { +const int reportStatus(const failable<int>& rc) { if (!hasContent(rc)) return HTTP_INTERNAL_SERVER_ERROR; return content(rc); diff --git a/sca-cpp/trunk/modules/json/json-test.cpp b/sca-cpp/trunk/modules/json/json-test.cpp index 4d1bbffd5a..b4a6ba8746 100644 --- a/sca-cpp/trunk/modules/json/json-test.cpp +++ b/sca-cpp/trunk/modules/json/json-test.cpp @@ -24,10 +24,8 @@ */ #include <assert.h> -#include <iostream> -#include <sstream> -#include <string> -#include "slist.hpp" +#include "stream.hpp" +#include "string.hpp" #include "json.hpp" namespace tuscany { @@ -35,15 +33,15 @@ namespace json { bool testJSEval() { JSONContext cx; - const std::string script("(function testJSON(n){ return JSON.parse(JSON.stringify(n)) })(5)"); + const string script("(function testJSON(n){ return JSON.parse(JSON.stringify(n)) })(5)"); jsval rval; - assert(JS_EvaluateScript(cx, cx.getGlobal(), script.c_str(), script.length(), "testJSON.js", 1, &rval)); - const std::string r(JS_GetStringBytes(JS_ValueToString(cx, rval))); + assert(JS_EvaluateScript(cx, cx.getGlobal(), c_str(script), length(script), "testJSON.js", 1, &rval)); + const string r(JS_GetStringBytes(JS_ValueToString(cx, rval))); assert(r == "5"); return true; } -std::ostringstream* jsonWriter(const std::string& s, std::ostringstream* os) { +ostream* jsonWriter(const string& s, ostream* os) { (*os) << s; return os; } @@ -52,30 +50,30 @@ bool testJSON() { const JSONContext cx; { - const list<value> ad = mklist<value>(mklist<value>(attribute, "city", std::string("san francisco")), mklist<value>(attribute, "state", std::string("ca"))); - const list<value> ac = mklist<value>(mklist<value>(element, "id", std::string("1234")), mklist<value>(attribute, "balance", 1000)); - const list<value> cr = mklist<value>(mklist<value> (attribute, "name", std::string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac))); + const list<value> ad = mklist<value>(mklist<value>(attribute, "city", string("san francisco")), mklist<value>(attribute, "state", string("ca"))); + const list<value> ac = mklist<value>(mklist<value>(element, "id", string("1234")), mklist<value>(attribute, "balance", 1000)); + const list<value> cr = mklist<value>(mklist<value> (attribute, "name", string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac))); const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr))); - std::ostringstream os; - writeJSON<std::ostringstream*>(jsonWriter, &os, c, cx); - assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}"); + ostringstream os; + writeJSON<ostream*>(jsonWriter, &os, c, cx); + assert(str(os) == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}"); } { - const list<value> phones = mklist<value> (std::string("408-1234"), std::string("650-1234")); - const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", std::string("test\ttab")), mklist<value> (element, "firstName", std::string("test1"))); + const list<value> phones = mklist<value> (string("408-1234"), string("650-1234")); + const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", string("test\ttab")), mklist<value> (element, "firstName", string("test1"))); - std::ostringstream os; - writeJSON<std::ostringstream*>(jsonWriter, &os, l, cx); - assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}"); + ostringstream os; + writeJSON<ostream*>(jsonWriter, &os, l, cx); + assert(str(os) == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}"); - std::istringstream is(os.str()); - const list<std::string> il = streamList(is); + istringstream is(str(os)); + const list<string> il = streamList(is); const list<value> r = content(readJSON(il, cx)); assert(r == l); - std::ostringstream wos; + ostringstream wos; write(content(writeJSON(r, cx)), wos); - assert(wos.str() == os.str()); + assert(str(wos) == str(os)); } return true; } @@ -83,45 +81,45 @@ bool testJSON() { bool testJSONRPC() { JSONContext cx; { - const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}"); + const string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}"); const list<value> e = content(readJSON(mklist(lm), cx)); const list<value> v = elementsToValues(e); assert(assoc<value>("id", v) == mklist<value>("id", 1)); - assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods"))); + assert(assoc<value>("method", v) == mklist<value>("method", string("system.listMethods"))); assert(assoc<value>("params", v) == mklist<value>("params", list<value>())); } { - const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); + const string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); const list<value> e = content(readJSON(mklist(i), cx)); - const std::string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}"); + const string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}"); const list<value> e2 = content(readJSON(mklist(i), cx)); assert(e == e2); } { - const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); + const string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}"); const list<value> e = content(readJSON(mklist(i), cx)); - std::ostringstream os; + ostringstream os; write(content(writeJSON(e, cx)), os); - assert(os.str() == i); + assert(str(os) == i); const list<value> v = elementsToValues(e); const list<value> r = valuesToElements(v); assert(r == e); } { - const list<value> r = mklist<value>(mklist<value>("id", 1), mklist<value>("result", mklist<value>(std::string("Service.get"), std::string("Service.getTotal")))); + const list<value> r = mklist<value>(mklist<value>("id", 1), mklist<value>("result", mklist<value>(string("Service.get"), string("Service.getTotal")))); const list<value> e = valuesToElements(r); - std::ostringstream os; + ostringstream os; write(content(writeJSON(e, cx)), os); - assert(os.str() == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}"); + assert(str(os) == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}"); } { - const std::string f("{\"id\":1,\"result\":[\"Sample Feed\",\"123456789\",[\"Item\",\"111\",{\"javaClass\":\"services.Item\",\"name\":\"Apple\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":2.99}],[\"Item\",\"222\",{\"javaClass\":\"services.Item\",\"name\":\"Orange\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":3.55}],[\"Item\",\"333\",{\"javaClass\":\"services.Item\",\"name\":\"Pear\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":1.55}]]}"); + const string f("{\"id\":1,\"result\":[\"Sample Feed\",\"123456789\",[\"Item\",\"111\",{\"javaClass\":\"services.Item\",\"name\":\"Apple\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":2.99}],[\"Item\",\"222\",{\"javaClass\":\"services.Item\",\"name\":\"Orange\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":3.55}],[\"Item\",\"333\",{\"javaClass\":\"services.Item\",\"name\":\"Pear\",\"currencyCode\":\"USD\",\"currencySymbol\":\"$\",\"price\":1.55}]]}"); const list<value> r = content(readJSON(mklist(f), cx)); const list<value> v = elementsToValues(r); const list<value> e = valuesToElements(v); - std::ostringstream os; + ostringstream os; write(content(writeJSON(e, cx)), os); - assert(os.str() == f); + assert(str(os) == f); } return true; } @@ -130,13 +128,13 @@ bool testJSONRPC() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::json::testJSEval(); tuscany::json::testJSON(); tuscany::json::testJSONRPC(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp index 6ce4e3a9a1..9124c5143c 100644 --- a/sca-cpp/trunk/modules/json/json.hpp +++ b/sca-cpp/trunk/modules/json/json.hpp @@ -28,7 +28,7 @@ #define XP_UNIX #include <jsapi.h> -#include <string> +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "element.hpp" @@ -41,8 +41,8 @@ namespace json { * Report JSON errors. */ void reportError(unused JSContext *cx, const char *message, JSErrorReport *report) { - std::cerr << (const char*)(report->filename? report->filename : "<no filename>") << ":" - << (unsigned int)report->lineno << ":" << message << std::endl; + cerr << (const char*)(report->filename? report->filename : "<no filename>") << ":" + << (int)report->lineno << ":" << message << endl; } /** @@ -168,7 +168,7 @@ const list<value> jsPropertiesToValues(const list<value>& propertiesSoFar, JSObj const value jsValToValue(const jsval& jsv, const JSONContext& cx) { switch(JS_TypeOfValue(cx, jsv)) { case JSTYPE_STRING: { - return value(std::string(JS_GetStringBytes(JSVAL_TO_STRING(jsv)))); + return value(string(JS_GetStringBytes(JSVAL_TO_STRING(jsv)))); } case JSTYPE_BOOLEAN: { return value((bool)JSVAL_TO_BOOLEAN(jsv)); @@ -195,30 +195,30 @@ const value jsValToValue(const jsval& jsv, const JSONContext& cx) { /** * Consumes JSON strings and populates a JS object. */ -failable<bool, std::string> consume(JSONParser* parser, const list<std::string>& ilist, const JSONContext& cx) { +failable<bool> consume(JSONParser* parser, const list<string>& ilist, const JSONContext& cx) { if (isNil(ilist)) return true; - JSString* jstr = JS_NewStringCopyZ(cx, car(ilist).c_str()); + JSString* jstr = JS_NewStringCopyZ(cx, c_str(car(ilist))); if(!JS_ConsumeJSONText(cx, parser, JS_GetStringChars(jstr), JS_GetStringLength(jstr))) - return mkfailure<bool, std::string>("JS_ConsumeJSONText failed"); + return mkfailure<bool>("JS_ConsumeJSONText failed"); return consume(parser, cdr(ilist), cx); } /** * Convert a list of strings representing a JSON document to a list of values. */ -const failable<list<value>, std::string> readJSON(const list<std::string>& ilist, const JSONContext& cx) { +const failable<list<value> > readJSON(const list<string>& ilist, const JSONContext& cx) { jsval val; JSONParser* parser = JS_BeginJSONParse(cx, &val); if(parser == NULL) - return mkfailure<list<value>, std::string>("JS_BeginJSONParse failed"); + return mkfailure<list<value> >("JS_BeginJSONParse failed"); - const failable<bool, std::string> consumed = consume(parser, ilist, cx); + const failable<bool> consumed = consume(parser, ilist, cx); if(!JS_FinishJSONParse(cx, parser, JSVAL_NULL)) - return mkfailure<list<value>, std::string>("JS_FinishJSONParse failed"); + return mkfailure<list<value> >("JS_FinishJSONParse failed"); if(!hasContent(consumed)) - return mkfailure<list<value>, std::string>(reason(consumed)); + return mkfailure<list<value> >(reason(consumed)); return list<value>(jsValToValue(val, cx)); } @@ -261,7 +261,7 @@ JSObject* valuesToJSProperties(JSObject* o, const list<value>& l, const JSONCont return o; const list<value> p = car(l); jsval pv = valueToJSVal(caddr(p), cx); - JS_SetProperty(cx, o, ((std::string)cadr(p)).c_str(), &pv); + JS_SetProperty(cx, o, c_str((string)cadr(p)), &pv); return valuesToJSProperties(o, cdr(l), cx); } @@ -272,7 +272,7 @@ const jsval valueToJSVal(const value& val, const JSONContext& cx) { switch(type(val)) { case value::String: case value::Symbol: { - return STRING_TO_JSVAL(JS_NewStringCopyZ(cx, ((std::string)val).c_str())); + return STRING_TO_JSVAL(JS_NewStringCopyZ(cx, c_str((string)val))); } case value::Bool: { return BOOLEAN_TO_JSVAL((bool)val); @@ -291,7 +291,7 @@ const jsval valueToJSVal(const value& val, const JSONContext& cx) { } } -const failable<bool, std::string> writeList(const list<value>& l, JSObject* o, const JSONContext& cx) { +const failable<bool> writeList(const list<value>& l, JSObject* o, const JSONContext& cx) { if (isNil(l)) return true; @@ -300,24 +300,24 @@ const failable<bool, std::string> writeList(const list<value>& l, JSObject* o, c if (isTaggedList(token, attribute)) { jsval pv = valueToJSVal(attributeValue(token), cx); - JS_SetProperty(cx, o, std::string(attributeName(token)).c_str(), &pv); + JS_SetProperty(cx, o, c_str(string(attributeName(token))), &pv); } else if (isTaggedList(token, element)) { // Write the value of an element if (elementHasValue(token)) { jsval pv = valueToJSVal(elementValue(token), cx); - JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); + JS_SetProperty(cx, o, c_str(string(elementName(token))), &pv); } else { // Write a parent element JSObject* child = JS_NewObject(cx, NULL, NULL, NULL); jsval pv = OBJECT_TO_JSVAL(child); - JS_SetProperty(cx, o, std::string(elementName(token)).c_str(), &pv); + JS_SetProperty(cx, o, c_str(string(elementName(token))), &pv); // Write its children - const failable<bool, std::string> w = writeList(elementChildren(token), child, cx); + const failable<bool> w = writeList(elementChildren(token), child, cx); if (!hasContent(w)) return w; } @@ -332,10 +332,10 @@ const failable<bool, std::string> writeList(const list<value>& l, JSObject* o, c */ template<typename R> class WriteContext { public: - WriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { + WriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) { } const JSONContext& cx; - const lambda<R(const std::string&, const R)> reduce; + const lambda<R(const string&, const R)> reduce; R accum; }; @@ -345,40 +345,40 @@ public: template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *data) { WriteContext<R>& wcx = *(static_cast<WriteContext<R>*> (data)); JSString* jstr = JS_NewUCStringCopyN(wcx.cx, buf, len); - wcx.accum = wcx.reduce(std::string(JS_GetStringBytes(jstr), JS_GetStringLength(jstr)), wcx.accum); + wcx.accum = wcx.reduce(string(JS_GetStringBytes(jstr), JS_GetStringLength(jstr)), wcx.accum); return JS_TRUE; } /** * Convert a list of values to a JSON document. */ -template<typename R> const failable<R, std::string> writeJSON(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) { +template<typename R> const failable<R> writeJSON(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) { JSObject* o = JS_NewObject(cx, NULL, NULL, NULL); jsval val = OBJECT_TO_JSVAL(o); - const failable<bool, std::string> w = writeList(l, o, cx); + const failable<bool> w = writeList(l, o, cx); if (!hasContent(w)) - return mkfailure<R, std::string>(reason(w)); + return mkfailure<R>(reason(w)); WriteContext<R> wcx(reduce, initial, cx); if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx)) - return mkfailure<R, std::string>("JS_Stringify failed"); + return mkfailure<R>("JS_Stringify failed"); return wcx.accum; } /** * Convert a list of values to a list of strings representing a JSON document. */ -const failable<list<std::string>, std::string> writeJSON(const list<value>& l, const JSONContext& cx) { - const failable<list<std::string>, std::string> ls = writeJSON<list<std::string> >(rcons<std::string>, list<std::string>(), l, cx); +const failable<list<string> > writeJSON(const list<value>& l, const JSONContext& cx) { + const failable<list<string> > ls = writeJSON<list<string>>(rcons<string>, list<string>(), l, cx); if (!hasContent(ls)) return ls; - return reverse(list<std::string>(content(ls))); + return reverse(list<string>(content(ls))); } /** * Convert a function + params to a JSON request. */ -const failable<list<std::string>, std::string> jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) { +const failable<list<string> > jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) { const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("method", func), mklist<value>("params", params)); return writeJSON(valuesToElements(r), cx); } @@ -386,7 +386,7 @@ const failable<list<std::string>, std::string> jsonRequest(const value& id, cons /** * Convert a value to a JSON result. */ -const failable<list<std::string>, std::string> jsonResult(const value& id, const value& val, JSONContext& cx) { +const failable<list<string> > jsonResult(const value& id, const value& val, JSONContext& cx) { return writeJSON(valuesToElements(mklist<value>(mklist<value>("id", id), mklist<value>("result", val))), cx); } diff --git a/sca-cpp/trunk/modules/scdl/scdl-test.cpp b/sca-cpp/trunk/modules/scdl/scdl-test.cpp index 582d1ee073..d6034d1e2f 100644 --- a/sca-cpp/trunk/modules/scdl/scdl-test.cpp +++ b/sca-cpp/trunk/modules/scdl/scdl-test.cpp @@ -24,12 +24,9 @@ */ #include <assert.h> -#include <iostream> -#include <sstream> -#include <fstream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "list.hpp" -#include "slist.hpp" #include "tree.hpp" #include "scdl.hpp" @@ -37,24 +34,24 @@ namespace tuscany { namespace scdl { bool testComposite() { - std::ifstream is("test.composite"); + ifstream is("test.composite"); const list<value> c = readXML(streamList(is)); return true; } bool testComponents() { - std::ifstream is("test.composite"); + ifstream is("test.composite"); const list<value> c = components(readXML(streamList(is))); assert(length(c) == 4); const value store = car(c); - assert(name(store) == std::string("Store")); + assert(name(store) == string("Store")); const value impl = implementation(store); - assert(uri(impl) == std::string("store.html")); + assert(uri(impl) == string("store.html")); assert(implementationType(impl) == "t:implementation.widget"); - const value catalog = named(std::string("Catalog"), c); - assert(name(catalog) == std::string("Catalog")); + const value catalog = named(string("Catalog"), c); + assert(name(catalog) == string("Catalog")); const list<value> t = mkbtree(sort(nameToElementAssoc(c))); assert(assoctree<value>("Catalog", t) == mklist<value>("Catalog" , cadr(c))); @@ -62,30 +59,30 @@ bool testComponents() { } bool testServices() { - std::ifstream is("test.composite"); + ifstream is("test.composite"); const list<value> c = components(readXML(streamList(is))); const value store = car(c); assert(length(services(store)) == 1); const value widget = car(services(store)); - assert(name(widget) == std::string("Widget")); + assert(name(widget) == string("Widget")); assert(length(bindings(widget)) == 1); const value binding = car(bindings(widget)); - assert(uri(binding) == std::string("/store")); + assert(uri(binding) == string("/store")); assert(bindingType(binding) == "t:binding.http"); return true; } bool testReferences() { - std::ifstream is("test.composite"); + ifstream is("test.composite"); const list<value> c = components(readXML(streamList(is))); const value store = car(c); assert(length(references(store)) == 3); const value catalog = car(references(store)); - assert(name(catalog) == std::string("catalog")); - assert(target(catalog) == std::string("Catalog")); + assert(name(catalog) == string("catalog")); + assert(target(catalog) == string("Catalog")); assert(length(bindings(catalog)) == 1); const value binding = car(bindings(catalog)); @@ -93,19 +90,19 @@ bool testReferences() { assert(bindingType(binding) == "t:binding.jsonrpc"); const list<value> t = mkbtree(sort(referenceToTargetAssoc(references(store)))); - assert(assoctree<value>("shoppingCart", t) == mklist<value>(std::string("shoppingCart"), std::string("ShoppingCart/Cart"))); + assert(assoctree<value>("shoppingCart", t) == mklist<value>(string("shoppingCart"), string("ShoppingCart/Cart"))); return true; } bool testProperties() { - std::ifstream is("test.composite"); + ifstream is("test.composite"); const list<value> c = components(readXML(streamList(is))); - const value catalog = named(std::string("Catalog"), c); + const value catalog = named(string("Catalog"), c); assert(length(properties(catalog)) == 1); const value currencyCode = car(properties(catalog)); - assert(name(currencyCode) == std::string("currencyCode")); - assert(propertyValue(currencyCode) == std::string("USD")); + assert(name(currencyCode) == string("currencyCode")); + assert(propertyValue(currencyCode) == string("USD")); return true; } @@ -113,7 +110,7 @@ bool testProperties() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::scdl::testComposite(); tuscany::scdl::testComponents(); @@ -121,7 +118,7 @@ int main() { tuscany::scdl::testReferences(); tuscany::scdl::testProperties(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/scdl/scdl.hpp b/sca-cpp/trunk/modules/scdl/scdl.hpp index 9d4bf38b50..531144e219 100644 --- a/sca-cpp/trunk/modules/scdl/scdl.hpp +++ b/sca-cpp/trunk/modules/scdl/scdl.hpp @@ -26,7 +26,7 @@ * SCDL read functions. */ -#include <string> +#include "string.hpp" #include "list.hpp" #include "value.hpp" #include "monad.hpp" @@ -85,7 +85,7 @@ const value named(const value& name, const value& l) { * Returns the implementation of a component. */ const bool filterImplementation(const value& v) { - return isElement(v) && std::string(cadr<value>(v)).find("implementation.") != std::string::npos; + return isElement(v) && contains(string(cadr<value>(v)), "implementation."); } const value implementation(const value& l) { @@ -137,7 +137,7 @@ const list<value> referenceToTargetAssoc(const list<value>& r) { * Returns a list of bindings in a service or reference. */ const bool filterBinding(const value& v) { - return isElement(v) && std::string(cadr<value>(v)).find("binding.") != std::string::npos; + return isElement(v) && contains(string(cadr<value>(v)), "binding."); } const list<value> bindings(const value& l) { diff --git a/sca-cpp/trunk/modules/server/client-test.cpp b/sca-cpp/trunk/modules/server/client-test.cpp index 496d67f59c..2728cfc6d5 100644 --- a/sca-cpp/trunk/modules/server/client-test.cpp +++ b/sca-cpp/trunk/modules/server/client-test.cpp @@ -23,11 +23,12 @@ * Test HTTP client functions. */ +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> #include <assert.h> -#include <iostream> -#include <sstream> -#include <string> -#include "slist.hpp" +#include "stream.hpp" +#include "string.hpp" #include "parallel.hpp" #include "perf.hpp" #include "../http/curl.hpp" @@ -35,11 +36,7 @@ namespace tuscany { namespace server { -const bool contains(const std::string& str, const std::string& pattern) { - return str.find(pattern) != str.npos; -} - -std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { +ostream* curlWriter(const string& s, ostream* os) { (*os) << s; return os; } @@ -47,16 +44,16 @@ std::ostringstream* curlWriter(const std::string& s, std::ostringstream* os) { const bool testGet() { http::CURLSession ch; { - std::ostringstream os; - const failable<list<std::ostringstream*>, std::string> r = http::get<std::ostringstream*>(curlWriter, &os, "http://localhost:8090", ch); + ostringstream os; + const failable<list<ostream*> > r = http::get<ostream*>(curlWriter, &os, "http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(os.str(), "HTTP/1.1 200 OK")); - assert(contains(os.str(), "It works")); + assert(contains(str(os), "HTTP/1.1 200 OK")); + assert(contains(str(os), "It works")); } { - const failable<value, std::string> r = http::get("http://localhost:8090", ch); + const failable<value> r = http::getcontent("http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(content(r), "It works")); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); } return true; } @@ -66,9 +63,9 @@ struct getLoop { getLoop(http::CURLSession& ch) : ch(ch) { } const bool operator()() const { - const failable<value, std::string> r = get("http://localhost:8090", ch); + const failable<value> r = http::getcontent("http://localhost:8090", ch); assert(hasContent(r)); - assert(contains(content(r), "It works")); + assert(contains(car(reverse(list<value>(content(r)))), "It works")); return true; } }; @@ -76,14 +73,14 @@ struct getLoop { const bool testGetPerf() { http::CURLSession ch; const lambda<bool()> gl = getLoop(ch); - std::cout << "Static GET test " << time(gl, 5, 200) << " ms" << std::endl; + cout << "Static GET test " << time(gl, 5, 200) << " ms" << endl; return true; } const bool testEval() { http::CURLSession ch; - const value val = content(http::evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8090/test", ch)); - assert(val == std::string("Hello")); + const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), "http://localhost:8090/test", ch)); + assert(val == string("Hello")); return true; } @@ -92,13 +89,13 @@ struct evalLoop { evalLoop(http::CURLSession& ch) : ch(ch) { } const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(std::string("echo"), std::string("Hello")), "http://localhost:8090/test", ch)); - assert(val == std::string("Hello")); + const value val = content(http::evalExpr(mklist<value>(string("echo"), string("Hello")), "http://localhost:8090/test", ch)); + assert(val == string("Hello")); return true; } }; -const value blob(std::string(3000, 'A')); +const value blob(string(3000, 'A')); const list<value> blobs = mklist(blob, blob, blob, blob, blob); struct blobEvalLoop { @@ -106,7 +103,7 @@ struct blobEvalLoop { blobEvalLoop(http::CURLSession& ch) : ch(ch) { } const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(std::string("echo"), blobs), "http://localhost:8090/test", ch)); + const value val = content(http::evalExpr(mklist<value>(string("echo"), blobs), "http://localhost:8090/test", ch)); assert(val == blobs); return true; } @@ -115,19 +112,19 @@ struct blobEvalLoop { const bool testEvalPerf() { http::CURLSession ch; const lambda<bool()> el = evalLoop(ch); - std::cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << std::endl; + cout << "JSON-RPC eval echo test " << time(el, 5, 200) << " ms" << endl; const lambda<bool()> bel = blobEvalLoop(ch); - std::cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << std::endl; + cout << "JSON-RPC eval blob test " << time(bel, 5, 200) << " ms" << endl; return true; } bool testPost() { const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$2.99")); - const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); http::CURLSession ch; - const failable<value, std::string> id = http::post(a, "http://localhost:8090/test", ch); + const failable<value> id = http::post(a, "http://localhost:8090/test", ch); assert(hasContent(id)); return true; } @@ -138,7 +135,7 @@ struct postLoop { postLoop(const value& val, http::CURLSession& ch) : val(val), ch(ch) { } const bool operator()() const { - const failable<value, std::string> id = http::post(val, "http://localhost:8090/test", ch); + const failable<value> id = http::post(val, "http://localhost:8090/test", ch); assert(hasContent(id)); return true; } @@ -148,28 +145,30 @@ const bool testPostPerf() { http::CURLSession ch; { const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$2.99")); - const list<value> val = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); const lambda<bool()> pl = postLoop(val, ch); - std::cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << std::endl; + cout << "ATOMPub POST small test " << time(pl, 5, 200) << " ms" << endl; } { const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "blob1" << blob) - << (list<value>() << "blob2" << blob) - << (list<value>() << "blob3" << blob) - << (list<value>() << "blob4" << blob) - << (list<value>() << "blob5" << blob) - << (list<value>() << "price" << std::string("$2.99")); - const list<value> val = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "blob1" + blob) + + (list<value>() + "blob2" + blob) + + (list<value>() + "blob3" + blob) + + (list<value>() + "blob4" + blob) + + (list<value>() + "blob5" + blob) + + (list<value>() + "price" + string("$2.99")); + const list<value> val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); const lambda<bool()> pl = postLoop(val, ch); - std::cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << std::endl; + cout << "ATOMPub POST blob test " << time(pl, 5, 200) << " ms" << endl; } return true; } +#ifdef _REENTRANT + const bool postThread(const int count, const value& val) { http::CURLSession ch; const lambda<bool()> pl = postLoop(val, ch); @@ -194,7 +193,7 @@ struct postThreadLoop { const lambda<bool()> l; const int threads; const gc_ptr<worker> w; - postThreadLoop(const lambda<bool()>& l, const int threads) : l(l), threads(threads), w(new worker(threads)) { + postThreadLoop(const lambda<bool()>& l, const int threads) : l(l), threads(threads), w(new (gc_new<worker>()) worker(threads)) { } const bool operator()() const { list<future<bool> > r = startPost(*w, threads, l); @@ -208,23 +207,83 @@ const bool testPostThreadPerf() { const int threads = 10; const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$2.99")); - const value val = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); const lambda<bool()> pl= curry(lambda<bool(const int, const value)>(postThread), count, val); const lambda<bool()> ptl = postThreadLoop(pl, threads); double t = time(ptl, 0, 1) / (threads * count); - std::cout << "ATOMPub POST thread test " << t << " ms" << std::endl; + cout << "ATOMPub POST thread test " << t << " ms" << endl; return true; } +#else + +const bool postProc(const int count, const value& val) { + http::CURLSession ch; + const lambda<bool()> pl = postLoop(val, ch); + time(pl, 0, count); + return true; +} + +const list<pid_t> startPost(const int procs, const lambda<bool()>& l) { + if (procs == 0) + return list<pid_t>(); + pid_t pid = fork(); + if (pid == 0) { + assert(l() == true); + exit(0); + } + return cons(pid, startPost(procs - 1, l)); +} + +const bool checkPost(const list<pid_t>& r) { + if (isNil(r)) + return true; + int status; + waitpid(car(r), &status, 0); + assert(status == 0); + return checkPost(cdr(r)); +} + +struct postForkLoop { + const lambda<bool()> l; + const int procs; + postForkLoop(const lambda<bool()>& l, const int procs) : l(l), procs(procs) { + } + const bool operator()() const { + list<pid_t> r = startPost(procs, l); + checkPost(r); + return true; + } +}; + +const bool testPostForkPerf() { + const int count = 50; + const int procs = 10; + + const list<value> i = list<value>() + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const value val = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + const lambda<bool()> pl= curry(lambda<bool(const int, const value)>(postProc), count, val); + const lambda<bool()> ptl = postForkLoop(pl, procs); + double t = time(ptl, 0, 1) / (procs * count); + cout << "ATOMPub POST fork test " << t << " ms" << endl; + + return true; +} + +#endif + const bool testPut() { const list<value> i = list<value>() - << (list<value>() << "name" << std::string("Apple")) - << (list<value>() << "price" << std::string("$2.99")); - const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); + + (list<value>() + "name" + string("Apple")) + + (list<value>() + "price" + string("$2.99")); + const list<value> a = mklist<value>(string("item"), string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i); http::CURLSession ch; value rc = content(http::put(a, "http://localhost:8090/test/111", ch)); assert(rc == value(true)); @@ -240,8 +299,8 @@ const bool testDel() { const bool testEvalCpp() { http::CURLSession ch; - const value val = content(http::evalExpr(mklist<value>(std::string("hello"), std::string("world")), "http://localhost:8090/cpp", ch)); - assert(val == std::string("hello world")); + const value val = content(http::evalExpr(mklist<value>(string("hello"), string("world")), "http://localhost:8090/cpp", ch)); + assert(val == string("hello world")); return true; } @@ -250,8 +309,8 @@ struct evalCppLoop { evalCppLoop(http::CURLSession& ch) : ch(ch) { } const bool operator()() const { - const value val = content(http::evalExpr(mklist<value>(std::string("hello"), std::string("world")), "http://localhost:8090/cpp", ch)); - assert(val == std::string("hello world")); + const value val = content(http::evalExpr(mklist<value>(string("hello"), string("world")), "http://localhost:8090/cpp", ch)); + assert(val == string("hello world")); return true; } }; @@ -259,7 +318,7 @@ struct evalCppLoop { const bool testEvalCppPerf() { http::CURLSession ch; const lambda<bool()> el = evalCppLoop(ch); - std::cout << "JSON-RPC C++ eval test " << time(el, 5, 200) << " ms" << std::endl; + cout << "JSON-RPC C++ eval test " << time(el, 5, 200) << " ms" << endl; return true; } @@ -267,13 +326,17 @@ const bool testEvalCppPerf() { } int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; tuscany::server::testGet(); tuscany::server::testGetPerf(); tuscany::server::testPost(); tuscany::server::testPostPerf(); +#ifdef _REENTRANT tuscany::server::testPostThreadPerf(); +#else + tuscany::server::testPostForkPerf(); +#endif tuscany::server::testEval(); tuscany::server::testEvalPerf(); tuscany::server::testPut(); @@ -281,7 +344,7 @@ int main() { tuscany::server::testEvalCpp(); tuscany::server::testEvalCppPerf(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } diff --git a/sca-cpp/trunk/modules/server/impl-test.cpp b/sca-cpp/trunk/modules/server/impl-test.cpp index 171a78f2d5..d2a45c2fa9 100644 --- a/sca-cpp/trunk/modules/server/impl-test.cpp +++ b/sca-cpp/trunk/modules/server/impl-test.cpp @@ -23,7 +23,7 @@ * Test component implementation. */ -#include <string> +#include "string.hpp" #include "function.hpp" #include "list.hpp" @@ -34,24 +34,24 @@ namespace tuscany { namespace server { -const failable<value, std::string> get(unused const list<value>& params) { - return value(std::string("Hey")); +const failable<value> get(unused const list<value>& params) { + return value(string("Hey")); } -const failable<value, std::string> post(unused const list<value>& params) { - return value(std::string("1234")); +const failable<value> post(unused const list<value>& params) { + return value(string("1234")); } -const failable<value, std::string> put(unused const list<value>& params) { +const failable<value> put(unused const list<value>& params) { return value(true); } -const failable<value, std::string> del(unused const list<value>& params) { +const failable<value> del(unused const list<value>& params) { return value(true); } -const failable<value, std::string> hello(const list<value>& params) { - return value(std::string("hello ") + std::string(car(params))); +const failable<value> hello(const list<value>& params) { + return value(string("hello ") + string(car(params))); } } @@ -71,7 +71,7 @@ const tuscany::value eval(const tuscany::list<tuscany::value>& params) { return tuscany::server::del(cdr(params)); if (func == "hello") return tuscany::server::hello(cdr(params)); - return tuscany::mkfailure<tuscany::value, std::string>(std::string("Function not supported: ") + std::string(func)); + return tuscany::mkfailure<tuscany::value>(tuscany::string("Function not supported: ") + func); } } diff --git a/sca-cpp/trunk/modules/server/mod-cpp.hpp b/sca-cpp/trunk/modules/server/mod-cpp.hpp index 664e9d2e41..2cf2e540d6 100644 --- a/sca-cpp/trunk/modules/server/mod-cpp.hpp +++ b/sca-cpp/trunk/modules/server/mod-cpp.hpp @@ -27,9 +27,8 @@ * component implementations. */ -#include <string> -#include <iostream> -#include <fstream> +#include "string.hpp" +#include "stream.hpp" #include "function.hpp" #include "list.hpp" @@ -65,12 +64,12 @@ struct evalImplementation { /** * Read a C++ component implementation. */ -const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string path, const list<value>& px) { - const failable<lib, std::string> ilib(dynlib(path + dynlibExt)); +const failable<lambda<value(const list<value>&)> > readImplementation(const string& path, const list<value>& px) { + const failable<lib> ilib(dynlib(path + dynlibExt)); if (!hasContent(ilib)) - return mkfailure<lambda<value(const list<value>&)>, std::string>(reason(ilib)); + return mkfailure<lambda<value(const list<value>&)> >(reason(ilib)); - const failable<lambda<value(const list<value>&)>, std::string> impl(dynlambda<value(const list<value>&)>("eval", content(ilib))); + const failable<lambda<value(const list<value>&)> > impl(dynlambda<value(const list<value>&)>("eval", content(ilib))); if (!hasContent(impl)) return impl; return lambda<value(const list<value>&)>(evalImplementation(content(ilib), content(impl), px)); diff --git a/sca-cpp/trunk/modules/server/mod-eval.cpp b/sca-cpp/trunk/modules/server/mod-eval.cpp index d8354c6a58..8e8870dd52 100644 --- a/sca-cpp/trunk/modules/server/mod-eval.cpp +++ b/sca-cpp/trunk/modules/server/mod-eval.cpp @@ -23,15 +23,11 @@ * HTTPD module used to eval component implementations. */ -#include <string> -#include <iostream> -#include <sstream> -#include <fstream> - +#include "string.hpp" +#include "stream.hpp" #include "function.hpp" #include "list.hpp" #include "tree.hpp" -#include "slist.hpp" #include "value.hpp" #include "element.hpp" #include "monad.hpp" @@ -58,9 +54,10 @@ class ServerConf { public: ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") { } + const server_rec* s; - std::string home; - std::string wiringServerName; + string home; + string wiringServerName; }; /** @@ -71,8 +68,8 @@ public: DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName("") { } const char* dirspec; - std::string contributionPath; - std::string compositeName; + string contributionPath; + string compositeName; list<value> implementations; }; @@ -80,16 +77,16 @@ public: * Convert a result represented as a content + failure pair to a * failable monad. */ -const failable<value, std::string> failableResult(const list<value>& v) { +const failable<value> failableResult(const list<value>& v) { if (isNil(cdr(v))) return car(v); - return mkfailure<value, std::string>(cadr(v)); + return mkfailure<value>(string(cadr(v))); } /** * Handle an HTTP GET. */ -const failable<int, std::string> get(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> get(request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::get::uri"); // Inspect the query string @@ -102,12 +99,12 @@ const failable<int, std::string> get(request_rec* r, const lambda<value(const li // Extract the request id, method and params const value id = cadr(ia); - const value func = std::string(cadr(ma)).c_str(); + const value func = c_str(string(cadr(ma))); // Apply the requested function - const failable<value, std::string> val = failableResult(impl(cons(func, httpd::queryParams(args)))); + const failable<value> val = failableResult(impl(cons(func, httpd::queryParams(args)))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); // Return JSON result json::JSONContext cx; @@ -115,58 +112,58 @@ const failable<int, std::string> get(request_rec* r, const lambda<value(const li } // Evaluate an ATOM GET request and return an ATOM feed - const list<value> path(httpd::path(r->uri)); + const list<value> path(httpd::pathValues(r->uri)); if (isNil(cddr(path))) { - const failable<value, std::string> val = failableResult(impl(cons<value>("getall", list<value>()))); + const failable<value> val = failableResult(impl(cons<value>("getall", list<value>()))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); return httpd::writeResult(atom::writeATOMFeed(atom::feedValuesToElements(content(val))), "application/atom+xml;type=feed", r); } // Evaluate an ATOM GET and return an ATOM entry - const failable<value, std::string> val = failableResult(impl(cons<value>("get", mklist<value>(caddr(path))))); + const failable<value> val = failableResult(impl(cons<value>("get", mklist<value>(caddr(path))))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); return httpd::writeResult(atom::writeATOMEntry(atom::entryValuesToElements(content(val))), "application/atom+xml;type=entry", r); } /** * Handle an HTTP POST. */ -const failable<int, std::string> post(request_rec* r, const lambda<value(const list<value>&)>& impl) { - const list<std::string> ls = httpd::read(r); +const failable<int> post(request_rec* r, const lambda<value(const list<value>&)>& impl) { + const list<string> ls = httpd::read(r); debug(r->uri, "modeval::post::url"); debug(ls, "modeval::post::input"); // Evaluate a JSON-RPC request and return a JSON result - const std::string ct = httpd::contentType(r); - if (ct.find("application/json-rpc") != std::string::npos || ct.find("text/plain") != std::string::npos) { + const string ct = httpd::contentType(r); + if (contains(ct, "application/json-rpc") || contains(ct, "text/plain")) { json::JSONContext cx; const list<value> json = elementsToValues(content(json::readJSON(ls, cx))); const list<list<value> > args = httpd::postArgs(json); // Extract the request id, method and params const value id = cadr(assoc(value("id"), args)); - const value func = std::string(cadr(assoc(value("method"), args))).c_str(); + const value func = c_str(cadr(assoc(value("method"), args))); const list<value> params = (list<value>)cadr(assoc(value("params"), args)); // Evaluate the request expression - const failable<value, std::string> val = failableResult(impl(cons<value>(func, params))); + const failable<value> val = failableResult(impl(cons<value>(func, params))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); // Return JSON result return httpd::writeResult(json::jsonResult(id, content(val), cx), "application/json-rpc", r); } // Evaluate an ATOM POST request and return the created resource location - if (ct.find("application/atom+xml") != std::string::npos) { + if (contains(ct, "application/atom+xml")) { // Evaluate the request expression const value entry = atom::entryValue(content(atom::readEntry(ls))); - const failable<value, std::string> val = failableResult(impl(cons<value>("post", mklist<value>(entry)))); + const failable<value> val = failableResult(impl(cons<value>("post", mklist<value>(entry)))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); // Return the created resource location apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, httpd::url(content(val), r))); @@ -180,17 +177,17 @@ const failable<int, std::string> post(request_rec* r, const lambda<value(const l /** * Handle an HTTP PUT. */ -const failable<int, std::string> put(request_rec* r, const lambda<value(const list<value>&)>& impl) { - const list<std::string> ls = httpd::read(r); +const failable<int> put(request_rec* r, const lambda<value(const list<value>&)>& impl) { + const list<string> ls = httpd::read(r); debug(r->uri, "modeval::put::url"); debug(ls, "modeval::put::input"); // Evaluate an ATOM PUT request - const list<value> path(httpd::path(r->uri)); + const list<value> path(httpd::pathValues(r->uri)); const value entry = atom::entryValue(content(atom::readEntry(ls))); - const failable<value, std::string> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry)))); + const failable<value> val = failableResult(impl(cons<value>("put", mklist<value>(caddr(path), entry)))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); if (val == value(false)) return HTTP_NOT_FOUND; return OK; @@ -199,14 +196,14 @@ const failable<int, std::string> put(request_rec* r, const lambda<value(const li /** * Handle an HTTP DELETE. */ -const failable<int, std::string> del(request_rec* r, const lambda<value(const list<value>&)>& impl) { +const failable<int> del(request_rec* r, const lambda<value(const list<value>&)>& impl) { debug(r->uri, "modeval::delete::url"); // Evaluate an ATOM delete request - const list<value> path(httpd::path(r->uri)); - const failable<value, std::string> val = failableResult(impl(cons<value>("delete", mklist<value>(caddr(path))))); + const list<value> path(httpd::pathValues(r->uri)); + const failable<value> val = failableResult(impl(cons<value>("delete", mklist<value>(caddr(path))))); if (!hasContent(val)) - return mkfailure<int, std::string>(reason(val)); + return mkfailure<int>(reason(val)); if (val == value(false)) return HTTP_NOT_FOUND; return OK; @@ -216,6 +213,7 @@ const failable<int, std::string> del(request_rec* r, const lambda<value(const li * Translate a component request. */ int translate(request_rec *r) { + gc_scoped_pool pool(r->pool); if (strncmp(r->uri, "/components/", 12) != 0) return DECLINED; r->handler = "mod_tuscany_eval"; @@ -226,6 +224,7 @@ int translate(request_rec *r) { * HTTP request handler. */ int handler(request_rec *r) { + gc_scoped_pool pool(r->pool); if(strcmp(r->handler, "mod_tuscany_eval")) return DECLINED; httpdDebugRequest(r, "modeval::handler::input"); @@ -237,7 +236,7 @@ int handler(request_rec *r) { // Get the component implementation lambda DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_eval); - const list<value> path(httpd::path(r->uri)); + const list<value> path(httpd::pathValues(r->uri)); const list<value> impl(assoctree<value>(cadr(path), dc.implementations)); if (isNil(impl)) return HTTP_NOT_FOUND; @@ -260,11 +259,11 @@ int handler(request_rec *r) { /** * Convert a list of component references to a list of HTTP proxy lambdas. */ -const value mkproxy(const value& ref, const std::string& base) { - return lambda<value(const list<value>&)>(http::proxy(base + std::string(scdl::name(ref)))); +const value mkproxy(const value& ref, const string& base) { + return lambda<value(const list<value>&)>(http::proxy(base + string(scdl::name(ref)))); } -const list<value> proxies(const list<value>& refs, const std::string& base) { +const list<value> proxies(const list<value>& refs, const string& base) { if (isNil(refs)) return refs; return cons(mkproxy(car(refs), base), proxies(cdr(refs), base)); @@ -274,31 +273,31 @@ const list<value> proxies(const list<value>& refs, const std::string& base) { * Return a configured component implementation. * For now only Scheme and C++ implementations are supported. */ -const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string& itype, const std::string& path, const list<value>& px) { - if (itype.find(".scheme") != std::string::npos) +const failable<lambda<value(const list<value>&)> > readImplementation(const string& itype, const string& path, const list<value>& px) { + if (contains(itype, ".scheme")) return scm::readImplementation(path, px); - if (itype.find(".cpp") != std::string::npos) + if (contains(itype, ".cpp")) return cpp::readImplementation(path, px); - return mkfailure<lambda<value(const list<value>&)>, std::string>("Unsupported implementation type: " + itype); + return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); } const value confImplementation(DirConf& dc, ServerConf& sc, server_rec& server, const value& comp) { const value impl = scdl::implementation(comp); - const std::string path = dc.contributionPath + std::string(scdl::uri(impl)); + const string path = dc.contributionPath + string(scdl::uri(impl)); // Convert component references to configured proxy lambdas - std::ostringstream base; + ostringstream base; if (sc.wiringServerName == "") base << (server.server_scheme == NULL? "http" : server.server_scheme) << "://" << (server.server_hostname == NULL? "localhost" : server.server_hostname) << ":" << (server.port == 0? 80 : server.port) - << "/references/" << std::string(scdl::name(comp)) << "/"; + << "/references/" << string(scdl::name(comp)) << "/"; else - base << sc.wiringServerName << "/references/" << std::string(scdl::name(comp)) << "/"; - const list<value> px(proxies(scdl::references(comp), base.str())); + base << sc.wiringServerName << "/references/" << string(scdl::name(comp)) << "/"; + const list<value> px(proxies(scdl::references(comp), str(base))); // Read and configure the implementation - const failable<lambda<value(const list<value>&)>, std::string> cimpl(readImplementation(elementName(impl), path, px)); + const failable<lambda<value(const list<value>&)> > cimpl(readImplementation(elementName(impl), path, px)); if (!hasContent(cimpl)) return reason(cimpl); return content(cimpl); @@ -320,10 +319,10 @@ const list<value> componentToImplementationTree(DirConf& dc, ServerConf& sc, ser /** * Read the components declared in a composite. */ -const failable<list<value>, std::string> readComponents(const std::string& path) { - std::ifstream is(path); - if (is.fail() || is.bad()) - return mkfailure<list<value>, std::string>("Could not read composite: " + path); +const failable<list<value> > readComponents(const string& path) { + ifstream is(path); + if (fail(is)) + return mkfailure<list<value> >(string("Could not read composite: ") + path); return scdl::components(readXML(streamList(is))); } @@ -333,7 +332,7 @@ const failable<list<value>, std::string> readComponents(const std::string& path) const bool confComponents(DirConf& dc, ServerConf& sc, server_rec& server) { if (dc.contributionPath == "" || dc.compositeName == "") return true; - const failable<list<value>, std::string> comps = readComponents(dc.contributionPath + dc.compositeName); + const failable<list<value> > comps = readComponents(dc.contributionPath + dc.compositeName); if (!hasContent(comps)) return true; dc.implementations = componentToImplementationTree(dc, sc, server, content(comps)); @@ -345,16 +344,19 @@ const bool confComponents(DirConf& dc, ServerConf& sc, server_rec& server) { * Configuration commands. */ const char *confHome(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.home = arg; return NULL; } const char *confWiringServerName(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); sc.wiringServerName = arg; return NULL; } const char *confContribution(cmd_parms *cmd, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); DirConf& dc = *(DirConf*)c; dc.contributionPath = arg; @@ -362,6 +364,7 @@ const char *confContribution(cmd_parms *cmd, void *c, const char *arg) { return NULL; } const char *confComposite(cmd_parms *cmd, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_eval); DirConf& dc = *(DirConf*)c; dc.compositeName = arg; @@ -384,10 +387,11 @@ int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t return OK; } -void childInit(unused apr_pool_t* p, server_rec* svr_rec) { +void childInit(apr_pool_t* p, server_rec* svr_rec) { + gc_scoped_pool pool(p); ServerConf* c = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_eval); if(c == NULL) { - std::cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << std::endl; + cerr << "[Tuscany] Due to one or more errors mod_tuscany_eval loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); } } diff --git a/sca-cpp/trunk/modules/server/mod-scm.hpp b/sca-cpp/trunk/modules/server/mod-scm.hpp index c454c6a216..887b1de968 100644 --- a/sca-cpp/trunk/modules/server/mod-scm.hpp +++ b/sca-cpp/trunk/modules/server/mod-scm.hpp @@ -27,10 +27,8 @@ * component implementations. */ -#include <string> -#include <iostream> -#include <fstream> - +#include "string.hpp" +#include "stream.hpp" #include "function.hpp" #include "list.hpp" #include "value.hpp" @@ -65,12 +63,12 @@ struct evalImplementation { const value operator()(const list<value>& params) const { const value expr = cons<value>(car(params), append(eval::quotedParameters(cdr(params)), px)); debug(expr, "modeval::scm::evalImplementation::input"); - gc_pool pool; + gc_pool pool(gc_current_pool()); eval::Env globalEnv = eval::setupEnvironment(pool); const value val = eval::evalScript(expr, impl, globalEnv, pool); debug(val, "modeval::scm::evalImplementation::result"); if (isNil(val)) - return mklist<value>(value(), std::string("Could not evaluate expression")); + return mklist<value>(value(), string("Could not evaluate expression")); return mklist<value>(val); } }; @@ -78,13 +76,13 @@ struct evalImplementation { /** * Read a script component implementation. */ -const failable<lambda<value(const list<value>&)>, std::string> readImplementation(const std::string path, const list<value>& px) { - std::ifstream is(path.c_str(), std::ios_base::in); - if (is.fail() || is.bad()) - return mkfailure<lambda<value(const list<value>&)>, std::string>("Could not read implementation: " + path); +const failable<lambda<value(const list<value>&)> > readImplementation(const string& path, const list<value>& px) { + ifstream is(path); + if (fail(is)) + return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + path); const value impl = eval::readScript(is); if (isNil(impl)) - return mkfailure<lambda<value(const list<value>&)>, std::string>("Could not read implementation: " + path); + return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + path); return lambda<value(const list<value>&)>(evalImplementation(impl, px)); } diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index 1bb5d1a687..6b4308edda 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -26,13 +26,9 @@ #include <sys/stat.h> -#include <string> -#include <iostream> -#include <sstream> -#include <fstream> - +#include "string.hpp" +#include "stream.hpp" #include "list.hpp" -#include "slist.hpp" #include "tree.hpp" #include "value.hpp" #include "debug.hpp" @@ -56,8 +52,8 @@ public: ServerConf(server_rec* s) : s(s), home(""), wiringServerName("") { } const server_rec* s; - std::string home; - std::string wiringServerName; + string home; + string wiringServerName; }; /** @@ -73,8 +69,8 @@ public: DirConf(char* dirspec) : dirspec(dirspec), contributionPath(""), compositeName("") { } const char* dirspec; - std::string contributionPath; - std::string compositeName; + string contributionPath; + string compositeName; list<value> references; list<value> services; }; @@ -82,8 +78,8 @@ public: /** * Returns true if a URI is absolute. */ -const bool isAbsolute(const std::string& uri) { - return uri.find("://") != std::string::npos; +const bool isAbsolute(const string& uri) { + return contains(uri, "://"); } /** @@ -96,7 +92,7 @@ int translateReference(request_rec *r) { // Find the requested component DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_wiring); - const list<value> rpath(httpd::path(r->uri)); + const list<value> rpath(httpd::pathValues(r->uri)); const list<value> comp(assoctree(cadr(rpath), dc.references)); if (isNil(comp)) return HTTP_NOT_FOUND; @@ -105,26 +101,26 @@ int translateReference(request_rec *r) { const list<value> ref(assoctree<value>(caddr(rpath), cadr(comp))); if (isNil(ref)) return HTTP_NOT_FOUND; - const std::string target(cadr(ref)); + const string target(cadr(ref)); debug(target, "modwiring::translateReference::target"); // Route to an absolute target URI using mod_proxy or an HTTP client redirect if (isAbsolute(target)) { if (useModProxy) { - r->filename = apr_pstrdup(r->pool, std::string("proxy:" + target).c_str()); + r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + target)); r->proxyreq = PROXYREQ_REVERSE; r->handler = "proxy-server"; return OK; } r->status = HTTP_MOVED_TEMPORARILY; - apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, target.c_str())); + apr_table_setn(r->headers_out, "Location", apr_pstrdup(r->pool, c_str(target))); r->handler = "mod_tuscany_wiring"; return OK; } // Route to a relative target URI using a local internal redirect - r->filename = apr_pstrdup(r->pool, std::string("/redirect:/components/" + target).c_str()); + r->filename = apr_pstrdup(r->pool, c_str(string("/redirect:/components/") + target)); r->handler = "mod_tuscany_wiring"; return OK; } @@ -161,7 +157,7 @@ int translateService(request_rec *r) { // Find the requested component DirConf& dc = httpd::dirConf<DirConf>(r, &mod_tuscany_wiring); - const list<value> path(httpd::path(r->uri)); + const list<value> path(httpd::pathValues(r->uri)); const list<value> svc(assocPath(path, dc.services)); if (isNil(svc)) return DECLINED; @@ -172,9 +168,11 @@ int translateService(request_rec *r) { debug(target, "modwiring::translateService::target"); // Dispatch to the target component using a local internal redirect - const std::string redir(std::string("/redirect:/components") + httpd::path(target)); + const string p(httpd::path(target)); + debug(p, "modwiring::translateService::path"); + const string redir(string("/redirect:/components") + httpd::path(target)); debug(redir, "modwiring::translateService::redirect"); - r->filename = apr_pstrdup(r->pool, redir.c_str()); + r->filename = apr_pstrdup(r->pool, c_str(redir)); r->handler = "mod_tuscany_wiring"; return OK; } @@ -184,6 +182,7 @@ int translateService(request_rec *r) { * to the target component. */ int translate(request_rec *r) { + gc_scoped_pool pool(r->pool); if (!strncmp(r->uri, "/components/", 12) != 0) return DECLINED; @@ -198,11 +197,11 @@ int translate(request_rec *r) { /** * Construct a redirect URI. */ -const std::string redirect(const std::string& file, const std::string& pi) { +const string redirect(const string& file, const string& pi) { return file + pi; } -const std::string redirect(const std::string& file, const std::string& pi, const std::string& args) { +const string redirect(const string& file, const string& pi, const string& args) { return file + pi + "?" + args; } @@ -210,6 +209,7 @@ const std::string redirect(const std::string& file, const std::string& pi, const * HTTP request handler, redirect to a target component. */ int handler(request_rec *r) { + gc_scoped_pool pool(r->pool); if(strcmp(r->handler, "mod_tuscany_wiring")) return DECLINED; httpdDebugRequest(r, "modwiring::handler::input"); @@ -222,20 +222,20 @@ int handler(request_rec *r) { debug(r->path_info, "modwiring::handler::path info"); if (r->args == NULL) { - ap_internal_redirect(apr_pstrdup(r->pool, redirect(r->filename + 10, r->path_info).c_str()), r); + ap_internal_redirect(apr_pstrdup(r->pool, c_str(redirect(string(r->filename + 10), string(r->path_info)))), r); return OK; } - ap_internal_redirect(apr_pstrdup(r->pool, redirect(r->filename + 10, r->path_info, r->args).c_str()), r); + ap_internal_redirect(apr_pstrdup(r->pool, c_str(redirect(string(r->filename + 10), string(r->path_info), string(r->args)))), r); return OK; } /** * Read the components declared in a composite. */ -const failable<list<value>, std::string> readComponents(const std::string& path) { - std::ifstream is(path); - if (is.fail() || is.bad()) - return mkfailure<list<value>, std::string>("Could not read composite: " + path); +const failable<list<value> > readComponents(const string& path) { + ifstream is(path); + if (fail(is)) + return mkfailure<list<value> >(string("Could not read composite: ") + path); return scdl::components(readXML(streamList(is))); } @@ -261,23 +261,23 @@ const list<value> componentReferenceToTargetTree(const list<value>& c) { * Return a tree of service-URI-path + component-name pairs. Service-URI-paths are * represented as lists of URI path fragments. */ -const list<value> defaultBindingURI(const std::string& cn, const std::string& sn) { +const list<value> defaultBindingURI(const string& cn, const string& sn) { return mklist<value>(cn, sn); } -const list<value> bindingToComponentAssoc(const std::string& cn, const std::string& sn, const list<value>& b) { +const list<value> bindingToComponentAssoc(const string& cn, const string& sn, const list<value>& b) { if (isNil(b)) return b; const value uri(scdl::uri(car(b))); if (isNil(uri)) return cons<value>(mklist<value>(defaultBindingURI(cn, sn), cn), bindingToComponentAssoc(cn, sn, cdr(b))); - return cons<value>(mklist<value>(httpd::path(std::string(uri).c_str()), cn), bindingToComponentAssoc(cn, sn, cdr(b))); + return cons<value>(mklist<value>(httpd::pathValues(c_str(string(uri))), cn), bindingToComponentAssoc(cn, sn, cdr(b))); } -const list<value> serviceToComponentAssoc(const std::string& cn, const list<value>& s) { +const list<value> serviceToComponentAssoc(const string& cn, const list<value>& s) { if (isNil(s)) return s; - const std::string sn(scdl::name(car(s))); + const string sn(scdl::name(car(s))); const list<value> btoc(bindingToComponentAssoc(cn, sn, scdl::bindings(car(s)))); if (isNil(btoc)) return cons<value>(mklist<value>(defaultBindingURI(cn, sn), cn), serviceToComponentAssoc(cn, cdr(s))); @@ -300,7 +300,7 @@ const list<value> uriToComponentTree(const list<value>& c) { const bool confComponents(DirConf& dc) { if (dc.contributionPath == "" || dc.compositeName == "") return true; - const failable<list<value>, std::string> comps = readComponents(dc.contributionPath + dc.compositeName); + const failable<list<value> > comps = readComponents(dc.contributionPath + dc.compositeName); if (!hasContent(comps)) return true; dc.references = componentReferenceToTargetTree(content(comps)); @@ -314,22 +314,26 @@ const bool confComponents(DirConf& dc) { * Configuration commands. */ const char *confHome(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring); sc.home = arg; return NULL; } const char *confWiringServerName(cmd_parms *cmd, unused void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); ServerConf& sc = httpd::serverConf<ServerConf>(cmd, &mod_tuscany_wiring); sc.wiringServerName = arg; return NULL; } -const char *confContribution(unused cmd_parms *cmd, void *c, const char *arg) { +const char *confContribution(cmd_parms *cmd, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); DirConf& dc = *(DirConf*)c; dc.contributionPath = arg; confComponents(dc); return NULL; } -const char *confComposite(unused cmd_parms *cmd, void *c, const char *arg) { +const char *confComposite(cmd_parms *cmd, void *c, const char *arg) { + gc_scoped_pool pool(cmd->pool); DirConf& dc = *(DirConf*)c; dc.compositeName = arg; confComponents(dc); @@ -351,10 +355,11 @@ int postConfig(unused apr_pool_t *p, unused apr_pool_t *plog, unused apr_pool_t return OK; } -void childInit(unused apr_pool_t* p, server_rec* svr_rec) { +void childInit(apr_pool_t* p, server_rec* svr_rec) { + gc_scoped_pool pool(p); ServerConf *conf = (ServerConf*)ap_get_module_config(svr_rec->module_config, &mod_tuscany_wiring); if(conf == NULL) { - std::cerr << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << std::endl; + cerr << "[Tuscany] Due to one or more errors mod_tuscany_wiring loading failed. Causing apache to stop loading." << endl; exit(APEXIT_CHILDFATAL); } } diff --git a/sca-cpp/trunk/test/store-script/store-script-test.cpp b/sca-cpp/trunk/test/store-script/store-script-test.cpp index add5cb75e5..a85b661b43 100644 --- a/sca-cpp/trunk/test/store-script/store-script-test.cpp +++ b/sca-cpp/trunk/test/store-script/store-script-test.cpp @@ -25,12 +25,10 @@ #include <assert.h> #include <regex.h> -#include <iostream> -#include <fstream> -#include <string> +#include "stream.hpp" +#include "string.hpp" #include "list.hpp" #include "driver.hpp" -#include "slist.hpp" #include "xml.hpp" #include "../json/json.hpp" @@ -38,51 +36,47 @@ namespace store { using namespace tuscany; -bool contains(const std::string& str, const std::string& pattern) { - return str.find(pattern) != std::string::npos; -} - bool testScript() { - std::ifstream is("store-script.scm", std::ios_base::in); - std::ostringstream os; - eval::evalDriverRun(is, os); - - assert(contains(os.str(), "(\"Sample Feed\" \"")); - assert(contains(os.str(), "\" (\"Item\" \"")); - assert(contains(os.str(), "\" ((javaClass \"services.Item\") (name \"Orange\") (currencyCode \"USD\") (currencySymbol \"$\") (price 3.55))) (\"Item\" \"")); - assert(contains(os.str(), "\" ((javaClass \"services.Item\") (name \"Apple\") (currencyCode \"USD\") (currencySymbol \"$\") (price 2.99))))")); + gc_scoped_pool pool; + + ifstream is("store-script.scm"); + ostringstream os; + eval::evalDriverRun(is, os, pool); + assert(contains(str(os), "(\"Sample Feed\" \"")); + assert(contains(str(os), "\" (\"Item\" \"")); + assert(contains(str(os), "\" ((javaClass \"services.Item\") (name \"Orange\") (currencyCode \"USD\") (currencySymbol \"$\") (price 3.55))) (\"Item\" \"")); + assert(contains(str(os), "\" ((javaClass \"services.Item\") (name \"Apple\") (currencyCode \"USD\") (currencySymbol \"$\") (price 2.99))))")); return true; } bool testEval() { { - std::ifstream is("store-script.scm", std::ios_base::in); - std::ostringstream os; + gc_scoped_pool pool; + ifstream is("store-script.scm"); + ostringstream os; eval::setupDisplay(os); - - gc_pool pool; eval::Env globalEnv = eval::setupEnvironment(pool); - const value exp(mklist<value>("storeui_service", std::string("getcatalog"))); + const value exp(mklist<value>("storeui_service", string("getcatalog"))); const value val = eval::evalScript(exp, is, globalEnv, pool); - std::ostringstream vs; + ostringstream vs; vs << val; - assert(contains(vs.str(), "(((javaClass \"services.Item\") (name \"Apple\") (currencyCode \"USD\") (currencySymbol \"$\") (price 2.99)) ((javaClass \"services.Item\") (name \"Orange\") (currencyCode \"USD\") (currencySymbol \"$\") (price 3.55)) ((javaClass \"services.Item\") (name \"Pear\") (currencyCode \"USD\") (currencySymbol \"$\") (price 1.55)))")); + assert(contains(str(vs), "(((javaClass \"services.Item\") (name \"Apple\") (currencyCode \"USD\") (currencySymbol \"$\") (price 2.99)) ((javaClass \"services.Item\") (name \"Orange\") (currencyCode \"USD\") (currencySymbol \"$\") (price 3.55)) ((javaClass \"services.Item\") (name \"Pear\") (currencyCode \"USD\") (currencySymbol \"$\") (price 1.55)))")); } { - std::ifstream is("store-script.scm", std::ios_base::in); - std::ostringstream os; + gc_scoped_pool pool; + ifstream is("store-script.scm"); + ostringstream os; eval::setupDisplay(os); - gc_pool pool; eval::Env globalEnv = eval::setupEnvironment(pool); - const value exp(mklist<value>("storeui_service", std::string("gettotal"))); + const value exp(mklist<value>("storeui_service", string("gettotal"))); const value res = eval::evalScript(exp, is, globalEnv, pool); - std::ostringstream rs; + ostringstream rs; rs << res; - assert(contains(rs.str(), "10")); + assert(contains(str(rs), "10")); } return true; } @@ -91,12 +85,12 @@ bool testEval() { int main() { - std::cout << "Testing..." << std::endl; + tuscany::cout << "Testing..." << tuscany::endl; store::testScript(); store::testEval(); - std::cout << "OK" << std::endl; + tuscany::cout << "OK" << tuscany::endl; return 0; } |