diff options
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; } |