Port kernel to C++11 and refactor some of the core modules. Convert functors to lambdas, and add C++ const, noexcept and inline annotations to get more efficient generated code.

git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1419985 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
jsdelfino 2012-12-11 03:51:03 +00:00
commit ae0b7c0063
55 changed files with 2977 additions and 2270 deletions

View file

@ -61,8 +61,8 @@ cache-manifest.cmf
*-min.html
*-min.js
*-min.css
*.b64
intro*.png
intro*.b64
depcomp
install-sh
ltmain.sh
@ -138,8 +138,8 @@ js-shell
file-test
test-start*
test-stop*
xml-value
value-xml
xml-element
element-xml
json-value
value-json
element-value

25
sca-cpp/trunk/etc/callgrind Executable file
View file

@ -0,0 +1,25 @@
#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# Run valgrind to record call history, generate a call graph and help analyze
# cache and branch prediction
here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
valgrind --tool=callgrind $* 2>&1 | tee callgrind.log

View file

@ -20,5 +20,5 @@
# Run valgrind to analyze memory usage and track memory leaks
here=`echo "import os; print os.path.realpath('$0')" | python`; here=`dirname $here`
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=50 --track-fds=yes --trace-children=yes --suppressions=$here/../../Python-2.6.6/Misc/valgrind-python.supp --suppressions=$here/valgrind-apr.supp $* 2>&1 | tee memgrind.log
valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=50 --track-fds=yes --trace-children=yes --suppressions=$here/../../Python-2.7.3/Misc/valgrind-python.supp --suppressions=$here/valgrind-apr.supp $* 2>&1 | tee memgrind.log

View file

@ -37,14 +37,8 @@ mem_test_SOURCES = mem-test.cpp
parallel_test_SOURCES = parallel-test.cpp
xml_test_SOURCES = xml-test.cpp
xml_test_LDFLAGS = -lxml2
xsd_test_SOURCES = xsd-test.cpp
xsd_test_LDFLAGS = -lxml2
hash_test_SOURCES = hash-test.cpp
noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test xsd-test
TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test xml-test
noinst_PROGRAMS = string-test kernel-test lambda-test hash-test mem-test parallel-test
TESTS = string-test kernel-test lambda-test hash-test mem-test parallel-test

View file

@ -93,12 +93,12 @@ namespace tuscany
#ifdef WANT_MAINTAINER_COUNTERS
bool debug_inc(long int& c) {
const bool debug_inc(long int& c) {
c++;
return true;
}
bool debug_dec(long int& c) {
const bool debug_dec(long int& c) {
c--;
return true;
}

View file

@ -28,7 +28,7 @@
namespace tuscany {
namespace test {
const int cppsquare(int x) {
const int cppsquare(const int x) {
return x * x;
}
@ -41,8 +41,8 @@ extern "C" {
return tuscany::test::cppsquare(x);
}
const tuscany::lambda<int(const int)> csquarel() {
return tuscany::lambda<int(const int)>(tuscany::test::cppsquare);
const tuscany::lambda<const int(const int)> csquarel() {
return tuscany::lambda<const int(const int)>(tuscany::test::cppsquare);
}
}

View file

@ -48,27 +48,18 @@ const string dynlibExt(".so");
*/
class lib {
public:
lib() : h(NULL), owner(false) {
inline lib() : h(NULL), owner(false) {
}
lib(const string& name) : name(name), h(dlopen(c_str(name), RTLD_NOW)), owner(true) {
if (h == NULL)
h = mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror());
inline lib(const string& name) : name(name), h(open(name)), owner(true) {
}
lib(const lib& l) : name(l.name), h(l.h), owner(false) {
inline lib(const lib& l) : name(l.name), h(l.h), owner(false) {
}
const lib& operator=(const lib& l) {
if(this == &l)
return *this;
name = l.name;
h = l.h;
owner = false;
return *this;
}
lib& operator=(const lib& l) = delete;
~lib() {
inline ~lib() {
if (!owner)
return;
if (!hasContent(h) || content(h) == NULL)
@ -77,17 +68,22 @@ public:
}
private:
const failable<void*> open(const string& name) {
void * h = dlopen(c_str(name), RTLD_NOW);
return h != NULL? failable<void*>(h) : mkfailure<void*>(string("Could not load library: ") + name + ": " + dlerror());
}
template<typename S> friend const failable<lambda<S> > dynlambda(const string& name, const lib& l);
string name;
failable<void*> h;
bool owner;
const string name;
const failable<void*> h;
const bool owner;
};
/**
* Find a lambda function in a dynamic library.
*/
template<typename S> const failable<lambda<S> > dynlambda(const string& name, const lib& l) {
template<typename S> inline const failable<lambda<S> > dynlambda(const string& name, const lib& l) {
if (!hasContent(l.h))
return mkfailure<lambda<S>>(l.h);
const void* s = dlsym(content(l.h), c_str(name));

View file

@ -42,7 +42,7 @@ const string atsign("@");
/**
* Returns true if a value is an element.
*/
bool isElement(const value& v) {
inline const bool isElement(const value& v) {
if (!isList(v) || isNil(v) || element != car<value>(v))
return false;
return true;
@ -51,7 +51,7 @@ bool isElement(const value& v) {
/**
* Returns true if a value is an attribute.
*/
bool isAttribute(const value& v) {
inline const bool isAttribute(const value& v) {
if (!isList(v) || isNil(v) || attribute != car<value>(v))
return false;
return true;
@ -60,42 +60,42 @@ bool isAttribute(const value& v) {
/**
* Returns the name of an attribute.
*/
const value attributeName(const list<value>& l) {
inline const value attributeName(const list<value>& l) {
return cadr(l);
}
/**
* Returns the value of an attribute.
*/
const value attributeValue(const list<value>& l) {
inline const value attributeValue(const list<value>& l) {
return caddr(l);
}
/**
* Returns the name of an element.
*/
const value elementName(const list<value>& l) {
inline const value elementName(const list<value>& l) {
return cadr(l);
}
/**
* Returns true if an element has children.
*/
const bool elementHasChildren(const list<value>& l) {
inline const bool elementHasChildren(const list<value>& l) {
return !isNil(cddr(l));
}
/**
* Returns the children of an element.
*/
const list<value> elementChildren(const list<value>& l) {
inline const list<value> elementChildren(const list<value>& l) {
return cddr(l);
}
/**
* Returns true if an element has a value.
*/
const bool elementHasValue(const list<value>& l) {
inline const bool elementHasValue(const list<value>& l) {
const list<value> r = reverse(l);
if (isSymbol(car(r)))
return false;
@ -107,26 +107,26 @@ const bool elementHasValue(const list<value>& l) {
/**
* Returns the value of an element.
*/
const value elementValue(const list<value>& l) {
inline const value elementValue(const list<value>& l) {
return car(reverse(l));
}
/**
* Convert an element to a value.
*/
const bool elementToValueIsList(const value& v) {
inline const bool elementToValueIsList(const value& v) {
if (!isList(v))
return false;
const list<value> l = v;
return (isNil(l) || !isSymbol(car(l)));
}
const value elementToValue(const value& t) {
inline const value elementToValue(const value& t) {
const list<value> elementsToValues(const list<value>& e);
// Convert an attribute
if (isTaggedList(t, attribute))
return mklist<value>(c_str(atsign + attributeName(t)), attributeValue(t));
return mklist<value>(c_str(atsign + (string)attributeName(t)), attributeValue(t));
// Convert an element
if (isTaggedList(t, element)) {
@ -155,7 +155,7 @@ const value elementToValue(const value& t) {
/**
* Convert a list of elements to a list of values.
*/
const bool elementToValueIsSymbol(const value& v) {
inline const bool elementToValueIsSymbol(const value& v) {
if (!isList(v))
return false;
const list<value> l = v;
@ -166,7 +166,7 @@ const bool elementToValueIsSymbol(const value& v) {
return true;
}
const list<value> elementToValueGroupValues(const value& v, const list<value>& l) {
inline const list<value> elementToValueGroupValues(const value& v, const list<value>& l) {
if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l)))
return cons(v, l);
if (car<value>(car(l)) != car<value>(v))
@ -180,7 +180,7 @@ const list<value> elementToValueGroupValues(const value& v, const list<value>& l
}
const list<value> elementsToValues(const list<value>& e) {
inline const list<value> elementsToValues(const list<value>& e) {
if (isNil(e))
return e;
return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e)));
@ -189,13 +189,13 @@ const list<value> elementsToValues(const list<value>& e) {
/**
* Convert a value to an element.
*/
const value valueToElement(const value& t) {
inline const value valueToElement(const value& t) {
const list<value> valuesToElements(const list<value>& l);
// Convert a name value pair
if (isList(t) && !isNil((list<value>)t) && isSymbol(car<value>(t))) {
const value n = car<value>(t);
const value v = isNil(cdr<value>(t))? value() : cadr<value>(t);
const value v = isNil(cdr<value>(t))? nilValue : cadr<value>(t);
// Convert a single value to an attribute or an element
if (!isList(v)) {
@ -221,7 +221,7 @@ const value valueToElement(const value& t) {
/**
* Convert a list of values to a list of elements.
*/
const list<value> valuesToElements(const list<value>& l) {
inline const list<value> valuesToElements(const list<value>& l) {
if (isNil(l))
return l;
return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l)));
@ -231,72 +231,51 @@ const list<value> valuesToElements(const list<value>& l) {
* Returns a selector lambda function which can be used to filter
* elements against the given element pattern.
*/
struct selectorLambda {
const list<value> select;
selectorLambda(const list<value>& s) : select(s) {
}
const bool evalSelect(const list<value>& s, const list<value> v) const {
if (isNil(s))
return true;
if (isNil(v))
return false;
if (car(s) != car(v))
return false;
return evalSelect(cdr(s), cdr(v));
}
const bool operator()(const value& v) const {
inline const lambda<const bool(const value&)> selector(const list<value>& select) {
return [select](const value& v) -> const bool {
const lambda<const bool(const list<value>&, const list<value>&)> evalSelect = [&evalSelect](const list<value>& s, const list<value>& v) -> const bool {
if (isNil(s))
return true;
if (isNil(v))
return false;
if (car(s) != car(v))
return false;
return evalSelect(cdr(s), cdr(v));
};
if (!isList(v))
return false;
return evalSelect(select, v);
}
};
const lambda<bool(const value&)> selector(const list<value> s) {
return selectorLambda(s);
};
}
/**
* Returns the value of the attribute with the given name.
*/
struct filterAttribute {
const value name;
filterAttribute(const value& n) : name(n) {
}
const bool operator()(const value& v) const {
return isAttribute(v) && attributeName((list<value>)v) == name;
}
};
const value attributeValue(const value& name, const value& l) {
const list<value> f = filter<value>(filterAttribute(name), list<value>(l));
inline const value attributeValue(const value& name, const value& l) {
const list<value> f = filter<value>([name](const value& v) {
return isAttribute(v) && attributeName((list<value>)v) == name;
}, list<value>(l));
if (isNil(f))
return value();
return nilValue;
return caddr<value>(car(f));
}
/**
* Returns child elements with the given name.
*/
struct filterElement {
const value name;
filterElement(const value& n) : name(n) {
}
const bool operator()(const value& v) const {
return isElement(v) && elementName((list<value>)v) == name;
}
};
const value elementChildren(const value& name, const value& l) {
return filter<value>(filterElement(name), list<value>(l));
inline const value elementChildren(const value& name, const value& l) {
return filter<value>([name](const value& v) {
return isElement(v) && elementName((list<value>)v) == name;
}, list<value>(l));
}
/**
* Return the child element with the given name.
*/
const value elementChild(const value& name, const value& l) {
inline const value elementChild(const value& name, const value& l) {
const list<value> f = elementChildren(name, l);
if (isNil(f))
return value();
return nilValue;
return car(f);
}

View file

@ -69,24 +69,18 @@ namespace tuscany {
*/
class ofstream : public ostream {
public:
ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) {
inline ofstream(const string& path) : file(fopen(c_str(path), "wb")), owner(true) {
}
ofstream(FILE* file) : file(file), owner(false) {
inline ofstream(FILE* const file) : file(file), owner(false) {
}
ofstream(const ofstream& os) : file(os.file), owner(false) {
inline ofstream(const ofstream& os) : file(os.file), owner(false) {
}
const ofstream& operator=(const ofstream& os) {
if(this == &os)
return *this;
file = os.file;
owner = false;
return *this;
}
ofstream& operator=(const ofstream& os) = delete;
~ofstream() {
inline ~ofstream() {
if (!owner)
return;
if (file == NULL)
@ -94,11 +88,11 @@ public:
fclose(file);
}
const bool fail() {
inline const bool fail() {
return file == NULL;
}
ofstream& vprintf(const char* fmt, ...) {
inline ofstream& vprintf(const char* const fmt, ...) {
va_list args;
va_start (args, fmt);
vfprintf (file, fmt, args);
@ -106,19 +100,24 @@ public:
return *this;
}
ofstream& write(const string& s) {
inline ofstream& write(const string& s) {
fwrite(c_str(s), 1, length(s), file);
return *this;
}
ofstream& flush() {
inline ofstream& write(const char c) {
fwrite(&c, 1, 1, file);
return *this;
}
inline ofstream& flush() {
fflush(file);
return *this;
}
private:
FILE* file;
bool owner;
FILE* const file;
const bool owner;
};
/*
@ -126,24 +125,18 @@ private:
*/
class ifstream : public istream {
public:
ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) {
inline ifstream(const string& path) : file(fopen(c_str(path), "rb")), owner(true) {
}
ifstream(FILE* file) : file(file), owner(false) {
inline ifstream(FILE* const file) : file(file), owner(false) {
}
ifstream(const ifstream& is) : file(is.file), owner(false) {
inline ifstream(const ifstream& is) : file(is.file), owner(false) {
}
const ifstream& operator=(const ifstream& is) {
if(this == &is)
return *this;
file = is.file;
owner = false;
return *this;
}
ifstream& operator=(const ifstream& is) = delete;
~ifstream() {
inline ~ifstream() {
if (!owner)
return;
if (file == NULL)
@ -151,23 +144,23 @@ public:
fclose(file);
}
const size_t read(void* buf, size_t size) {
inline const size_t read(void* const buf, const size_t size) {
return fread(buf, 1, size, file);
}
const bool eof() {
inline const bool eof() {
return feof(file);
}
const bool fail() {
inline const bool fail() {
return file == NULL;
}
const int get() {
inline const int get() {
return fgetc(file);
}
const int peek() {
inline const int peek() {
int c = fgetc(file);
if (c == -1)
return c;
@ -176,8 +169,8 @@ public:
}
private:
FILE* file;
bool owner;
FILE* const file;
const bool owner;
};
/**
@ -198,24 +191,24 @@ ifstream cin(stdin);
*/
class loghstream : public ostream {
public:
loghstream(const int level) : level(level), len(0) {
inline loghstream(const int level) : level(level), len(0) {
}
~loghstream() {
inline ~loghstream() {
}
ostream& vprintf(const char* fmt, ...) {
inline ostream& vprintf(const char* const fmt, ...) {
va_list args;
va_start (args, fmt);
va_start(args, fmt);
const int l = vsnprintf(buf + len, (sizeof(buf) - 1) - len, fmt, args);
va_end (args);
va_end(args);
len += l;
if (len > (int)(sizeof(buf) - 1))
len = sizeof(buf) - 1;
return *this;
}
ostream& write(const string& s) {
inline ostream& write(const string& s) {
if (s != "\n")
return this->vprintf("%s", c_str(s));
buf[len] = '\0';
@ -224,14 +217,23 @@ public:
return *this;
}
ostream& flush() {
inline ostream& write(const char c) {
if (c != '\n')
return this->vprintf("%c", c);
buf[len] = '\0';
ap_log_error(NULL, 0, -1, level, 0, ap_server_conf, "%s", buf);
len = 0;
return *this;
}
inline ostream& flush() {
return *this;
}
private:
const int level;
int len;
char buf[2049];
char buf[513];
};
/**
@ -259,11 +261,11 @@ loghstream cdebug(APLOG_DEBUG);
/**
* Format the current time.
*/
const string logTime() {
inline const string logTime() {
struct timeval tv;
gettimeofday(&tv, NULL);
const time_t t = tv.tv_sec;
const tm* lt = localtime(&t);
const tm* const lt = localtime(&t);
char ft[32];
strftime(ft, 20, "%a %b %d %H:%M:%S", lt);
sprintf(ft + 19, ".%06lu ", (unsigned long)tv.tv_usec);
@ -276,16 +278,16 @@ const string logTime() {
*/
class logfstream : public ostream {
public:
logfstream(FILE* file, const string& type) : file(file), type(type), head(false) {
inline logfstream(FILE* const file, const string& type) : file(file), type(type), head(false) {
}
logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) {
inline logfstream(const logfstream& os) : file(os.file), type(os.type), head(os.head) {
}
~logfstream() {
inline ~logfstream() {
}
ostream& vprintf(const char* fmt, ...) {
inline ostream& vprintf(const char* const fmt, ...) {
whead();
va_list args;
va_start (args, fmt);
@ -294,7 +296,7 @@ public:
return *this;
}
ostream& write(const string& s) {
inline ostream& write(const string& s) {
whead();
fwrite(c_str(s), 1, length(s), file);
if (s == "\n")
@ -302,17 +304,25 @@ public:
return *this;
}
ostream& flush() {
inline ostream& write(const char c) {
whead();
fwrite(&c, 1, 1, file);
if (c == '\n')
head = false;
return *this;
}
inline ostream& flush() {
fflush(file);
return *this;
}
private:
FILE* file;
FILE* const file;
const string type;
bool head;
const unsigned long tid() const {
inline const unsigned long tid() const {
#ifdef WANT_THREADS
return (unsigned long)pthread_self();
#else
@ -320,7 +330,7 @@ private:
#endif
}
ostream& whead() {
inline ostream& whead() {
if (head)
return *this;
head = true;
@ -348,7 +358,7 @@ logfstream cdebug(stderr, "debug");
bool debug_isLoggingSet = false;
bool debug_isLoggingEnv = false;
const bool debug_isLogging() {
inline const bool debug_isLogging() {
if (debug_isLoggingSet)
return debug_isLoggingEnv;
debug_isLoggingEnv = getenv("TUSCANY_DEBUG_LOG") != NULL;
@ -366,8 +376,8 @@ const bool debug_isLogging() {
/**
* Log a debug message.
*/
const bool debugLog(const string& msg) {
gc_scoped_pool p;
inline const bool debugLog(const string& msg) {
const gc_scoped_pool p;
cdebug << msg << endl;
return true;
}
@ -375,8 +385,8 @@ const bool debugLog(const string& msg) {
/**
* Log a debug message and a value.
*/
template<typename V> const bool debugLog(const V& v, const string& msg) {
gc_scoped_pool p;
template<typename V> inline const bool debugLog(const V& v, const string& msg) {
const gc_scoped_pool p;
cdebug << msg << ": " << v << endl;
return true;
}
@ -384,8 +394,8 @@ template<typename V> const bool debugLog(const V& v, const string& msg) {
/**
* Log a debug message and two values.
*/
template<typename V, typename W> const bool debugLog(const V& v, const W& w, const string& msg) {
gc_scoped_pool p;
template<typename V, typename W> inline const bool debugLog(const V& v, const W& w, const string& msg) {
const gc_scoped_pool p;
cdebug << msg << ": " << v << " : " << w << endl;
return true;
}

View file

@ -23,7 +23,9 @@
#define tuscany_function_hpp
/**
* Lambda function type.
* Lambda function type that enforces pass by ref and constant parameters,
* allocates memory only as needed and using an APR memory pool, is about
* 2 times faster than std::function and between 1/4 and 1/6 of its size.
*/
#include <utility>
@ -46,16 +48,16 @@ long int countELambdas = 0;
long int countCLambdas = 0;
long int countFLambdas = 0;
bool resetLambdaCounters() {
inline const bool resetLambdaCounters() {
countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0;
return true;
}
bool checkLambdaCounters() {
inline const bool checkLambdaCounters() {
return countLambdas == 0;
}
bool printLambdaCounters() {
inline const bool printLambdaCounters() {
cout << "countLambdas " << countLambdas << endl;
cout << "countELambdas " << countELambdas << endl;
cout << "countFLambdas " << countFLambdas << endl;
@ -80,38 +82,32 @@ bool printLambdaCounters() {
template<typename R, typename... P> class Callable {
public:
Callable() {
inline Callable() noexcept {
}
virtual const size_t size() const = 0;
virtual const R operator()(const P&&... p) const noexcept = 0;
virtual const R operator()(P... p) const = 0;
virtual ~Callable() {
inline virtual ~Callable() noexcept {
}
template<typename F> class Proxy: public Callable {
template<typename F> class Proxy: public Callable<R, P...> {
public:
Proxy(const F& f) : function(f) {
inline Proxy(const F& f) noexcept : function(f) {
debug_inc(countProxies);
debug_inc(countFProxies);
}
Proxy(const Proxy& p) : function(p.function) {
inline Proxy(const Proxy& p) noexcept : function(p.function) {
debug_inc(countProxies);
debug_inc(countCProxies);
}
~Proxy() {
inline ~Proxy() noexcept {
debug_dec(countProxies);
}
virtual const R operator() (P... p) const {
return function(std::forward<P>(p)...);
}
virtual const size_t size() const {
return sizeof(function);
virtual const R operator() (const P&&... p) const noexcept {
return function(std::forward<const P&&>(p)...);
}
private:
@ -123,67 +119,68 @@ template<typename S> class lambda;
template<typename R, typename... P> class lambda<R(P...)> {
public:
lambda() : callable(0) {
inline lambda() noexcept : callable(NULL) {
debug_inc(countLambdas);
debug_inc(countELambdas);
}
template<typename F> lambda(const F f) {
template<typename F> inline lambda(const F f) noexcept : callable(mkproxy<F>(f)) {
debug_inc(countLambdas);
debug_inc(countFLambdas);
typedef typename CallableType::template Proxy<F> ProxyType;
callable = gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
}
lambda(const lambda& l) {
template<typename F> inline lambda(const gc_mutable_ref<F>& r) noexcept : callable(mkproxy<F>(*(F*)r)) {
debug_inc(countLambdas);
debug_inc(countFLambdas);
}
inline lambda(const lambda& l) noexcept : callable(l.callable) {
debug_inc(countLambdas);
debug_inc(countCLambdas);
callable = l.callable;
}
const lambda& operator=(const lambda& l) {
if (this == &l)
return *this;
callable = l.callable;
return *this;
}
lambda& operator=(const lambda& l) = delete;
~lambda() {
inline ~lambda() noexcept {
debug_dec(countLambdas);
}
const bool operator==(const lambda& l) const {
inline const bool operator==(const lambda& l) const noexcept {
if (this == &l)
return true;
return callable == l.callable;
return false;
}
const bool operator!=(const lambda& l) const {
inline const bool operator!=(const lambda& l) const noexcept {
return !this->operator==(l);
}
const R operator()(P... p) const {
return (*callable)(std::forward<P>(p)...);
inline const R operator()(const P&... p) const noexcept {
return (*callable)(std::forward<const P&&>(p)...);
}
template<typename S> friend ostream& operator<<(ostream&, const lambda<S>&);
template<typename S> friend const bool isNil(const lambda<S>& l);
template<typename S> friend const bool isNil(const lambda<S>& l) noexcept;
private:
typedef Callable<R,P...> CallableType;
gc_ptr<CallableType> callable;
const gc_ptr<CallableType> callable;
template<typename F> inline gc_ptr<CallableType> mkproxy(const F& f) noexcept {
typedef typename CallableType::template Proxy<F> ProxyType;
return gc_ptr<CallableType>(new (gc_new<ProxyType>()) ProxyType(f));
}
};
template<typename S> ostream& operator<<(ostream& out, const lambda<S>& l) {
template<typename S> inline ostream& operator<<(ostream& out, const lambda<S>& l) {
return out << "lambda::" << l.callable;
}
/**
* Return true if a lambda is nil.
*/
template<typename S> const bool isNil(const lambda<S>& l) {
return ((void*)l.callable) == 0;
template<typename S> inline const bool isNil(const lambda<S>& l) noexcept {
return (const void*)l.callable == NULL;
}
/**
@ -191,11 +188,11 @@ template<typename S> const bool isNil(const lambda<S>& l) {
*/
template<typename R, typename T, typename... P> class curried {
public:
curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) {
inline curried(const lambda<R(T, P...)>& f, const T& v) noexcept: v(v), f(f) {
}
const R operator()(P... p) const {
return f(v, std::forward<P>(p)...);
inline const R operator()(const P&... p) const noexcept {
return f(v, std::forward<const P&>(p)...);
}
private:
@ -203,36 +200,29 @@ private:
const lambda<R(T, P...)>f;
};
template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) {
template<typename R, typename T, typename... P> inline const lambda<const R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) noexcept {
return curried<R, T, P...>(f, t);
}
template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) {
template<typename R, typename T, typename U, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) noexcept {
return curry(curry(f, t), u);
}
template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) {
template<typename R, typename T, typename U, typename V, typename... P> inline const lambda<R(P...)> curry(const lambda<R(T, U, V, P...)>& f, const T& t, const U& u, const V& v) noexcept {
return curry(curry(curry(f, t), u), v);
}
/**
* A lambda function that returns the given value.
*/
template<typename T> class returnResult {
public:
returnResult(const T& v) :
v(v) {
}
const T operator()() const {
return v;
}
private:
const T v;
};
template<typename T> const lambda<T()> result(const T& v) {
return returnResult<T> (v);
template<typename T> inline const lambda<const T()> result(const T& v) {
return [v]()->T { return v; };
}
/**
* Commonly used lambda types.
*/
typedef lambda<const bool()> blambda;
}
#endif /* tuscany_function_hpp */

View file

@ -49,7 +49,7 @@ namespace tuscany
/**
* Force a core dump on assertion violation.
*/
bool assertOrFail(const bool expr) {
inline const bool assertOrFail(const bool expr) {
if (!expr)
abort();
return true;
@ -64,63 +64,135 @@ bool assertOrFail(const bool expr) {
/**
* Pointer to a value.
*/
#ifdef WANT_RAW_PTR
template<typename T> using gc_ptr = T*;
#else
template<typename T> class gc_ptr {
public:
gc_ptr(T* ptr = NULL) throw() : ptr(ptr) {
inline gc_ptr(T* const ptr = NULL) noexcept : ptr(ptr) {
}
~gc_ptr() throw() {
inline ~gc_ptr() noexcept {
}
gc_ptr(const gc_ptr& r) throw() : ptr(r.ptr) {
inline gc_ptr(const gc_ptr& r) noexcept : ptr(r.ptr) {
}
gc_ptr& operator=(const gc_ptr& r) throw() {
if(this == &r)
return *this;
ptr = r.ptr;
return *this;
}
gc_ptr& operator=(const gc_ptr& r) = delete;
const bool operator==(const gc_ptr& r) const throw() {
inline const bool operator==(const gc_ptr& r) const noexcept {
if (this == &r)
return true;
return ptr == r.ptr;
}
const bool operator==(T* p) const throw() {
inline const bool operator==(const T* const p) const noexcept {
return ptr == p;
}
const bool operator!=(const gc_ptr& r) const throw() {
inline const bool operator!=(const gc_ptr& r) const noexcept {
return !this->operator==(r);
}
const bool operator!=(T* p) const throw() {
inline const bool operator!=(const T* const p) const noexcept {
return !this->operator==(p);
}
T& operator*() const throw() {
inline T& operator*() const noexcept {
return *ptr;
}
T* operator->() const throw() {
inline T* const operator->() const noexcept {
return ptr;
}
operator T*() const throw() {
inline operator T* const () const noexcept {
return ptr;
}
private:
T* const ptr;
};
#endif
/**
* Mutable pointer to an immutable value.
*/
#ifdef WANT_RAW_PTR
template<typename T> using gc_mutable_ptr = T*;
#else
template<typename T> class gc_mutable_ptr {
public:
inline gc_mutable_ptr(T* const ptr = NULL) noexcept : ptr(ptr) {
}
inline ~gc_mutable_ptr() noexcept {
}
inline gc_mutable_ptr(const gc_mutable_ptr& r) noexcept : ptr(r.ptr) {
}
inline gc_mutable_ptr& operator=(T* const p) noexcept {
ptr = p;
return *this;
}
inline gc_mutable_ptr& operator=(const gc_mutable_ptr& r) noexcept {
if (this == &r)
return *this;
ptr = r.ptr;
return *this;
}
inline const bool operator==(const gc_mutable_ptr& r) const noexcept {
if (this == &r)
return true;
return ptr == r.ptr;
}
inline const bool operator==(T* const p) const noexcept {
return ptr == p;
}
inline const bool operator!=(const gc_mutable_ptr& r) const noexcept {
return !this->operator==(r);
}
inline const bool operator!=(T* const p) const noexcept {
return !this->operator==(p);
}
inline T& operator*() const noexcept {
return *ptr;
}
inline T* const operator->() const noexcept {
return ptr;
}
inline operator T* const () const noexcept {
return ptr;
}
private:
T* ptr;
};
#endif
/**
* Initialize APR.
*/
class gc_apr_context_t {
public:
gc_apr_context_t() {
inline gc_apr_context_t() {
apr_initialize();
}
} gc_apr_context;
@ -130,36 +202,31 @@ public:
*/
class gc_pool {
public:
gc_pool() : apr_pool(NULL) {
inline gc_pool() noexcept : apr_pool(NULL) {
}
gc_pool(apr_pool_t* p) : apr_pool(p) {
inline gc_pool(apr_pool_t* const p) noexcept : apr_pool(p) {
}
gc_pool(const gc_pool& pool) : apr_pool(pool.apr_pool) {
inline gc_pool(const gc_pool& pool) noexcept : apr_pool(pool.apr_pool) {
}
gc_pool& operator=(const gc_pool& pool) {
if (this == &pool)
return *this;
apr_pool = pool.apr_pool;
return *this;
}
gc_pool& operator=(const gc_pool& pool) = delete;
private:
friend apr_pool_t* pool(const gc_pool& pool);
friend apr_pool_t* pool(const gc_pool& pool) noexcept;
friend class gc_global_pool_t;
friend class gc_child_pool;
friend class gc_local_pool;
friend class gc_scoped_pool;
apr_pool_t* apr_pool;
apr_pool_t* const apr_pool;
};
/**
* Return the APR pool used by a gc_pool.
*/
apr_pool_t* pool(const gc_pool& pool) {
inline apr_pool_t* pool(const gc_pool& pool) noexcept {
return pool.apr_pool;
}
@ -168,35 +235,51 @@ apr_pool_t* pool(const gc_pool& pool) {
*/
#ifdef WANT_THREADS
#ifdef __clang__
class gc_pool_stack_t {
public:
gc_pool_stack_t() {
int rc = pthread_key_create(&key, NULL);
assertOrFail(rc == 0);
inline gc_pool_stack_t() noexcept : key(mkkey()) {
}
operator apr_pool_t*() const {
return static_cast<apr_pool_t*>(pthread_getspecific(key));
inline operator apr_pool_t*() const noexcept {
return (apr_pool_t*)pthread_getspecific(key);
}
const gc_pool_stack_t& operator=(apr_pool_t* p) {
inline const gc_pool_stack_t& operator=(apr_pool_t* p) noexcept {
pthread_setspecific(key, p);
return *this;
}
private:
pthread_key_t key;
pthread_key_t mkkey() {
pthread_key_t k;
int rc = pthread_key_create(&k, NULL);
assertOrFail(rc == 0);
return k;
}
} gc_pool_stack;
#else
__thread apr_pool_t* gc_pool_stack = NULL;
#endif
#else
apr_pool_t* gc_pool_stack = NULL;
#endif
/**
* Push a pool onto the stack.
*/
apr_pool_t* gc_push_pool(apr_pool_t* pool) {
apr_pool_t* p = gc_pool_stack;
inline apr_pool_t* const gc_push_pool(apr_pool_t* pool) noexcept {
apr_pool_t* const p = gc_pool_stack;
gc_pool_stack = pool;
return p;
}
@ -204,8 +287,8 @@ apr_pool_t* gc_push_pool(apr_pool_t* pool) {
/**
* Pop a pool from the stack.
*/
apr_pool_t* gc_pop_pool(apr_pool_t* pool) {
apr_pool_t* p = gc_pool_stack;
inline apr_pool_t* const gc_pop_pool(apr_pool_t* pool) noexcept {
apr_pool_t* const p = gc_pool_stack;
gc_pool_stack = pool;
return p;
}
@ -213,16 +296,17 @@ apr_pool_t* gc_pop_pool(apr_pool_t* pool) {
/**
* Return the current memory pool.
*/
apr_pool_t* gc_current_pool() {
apr_pool_t* p = gc_pool_stack;
inline apr_pool_t* const gc_current_pool() noexcept {
apr_pool_t* const p = gc_pool_stack;
if (p != NULL)
return p;
// Create a parent pool for the current thread
apr_pool_create(&p, NULL);
assertOrFail(p != NULL);
gc_push_pool(p);
return p;
apr_pool_t* pp;
apr_pool_create(&pp, NULL);
assertOrFail(pp != NULL);
gc_push_pool(pp);
return pp;
}
/**
@ -231,25 +315,23 @@ apr_pool_t* gc_current_pool() {
class gc_child_pool : public gc_pool {
public:
gc_child_pool() : gc_pool(NULL), owner(true) {
apr_pool_create(&apr_pool, gc_current_pool());
assertOrFail(apr_pool != NULL);
inline gc_child_pool() noexcept : gc_pool(mkpool()), owner(true) {
}
gc_child_pool(const gc_child_pool& p) : gc_pool(p.apr_pool), owner(false) {
}
const gc_child_pool& operator=(const gc_child_pool& p) {
if(this == &p)
return *this;
apr_pool = p.apr_pool;
owner = false;
return *this;
inline gc_child_pool(const gc_child_pool& p) noexcept : gc_pool(p.apr_pool), owner(false) {
}
gc_child_pool& operator=(const gc_child_pool& p) = delete;
private:
bool owner;
const bool owner;
apr_pool_t* const mkpool() {
apr_pool_t* p;
apr_pool_create(&p, gc_current_pool());
assertOrFail(p != NULL);
return p;
}
};
/**
@ -258,29 +340,28 @@ private:
class gc_local_pool : public gc_pool {
public:
gc_local_pool() : gc_pool(NULL), owner(true) {
apr_pool_create(&apr_pool, gc_current_pool());
assertOrFail(apr_pool != NULL);
inline gc_local_pool() noexcept : gc_pool(mkpool()), owner(true) {
}
~gc_local_pool() {
inline ~gc_local_pool() noexcept {
if (owner)
apr_pool_destroy(apr_pool);
}
gc_local_pool(const gc_local_pool& p) : gc_pool(p.apr_pool), owner(false) {
inline gc_local_pool(const gc_local_pool& p) noexcept : gc_pool(p.apr_pool), owner(false) {
}
const gc_local_pool& operator=(const gc_local_pool& p) {
if(this == &p)
return *this;
apr_pool = p.apr_pool;
owner = false;
return *this;
}
gc_local_pool& operator=(const gc_local_pool& p) = delete;
private:
bool owner;
const bool owner;
apr_pool_t* const mkpool() {
apr_pool_t* p;
apr_pool_create(&p, gc_current_pool());
assertOrFail(p != NULL);
return p;
}
};
/**
@ -290,66 +371,64 @@ private:
class gc_scoped_pool : public gc_pool {
public:
gc_scoped_pool() : gc_pool(NULL), prev(gc_current_pool()), owner(true) {
apr_pool_create(&apr_pool, prev);
assertOrFail(apr_pool != NULL);
inline gc_scoped_pool() noexcept : gc_pool(mkpool()), prev(gc_current_pool()), owner(true) {
gc_push_pool(apr_pool);
}
gc_scoped_pool(apr_pool_t* p) : gc_pool(p), prev(gc_current_pool()), owner(false) {
inline gc_scoped_pool(apr_pool_t* p) noexcept : gc_pool(p), prev(gc_current_pool()), owner(false) {
gc_push_pool(apr_pool);
}
~gc_scoped_pool() {
inline ~gc_scoped_pool() noexcept {
if (owner)
apr_pool_destroy(apr_pool);
gc_pop_pool(prev);
}
gc_scoped_pool(const gc_scoped_pool& p) : gc_pool(p.apr_pool), prev(p.prev), owner(false) {
inline gc_scoped_pool(const gc_scoped_pool& p) noexcept : gc_pool(p.apr_pool), prev(p.prev), owner(false) {
}
const gc_scoped_pool& operator=(const gc_scoped_pool& p) {
if(this == &p)
return *this;
apr_pool = p.apr_pool;
prev = p.prev;
owner = false;
return *this;
}
gc_scoped_pool& operator=(const gc_scoped_pool& p) = delete;
private:
apr_pool_t* prev;
bool owner;
apr_pool_t* const prev;
const bool owner;
apr_pool_t* const mkpool() {
apr_pool_t* p;
apr_pool_create(&p, gc_current_pool());
assertOrFail(p != NULL);
return p;
}
};
/**
* Allocates a pointer to an object allocated from a memory pool and
* register a cleanup callback for it.
*/
template<typename T> apr_status_t gc_pool_cleanup(void* v) {
template<typename T> inline apr_status_t gc_pool_cleanup(void* v) {
T* t = (T*)v;
t->~T();
return APR_SUCCESS;
}
template<typename T> T* gc_new(apr_pool_t* p) {
template<typename T> inline T* const gc_new(apr_pool_t* const p) noexcept {
void* gc_new_ptr = apr_palloc(p, sizeof(T));
assertOrFail(gc_new_ptr != NULL);
apr_pool_cleanup_register(p, gc_new_ptr, gc_pool_cleanup<T>, apr_pool_cleanup_null) ;
return (T*)(gc_new_ptr);
}
template<typename T> T* gc_new(const gc_pool& p) {
template<typename T> inline T* const gc_new(const gc_pool& p) noexcept {
return gc_new<T>(pool(p));
}
template<typename T> T* gc_new() {
template<typename T> inline T* const gc_new() noexcept {
return gc_new<T>(gc_current_pool());
}
template<typename T> apr_status_t gc_pool_acleanup(void* v) {
size_t* m = static_cast<size_t*>(v);
template<typename T> inline apr_status_t gc_pool_acleanup(void* v) {
size_t* m = (size_t*)v;
size_t n = *m;
T* t = (T*)(m + 1);
for (size_t i = 0; i < n; i++, t++)
@ -357,40 +436,101 @@ template<typename T> apr_status_t gc_pool_acleanup(void* v) {
return APR_SUCCESS;
}
template<typename T> T* gc_anew(apr_pool_t* p, size_t n) {
size_t* gc_anew_ptr = static_cast<size_t*>(apr_palloc(p, sizeof(size_t) + sizeof(T) * n));
template<typename T> inline T* const gc_anew(apr_pool_t* const p, const size_t n) noexcept {
size_t* const gc_anew_ptr = (size_t*)apr_palloc(p, sizeof(size_t) + sizeof(T) * n);
assertOrFail(gc_anew_ptr != NULL);
*gc_anew_ptr = n;
apr_pool_cleanup_register(p, gc_anew_ptr, gc_pool_acleanup<T>, apr_pool_cleanup_null) ;
return (T*)(gc_anew_ptr + 1);
}
template<typename T> T* gc_anew(const gc_pool& p, size_t n) {
template<typename T> inline T* const gc_anew(const gc_pool& p, const size_t n) noexcept {
return gc_anew<T>(pool(p), n);
}
template<typename T> T* gc_anew(size_t n) {
template<typename T> inline T* const gc_anew(const size_t n) noexcept {
return gc_anew<T>(gc_current_pool(), n);
}
/**
* Allocate an array of chars.
*/
char* gc_cnew(apr_pool_t* p, size_t n) {
char* gc_cnew_ptr = static_cast<char*>(apr_palloc(p, n));
inline char* const gc_cnew(apr_pool_t* const p, const size_t n) noexcept {
char* const gc_cnew_ptr = (char*)apr_palloc(p, n);
assertOrFail(gc_cnew_ptr != NULL);
return gc_cnew_ptr;
}
char* gc_cnew(size_t n) {
inline char* const gc_cnew(const size_t n) noexcept {
return gc_cnew(gc_current_pool(), n);
}
/**
* Mutable reference to an immutable value.
*/
template<typename T> class gc_mutable_ref {
public:
inline gc_mutable_ref() noexcept : ptr(new (gc_new<T>()) T()) {
}
inline ~gc_mutable_ref() noexcept {
}
inline gc_mutable_ref(const gc_mutable_ref& r) noexcept : ptr(r.ptr) {
}
inline gc_mutable_ref(const T& v) noexcept : ptr(new (gc_new<T>()) T(v)) {
}
inline gc_mutable_ref& operator=(const gc_mutable_ref& r) noexcept {
if (this == &r)
return *this;
ptr = r.ptr;
return *this;
}
inline gc_mutable_ref& operator=(const T& v) noexcept {
ptr = new (gc_new<T>()) T(v);
return *this;
}
inline const bool operator==(const gc_mutable_ref& r) const noexcept {
if (this == &r)
return true;
if (ptr == r.ptr)
return true;
return *ptr == *r.ptr;
}
inline const bool operator==(const T& v) const noexcept {
return *ptr == v;
}
inline const bool operator!=(const gc_mutable_ref& r) const noexcept {
return !this->operator==(r);
}
inline const bool operator!=(const T& v) const noexcept {
return !this->operator==(v);
}
inline operator T&() const noexcept {
return *ptr;
}
inline operator T* const () const noexcept {
return ptr;
}
private:
T* ptr;
};
/**
* Pool based equivalent of the standard malloc function.
*/
void* gc_pool_malloc(size_t n) {
size_t* ptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n));
inline void* gc_pool_malloc(size_t n) {
size_t* ptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n);
assertOrFail(ptr != NULL);
*ptr = n;
return ptr + 1;
@ -399,9 +539,9 @@ void* gc_pool_malloc(size_t n) {
/**
* Pool based equivalent of the standard realloc function.
*/
void* gc_pool_realloc(void* ptr, size_t n) {
size_t size = *(static_cast<size_t*>(ptr) - 1);
size_t* rptr = static_cast<size_t*>(apr_palloc(gc_current_pool(), sizeof(size_t) + n));
inline void* gc_pool_realloc(void* ptr, size_t n) {
size_t size = *(((size_t*)ptr) - 1);
size_t* rptr = (size_t*)apr_palloc(gc_current_pool(), sizeof(size_t) + n);
assertOrFail(rptr != NULL);
*rptr = n;
memcpy(rptr + 1, ptr, size < n? size : n);
@ -411,15 +551,15 @@ void* gc_pool_realloc(void* ptr, size_t n) {
/**
* Pool based equivalent of the standard free function.
*/
void gc_pool_free(unused void* ptr) {
inline void gc_pool_free(unused void* ptr) {
// Memory allocated from a pool is freed when the pool is freed
}
/**
* Pool based equivalent of the standard strdup function.
*/
char* gc_pool_strdup(const char* str) {
char* dptr = static_cast<char*>(gc_pool_malloc(strlen(str) + 1));
inline char* gc_pool_strdup(const char* str) {
char* dptr = (char*)gc_pool_malloc(strlen(str) + 1);
assertOrFail(dptr != NULL);
strcpy(dptr, str);
return dptr;
@ -434,9 +574,9 @@ char* gc_pool_strdup(const char* str) {
/**
* Mmap based equivalent of the standard malloc function.
*/
void* gc_mmap_malloc(size_t n, unused const void* caller) {
inline void* gc_mmap_malloc(size_t n, unused const void* caller) {
//printf("gc_mmap_malloc %d", n);
size_t* ptr = static_cast<size_t*>(mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0));
size_t* ptr = (size_t*)mmap(NULL, sizeof(size_t) + n, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
assertOrFail(ptr != NULL);
*ptr = n;
//printf(" %p\n", ptr + 1);
@ -446,12 +586,12 @@ void* gc_mmap_malloc(size_t n, unused const void* caller) {
/**
* Mmap based equivalent of the standard realloc function.
*/
void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) {
inline void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) {
if (ptr == NULL)
return gc_mmap_malloc(n, caller);;
//printf("gc_mmap_realloc %p %d", ptr, n);
size_t size = *(static_cast<size_t*>(ptr) - 1);
size_t* rptr = static_cast<size_t*>(mremap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL));
size_t size = *(((size_t*)ptr) - 1);
size_t* rptr = (size_t*)mremap(((size_t*)ptr) - 1, sizeof(size_t) + size, sizeof(size_t) + n, MREMAP_MAYMOVE, NULL);
assertOrFail(rptr != NULL);
*rptr = n;
//printf(" %p\n", rptr + 1);
@ -461,18 +601,18 @@ void* gc_mmap_realloc(void* ptr, size_t n, const void* caller) {
/**
* Mmap based equivalent of the standard free function.
*/
void gc_mmap_free(void* ptr, unused const void* caller) {
inline void gc_mmap_free(void* ptr, unused const void* caller) {
//printf("gc_mmap_free %p\n", ptr);
if (ptr == NULL)
return;
size_t size = *(static_cast<size_t*>(ptr) - 1);
munmap(static_cast<size_t*>(ptr) - 1, sizeof(size_t) + size);
size_t size = *(((size_t*)ptr) - 1);
munmap(((size_t*)ptr) - 1, sizeof(size_t) + size);
}
/**
* Mmap based equivalent of the standard memalign function.
*/
void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) {
inline void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* caller) {
//printf("gc_mmap_memalign %d %d\n", alignment, n);
return gc_mmap_malloc(n, caller);
}
@ -480,7 +620,7 @@ void* gc_mmap_memalign(unused size_t alignment, size_t n, unused const void* cal
/**
* Install the mmap based memory allocation functions.
*/
void gc_mmap_init_hook(void) {
inline void gc_mmap_init_hook(void) {
__malloc_hook = gc_mmap_malloc;
__realloc_hook = gc_mmap_realloc;
__free_hook = gc_mmap_free;

View file

@ -30,89 +30,64 @@
namespace tuscany {
bool testCrc32hash() {
const bool testCrc32hash() {
const string key("This is a test key");
unsigned int h = crc32hash(c_str(key), length(key));
const unsigned int h = crc32hash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testTimes33hash() {
const bool testTimes33hash() {
const string key("This is a test key");
unsigned int h = times33hash(c_str(key), length(key));
const unsigned int h = times33hash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testMurmurhash() {
const bool testMurmurhash() {
const string key("This is a test key");
unsigned int h = murmurhash(c_str(key), length(key));
const unsigned int h = murmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
bool testPortablemurmurhash() {
const bool testPortablemurmurhash() {
const string key("This is a test key");
unsigned int h = portablemurmurhash(c_str(key), length(key));
const unsigned int h = portablemurmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
struct crc32hashTest {
const string key;
crc32hashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = crc32hash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct times33hashTest {
const string key;
times33hashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = times33hash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct murmurhashTest {
const string key;
murmurhashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = murmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
struct portablemurmurhashTest {
const string key;
portablemurmurhashTest(const string& key) : key(key) {
}
bool operator()() const {
unsigned int h = portablemurmurhash(c_str(key), length(key));
assert(h != 0);
return true;
}
};
bool testHashPerf() {
const bool testHashPerf() {
const string key("This is a test key");
const int count = 100000;
const lambda<bool()> crc32 = crc32hashTest(key);
const blambda crc32 = [key]() -> const bool {
const unsigned int h = crc32hash(c_str(key), length(key));
assert(h != 0);
return true;
};
cout << "crc32hash test " << time(crc32, 5, count) << " ms" << endl;
const lambda<bool()> times33 = times33hashTest(key);
const blambda times33 = [key]() -> const bool {
const unsigned int h = times33hash(c_str(key), length(key));
assert(h != 0);
return true;
};
cout << "times33hash test " << time(times33, 5, count) << " ms" << endl;
const lambda<bool()> murmur = murmurhashTest(key);
const blambda murmur = [key]() -> const bool {
const unsigned int h = murmurhash(c_str(key), length(key));
assert(h != 0);
return true;
};
cout << "murmurhash test " << time(murmur, 5, count) << " ms" << endl;
const lambda<bool()> portablemurmur = portablemurmurhashTest(key);
const blambda portablemurmur = [key]() -> const bool {
const unsigned int h = portablemurmurhash(c_str(key), length(key));
assert(h != 0);
return true;
};
cout << "portable murmurhash test " << time(portablemurmur, 5, count) << " ms" << endl;
return true;
@ -121,7 +96,7 @@ bool testHashPerf() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testCrc32hash();

View file

@ -43,7 +43,7 @@ namespace tuscany
* tree at contrib/ltree/crc32.[ch] and from FreeBSD at
* src/usr.bin/cksum/crc32.c.
*/
const unsigned int crc32hash(const char* data, const size_t len) {
inline const unsigned int crc32hash(const char* const data, const size_t len) {
return (unsigned int)apr_memcache_hash_default(NULL, data, len);
}
@ -89,7 +89,7 @@ const unsigned int crc32hash(const char* data, const size_t len) {
*
* -- Ralf S. Engelschall <rse@engelschall.com>
*/
const unsigned int times33hash(const char* data, const size_t len) {
inline const unsigned int times33hash(const char* const data, const size_t len) {
apr_ssize_t l = len;
return apr_hashfunc_default(data, &l);
}
@ -107,7 +107,7 @@ const unsigned int times33hash(const char* data, const size_t len) {
* Passes Bob Jenkin's frog.c torture-test. No collisions possible for 4 byte
* keys, no small 1 to 7 bit differentials.
*/
const unsigned int murmurhash(const char* key, const size_t klen) {
inline const unsigned int murmurhash(const char* const key, const size_t klen) {
unsigned int len = (unsigned int)klen;
const unsigned int seed = 0;
@ -153,7 +153,7 @@ const unsigned int murmurhash(const char* key, const size_t klen) {
* An endian and alignment neutral, but half the speed, version of
* the murmur hash.
*/
const unsigned int portablemurmurhash(const char* key, const size_t klen) {
inline const unsigned int portablemurmurhash(const char* const key, const size_t klen) {
unsigned int len = (unsigned int)klen;
const unsigned int seed = 0;
@ -199,7 +199,7 @@ const unsigned int portablemurmurhash(const char* key, const size_t klen) {
return h;
}
const unsigned int hashselect(const unsigned int hash, const unsigned int max) {
inline const unsigned int hashselect(const unsigned int hash, const unsigned int max) {
return hash % max;
}

View file

@ -23,6 +23,7 @@
* Test kernel functions.
*/
#include <functional>
#include <assert.h>
#include "string.hpp"
#include "sstream.hpp"
@ -36,58 +37,324 @@
namespace tuscany {
struct inc {
int i;
inc(int i) :
const bool ptrPerf() {
int x = 1;
for (int i = 0; i < 10000; i++) {
int* const y = &x;
int z = *y + *y;
z = z + 1;
}
return true;
}
const bool gcptrPerf() {
int x = 1;
for (int i = 0; i < 10000; i++) {
const gc_ptr<int> y = &x;
int z = *y + *y;
z = z + 1;
}
return true;
}
const bool testPtrPerf() {
{
const gc_scoped_pool gcp;
const blambda pp = ptrPerf;
cout << "Pointer test " << (time(pp, 5, 10000) / 10000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda gpp = gcptrPerf;
cout << "GC Pointer test " << (time(gpp, 5, 10000) / 10000) << " ms" << endl;
}
return true;
}
class incFunctor {
public:
incFunctor(const int i) :
i(i) {
}
const int operator()(const int x) const {
return x + i;
}
private:
const int i;
};
const int square(const int x) {
return x * x;
}
int mapLambda(lambda<int(const int)> f, int v) {
const int mapLambda(lambda<const int(const int)> f, int v) {
return f(v);
}
bool testLambda() {
const lambda<int(const int)> sq(square);
assert(sq(2) == 4);
assert(mapLambda(sq, 2) == 4);
assert(mapLambda(square, 2) == 4);
const lambda<const int(const int)> mksquare() {
return square;
}
const lambda<int(const int)> incf(inc(10));
assert(incf(1) == 11);
assert(mapLambda(incf, 1) == 11);
assert(mapLambda(inc(10), 1) == 11);
lambda<int(const int)> l;
l = incf;
assert(l(1) == 11);
l = square;
assert(l(2) == 4);
const bool testSizes() {
const gc_ptr<int> p(NULL);
cout << "sizeof gc_ptr " << sizeof(p) << endl;
const lambda<const int(const int)> sq(square);
cout << "sizeof C function lambda " << sizeof(sq) << endl;
const lambda<const int(const int)> incl(incFunctor(10));
cout << "sizeof functor lambda " << sizeof(incl) << endl;
const std::function<int(const int)> sqf(square);
cout << "sizeof C function std::function " << sizeof(sqf) << endl;
const std::function<int(const int)> incf(incFunctor(10));
cout << "sizeof functor std::function " << sizeof(incf) << endl;
const string s("abcd");
cout << "sizeof string " << sizeof(s) << endl;
const string v(s);
cout << "sizeof val " << sizeof(v) << endl;
const list<int> li = cons<int>(2, mklist<int>(3, 4));
cout << "sizeof list<int> " << sizeof(li) << endl;
const list<string> ls = cons<string>("a", mklist<string>("b", "c"));
cout << "sizeof list<string> " << sizeof(ls) << endl;
const list<value> lv = cons<value>("a", mklist<value>("b", "c"));
cout << "sizeof list<value> " << sizeof(lv) << endl;
return true;
}
bool testLambdaGC() {
const bool testLambda() {
const lambda<const int(const int)> sq(square);
assert(sq(2) == 4);
const lambda<const lambda<const int(const int)>()> mksq(mksquare);
assert(mksq()(2) == 4);
assert(mapLambda(sq, 2) == 4);
assert(mapLambda(square, 2) == 4);
const lambda<const int(const int)> incf(incFunctor(10));
assert(incf(1) == 11);
assert(mapLambda(incf, 1) == 11);
assert(mapLambda(incFunctor(10), 1) == 11);
const int base = 10;
auto incl11 = [base](const int i) { return base + i; };
const lambda<const int(const int)> incl(incl11);
assert(incl(1) == 11);
assert(mapLambda(incl, 1) == 11);
assert(mapLambda(incl11, 1) == 11);
const lambda<const int(const int)> il(incf);
assert(il(1) == 11);
const lambda<const int(const int)> sl(square);
assert(sl(2) == 4);
return true;
}
int constructCopiable = 0;
int copyCopiable = 0;
class Copiable {
public:
Copiable() {
assert(false);
}
Copiable(const string& s) : s(s) {
constructCopiable++;
}
Copiable(const Copiable& c) : s(c.s) {
copyCopiable++;
}
Copiable& operator=(const Copiable& c) = delete;
~Copiable() {
}
void doit() const {
}
private:
const string s;
};
bool testLambdaRef(const Copiable& c) {
[&c] { c.doit(); }();
return true;
}
bool testLambdaCopy(const Copiable& c) {
[c] { c.doit(); }();
return true;
}
const bool testCopiable() {
const Copiable ac = Copiable("assigned");
ac.doit();
assert(constructCopiable = 1);
assert(copyCopiable = 1);
const Copiable ac2 = []{ return Copiable("returned"); }();
ac2.doit();
assert(constructCopiable = 2);
assert(copyCopiable = 2);
const Copiable rc = Copiable("captured by ref");
testLambdaRef(rc);
assert(constructCopiable = 3);
assert(copyCopiable = 3);
const Copiable cc = Copiable("captured by value");
testLambdaCopy(cc);
assert(constructCopiable = 4);
assert(copyCopiable = 5);
return true;
}
const bool testMutable() {
{
gc_mutable_ref<string> s = string("aaa");
s = "bbb";
assert(s == "bbb");
}
{
gc_mutable_ref<string> s;
assert(s == "");
s = "bbb";
assert(s == "bbb");
}
{
gc_mutable_ref<value> v;
assert(isNil((value)v));
v = 1;
assert(v == 1);
}
return true;
}
const bool testLambdaGC() {
resetLambdaCounters();
{
gc_scoped_pool gc;
const gc_scoped_pool gcp;
testLambda();
}
assert(checkLambdaCounters());
return true;
}
class sint {
public:
sint(const int i) : i(i) {
}
const int i;
char b[4];
};
const int mult(const sint& a, const sint& b) {
return a.i * b.i;
}
const bool testCurry() {
const lambda<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)mult, sint(2));
assert(6 == mult2(sint(3)));
return true;
}
const bool curryPerf() {
const sint a(2);
const sint b(3);
const lambda<const int(const sint)> mult2 = curry((lambda<const int(const sint, const sint)>)mult, a);
for(int i = 0; i < 1000; i++)
mult2(b);
return true;
}
class multFunctor {
public:
multFunctor(const sint& a) : a(a) {
}
const int operator()(const sint& b) const {
return a.i * b.i;
}
private:
const sint a;
};
const bool testFunctor() {
const lambda<const int(const sint)> mult2 = multFunctor(sint(2));
assert(6 == mult2(sint(3)));
return true;
}
const bool functorPerf() {
const sint a(2);
const sint b(3);
const lambda<const int(const sint)> mult2 = lambda<const int(const sint)>(multFunctor(a));
for(int i = 0; i < 1000; i++)
mult2(b);
return true;
}
const bool test11Lambda() {
const sint a(2);
assert(6 == [a](const sint& b) { return a.i * b.i; } (sint(3)));
return true;
}
const lambda<const sint(const sint)> multlambda11(const sint& a) {
return [a](const sint& b) { return a.i * b.i; };
}
const bool lambda11Perf() {
const sint a(2);
const sint b(3);
const lambda<const sint(const sint)> mult2 = multlambda11(a);
for(int i = 0; i < 1000; i++)
mult2(b);
return true;
}
const std::function<sint(const sint&)> multfunction11(const sint& a) {
return [a](const sint& b) { return a.i * b.i; };
}
const bool function11Perf() {
const sint a(2);
const sint b(3);
const std::function<sint(const sint&)> mult2 = multfunction11(a);
for(int i = 0; i < 1000; i++)
mult2(b);
return true;
}
const bool testFuncPerf() {
{
const gc_scoped_pool gcp;
const blambda cp = curryPerf;
cout << "Curry test " << (time(cp, 5, 1000) / 1000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda fp = functorPerf;
cout << "Functor test " << (time(fp, 5, 1000) / 1000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda lp = lambda11Perf;
cout << "Lambda11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda lp = function11Perf;
cout << "Function11 test " << (time(lp, 5, 1000) / 1000) << " ms" << endl;
}
return true;
}
int countElements = 0;
struct Element {
int i;
class Element {
public:
Element() : i(0) {
countElements++;
}
@ -107,13 +374,16 @@ struct Element {
const bool operator==(const Element& o) const {
return o.i == i;
}
int i;
};
ostream& operator<<(ostream& out, const Element& v) {
out << v.i ;
return out;
}
bool testCons() {
const bool testCons() {
assert(car(cons(2, mklist(3))) == 2);
assert(car(cdr(cons(2, mklist(3)))) == 3);
assert(isNil(cdr(cdr(cons(2, mklist(3))))));
@ -122,12 +392,12 @@ bool testCons() {
return true;
}
bool testListGC() {
const bool testListGC() {
resetLambdaCounters();
resetListCounters();
countElements = 0;
{
gc_scoped_pool gc;
const gc_scoped_pool gcp;
testCons();
}
assert(checkLambdaCounters());
@ -136,7 +406,41 @@ bool testListGC() {
return true;
}
bool testOut() {
template<typename T> const list<T> listPerf(const T& v, const long int i) {
if (i == 0)
return list<T>();
return cons<T>(v, listPerf<T>(v, i -1));
}
const bool testListPerf() {
{
const gc_scoped_pool gcp;
const blambda lp = []() -> const bool {
listPerf<int>(0, 1000);
return true;
};
cout << "List<int> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda lp = []() -> const bool {
listPerf<string>(string("x"), 1000);
return true;
};
cout << "List<string> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl;
}
{
const gc_scoped_pool gcp;
const blambda lp = []() -> const bool {
listPerf<string>(value("x"), 1000);
return true;
};
cout << "List<value> test " << (time(lp, 5, 1000) / 1000) << " ms" << endl;
}
return true;
}
const bool testOut() {
ostringstream os1;
os1 << list<int> ();
assert(str(os1) == "()");
@ -147,7 +451,7 @@ bool testOut() {
return true;
}
bool testEquals() {
const bool testEquals() {
assert(list<int>() == list<int>());
assert(mklist(1, 2) == mklist(1, 2));
assert(list<int>() != mklist(1, 2));
@ -156,14 +460,14 @@ bool testEquals() {
return true;
}
bool testLength() {
const bool testLength() {
assert(0 == length(list<int>()));
assert(1 == length(mklist(1)));
assert(2 == length(cons(1, mklist(2))));
return true;
}
bool testAppend() {
const bool testAppend() {
assert(car(append(mklist(1), mklist(2))) == 1);
assert(car(cdr(append(mklist(1), mklist(2)))) == 2);
assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3);
@ -173,21 +477,23 @@ bool testAppend() {
return true;
}
struct Complex {
int x;
int y;
Complex() {
class Complex {
public:
Complex() : x(0), y(0) {
}
Complex(int x, int y) :
x(x), y(y) {
Complex(const int x, const int y) : x(x), y(y) {
}
const int x;
const int y;
};
ostream& operator<<(ostream& out, const Complex& v) {
out << "[" << v.x << ":" << v.y << "]";
return out;
}
bool testComplex() {
const bool testComplex() {
const list<Complex> p = mklist(Complex(1, 2), Complex(3, 4));
assert(car(p).x == 1);
assert(car(cdr(p)).x == 3);
@ -195,7 +501,7 @@ bool testComplex() {
return true;
}
bool testMap() {
const bool testMap() {
assert(isNil(map<int, int>(square, list<int>())));
const list<int> m = map<int, int>(square, mklist(2, 3));
@ -209,26 +515,26 @@ const int add(const int x, const int y) {
return x + y;
}
bool testReduce() {
const lambda<int(const int, const int)> r(add);
const bool testReduce() {
const lambda<const int(const int, const int)> r(add);
assert(reduce(r, 0, mklist(1, 2, 3)) == 6);
return true;
}
bool isPositive(const int x) {
const bool isPositive(const int x) {
if(x >= 0)
return true;
else
return false;
}
bool testFilter() {
const bool testFilter() {
assert(car(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 1);
assert(cadr(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 2);
return true;
}
bool testMember() {
const bool testMember() {
assert(isNil(member(4, mklist(1, 2, 3))));
assert(car(member(1, mklist(1, 2, 3))) == 1);
assert(car(member(2, mklist(1, 2, 3))) == 2);
@ -236,14 +542,14 @@ bool testMember() {
return true;
}
bool testReverse() {
const bool testReverse() {
assert(isNil(reverse(list<int>())));
assert(car(reverse(mklist(1, 2, 3))) == 3);
assert(cadr(reverse(mklist(1, 2, 3))) == 2);
return true;
}
bool testListRef() {
const bool testListRef() {
assert(listRef(mklist(1), 0) == 1);
assert(listRef(mklist(1, 2, 3), 0) == 1);
assert(listRef(mklist(1, 2, 3), 1) == 2);
@ -251,7 +557,7 @@ bool testListRef() {
return true;
}
bool testAssoc() {
const bool testAssoc() {
const list<list<string> > l = mklist(mklist<string>("x", "X"), mklist<string>("a", "A"), mklist<string>("y", "Y"), mklist<string>("a", "AA"));
assert(assoc<string>("a", l) == mklist<string>("a", "A"));
assert(isNil(assoc<string>("z", l)));
@ -261,10 +567,13 @@ bool testAssoc() {
const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
assert(assoc<value>("a", v) == mklist<value>("a", "A"));
const list<value> v2 = mklist<value>(mklist<value>("x", "X"), "a", mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
assert(assoc<value>("a", v2) == mklist<value>("a", "A"));
return true;
}
bool testZip() {
const bool testZip() {
const list<string> k = mklist<string>("x", "a", "y", "a");
const list<string> v = mklist<string>("X", "A", "Y", "AA");
const list<list<string> > z = mklist(k, v);
@ -274,7 +583,7 @@ bool testZip() {
return true;
}
bool testTokenize() {
const bool testTokenize() {
assert(tokenize("/", "") == list<string>());
assert(tokenize("/", "aaa") == mklist<string>("aaa"));
assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<string>("aaa", "bbb", "ccc", "ddd"));
@ -292,11 +601,11 @@ bool testTokenize() {
return true;
}
double testSeqMap(double x) {
const double testSeqMap(const double x) {
return x;
}
double testSeqReduce(unused double v, double accum) {
double testSeqReduce(unused const double v, const double accum) {
return accum + 1.0;
}
@ -316,16 +625,16 @@ bool testSeq() {
return true;
}
value valueSquare(list<value> x) {
const value valueSquare(const list<value>& x) {
return (int)car(x) * (int)car(x);
}
bool testValue() {
assert(value(true) == value(true));
const bool testValue() {
assert(value(true) == trueValue);
assert(value(1) == value(1));
assert(value("abcd") == value("abcd"));
lambda<value(const list<value>&)> vl(valueSquare);
assert(value(vl) == value(vl));
lvvlambda vl(valueSquare);
//assert(value(vl) == value(vl));
assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2)));
const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"));
@ -339,12 +648,12 @@ bool testValue() {
return true;
}
bool testValueGC() {
const bool testValueGC() {
resetLambdaCounters();
resetListCounters();
resetValueCounters();
{
gc_scoped_pool gc;
const gc_scoped_pool gcp;
testValue();
}
assert(checkValueCounters());
@ -353,8 +662,8 @@ bool testValueGC() {
return true;
}
bool testTree() {
const list<value> t = mktree<value>("a", list<value>(), list<value>());
const bool testTree() {
const list<value> t = mktree<value>("a", nilListValue, nilListValue);
const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t)))));
const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a"));
assert(mt == ct);
@ -371,8 +680,8 @@ const list<value> lta(const string& x) {
return mklist<value>(c_str(x), c_str(x + x));
}
bool testTreeAssoc() {
const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>());
const bool testTreeAssoc() {
const list<value> t = mktree<value>(lta("a"), nilListValue, nilListValue);
const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t)))));
const list<value> l = flatten<value>(at);
assert(length(l) == 6);
@ -387,58 +696,46 @@ bool testTreeAssoc() {
return true;
}
double fib_aux(double n, double a, double b) {
const double fib_aux(const double n, const double a, const double b) {
if(n == 0.0)
return a;
return fib_aux(n - 1.0, b, a + b);
}
double fib(double n) {
const double fib(const double n) {
return fib_aux(n, 0.0, 1.0);
}
struct fibMapPerf {
const bool operator()() const {
list<double> s = seq(0.0, 999.0);
list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
}
};
const bool fibMapPerf() {
const list<double> s = seq(0.0, 999.0);
const list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
}
struct nestedFibMapPerf {
const lambda<double(const double)> fib;
nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) {
}
const bool operator()() const {
list<double> s = seq(0.0, 999.0);
list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
}
};
bool testCppPerf() {
const bool testCppPerf() {
{
const lambda<bool()> fml = fibMapPerf();
const gc_scoped_pool gcp;
const blambda fml = fibMapPerf;
cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << endl;
}
{
struct nested {
static double fib(double n) {
struct nested {
static double fib_aux(double n, double a, double b) {
if(n == 0.0)
return a;
return fib_aux(n - 1.0, b, a + b);
}
};
return nested::fib_aux(n, 0.0, 1.0);
}
const lambda<const double(const double n)> fib = [](const double n) -> const double {
const lambda<const double(const double, const double, const double)> fib_aux = [&fib_aux](double n, double a, double b) -> const double {
if(n == 0.0)
return a;
return fib_aux(n - 1.0, b, a + b);
};
return fib_aux(n, 0.0, 1.0);
};
const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib));
const blambda nfml = [fib]() -> const bool {
const list<double> s = seq(0.0, 999.0);
const list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
return true;
};
cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << endl;
}
return true;
@ -456,7 +753,7 @@ const id<int> idH(const int v) {
return idF(v) >> idG;
}
bool testIdMonad() {
const bool testIdMonad() {
const id<int> m(2);
assert(m >> idF == idF(2));
assert(m >> unit<int>() == m);
@ -476,7 +773,7 @@ const maybe<int> maybeH(const int v) {
return maybeF(v) >> maybeG;
}
bool testMaybeMonad() {
const bool testMaybeMonad() {
const maybe<int> m(2);
assert(m >> maybeF == maybeF(2));
assert((m >> just<int>()) == m);
@ -498,7 +795,7 @@ const failable<int> failableH(const int v) {
return failableF(v) >> failableG;
}
bool testFailableMonad() {
const bool testFailableMonad() {
const failable<int> m(2);
assert(m >> failableF == failableF(2));
assert((m >> success<int, string, int>()) == m);
@ -515,23 +812,16 @@ bool testFailableMonad() {
assert(rcode(vooops) == 500);
const value v = value(vooops);
assert(car<value>(v) == value());
assert(car<value>(v) == nilValue);
assert(cadr<value>(v) == string("test"));
assert(caddr<value>(v) == value((double)500));
return true;
}
struct tickInc {
const double v;
tickInc(const double v) : v(v) {
}
const scp<int, double> operator()(int s) const {
return scp<int, double>(s + 1, v);
}
};
const state<int, double> tick(const double v) {
return transformer<int, double>(tickInc(v));
return transformer<int, double>([v](const int s) {
return scp<int, double>(s + 1, v);
});
}
const state<int, double> stateF(const double v) {
@ -546,8 +836,8 @@ const state<int, double> stateH(const double v) {
return stateF(v) >> stateG;
}
bool testStateMonad() {
const lambda<state<int, double>(const double)> r(result<int, double>);
const bool testStateMonad() {
const lambda<const state<int, double>(const double)> r(result<int, double>);
state<int, double> m = result<int, double>(2.0);
assert((m >> stateF)(0) == stateF(2.0)(0));
@ -558,30 +848,40 @@ bool testStateMonad() {
return true;
}
bool testDynLib() {
const bool testDynLib() {
const lib dl(string("./libdynlib-test") + dynlibExt);
const failable<lambda<int(const int)> > sq(dynlambda<int(const int)>("csquare", dl));
const failable<lambda<const int(const int)> > sq(dynlambda<const int(const int)>("csquare", dl));
assert(hasContent(sq));
lambda<int(const int)> l(content(sq));
lambda<const int(const int)> l(content(sq));
assert(l(2) == 4);
const failable<lambda<lambda<int(const int)>()> > sql(dynlambda<lambda<int(const int)>()>("csquarel", dl));
const failable<lambda<const lambda<const int(const int)>()> > sql(dynlambda<const lambda<const int(const int)>()>("csquarel", dl));
assert(hasContent(sql));
lambda<lambda<int(const int)>()> ll(content(sql));
lambda<const lambda<const int(const int)>()> ll(content(sql));
assert(ll()(3) == 9);
return true;
}
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testSizes();
tuscany::testCopiable();
tuscany::testMutable();
tuscany::testPtrPerf();
tuscany::testLambda();
tuscany::testLambdaGC();
tuscany::testCurry();
tuscany::testFunctor();
tuscany::test11Lambda();
tuscany::testFuncPerf();
tuscany::testCons();
tuscany::testListGC();
tuscany::testListPerf();
tuscany::testOut();
tuscany::testEquals();
tuscany::testLength();

View file

@ -34,7 +34,7 @@ namespace tuscany {
#ifdef HAS_CXX0X_LAMBDAS
const lambda<const int(const int)> inc(const int i) {
return [=](const int x)->const int {
return [i](const int x)->const int {
return x + i;
};
}
@ -43,27 +43,26 @@ const int square(const int x) {
return x * x;
}
int mapLambda(const lambda<const int(const int)> f, int v) {
const int mapLambda(const lambda<const int(const int)> f, int v) {
return f(v);
}
bool testLambda() {
const bool testLambda() {
const lambda<const int(const int)> sq = square;
assert(sq(2) == 4);
assert(mapLambda(square, 2) == 4);
assert(mapLambda(sq, 2) == 4);
assert(mapLambda([](const int x)->const int { return x * x; }, 2) == 4);
const lambda<int(int)> incf = inc(10);
const lambda<const int(const int)> incf = inc(10);
assert(incf(1) == 11);
assert(mapLambda(incf, 1) == 11);
assert(mapLambda(inc(10), 1) == 11);
lambda<const int(const int)> l;
l = incf;
assert(l(1) == 11);
l = square;
assert(l(2) == 4);
const lambda<const int(const int)> il(incf);
assert(il(1) == 11);
const lambda<const int(const int)> sl(square);
assert(sl(2) == 4);
return true;
}
@ -72,13 +71,13 @@ const double fib_aux(const double n, const double a, const double b) {
}
const bool fibMapPerf() {
list<double> s = seq(0.0, 4999.0);
list<double> r = map<double, double>([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s);
const list<double> s = seq(0.0, 4999.0);
const list<double> r = map<double, double>([](const double n)->const double { return fib_aux(n, 0.0, 1.0); }, s);
assert(5000 == length(r));
return true;
}
bool testCppPerf() {
const bool testCppPerf() {
cout << "Fibonacci map test " << (time([]()->const bool { return fibMapPerf(); }, 1, 1) / 5000) << " ms" << endl;
return true;
}
@ -87,7 +86,7 @@ bool testCppPerf() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
#ifdef HAS_CXX0X_LAMBDAS

View file

@ -43,16 +43,16 @@ long countILists = 0;
long countCLists = 0;
long countELists = 0;
bool resetListCounters() {
inline const bool resetListCounters() {
countLists = countILists = countCLists = countELists = 0;
return true;
}
bool checkListCounters() {
inline const bool checkListCounters() {
return countLists == 0;
}
bool printListCounters() {
inline const bool printListCounters() {
cout << "countLists " << countLists << endl;
cout << "countELists " << countELists << endl;
cout << "countILists " << countILists << endl;
@ -91,19 +91,19 @@ bool printListCounters() {
template<typename T> class list {
public:
list() {
inline list() : car() {
debug_inc(countLists);
debug_inc(countELists);
debug_watchList();
}
list(const T car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) {
inline list(const T& car, const lambda<list<T>()>& cdr) : car(car), cdr(cdr) {
debug_inc(countLists);
debug_inc(countILists);
debug_watchList();
}
list(const list& p) : car(p.car), cdr(p.cdr) {
inline list(const list& p) : car(p.car), cdr(p.cdr) {
debug_inc(countLists);
debug_inc(countCLists);
#ifdef WANT_MAINTAINER_WATCH
@ -111,22 +111,13 @@ public:
#endif
}
const list<T>& operator=(const list<T>& p) {
if(this == &p)
return *this;
car = p.car;
cdr = p.cdr;
#ifdef WANT_MAINTAINER_WATCH
watch = p.watch;
#endif
return *this;
}
list<T>& operator=(const list<T>& p) = delete;
~list() {
inline ~list() {
debug_dec(countLists);
}
const bool operator==(const list<T>& p) const {
inline const bool operator==(const list<T>& p) const {
if(this == &p)
return true;
if(isNil(cdr))
@ -140,7 +131,7 @@ public:
return cdr() == p.cdr();
}
const bool operator<(const list<T>& p) const {
inline const bool operator<(const list<T>& p) const {
if(this == &p)
return false;
if (isNil(cdr))
@ -154,7 +145,7 @@ public:
return cdr() < p.cdr();
}
const bool operator>(const list<T>& p) const {
inline const bool operator>(const list<T>& p) const {
if(this == &p)
return false;
if (isNil(cdr))
@ -168,11 +159,11 @@ public:
return cdr() > p.cdr();
}
const bool operator!=(const list<T>& p) const {
inline const bool operator!=(const list<T>& p) const {
return !this->operator==(p);
}
operator const list<list<T> >() const {
inline operator const list<list<T> >() const {
return (list<list<T> >)T(*this);
}
@ -185,9 +176,10 @@ private:
template<typename X> friend const bool isNil(const list<X>& p);
template<typename X> friend const X car(const list<X>& p);
template<typename X> friend const list<X> cdr(const list<X>& p);
template<typename X> friend const bool setlist(list<X>& target, const list<X>& l);
T car;
lambda<list<T>()> cdr;
const T car;
const lambda<list<T>()> cdr;
};
#ifdef WANT_MAINTAINER_WATCH
@ -196,7 +188,7 @@ private:
* Debug utility used to write the contents of a list to a string, easier
* to watch than the list itself in a debugger.
*/
template<typename T> const string watchList(const list<T>& p) {
template<typename T> inline const string watchList(const list<T>& p) {
if(isNil(p))
return "()";
odebugstream os;
@ -209,21 +201,21 @@ template<typename T> const string watchList(const list<T>& p) {
/**
* Returns true if the given list is nil.
*/
template<typename T> const bool isNil(const list<T>& p) {
template<typename T> inline const bool isNil(const list<T>& p) {
return isNil(p.cdr);
}
/**
* Write a list to an output stream.
*/
template<typename T> ostream& writeHelper(ostream& out, const list<T>& l) {
template<typename T> inline ostream& writeHelper(ostream& out, const list<T>& l) {
if (isNil(l))
return out;
out << " " << car(l);
return writeHelper(out, cdr(l));
}
template<typename T> ostream& operator<<(ostream& out, const list<T>& l) {
template<typename T> inline ostream& operator<<(ostream& out, const list<T>& l) {
if(isNil(l))
return out << "()";
out << "(" << car(l);
@ -234,74 +226,74 @@ template<typename T> ostream& operator<<(ostream& out, const list<T>& l) {
/**
* Construct a (lazy) list from a value and a lambda function that returns the cdr.
*/
template<typename T> const list<T> cons(const T& car, const lambda<list<T>()>& cdr) {
template<typename T> inline const list<T> cons(const T& car, const lambda<const list<T>()>& cdr) {
return list<T> (car, cdr);
}
/**
* Construct a list from a value and a cdr list.
*/
template<typename T> const list<T> cons(const T& car, const list<T>& cdr) {
template<typename T> inline const list<T> cons(const T& car, const list<T>& cdr) {
return list<T> (car, result(cdr));
}
/**
* Cons variations for use with the reduce and reduceRight functions.
*/
template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) {
template<typename T> inline const list<T> lcons(const list<T>& cdr, const T& car) {
return cons<T>(car, cdr);
}
template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) {
template<typename T> inline const list<T> rcons(const T& car, const list<T>& cdr) {
return cons<T>(car, cdr);
}
/**
* Construct a list of one value.
*/
template<typename T> const list<T> mklist(const T& car) {
template<typename T> inline const list<T> mklist(const T& car) {
return list<T> (car, result(list<T> ()));
}
/**
* Construct a list of two values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b) {
template<typename T> inline const list<T> mklist(const T& a, const T& b) {
return cons(a, mklist(b));
}
/**
* Construct a list of three values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c) {
template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c) {
return cons(a, cons(b, mklist(c)));
}
/**
* Construct a list of four values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d) {
template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d) {
return cons(a, cons(b, cons(c, mklist(d))));
}
/**
* Construct a list of five values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) {
template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) {
return cons(a, cons(b, cons(c, cons(d, mklist(e)))));
}
/**
* Construct a list of six values.
*/
template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) {
template<typename T> inline const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) {
return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f))))));
}
/**
* Returns the car of a list.
*/
template<typename T> const T car(const list<T>& p) {
template<typename T> inline const T car(const list<T>& p) {
// Abort if trying to access the car of a nil list
assertOrFail(!isNil(p.cdr));
return p.car;
@ -310,159 +302,144 @@ template<typename T> const T car(const list<T>& p) {
/**
* Returns the cdr of a list.
*/
template<typename T> const list<T> cdr(const list<T>& p) {
template<typename T> inline const list<T> cdr(const list<T>& p) {
return p.cdr();
}
/**
* Returns the car of the cdr (the 2nd element) of a list.
*/
template<typename T> const T cadr(const list<T>& p) {
template<typename T> inline const T cadr(const list<T>& p) {
return car(cdr(p));
}
/**
* Returns the 3rd element of a list.
*/
template<typename T> const T caddr(const list<T>& p) {
template<typename T> inline const T caddr(const list<T>& p) {
return car(cdr(cdr(p)));
}
/**
* Returns the 4th element of a list.
*/
template<typename T> const T cadddr(const list<T>& p) {
template<typename T> inline const T cadddr(const list<T>& p) {
return car(cdr(cdr(cdr(p))));
}
/**
* Returns the 5th element of a list.
*/
template<typename T> const T caddddr(const list<T>& p) {
template<typename T> inline const T caddddr(const list<T>& p) {
return car(cdr(cdr(cdr(cdr(p)))));
}
/**
* Returns the 6th element of a list.
*/
template<typename T> const T cadddddr(const list<T>& p) {
template<typename T> inline const T cadddddr(const list<T>& p) {
return car(cdr(cdr(cdr(cdr(cdr(p))))));
}
/**
* Returns the 7th element of a list.
*/
template<typename T> const T caddddddr(const list<T>& p) {
template<typename T> inline const T caddddddr(const list<T>& p) {
return car(cdr(cdr(cdr(cdr(cdr(cdr(p)))))));
}
/**
* Returns the 8th element of a list.
*/
template<typename T> const T cadddddddr(const list<T>& p) {
template<typename T> inline const T cadddddddr(const list<T>& p) {
return car(cdr(cdr(cdr(cdr(cdr(cdr(cdr(p))))))));
}
/**
* Returns a list of elements from the 3rd to the end of a list.
*/
template<typename T> const list<T> cddr(const list<T>& p) {
template<typename T> inline const list<T> cddr(const list<T>& p) {
return cdr(cdr(p));
}
/**
* Returns a list of elements from the 4th to the end of a list.
*/
template<typename T> const list<T> cdddr(const list<T>& p) {
template<typename T> inline const list<T> cdddr(const list<T>& p) {
return cdr(cdr(cdr(p)));
}
/**
* Returns a list of elements from the 5th to the end of a list.
*/
template<typename T> const list<T> cddddr(const list<T>& p) {
template<typename T> inline const list<T> cddddr(const list<T>& p) {
return cdr(cdr(cdr(cdr(p))));
}
/**
* Returns a list of elements from the 6th to the end of a list.
*/
template<typename T> const list<T> cdddddr(const list<T>& p) {
template<typename T> inline const list<T> cdddddr(const list<T>& p) {
return cdr(cdr(cdr(cdr(cdr(p)))));
}
/**
* Returns a list of elements from the 7th to the end of a list.
*/
template<typename T> const list<T> cddddddr(const list<T>& p) {
template<typename T> inline const list<T> cddddddr(const list<T>& p) {
return cdr(cdr(cdr(cdr(cdr(cdr(p))))));
}
/**
* Returns a list of elements from the 8th to the end of a list.
*/
template<typename T> const list<T> cdddddddr(const list<T>& p) {
template<typename T> inline const list<T> cdddddddr(const list<T>& p) {
return cdr(cdr(cdr(cdr(cdr(cdr(cdr(p)))))));
}
/**
* Returns the length of a list.
*/
template<typename T> struct lengthRef {
const size_t operator()(const size_t c, const list<T>& p) {
template<typename T> inline const size_t length(const list<T>& p) {
const lambda<size_t(const size_t, const list<T>&)> lengthRef = [&lengthRef](const size_t c, const list<T>& p) -> const size_t {
if(isNil(p))
return c;
return (*this)(c + 1, cdr(p));
}
};
template<typename T> const size_t length(const list<T>& p) {
return lengthRef<T> ()(0, p);
return lengthRef(c + 1, cdr(p));
};
return lengthRef(0, p);
}
/**
* Appends a list and a lambda function returning a list.
*/
template<typename T> struct appendCdr {
const list<T> a;
const lambda<list<T>()> fb;
appendCdr(const list<T>& a, const lambda<list<T>()>& fb) :
a(a), fb(fb) {
}
const list<T> operator()() const {
return append(a, fb);
}
};
template<typename T> const list<T> append(const list<T>&a, const lambda<list<T>()>& fb) {
template<typename T> inline const list<T> append(const list<T>&a, const lambda<const list<T>()>& fb) {
if(isNil(a))
return fb();
return cons<T>(car(a), appendCdr<T> (cdr(a), fb));
return cons<T>(car(a), [a, fb]() { return append(cdr(a), fb); });
}
/**
* Appends two lists.
*/
template<typename T> const list<T> append(const list<T>&a, const list<T>& b) {
template<typename T> inline const list<T> append(const list<T>&a, const list<T>& b) {
return append(a, result(b));
}
/**
* Append a value to a list.
*/
template<typename T> const list<T> operator+(const list<T>& l, const T& v) {
template<typename T> inline const list<T> operator+(const list<T>& l, const T& v) {
return append(l, mklist(v));
}
template<typename T, typename V> const list<T> operator+(const list<T>& l, const V& v) {
template<typename T, typename V> const list<T> inline operator+(const list<T>& l, const V& v) {
return append(l, mklist<T>(v));
}
/**
* Map a lambda function on a list.
*/
template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, const list<T>& p) {
template<typename T, typename R> inline const list<R> map(const lambda<const R(const T)>& f, const list<T>& p) {
if(isNil(p))
return list<R> ();
return cons(f(car(p)), map(f, cdr(p)));
@ -471,46 +448,32 @@ template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f,
/**
* Run a reduce lambda function on a list.
*/
template<typename T, typename R> struct reduceAccumulate {
const lambda<R(const R&, const T&)> f;
reduceAccumulate(const lambda<R(const R, const T)>& f) :
f(f) {
}
R operator()(const R& acc, const list<T>& p) const {
template<typename T, typename R> inline const R reduce(const lambda<const R(const R, const T)>& f, const R& initial, const list<T>& p) {
const lambda<const R(const R&, const list<T>&p)> reduceAccumulate = [f, &reduceAccumulate](const R& acc, const list<T>& p) -> R {
if(isNil(p))
return acc;
return (*this)(f(acc, car(p)), cdr(p));
}
};
template<typename T, typename R> const R reduce(const lambda<R(const R, const T)>& f, const R& initial, const list<T>& p) {
return reduceAccumulate<T, R> (f)(initial, p);
return reduceAccumulate(f(acc, car(p)), cdr(p));
};
return reduceAccumulate(initial, p);
}
template<typename T, typename R> struct reduceRightAccumulate {
const lambda<R(const T&, const R&)> f;
reduceRightAccumulate(const lambda<R(const T, const R)>& f) :
f(f) {
}
R operator()(const list<T>& p, const R& acc) const {
template<typename T, typename R> inline const R reduceRight(const lambda<const R(const T, const R)>& f, const R& initial, const list<T>& p) {
const lambda<const R(const list<T>&p, const R&)> reduceRightAccumulate = [f, &reduceRightAccumulate](const list<T>& p, const R& acc) -> R {
if(isNil(p))
return acc;
return (*this)(cdr(p), f(car(p), acc));
}
};
template<typename T, typename R> const R reduceRight(const lambda<R(const T, const R)>& f, const R& initial, const list<T>& p) {
return reduceRightAccumulate<T, R> (f)(p, initial);
return reduceRightAccumulate(cdr(p), f(car(p), acc));
};
return reduceRightAccumulate(p, initial);
}
/**
* Run a filter lambda function on a list.
*/
template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const list<T>& p) {
template<typename T> inline const list<T> filter(const lambda<const bool(const T)>& f, const list<T>& p) {
if(isNil(p))
return list<T> ();
if(f(car(p))) {
const lambda<list<T>(const lambda<bool(const T)>, const list<T>)> ff(filter<T>);
const lambda<const list<T>(const lambda<const bool(const T)>, const list<T>)> ff(filter<T>);
return cons(car(p), curry(ff, f, cdr(p)));
}
return filter(f, cdr(p));
@ -519,7 +482,7 @@ template<typename T> const list<T> filter(const lambda<bool(const T)>& f, const
/**
* Returns a list pointing to a member of a list.
*/
template<typename T> const list<T> member(const T& t, const list<T>& p) {
template<typename T> inline const list<T> member(const T& t, const list<T>& p) {
if(isNil(p))
return list<T> ();
if(t == car(p))
@ -530,44 +493,31 @@ template<typename T> const list<T> member(const T& t, const list<T>& p) {
/**
* Reverse a list.
*/
template<typename T> const list<T> reverseIter(const list<T>& acc, const list<T>& p) {
template<typename T> inline const list<T> reverseIter(const list<T>& acc, const list<T>& p) {
if(isNil(p))
return acc;
return reverseIter(cons(car(p), acc), cdr(p));
}
template<typename T> const list<T> reverse(const list<T>& p) {
template<typename T> inline const list<T> reverse(const list<T>& p) {
return reverseIter(list<T> (), p);
}
template<typename T> const list<T> seq(const T& start, const T& end);
template<typename T> struct seqGenerate {
const T start;
const T end;
seqGenerate(const T& start, const T&end) :
start(start), end(end) {
}
const list<T> operator()() const {
return seq<T> (start, end);
}
};
/**
* Returns a sequence of values between the given bounds.
*/
template<typename T> const list<T> seq(const T& start, const T& end) {
template<typename T> inline const list<T> seq(const T& start, const T& end) {
if(start == end)
return mklist(start);
if(start < end)
return cons<T>(start, seqGenerate<T> (start + 1, end));
return cons<T>(start, seqGenerate<T> (start - 1, end));
return cons<T>(start, [start, end] { return seq<T> (start + 1, end); });
return cons<T>(start, [start, end] { return seq<T> (start - 1, end); });
}
/**
* Returns the i-th element of a list.
*/
template<typename T> const T listRef(const list<T>& l, const size_t i) {
template<typename T> inline const T listRef(const list<T>& l, const size_t i) {
if (i == 0)
return car(l);
return listRef(cdr(l), i - 1);
@ -576,7 +526,7 @@ template<typename T> const T listRef(const list<T>& l, const size_t i) {
/**
* Returns the first pair matching a key from a list of key value pairs.
*/
template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) {
template<typename T> inline const list<T> assoc(const T& k, const list<list<T> >& p) {
if(isNil(p))
return list<T> ();
if(k == car(car(p)))
@ -587,7 +537,7 @@ template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) {
/**
* Returns a list of lists containing elements from two input lists.
*/
template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b) {
template<typename T> inline const list<list<T> > zip(const list<T>& a, const list<T>& b) {
if (isNil(a) || isNil(b))
return list<list<T> >();
return cons<list<T> >(mklist<T>(car(a), car(b)), zip(cdr(a), cdr(b)));
@ -596,19 +546,19 @@ template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b
/**
* Converts a list of key value pairs to a list containing the list of keys and the list of values.
*/
template<typename T> const list<T> unzipKeys(const list<list<T> >& l) {
template<typename T> inline const list<T> unzipKeys(const list<list<T> >& l) {
if (isNil(l))
return list<T>();
return cons(car(car(l)), unzipKeys(cdr(l)));
}
template<typename T> const list<T> unzipValues(const list<list<T> >& l) {
template<typename T> inline const list<T> unzipValues(const list<list<T> >& l) {
if (isNil(l))
return list<T>();
return cons(cadr(car(l)), unzipValues(cdr(l)));
}
template<typename T> const list<list<T> > unzip(const list<list<T> >& l) {
template<typename T> inline const list<list<T> > unzip(const list<list<T> >& l) {
return mklist<list<T> >(unzipKeys(l), unzipValues(l));
}

View file

@ -43,7 +43,7 @@ public:
maxElements = countElements;
}
Element(int i) : i(i) {
Element(const int i) : i(i) {
countElements++;
if (countElements > maxElements)
maxElements = countElements;
@ -66,7 +66,7 @@ public:
private:
friend ostream& operator<<(ostream& out, const Element& v);
int i;
const int i;
char c[20];
};
@ -75,14 +75,14 @@ ostream& operator<<(ostream& out, const Element& v) {
return out;
}
bool poolAlloc(Element** p, const int count) {
const bool poolAlloc(Element** const p, const int count) {
if (count == 0)
return true;
p[count - 1] = new (gc_new<Element>()) Element();
return poolAlloc(p, count - 1);
};
bool poolFree(Element** p, const int count) {
bool poolFree(Element** const p, const int count) {
if (count == 0)
return true;
// Do nothing to free the element, but cycle through them just
@ -90,21 +90,14 @@ bool poolFree(Element** p, const int count) {
return poolFree(p, count - 1);
};
struct poolAllocPerf {
const int n;
Element** p;
poolAllocPerf(const int n) : n(n), p(new Element*[n]) {
}
const bool operator()() const {
gc_scoped_pool gc;
poolAlloc(p, n);
return true;
}
};
bool testPoolAllocPerf() {
const bool testPoolAllocPerf() {
const int count = 10000;
const lambda<bool()> pl = poolAllocPerf(count);
Element** const elements = new Element*[count];
const blambda pl = [elements, count]() -> const bool {
const gc_scoped_pool gc;
poolAlloc(elements, count);
return true;
};
maxElements = 0;
cout << "Memory pool alloc test " << (time(pl, 1, 1) / count) << " ms" << endl;
assert(countElements == 0);
@ -112,35 +105,28 @@ bool testPoolAllocPerf() {
return true;
}
bool stdAlloc(Element** p, const int count) {
const bool stdAlloc(Element** const p, const int count) {
if (count == 0)
return true;
p[count - 1] = new Element();
return stdAlloc(p, count - 1);
};
bool stdFree(Element** p, const int count) {
const bool stdFree(Element** const p, const int count) {
if (count == 0)
return true;
delete p[count -1];
return stdFree(p, count - 1);
};
struct stdAllocPerf {
const int n;
Element** p;
stdAllocPerf(const int n) : n(n), p(new Element*[n]) {
}
const bool operator()() const {
stdAlloc(p, n);
stdFree(p, n);
return true;
}
};
bool testStdAllocPerf() {
const bool testStdAllocPerf() {
const int count = 10000;
const lambda<bool()> sl = stdAllocPerf(count);
Element** const elements = new Element*[count];
const blambda sl = [elements, count]() -> const bool {
stdAlloc(elements, count);
stdFree(elements, count);
return true;
};
maxElements = 0;
cout << "Memory standard alloc test " << (time(sl, 1, 1) / count) << " ms" << endl;
assert(countElements == 0);
@ -151,7 +137,7 @@ bool testStdAllocPerf() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testPoolAllocPerf();

View file

@ -26,8 +26,11 @@
* Simple monad implementations.
*/
#ifdef WANT_MAINTAINER_BACKTRACE
#include <execinfo.h>
#include <cxxabi.h>
#endif
#include "function.hpp"
#include "string.hpp"
#include "stream.hpp"
@ -43,21 +46,16 @@ namespace tuscany
*/
template<typename V> class id {
public:
id(const V& v) : v(v) {
inline id(const V& v) : v(v) {
}
const id<V>& operator=(const id<V>& m) {
if(this == &m)
return *this;
v = m.v;
return *this;
}
id<V>& operator=(const id<V>& m) = delete;
const bool operator!=(const id<V>& m) const {
inline const bool operator!=(const id<V>& m) const {
return !this->operator==(m);
}
const bool operator==(const id<V>& m) const {
inline const bool operator==(const id<V>& m) const {
if (&m == this)
return true;
return v == m.v;
@ -72,7 +70,7 @@ private:
/**
* Write an identity monad to a stream.
*/
template<typename V> ostream& operator<<(ostream& out, const id<V>& m) {
template<typename V> inline ostream& operator<<(ostream& out, const id<V>& m) {
out << content(m);
return out;
}
@ -80,29 +78,29 @@ template<typename V> ostream& operator<<(ostream& out, const id<V>& m) {
/**
* Returns the content of an identity monad.
*/
template<typename V> const V content(const id<V>& m) {
template<typename V> inline const V content(const id<V>& m) {
return m.v;
}
/**
* Return an identity monad from a value.
*/
template<typename V> const id<V> mkunit(const V& v) {
template<typename V> inline const id<V> mkunit(const V& v) {
return id<V>(v);
}
template<typename V> const lambda<id<V>(const V)> unit() {
template<typename V> inline const lambda<const id<V>(const V)> unit() {
return mkunit<V>;
}
/**
* Bind a function to an identity monad. Pass the value in the monad to the function.
*/
template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(const V)>& f) {
template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const lambda<const id<R>(const V)>& f) {
return f(content(m));
}
template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) {
template<typename R, typename V> inline const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) {
return f(content(m));
}
@ -112,26 +110,22 @@ template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id
*/
template<typename V> class maybe {
public:
maybe(const V& v) : hasv(true), v(v) {
inline maybe(const V& v) : hasv(true), v(v) {
}
maybe() : hasv(false) {
inline maybe() : hasv(false), v() {
}
const maybe<V>& operator=(const maybe<V>& m) {
if(this == &m)
return *this;
hasv = m.hasv;
if (hasv)
v = m.v;
return *this;
inline maybe(const maybe<V>& m) : hasv(m.hasv), v(m.v) {
}
const bool operator!=(const maybe<V>& m) const {
maybe<V>& operator=(const maybe<V>& m) = delete;
inline const bool operator!=(const maybe<V>& m) const {
return !this->operator==(m);
}
const bool operator==(const maybe<V>& m) const {
inline const bool operator==(const maybe<V>& m) const {
if (this == &m)
return true;
if (!hasv)
@ -141,7 +135,7 @@ public:
private:
const bool hasv;
V v;
const V v;
template<typename X> friend const bool hasContent(const maybe<X>& m);
template<typename X> friend const X content(const maybe<X>& m);
@ -150,7 +144,7 @@ private:
/**
* Write a maybe monad to a stream.
*/
template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) {
template<typename V> inline ostream& operator<<(ostream& out, const maybe<V>& m) {
if (!hasContent(m)) {
out << "nothing";
return out;
@ -162,25 +156,25 @@ template<typename V> ostream& operator<<(ostream& out, const maybe<V>& m) {
/**
* Return a maybe monad with a value in it.
*/
template<typename V> const maybe<V> mkjust(const V& v) {
template<typename V> inline const maybe<V> mkjust(const V& v) {
return maybe<V>(v);
}
template<typename V> const lambda<maybe<V>(const V)> just() {
template<typename V> inline const lambda<const maybe<V>(const V)> just() {
return mkjust<V>;
}
/**
* Returns true if a maybe monad contains a content.
*/
template<typename V> const bool hasContent(const maybe<V>& m) {
template<typename V> inline const bool hasContent(const maybe<V>& m) {
return m.hasv;
}
/**
* Returns the content of a maybe monad.
*/
template<typename V> const V content(const maybe<V>& m) {
template<typename V> inline const V content(const maybe<V>& m) {
return m.v;
}
@ -188,13 +182,13 @@ template<typename V> const V content(const maybe<V>& m) {
* Bind a function to a maybe monad. Passes the value in the monad to the function
* if present, or does nothing if there's no value.
*/
template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(const V)>& f) {
template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const lambda<const maybe<R>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
}
template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) {
template<typename R, typename V> inline const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) {
if (!hasContent(m))
return m;
return f(content(m));
@ -207,30 +201,22 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co
*/
template<typename V, typename F = string, typename C = int> class failable {
public:
failable() : hasv(false), c(-1) {
inline failable() : hasv(false), v(), c(-1) {
}
failable(const V& v) : hasv(true), v(v), c(-1) {
inline failable(const V& v) : hasv(true), v(v), c(-1) {
}
failable(const failable<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) {
inline failable(const failable<V, F, C>& m) : hasv(m.hasv), v(m.v), f(m.f), c(m.c) {
}
const failable<V, F, C>& operator=(const failable<V, F, C>& m) {
if (&m == this)
return *this;
hasv = m.hasv;
v = m.v;
f = m.f;
c = m.c;
return *this;
}
failable<V, F, C>& operator=(const failable<V, F, C>& m) = delete;
const bool operator!=(const failable<V, F, C>& m) const {
inline const bool operator!=(const failable<V, F, C>& m) const {
return !this->operator==(m);
}
const bool operator==(const failable<V, F, C>& m) const {
inline const bool operator==(const failable<V, F, C>& m) const {
if (this == &m)
return true;
if (!hasv)
@ -239,7 +225,7 @@ public:
}
private:
failable(const bool hasv, const F& f, const C& c) : hasv(hasv), f(f), c(c) {
inline failable(const bool hasv, const F& f, const C& c) : hasv(hasv), v(), f(f), c(c) {
}
template<typename A, typename B, typename R> friend const bool hasContent(const failable<A, B, R>& m);
@ -250,16 +236,16 @@ private:
template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f, const int c, const bool log);
template<typename A> friend const failable<A> mkfailure();
bool hasv;
V v;
F f;
C c;
const bool hasv;
const V v;
const F f;
const C c;
};
/**
* Write a failable monad to a stream.
*/
template<typename V, typename F, typename C> ostream& operator<<(ostream& out, const failable<V, F, C>& m) {
template<typename V, typename F, typename C> inline ostream& operator<<(ostream& out, const failable<V, F, C>& m) {
if (!hasContent(m)) {
out << reason(m) << " : " << rcode(m);
return out;
@ -271,20 +257,22 @@ template<typename V, typename F, typename C> ostream& operator<<(ostream& out, c
/**
* Returns a failable monad with a success value in it.
*/
template<typename V, typename F, typename C> const failable<V, F, C> mksuccess(const V& v) {
template<typename V, typename F, typename C> inline const failable<V, F, C> mksuccess(const V& v) {
return failable<V, F, C>(v);
}
template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> success() {
template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> success() {
return mksuccess<V, F, C>;
}
#ifdef WANT_MAINTAINER_BACKTRACE
/**
* Demangle a C++ function name.
*/
const string demangleFrame(const char* fun) {
inline const string demangleFrame(const char* fun) {
int status;
char* name = abi::__cxa_demangle(fun, 0, 0, &status);
char* const name = abi::__cxa_demangle(fun, 0, 0, &status);
if (name == NULL)
return fun;
const string s = name;
@ -295,12 +283,12 @@ const string demangleFrame(const char* fun) {
/**
* Format a backtrace frame.
*/
const char* formatFrameFile(const char* file) {
const char* s = strrchr(file, '/');
inline const char* const formatFrameFile(const char* const file) {
const char* const s = strrchr(file, '/');
return s == NULL? file : s + 1;
}
const string formatFrame(const char* symbol) {
inline const string formatFrame(const char* const symbol) {
#ifdef __clang__
// Mac OS X CLang/LLVM stack frame format
// 0 kernel-test 0x000000010d440179 _ZN7tuscany9mkfailureINS_5valueENS_6stringEiEEKNS_8failableIT_T0_T1_EERKS5_RKS6_b + 265
@ -349,7 +337,7 @@ const string formatFrame(const char* symbol) {
/**
* Log backtrace frames.
*/
const bool logFrames(char** symbols, const int frames, const bool log) {
inline const bool logFrames(char** const symbols, const int frames, const bool log) {
if (frames == 0)
return true;
#ifdef WANT_MAINTAINER_LOG
@ -364,26 +352,30 @@ const bool logFrames(char** symbols, const int frames, const bool log) {
/**
* Log a backtrace.
*/
const bool logBacktrace(void** callstack, const int frames, const bool log) {
inline const bool logBacktrace(void** const callstack, const int frames, const bool log) {
char** symbols = backtrace_symbols(callstack, frames);
logFrames(symbols, frames, log);
free(symbols);
return true;
}
#endif
/**
* Returns a failable monad with a failure in it.
*/
template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) {
template<typename V, typename F, typename C> inline const failable<V, F, C> mkfailure(const F& f, const C& c, const bool log = true) {
#ifdef WANT_MAINTAINER_LOG
if (!log) {
// Log the failure
debug(f, "failable::mkfailure");
#ifdef WANT_MAINTAINER_BACKTRACE
// Log the call stack
void* callstack[16];
const int frames = backtrace(callstack, 16);
logBacktrace(callstack, frames, log);
#endif
}
#endif
if (log) {
@ -393,63 +385,65 @@ template<typename V, typename F, typename C> const failable<V, F, C> mkfailure(c
// Log the failure
cfailure << "failable::mkfailure: " << f << " : " << c << endl;
#ifdef WANT_MAINTAINER_BACKTRACE
// Print the call stack
void* callstack[16];
const int frames = backtrace(callstack, 16);
logBacktrace(callstack, frames, log);
#endif
}
}
return failable<V, F, C>(false, f, c);
}
template<typename V, typename F> const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) {
template<typename V, typename F> inline const failable<V, F> mkfailure(const F& f, const int c = -1, const bool log = true) {
return mkfailure<V, F, int>(f, c, log);
}
template<typename V> const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) {
template<typename V> inline const failable<V> mkfailure(const char* f, const int c = -1, const bool log = true) {
return mkfailure<V, string, int>(string(f), c, log);
}
template<typename V> const failable<V> mkfailure() {
template<typename V> inline const failable<V> mkfailure() {
return failable<V, string>(false, string(), -1);
}
template<typename V, typename F, typename C> const lambda<failable<V, F, C>(const V)> failure() {
template<typename V, typename F, typename C> inline const lambda<const failable<V, F, C>(const V)> failure() {
return mkfailure<V, F, C>;
}
/**
* Convert a failable of a given type to a failable of another type.
*/
template<typename V, typename F, typename C, typename X> const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = true) {
template<typename V, typename F, typename C, typename X> inline const failable<V, F, C> mkfailure(const failable<X, F, C>& f, const bool log = false) {
return mkfailure<V, F, C>(reason(f), rcode(f), log);
}
/**
* Returns true if the monad contains a content.
*/
template<typename V, typename F, typename C> const bool hasContent(const failable<V, F, C>& m) {
template<typename V, typename F, typename C> inline const bool hasContent(const failable<V, F, C>& m) {
return m.hasv;
}
/**
* Returns the content of a failable monad.
*/
template<typename V, typename F, typename C> const V content(const failable<V, F, C>& m) {
template<typename V, typename F, typename C> inline const V content(const failable<V, F, C>& m) {
return m.v;
}
/**
* Returns the reason for failure of a failable monad.
*/
template<typename V, typename F, typename C> const F reason(const failable<V, F, C>& m) {
template<typename V, typename F, typename C> inline const F reason(const failable<V, F, C>& m) {
return m.f;
}
/**
* Returns the reason code for failure of a failable monad.
*/
template<typename V, typename F, typename C> const C rcode(const failable<V, F, C>& m) {
template<typename V, typename F, typename C> inline const C rcode(const failable<V, F, C>& m) {
return m.c;
}
@ -458,14 +452,14 @@ template<typename V, typename F, typename C> const C rcode(const failable<V, F,
* if present, or does nothing if there's no value and a failure instead.
*/
template<typename R, typename FR, typename XR, typename V, typename FV, typename XV>
const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<failable<R, FR, XR>(const V)>& f) {
inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const lambda<const failable<R, FR, XR>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
}
template<typename R, typename FR, typename XR, typename V, typename FV, typename XV>
const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) {
inline const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failable<R, FR, XR> (* const f)(const V)) {
if (!hasContent(m))
return m;
return f(content(m));
@ -476,30 +470,27 @@ const failable<R, FR, XR> operator>>(const failable<V, FV, XV>& m, const failabl
*/
template<typename S, typename V> class scp {
public:
scp(const S& s, const V& v) : s(s), v(v) {
inline scp(const S& s, const V& v) : s(s), v(v) {
}
operator const S() const {
inline operator const S() const {
return s;
}
operator const V() const {
inline operator const V() const {
return v;
}
const scp<S, V>& operator=(const scp<S, V>& p) {
if(this == &p)
return *this;
s = p.s;
v = p.v;
return *this;
inline scp(const scp<S, V>& p) : s(p.s), v(p.v) {
}
const bool operator!=(const scp<S, V>& p) const {
scp<S, V>& operator=(const scp<S, V>& p) = delete;
inline const bool operator!=(const scp<S, V>& p) const {
return !this->operator==(p);
}
const bool operator==(const scp<S, V>& p) const {
inline const bool operator==(const scp<S, V>& p) const {
if (this == &p)
return true;
return s == p.s && v == p.v;
@ -516,14 +507,14 @@ private:
/**
* Returns the state of a state-content pair.
*/
template<typename S, typename V> const S scpstate(const scp<S, V>& m) {
template<typename S, typename V> inline const S scpstate(const scp<S, V>& m) {
return m.s;
}
/**
* Returns the content of a state-content pair.
*/
template<typename S, typename V> const S content(const scp<S, V>& m) {
template<typename S, typename V> inline const S content(const scp<S, V>& m) {
return m.v;
}
@ -532,38 +523,36 @@ template<typename S, typename V> const S content(const scp<S, V>& m) {
*/
template<typename S, typename V> class state {
public:
state(const lambda<scp<S, V>(const S)>& f) : f(f) {
inline state(const lambda<const scp<S, V>(const S)>& f) : f(f) {
}
const scp<S, V> operator()(const S& s) const {
inline const scp<S, V> operator()(const S& s) const {
return f(s);
}
const state<S, V>& operator=(const state<S, V>& m) {
if(this == &m)
return *this;
f = m.f;
return *this;
inline state(const state<S, V>& m) : f(m.f) {
}
const bool operator!=(const state<S, V>& m) const {
state<S, V>& operator=(const state<S, V>& m) = delete;
inline const bool operator!=(const state<S, V>& m) const {
return !this->operator==(m);
}
const bool operator==(const state<S, V>& m) const {
inline const bool operator==(const state<S, V>& m) const {
if (this == &m)
return true;
return f == m.f;
}
private:
const lambda<scp<S, V>(const S)> f;
const lambda<const scp<S, V>(const S)> f;
};
/**
* Write a state monad to a stream.
*/
template<typename S, typename V> ostream& operator<<(ostream& out, const state<S, V>& m) {
template<typename S, typename V> inline ostream& operator<<(ostream& out, const state<S, V>& m) {
const S s = m;
const V v = m;
out << '(' << s << ' ' << v << ')';
@ -573,17 +562,10 @@ template<typename S, typename V> ostream& operator<<(ostream& out, const state<S
/**
* Return a state monad carrying a result content.
*/
template<typename S, typename V> struct returnState {
const V v;
returnState(const V& v) : v(v) {
}
const scp<S, V> operator()(const S& s) const {
template<typename S, typename V> inline const state<S, V> result(const V& v) {
return state<S, V>([v](const S& s) -> const scp<S, V> {
return scp<S, V>(s, v);
}
};
template<typename S, typename V> const state<S, V> result(const V& v) {
return state<S, V>(returnState<S, V>(v));
});
}
/**
@ -591,7 +573,7 @@ template<typename S, typename V> const state<S, V> result(const V& v) {
* A transformer function takes a state and returns an scp pair carrying a content and a
* new (transformed) state.
*/
template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(const S)>& f) {
template<typename S, typename V> inline const state<S, V> transformer(const lambda<const scp<S, V>(const S)>& f) {
return state<S, V>(f);
}
@ -599,28 +581,19 @@ template<typename S, typename V> const state<S, V> transformer(const lambda<scp<
* Bind a function to a state monad. The function takes a content and returns a state
* monad carrying a return content.
*/
template<typename S, typename A, typename B> struct stateBind {
const state<S, A> st;
const lambda<state<S, B>(const A)>f;
stateBind(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) : st(st), f(f) {
}
const scp<S, B> operator()(const S& is) const {
template<typename S, typename A, typename B>
inline const state<S, B> operator>>(const state<S, A>& st, const lambda<const state<S, B>(const A)>& f) {
const lambda<const scp<S, B>(const S&)> stateBind = [st, f](const S& is) -> const scp<S, B> {
const scp<S, A> iscp = st(is);
const state<S, B> m = f((A)iscp);
return m((S)iscp);
}
};
template<typename S, typename A, typename B>
const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) {
return state<S, B>(stateBind<S, A , B>(st, f));
};
return state<S, B>(stateBind);
}
template<typename S, typename A, typename B>
const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) {
return state<S, B>(stateBind<S, A , B>(st, f));
inline const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) {
return st >> lambda<const state<S, B>(const A)>(f);
}
}

View file

@ -35,84 +35,58 @@ namespace tuscany {
int inci = 0;
struct incPerf {
incPerf() {
}
const bool operator()() const {
inci = inci + 1;
return true;
}
};
const gc_ptr<int> tlsic() {
gc_ptr<int> i = new (gc_new<int>()) int();
const gc_ptr<int> i = new (gc_new<int>()) int();
*i = 0;
return i;
}
const perthread_ptr<int> tlsi(tlsic);
struct tlsPerf {
tlsPerf() {
}
const bool operator()() const {
*tlsi = *tlsi + 1;
return true;
}
};
#ifdef WANT_THREADS
int addi = 0;
struct addAndFetchPerf {
addAndFetchPerf() {
}
const bool operator()() const {
__sync_add_and_fetch(&addi, 1);
return true;
}
};
int muxi = 0;
struct mutexPerf {
pthread_mutex_t* mutex;
mutexPerf(pthread_mutex_t* mutex) : mutex(mutex) {
}
const bool operator()() const {
pthread_mutex_lock(mutex);
muxi = muxi + 1;
pthread_mutex_unlock(mutex);
return true;
}
};
#endif
bool testAtomicPerf() {
const bool testAtomicPerf() {
const int count = 100000;
{
const lambda<bool()> l = incPerf();
const blambda l = []() -> const bool {
inci = inci + 1;
return true;
};
cout << "Non-atomic inc test " << time(l, 1000, count) << " ms" << endl;
assert(inci == count + 1000);
}
#ifdef WANT_THREADS
{
const lambda<bool()> l = addAndFetchPerf();
const blambda l = []() -> const bool {
__sync_add_and_fetch(&addi, 1);
return true;
};
cout << "Atomic inc test " << time(l, 1000, count) << " ms" << endl;
assert(addi == count + 1000);
}
{
pthread_mutex_t mutex;
pthread_mutex_init(&mutex, NULL);
const lambda<bool()> l = mutexPerf(&mutex);
const blambda l = [&mutex]() -> const bool {
pthread_mutex_lock(&mutex);
muxi = muxi + 1;
pthread_mutex_unlock(&mutex);
return true;
};
cout << "Locked inc test " << time(l, 1000, count) << " ms" << endl;
assert(muxi == count + 1000);
pthread_mutex_destroy(&mutex);
}
#endif
{
const lambda<bool()> l = tlsPerf();
const blambda l = []() -> const bool {
*tlsi = *tlsi + 1;
return true;
};
cout << "Thread local inc test " << time(l, 1000, count) << " ms" << endl;
assert(*tlsi == count + 1000);
}
@ -130,7 +104,7 @@ const int mtsquare(const int x) {
const list<future<int> > submitSquares(worker& w, const int max, const int i) {
if (i == max)
return list<future<int> >();
const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), i);
const lambda<const int()> func = curry(lambda<const int(const int)> (mtsquare), i);
return cons(submit(w, func), submitSquares(w, max, i + 1));
}
@ -143,7 +117,7 @@ bool checkSquareResults(const list<future<int> > r, int i) {
}
const gc_ptr<unsigned long> tlsvc() {
gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long();
const gc_ptr<unsigned long> i = new (gc_new<unsigned long>()) unsigned long();
*i = 0l;
return i;
}
@ -181,11 +155,11 @@ const bool unblockWorkers(wqueue<bool>& wq, const int n) {
const list<future<long int> > submitTLSSets(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) {
if (i == max)
return list<future<long int> >();
const lambda<long int()> func = curry(lambda<long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq);
const lambda<const long int()> func = curry(lambda<const long int(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlsset), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq);
return cons(submit(w, func), submitTLSSets(w, wq, xq, max, i + 1));
}
bool checkTLSSets(const list<future<long int> > s) {
const bool checkTLSSets(const list<future<long int> > s) {
if (isNil(s))
return true;
assert(car(s) == 0);
@ -195,22 +169,22 @@ bool checkTLSSets(const list<future<long int> > s) {
const list<future<bool> > submitTLSChecks(worker& w, wqueue<bool>& wq, wqueue<bool>& xq, const int max, const int i) {
if (i == max)
return list<future<bool> >();
const lambda<bool()> func = curry(lambda<bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq);
const blambda func = curry(lambda<const bool(gc_ptr<wqueue<bool>>, gc_ptr<wqueue<bool>>)>(tlscheck), (gc_ptr<wqueue<bool>>)&wq, (gc_ptr<wqueue<bool>>)&xq);
return cons(submit(w, func), submitTLSChecks(w, wq, xq, max, i + 1));
}
bool checkTLSResults(const list<future<bool> > r) {
const bool checkTLSResults(const list<future<bool> > r) {
if (isNil(r))
return true;
assert(car(r) == true);
return checkTLSResults(cdr(r));
}
bool testWorker() {
const bool testWorker() {
const int max = 100;
worker w(max);
{
const lambda<int()> func = curry(lambda<int(const int)> (mtsquare), 2);
const lambda<const int()> func = curry(lambda<const int(const int)> (mtsquare), 2);
assert(submit(w, func) == 4);
}
{
@ -245,7 +219,7 @@ bool testWorker() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testAtomicPerf();

View file

@ -39,7 +39,7 @@ namespace tuscany {
/**
* Returns the current process id.
*/
unsigned long processId() {
inline const unsigned long processId() noexcept {
return (unsigned long)getpid();
}
@ -48,7 +48,7 @@ unsigned long processId() {
/**
* Returns the current thread id.
*/
unsigned long threadId() {
inline const unsigned long threadId() noexcept{
return (unsigned long)pthread_self();
}
@ -60,20 +60,20 @@ template<typename T> class future {
private:
template<typename X> class futureValue {
public:
futureValue() : hasValue(false) {
inline futureValue() noexcept : hasValue(false) {
pthread_mutex_init(&valueMutex, NULL);
pthread_cond_init(&valueCond, NULL);
}
futureValue(const futureValue& fv) : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) {
inline futureValue(const futureValue& fv) noexcept : valueMutex(fv.valueMutex), valueCond(fv.valueCond), hasValue(fv.hasValue), value(fv.value) {
}
~futureValue() {
inline ~futureValue() noexcept {
//pthread_mutex_destroy(&valueMutex);
//pthread_cond_destroy(&valueCond);
}
bool set(const T& v) {
inline const bool set(const T& v) noexcept {
pthread_mutex_lock(&valueMutex);
if(hasValue) {
pthread_mutex_unlock(&valueMutex);
@ -86,7 +86,7 @@ private:
return true;
}
const T get() {
inline const T get() noexcept {
pthread_mutex_lock(&valueMutex);
while(!hasValue) {
pthread_cond_wait(&valueCond, &valueMutex);
@ -100,37 +100,32 @@ private:
pthread_mutex_t valueMutex;
pthread_cond_t valueCond;
bool hasValue;
X value;
gc_mutable_ref<X> value;
};
gc_ptr<futureValue<T> > fvalue;
const gc_ptr<futureValue<T> > fvalue;
template<typename X> friend const X get(const future<X>& f);
template<typename X> friend bool set(const future<X>& f, const X& v);
template<typename X> friend const X get(const future<X>& f) noexcept;
template<typename X> friend bool set(const future<X>& f, const X& v) noexcept;
public:
future() : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) {
inline future() noexcept : fvalue(new (gc_new<futureValue<T> >()) futureValue<T>()) {
}
~future() {
inline ~future() noexcept {
}
future(const future& f) : fvalue(f.fvalue) {
inline future(const future& f) noexcept : fvalue(f.fvalue) {
}
const future& operator=(const future& f) {
if (&f == this)
return *this;
fvalue = f.fvalue;
return *this;
}
const future& operator=(const future& f) = delete;
const future& operator=(const T& v) const {
inline const future& operator=(const T& v) const noexcept {
fvalue->set(v);
return *this;
}
operator const T() const {
inline operator const T() const noexcept {
return fvalue->get();
}
};
@ -140,16 +135,16 @@ public:
*/
template<typename T> class wqueue {
public:
wqueue(size_t max) : max(max), size(0), tail(0), head(0), values(new (gc_anew<T>(max)) T[max]) {
inline wqueue(size_t max) noexcept : max(max), size(0), tail(0), head(0), values(new (gc_anew<gc_mutable_ref<T> >(max)) gc_mutable_ref<T>[max]) {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&full, NULL);
pthread_cond_init(&empty, NULL);
}
wqueue(const wqueue& wq) : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) {
inline wqueue(const wqueue& wq) noexcept : max(wq.max), size(wq.size), tail(wq.tail), head(wq.head), mutex(wq.mutex), full(wq.full), empty(wq.empty), values(wq.values) {
}
~wqueue() {
inline ~wqueue() {
//pthread_mutex_destroy(&mutex);
//pthread_cond_destroy(&full);
//pthread_cond_destroy(&empty);
@ -163,16 +158,16 @@ private:
pthread_mutex_t mutex;
pthread_cond_t full;
pthread_cond_t empty;
gc_ptr<T> values;
gc_ptr<gc_mutable_ref<T> > values;
template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v);
template<typename X> friend const X dequeue(wqueue<X>& q);
template<typename X> friend const size_t enqueue(wqueue<X>& q, const X& v) noexcept;
template<typename X> friend const X dequeue(wqueue<X>& q) noexcept;
};
/**
* Adds an element to the tail of the queue.
*/
template<typename T> const size_t enqueue(wqueue<T>&q, const T& v) {
template<typename T> inline const size_t enqueue(wqueue<T>&q, const T& v) noexcept {
pthread_mutex_lock(&q.mutex);
while(q.size == q.max)
pthread_cond_wait(&q.full, &q.mutex);
@ -187,7 +182,7 @@ template<typename T> const size_t enqueue(wqueue<T>&q, const T& v) {
/**
* Returns the element at the head of the queue.
*/
template<typename T> const T dequeue(wqueue<T>& q) {
template<typename T> inline const T dequeue(wqueue<T>& q) noexcept {
pthread_mutex_lock(&q.mutex);
while(q.size == 0)
pthread_cond_wait(&q.empty, &q.mutex);
@ -202,13 +197,13 @@ template<typename T> const T dequeue(wqueue<T>& q) {
/**
* The worker thread function.
*/
void *workerThreadFunc(void *arg) {
inline void* workerThreadFunc(void* arg) noexcept {
int ost;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ost);
int ot;
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &ot);
wqueue<lambda<bool()> >* work = reinterpret_cast<wqueue<lambda<bool()> >*>(arg);
wqueue<blambda >* work = reinterpret_cast<wqueue<blambda >*>(arg);
while(dequeue(*work)())
;
return NULL;
@ -217,7 +212,7 @@ void *workerThreadFunc(void *arg) {
/**
* Returns a list of worker threads.
*/
const list<pthread_t> workerThreads(wqueue<lambda<bool()> >& wqueue, const size_t count) {
inline const list<pthread_t> workerThreads(wqueue<blambda >& wqueue, const size_t count) noexcept {
if (count == 0)
return list<pthread_t>();
pthread_t thread;
@ -235,32 +230,32 @@ private:
// copies of the queue and thread pool when a worker is copied
class sharedWorker {
public:
sharedWorker(size_t max) : work(wqueue<lambda<bool()> >(max)), threads(workerThreads(work, max)) {
inline sharedWorker(size_t max) noexcept : work(wqueue<blambda >(max)), threads(workerThreads(work, max)) {
}
wqueue<lambda<bool()> > work;
wqueue<blambda > work;
const list<pthread_t> threads;
};
public:
worker(size_t max) : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) {
inline worker(size_t max) noexcept : w(*(new (gc_new<sharedWorker>()) sharedWorker(max))) {
}
worker(const worker& wk) : w(wk.w) {
inline worker(const worker& wk) noexcept : w(wk.w) {
}
private:
sharedWorker& w;
template<typename X> friend const future<X> submit(worker& w, const lambda<X()>& func);
friend const bool shutdown(worker& w);
friend const bool cancel(worker& w);
template<typename X> friend const future<X> submit(const worker& w, const lambda<const X()>& func) noexcept;
friend const bool shutdown(const worker& w) noexcept;
friend const bool cancel(const worker& w) noexcept;
};
/**
* Function used to wrap work submitted to a worker.
*/
template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& fut) {
template<typename R> inline const bool submitFunc(const lambda<const R()>& func, const future<R>& fut) noexcept {
fut = func();
return true;
}
@ -268,9 +263,9 @@ template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& f
/**
* Submits work to a worker.
*/
template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) {
template<typename R> inline const future<R> submit(const worker& w, const lambda<const R()>& func) noexcept {
const future<R> fut;
const lambda<bool()> f = curry(lambda<bool(const lambda<R()>, future<R>)>(submitFunc<R>), func, fut);
const blambda f = curry(lambda<const bool(const lambda<const R()>, future<R>)>(submitFunc<R>), func, fut);
enqueue(w.w.work, f);
return fut;
}
@ -278,7 +273,7 @@ template<typename R> const future<R> submit(worker& w, const lambda<R()>& func)
/**
* Enqueues shutdown requests.
*/
const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()> >& work) {
inline const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<blambda>& work) noexcept {
if (isNil(threads))
return true;
enqueue(work, result(false));
@ -288,7 +283,7 @@ const bool shutdownEnqueue(const list<pthread_t>& threads, wqueue<lambda<bool()>
/**
* Waits for shut down threads to terminate.
*/
const bool shutdownJoin(const list<pthread_t>& threads) {
inline const bool shutdownJoin(const list<pthread_t>& threads) noexcept {
if (isNil(threads))
return true;
pthread_join(car(threads), NULL);
@ -298,7 +293,7 @@ const bool shutdownJoin(const list<pthread_t>& threads) {
/**
* Shutdown a worker.
*/
const bool shutdown(worker& w) {
inline const bool shutdown(const worker& w) noexcept {
shutdownEnqueue(w.w.threads, w.w.work);
shutdownJoin(w.w.threads);
return true;
@ -307,14 +302,14 @@ const bool shutdown(worker& w) {
/**
* Cancel a worker.
*/
const bool cancel(const list<pthread_t>& threads) {
inline const bool cancel(const list<pthread_t>& threads) noexcept {
if (isNil(threads))
return true;
pthread_cancel(car(threads));
return cancel(cdr(threads));
}
const bool cancel(worker& w) {
inline const bool cancel(const worker& w) noexcept {
cancel(w.w.threads);
return true;
}
@ -324,7 +319,7 @@ const bool cancel(worker& w) {
/**
* Returns the current thread id.
*/
unsigned long threadId() {
inline const unsigned long threadId() noexcept {
return 0;
}
@ -335,114 +330,106 @@ unsigned long threadId() {
*/
template<typename T> class perthread_ptr {
public:
perthread_ptr() : key(createkey()), owner(true), cl(lambda<gc_ptr<T>()>()), managed(false) {
inline perthread_ptr() noexcept : key(createkey()), owner(true), cl(lambda<const gc_ptr<T>()>()), managed(false) {
}
perthread_ptr(const lambda<gc_ptr<T>()>& cl) : key(createkey()), owner(true), cl(cl), managed(true) {
inline perthread_ptr(const lambda<const gc_ptr<T>()>& cl) noexcept : key(createkey()), owner(true), cl(cl), managed(true) {
}
~perthread_ptr() {
inline ~perthread_ptr() noexcept {
if (owner)
deletekey(key);
}
perthread_ptr(const perthread_ptr& c) : key(c.key), owner(false), cl(c.cl), managed(c.managed) {
inline perthread_ptr(const perthread_ptr& c) noexcept : key(c.key), owner(false), cl(c.cl), managed(c.managed) {
}
perthread_ptr& operator=(const perthread_ptr& r) throw() {
if(this == &r)
return *this;
key = r.key;
owner = false;
cl = r.cl;
managed = r.managed;
return *this;
}
perthread_ptr& operator=(const perthread_ptr& r) = delete;
const perthread_ptr& operator=(const gc_ptr<T>& v) {
inline const perthread_ptr& operator=(const gc_ptr<T>& v) const noexcept {
set(v);
return *this;
}
const perthread_ptr& operator=(T* v) {
inline const perthread_ptr& operator=(T* const v) const noexcept {
set(v);
return *this;
}
const bool operator==(const gc_ptr<T>& r) const throw() {
inline const bool operator==(const gc_ptr<T>& r) const noexcept {
return get() == r;
}
const bool operator==(T* p) const throw() {
inline const bool operator==(const T* const p) const noexcept {
return get() == p;
}
const bool operator!=(const gc_ptr<T>& r) const throw() {
inline const bool operator!=(const gc_ptr<T>& r) const noexcept {
return !this->operator==(r);
}
const bool operator!=(T* p) const throw() {
inline const bool operator!=(const T* const p) const noexcept {
return !this->operator==(p);
}
T& operator*() const throw() {
inline T& operator*() const noexcept {
return *get();
}
T* operator->() const throw() {
inline T* const operator->() const noexcept {
return get();
}
operator gc_ptr<T>() const {
inline operator gc_ptr<T>() const {
return get();
}
operator T*() const {
inline operator T* const () const {
return get();
}
private:
#ifdef WANT_THREADS
pthread_key_t createkey() {
inline const pthread_key_t createkey() noexcept {
pthread_key_t k;
pthread_key_create(&k, NULL);
return k;
}
bool deletekey(pthread_key_t k) {
inline const bool deletekey(pthread_key_t k) noexcept {
pthread_key_delete(k);
return true;
}
bool set(const gc_ptr<T>& v) {
inline const bool set(const gc_ptr<T>& v) const noexcept {
pthread_setspecific(key, (T*)v);
return true;
}
gc_ptr<T> get() const {
const gc_ptr<T> v = static_cast<T*>(pthread_getspecific(key));
inline const gc_ptr<T> get() const noexcept {
const gc_ptr<T> v = (T*)(pthread_getspecific(key));
if (v != NULL || !managed)
return v;
const gc_ptr<T> nv = cl();
pthread_setspecific(key, nv);
pthread_setspecific(key, (T*)nv);
return nv;
}
#else
gc_ptr<gc_ptr<T> > createkey() {
inline const gc_ptr<gc_ptr<T> > createkey() noexcept {
return new (gc_new<gc_ptr<T> >()) gc_ptr<T>();
}
bool deletekey(unused gc_ptr<gc_ptr<T> > k) {
inline const bool deletekey(unused gc_ptr<gc_ptr<T> > k) noexcept {
return true;
}
bool set(const gc_ptr<T>& v) {
inline const bool set(const gc_ptr<T>& v) const noexcept {
*key = v;
return true;
}
gc_ptr<T> get() const {
inline const gc_ptr<T> get() const noexcept {
if (*key != NULL || !managed)
return *key;
*key = cl();
@ -452,14 +439,14 @@ private:
#endif
#ifdef WANT_THREADS
pthread_key_t key;
const pthread_key_t key;
#else
gc_ptr<gc_ptr<T> >key;
const gc_ptr<gc_ptr<T> >key;
#endif
bool owner;
lambda<const gc_ptr<T>()> cl;
bool managed;
const bool owner;
const lambda<const gc_ptr<T>()> cl;
const bool managed;
};
}

View file

@ -37,21 +37,15 @@ namespace tuscany
/**
* Measure the time required to perform a function in msec.
*/
struct timeLambda {
const lambda<bool()> f;
timeLambda(const lambda<bool()>& f) : f(f) {
}
bool operator()(const long count) const {
inline const double time(const blambda& f, const long warmup, const long count) {
struct timeval start;
struct timeval end;
const lambda<const bool(const long)> tl = [f](const long count) -> const bool {
for (long i = 0; i < count; i++)
f();
return true;
}
};
const double time(const lambda<bool()>& f, const long warmup, const long count) {
const lambda<bool(long)> tl = timeLambda(f);
struct timeval start;
struct timeval end;
};
tl(warmup);
gettimeofday(&start, NULL);
@ -62,13 +56,13 @@ const double time(const lambda<bool()>& f, const long warmup, const long count)
return (double)t / (double)count;
}
const unsigned long timems() {
inline const unsigned long timems() {
struct timeval t;
gettimeofday(&t, NULL);
return (unsigned long)(t.tv_sec * 1000 + t.tv_usec / 1000);
}
const unsigned long timens() {
inline const unsigned long timens() {
struct timeval t;
gettimeofday(&t, NULL);
return (unsigned long)(t.tv_sec * 1000000000 + t.tv_usec * 1000);

View file

@ -38,14 +38,14 @@ namespace tuscany {
/**
* Instrumentable memcpy.
*/
void* stream_memcpy(void* t, const void* s, const size_t n) {
inline void* stream_memcpy(void* t, const void* s, const size_t n) {
return memcpy(t, s, n);
}
/**
* Write a list of strings into a buffer.
*/
const bool writeList(const list<string>& l, char* buf) {
const bool writeList(const list<string>& l, char* const buf) {
if (isNil(l))
return true;
const string c = car(l);
@ -59,63 +59,108 @@ const bool writeList(const list<string>& l, char* buf) {
*/
class ostringstream : public ostream {
public:
ostringstream() : len(0) {
inline ostringstream() : len(0), accumbuf(NULL), accumlen(0), buf() {
}
~ostringstream() {
inline ~ostringstream() {
}
ostringstream(const ostringstream& os) {
len = os.len;
buf = os.buf;
inline ostringstream(const ostringstream& os) : len(os.len), accumbuf(os.accumbuf), accumlen(os.accumlen), buf(os.buf) {
}
ostringstream& vprintf(const char* fmt, ...) {
inline ostringstream& vprintf(const char* const fmt, ...) {
va_list args;
string s;
va_start (args, fmt);
s.len = vsnprintf(NULL, 0, fmt, args);
s.buf = gc_cnew(s.len + 1);
const size_t l = vsnprintf(NULL, 0, fmt, args);
if (l <= 256) {
char c[256];
va_start (args, fmt);
vsnprintf(c, l + 1, fmt, args);
va_end (args);
accumulate(c, l);
return *this;
}
spill();
char* const sbuf = gc_cnew(l + 1);
va_start (args, fmt);
vsnprintf(s.buf, s.len + 1, fmt, args);
buf = cons(s, buf);
len += s.len;
vsnprintf(sbuf, l + 1, fmt, args);
va_end (args);
buf = cons(string(sbuf, l, false), (const list<string>)buf);
len += l;
return *this;
}
ostringstream& write(const string& s) {
buf = cons(s, buf);
inline ostringstream& write(const string& s) {
if (s.len <= 256) {
accumulate(s.buf, s.len);
return *this;
}
spill();
buf = cons(s, (const list<string>)buf);
len += s.len;
return *this;
}
ostringstream& flush() {
inline ostringstream& write(const char c) {
accumulate(&c, 1);
return *this;
}
inline ostringstream& flush() {
spill();
return *this;
}
private:
const string str() {
if (isNil(buf))
return string();
string s;
s.len = len;
s.buf = gc_cnew(s.len + 1);
writeList(buf, s.buf + len);
s.buf[s.len] = '\0';
return s;
inline const string str() {
spill();
if (isNil((const list<string>)buf))
return emptyString;
char* const sbuf = gc_cnew(len + 1);
writeList(buf, sbuf + len);
sbuf[len] = '\0';
return string(sbuf, len, false);
}
inline const bool accumulate(const char* const c, const size_t l) {
if (accumbuf == NULL)
accumbuf = gc_cnew(65);
for(size_t i = 0; i < l; i++) {
accumbuf[accumlen] = c[i];
accumlen++;
if (accumlen == 64) {
accumbuf[accumlen] = '\0';
buf = cons(string(accumbuf, accumlen, false), (const list<string>)buf);
accumbuf = i < l? gc_cnew(65) : NULL;
accumlen = 0;
}
}
accumbuf[accumlen] = '\0';
len += l;
return true;
}
inline const bool spill() {
if (accumbuf == NULL)
return true;
buf = cons(string(accumbuf, accumlen), (const list<string>)buf);
accumbuf = NULL;
accumlen = 0;
return true;
}
friend const string str(ostringstream& os);
size_t len;
list<string> buf;
char* accumbuf;
size_t accumlen;
gc_mutable_ref<list<string> > buf;
};
/**
* Return a string representation of a stream.
*/
const string str(ostringstream& os) {
inline const string str(ostringstream& os) {
return os.str();
}
@ -124,23 +169,16 @@ const string str(ostringstream& os) {
*/
class istringstream : public istream {
public:
istringstream(const string& s) {
cur = 0;
const size_t slen = length(s);
len = slen;
buf = c_str(s);
}
~istringstream() {
inline istringstream(const string& s) : len(length(s)), cur(0), buf(c_str(s)) {
}
istringstream(const istringstream& is) {
len = is.len;
cur = is.cur;
buf = is.buf;
inline ~istringstream() {
}
const size_t read(void* b, size_t size) {
inline istringstream(const istringstream& is) : len(is.len), cur(is.cur), buf(is.buf) {
}
inline const size_t read(void* const b, const size_t size) {
const size_t n = len - cur;
if (n == 0)
return 0;
@ -154,30 +192,28 @@ public:
return n;
}
const bool eof() {
inline const bool eof() {
return cur == len;
}
const bool fail() {
inline const bool fail() {
return false;
}
const int get() {
if (eof())
inline const int get() {
if (cur == len)
return -1;
const int c = buf[cur];
cur += 1;
return c;
return buf[cur++];
}
const int peek() {
if (eof())
inline const int peek() {
if (cur == len)
return -1;
return buf[cur];
}
private:
size_t len;
const size_t len;
size_t cur;
const char* buf;
};
@ -185,62 +221,52 @@ private:
/**
* Tokenize a string into a list of strings.
*/
const list<string> tokenize(const char* sep, const string& str) {
struct nested {
static const list<string> tokenize(const char* sep, const size_t slen, const string& str, const size_t start) {
if (start >= length(str))
return list<string>();
const size_t i = find(str, sep, start);
if (i == length(str))
return mklist(string(substr(str, start)));
return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen));
}
inline const list<string> tokenize(const char* const sep, const string& str) {
const lambda<const list<string>(const char* const, const size_t, const string&, const size_t)> tokenize = [&tokenize](const char* const sep, const size_t slen, const string& str, const size_t start) -> const list<string> {
if (start >= length(str))
return list<string>();
const size_t i = find(str, sep, start);
if (i == length(str))
return mklist(string(substr(str, start)));
return cons(string(substr(str, start, i - start)), tokenize(sep, slen, str, i + slen));
};
return nested::tokenize(sep, strlen(sep), str, 0);
return tokenize(sep, strlen(sep), str, 0);
}
/**
* Join a list of strings into a single string.
*/
const string join(const char* sep, const list<string>& l) {
struct nested {
static ostringstream& join(const char* sep, const list<string>& l, ostringstream& os) {
if (isNil(l))
return os;
os << car(l);
if (!isNil(cdr(l)))
os << sep;
return join(sep, cdr(l), os);
}
};
inline const string join(const char* const sep, const list<string>& l) {
ostringstream os;
return str(nested::join(sep, l, os));
const lambda<ostringstream&(const char* const, const list<string>&, ostringstream&)> join = [&join](const char* const sep, const list<string>& l, ostringstream& os) -> ostringstream& {
if (isNil(l))
return os;
os << car(l);
if (!isNil(cdr(l)))
os << sep;
return join(sep, cdr(l), os);
};
return str(join(sep, l, os));
}
/**
* Returns a lazy list view of an input stream.
*/
struct ilistRead{
istream &is;
ilistRead(istream& is) : is(is) {
}
const list<string> operator()() {
inline const list<string> streamList(istream& is) {
const lambda<const list<string>()> ilistRead = [&is, &ilistRead]() -> const list<string> {
char buffer[1024];
const size_t n = read(is, buffer, sizeof(buffer));
if (n ==0)
return list<string>();
return cons(string(buffer, n), (*this)());
}
};
const list<string> streamList(istream& is) {
return ilistRead(is)();
return cons(string(buffer, n), ilistRead());
};
return ilistRead();
}
/**
* Fragment the first element of a list of strings to fit the given max length.
*/
const list<string> fragment(list<string> l, size_t max) {
inline const list<string> fragment(const list<string>& l, const size_t max) {
const string s = car(l);
if (length(s) <= max)
return l;
@ -250,13 +276,26 @@ const list<string> fragment(list<string> l, size_t max) {
/**
* Write a list of strings to an output stream.
*/
ostream& write(const list<string>& l, ostream& os) {
inline ostream& write(const list<string>& l, ostream& os) {
if(isNil(l))
return os;
os << car(l);
return write(cdr(l), os);
}
/**
* Convert a list of strings to a string.
*/
inline const string write(const list<string>& l) {
if (isNil(l))
return emptyString;
if (isNil(cdr(l)))
return car(l);
ostringstream os;
write(l, os);
return str(os);
}
}
#endif /* tuscany_sstream_hpp */

View file

@ -38,66 +38,67 @@ namespace tuscany {
*/
class ostream {
public:
virtual ostream& vprintf(const char* fmt, ...) = 0;
virtual ostream& vprintf(const char* const fmt, ...) = 0;
virtual ostream& write(const string& s) = 0;
virtual ostream& write(const char c) = 0;
virtual ostream& flush() = 0;
};
/**
* Flush a stream.
*/
ostream& flush(ostream& os) {
inline ostream& flush(ostream& os) {
return os.flush();
}
/**
* Write simple values to a stream.
*/
ostream& operator<<(ostream& os, const char* v) {
inline ostream& operator<<(ostream& os, const char* const v) {
return os.vprintf("%s", v);
}
ostream& operator<<(ostream& os, const unsigned char* v) {
inline ostream& operator<<(ostream& os, const unsigned char* const v) {
return os.vprintf("%s", v);
}
ostream& operator<<(ostream& os, const char v) {
return os.vprintf("%c", v);
inline ostream& operator<<(ostream& os, const char v) {
return os.write(v);
}
ostream& operator<<(ostream& os, const int v) {
inline ostream& operator<<(ostream& os, const int v) {
return os.vprintf("%d", v);
}
ostream& operator<<(ostream& os, const unsigned int v) {
inline ostream& operator<<(ostream& os, const unsigned int v) {
return os.vprintf("%u", v);
}
ostream& operator<<(ostream& os, const long int v) {
inline ostream& operator<<(ostream& os, const long int v) {
return os.vprintf("%ld", v);
}
ostream& operator<<(ostream& os, const long unsigned int v) {
inline ostream& operator<<(ostream& os, const long unsigned int v) {
return os.vprintf("%lu", v);
}
ostream& operator<<(ostream& os, const double v) {
inline ostream& operator<<(ostream& os, const double v) {
return os.vprintf("%.10g", v);
}
ostream& operator<<(ostream& os, const void* v) {
inline ostream& operator<<(ostream& os, const void* const v) {
return os.vprintf("%p", v);
}
ostream& operator<<(ostream& os, const string& v) {
inline ostream& operator<<(ostream& os, const string& v) {
return os.write(v);
}
class stream_endl {
} endl;
ostream& operator<<(ostream& os, unused const stream_endl e) {
os.write("\n");
inline ostream& operator<<(ostream& os, unused const stream_endl e) {
os.write('\n');
return os.flush();
}
@ -106,7 +107,7 @@ ostream& operator<<(ostream& os, unused const stream_endl e) {
*/
class istream {
public:
virtual const size_t read(void* buf, size_t size) = 0;
virtual const size_t read(void* const buf, const size_t size) = 0;
virtual const bool eof() = 0;
virtual const bool fail() = 0;
virtual const int get() = 0;
@ -116,40 +117,61 @@ public:
/**
* Read from an input stream.
*/
const size_t read(istream& is, void * buf, size_t size) {
inline const size_t read(istream& is, void* const buf, const size_t size) {
return is.read(buf, size);
}
/**
* Return true if the end of an input stream has been reached.
*/
const bool eof(istream& is) {
inline const bool eof(istream& is) {
return is.eof();
}
/**
* Return true if an input stream can't be accessed.
*/
const bool fail(istream& is) {
inline const bool fail(istream& is) {
return is.fail();
}
/**
* Read a character from a stream.
*/
const int get(istream& is) {
inline const int get(istream& is) {
return is.get();
}
/**
* Peek a character from a stream.
*/
const int peek(istream& is) {
inline const int peek(istream& is) {
return is.peek();
}
template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) {
return out << p.ptr;
#ifndef WANT_RAW_PTR
/**
* Write a pointer.
*/
template<typename T> inline ostream& operator<<(ostream& out, const gc_ptr<T>& p) {
return out << (T*)p;
}
/**
* Write a mutable pointer.
*/
template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ptr<T>& p) {
return out << (T*)p;
}
#endif
/**
* Write a mutable reference.
*/
template<typename T> inline ostream& operator<<(ostream& out, const gc_mutable_ref<T>& r) {
return out << (T)r;
}
#ifdef WANT_MAINTAINER_LOG
@ -159,35 +181,40 @@ template<typename T> ostream& operator<<(ostream& out, const gc_ptr<T>& p) {
*/
class odebugstream : public ostream {
public:
odebugstream() {
inline odebugstream() : buf() {
}
odebugstream& vprintf(const char* fmt, ...) {
inline odebugstream& vprintf(const char* const fmt, ...) {
va_list args;
string s;
va_start (args, fmt);
s.len = vsnprintf(NULL, 0, fmt, args);
s.buf = gc_cnew(s.len + 1);
const size_t slen = vsnprintf(NULL, 0, fmt, args);
char* const sbuf = gc_cnew(slen + 1);
va_start (args, fmt);
vsnprintf(s.buf, s.len + 1, fmt, args);
buf = buf + s;
vsnprintf(sbuf, slen + 1, fmt, args);
buf = buf + string(sbuf, slen, false);
va_end (args);
return *this;
}
odebugstream& write(const string& s) {
inline odebugstream& write(const string& s) {
buf = buf + s;
return *this;
}
odebugstream& flush() {
inline odebugstream& write(const char c) {
buf = buf + c;
return *this;
}
inline odebugstream& flush() {
return *this;
}
private:
friend const string str(odebugstream& os);
string buf;
gc_mutable_ref<string> buf;
};
const string str(odebugstream& os) {

View file

@ -32,15 +32,15 @@
namespace tuscany {
bool testCopies() {
const bool testCopies() {
resetStringCopyCounters();
string x("abcd");
const string x("abcd");
assert(checkStringCopyCounters(1));
resetStringCopyCounters();
string y = string("abcd");
const string y = string("abcd");
assert(checkStringCopyCounters(1));
resetStringCopyCounters();
unused string z = y;
unused const string z = y;
assert(checkStringCopyCounters(0));
resetStringCopyCounters();
const list<string> pl = list<string>() + "abcd" + "efgh";
@ -51,7 +51,7 @@ bool testCopies() {
return true;
}
bool testString() {
const bool testString() {
const string s("abcd");
assert(length(s) == 4);
assert(!strcmp(c_str(s), "abcd"));
@ -89,12 +89,19 @@ bool testString() {
return true;
}
bool testStream() {
const bool testStream() {
ostringstream os;
os << "ab" << "cd";
cout << str(os) << endl;
assert(str(os) == "abcd");
ostringstream bos;
bos << "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
bos << "ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << str(bos) << endl;
assert(str(bos) ==
"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ");
ostringstream cs;
cs << "\'";
assert(str(cs) == "\'");
@ -113,69 +120,65 @@ bool testStream() {
return true;
}
std::string stdAdd(std::string& x, std::string& y) {
const std::string stdAdd(const std::string& x, const std::string& y) {
return x + y;
}
string add(string& x, string& y) {
const string add(const string& x, const string& y) {
return x + y;
}
char charBuffer[16385];
struct addStrings{
const size_t size;
addStrings(const size_t size) : size(size) {
}
bool operator()() const {
const size_t sz = size / 4;
string x(charBuffer, sz);
string y(charBuffer, sz);
assert(length(add(x, y)) == sz * 2);
return true;
}
};
struct addStdStrings{
const size_t size;
addStdStrings(const size_t size) : size(size) {
}
bool operator()() const {
const size_t sz = size / 4;
std::string x(charBuffer, sz);
std::string y(charBuffer, sz);
assert(stdAdd(x, y).length() == (unsigned int)(sz * 2));
return true;
}
};
bool testStringPerf() {
const bool testStringPerf() {
memset(charBuffer, 'A', 16384);
charBuffer[16384] = '\0';
const int count = 10000;
{
const lambda<bool()> a16 = addStrings(16);
const lambda<const blambda(const size_t size)> addStrings = [](const size_t size) -> const blambda {
const blambda l = [size]() -> const bool {
const size_t sz = size / 4;
const string x(charBuffer, sz);
const string y(charBuffer, sz);
assert(length(add(x, y)) == sz * 2);
return true;
};
return l;
};
const blambda a16 = addStrings(16);
cout << "string test " << time(a16, 5, count) << " ms" << endl;
const lambda<bool()> a32 =addStrings(32);
const blambda a32 =addStrings(32);
cout << "string test " << time(a32, 5, count) << " ms" << endl;
const lambda<bool()> a256 =addStrings(256);
const blambda a256 =addStrings(256);
cout << "string test " << time(a256, 5, count) << " ms" << endl;
const lambda<bool()> a1024 =addStrings(1024);
const blambda a1024 =addStrings(1024);
cout << "string test " << time(a1024, 5, count) << " ms" << endl;
const lambda<bool()> a4096 =addStrings(4096);
const blambda a4096 =addStrings(4096);
cout << "string test " << time(a4096, 5, count) << " ms" << endl;
}
{
const lambda<bool()> a16 =addStdStrings(16);
const lambda<const blambda(const size_t size)> addStdStrings = [](const size_t size) -> const blambda {
const blambda l = [size]() -> const bool {
const size_t sz = size / 4;
const std::string x(charBuffer, sz);
const std::string y(charBuffer, sz);
assert(stdAdd(x, y).length() == (unsigned int)(sz * 2));
return true;
};
return l;
};
const blambda a16 =addStdStrings(16);
cout << "Std string test " << time(a16, 5, count) << " ms" << endl;
const lambda<bool()> a32 =addStdStrings(32);
const blambda a32 =addStdStrings(32);
cout << "Std string test " << time(a32, 5, count) << " ms" << endl;
const lambda<bool()> a256 =addStdStrings(256);
const blambda a256 =addStdStrings(256);
cout << "Std string test " << time(a256, 5, count) << " ms" << endl;
const lambda<bool()> a1024 =addStdStrings(1024);
const blambda a1024 =addStdStrings(1024);
cout << "Std string test " << time(a1024, 5, count) << " ms" << endl;
const lambda<bool()> a4096 =addStdStrings(4096);
const blambda a4096 =addStdStrings(4096);
cout << "Std string test " << time(a4096, 5, count) << " ms" << endl;
}
@ -185,7 +188,7 @@ bool testStringPerf() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testCopies();

View file

@ -41,16 +41,16 @@ namespace tuscany {
*/
long countStringCopies = 0;
bool resetStringCopyCounters() {
inline const bool resetStringCopyCounters() {
countStringCopies = 0;
return true;
}
bool checkStringCopyCounters(long c) {
inline const bool checkStringCopyCounters(long c) {
return countStringCopies == c;
}
bool printStringCopyCounters() {
inline const bool printStringCopyCounters() {
printf("countStringCopies %ld\n", countStringCopies);
return true;
}
@ -66,13 +66,19 @@ bool printStringCopyCounters() {
/**
* Instrumented memcpy.
*/
void* string_memcpy(void* t, const void* s, const size_t n) {
#ifdef WANT_MAINTAINER_COUNTERS
inline void* string_memcpy(void* t, const void* s, const size_t n) {
countStringCopies += 1;
#endif
return memcpy(t, s, n);
}
#else
#define string_memcpy(t, s, n) memcpy(t, s, n)
#endif
char stringEmptyBuffer[1] = { '\0' };
/**
@ -80,56 +86,27 @@ char stringEmptyBuffer[1] = { '\0' };
*/
class string {
public:
string() : len(0) {
buf = stringEmptyBuffer;
inline string() noexcept : len(0), buf(stringEmptyBuffer) {
}
string(const char* s) {
len = strlen(s);
if (len == 0) {
buf = stringEmptyBuffer;
return;
}
buf = gc_cnew(len + 1);
string_memcpy(buf, s, len + 1);
inline string(const char* const s) noexcept : len(strlen(s)), buf(mksbuf(s, len)) {
}
string(const char* s, const size_t n) {
len = n;
if (len == 0) {
buf = stringEmptyBuffer;
return;
}
buf = gc_cnew(len + 1);
string_memcpy(buf, s, len);
buf[len] = '\0';
inline string(const char* const s, const size_t n) noexcept : len(n), buf(mksbuf(s, n)) {
}
string(const size_t n, const char c) {
len = n;
if (len == 0) {
buf = stringEmptyBuffer;
return;
}
buf = gc_cnew(len + 1);
memset(buf, c, n);
buf[len] = '\0';
inline string(const char* const s, const size_t n, const bool copy) noexcept : len(n), buf(mksbuf(s, n, copy)) {
}
string(const string& s) {
len = s.len;
buf = s.buf;
inline string(const size_t n, const char c) noexcept : len(n), buf(mkcbuf(c, n)) {
}
const string& operator=(const string& s) {
if (&s == this)
return *this;
len = s.len;
buf = s.buf;
return *this;
inline string(const string& s) noexcept : len(s.len), buf(s.buf) {
}
const bool operator==(const string& s) const {
string& operator=(const string& s) = delete;
inline const bool operator==(const string& s) const noexcept {
if (len != s.len)
return false;
if (buf == s.buf)
@ -137,21 +114,21 @@ public:
return memcmp(buf, s.buf, len) == 0;
}
const bool operator!=(const string& s) const {
inline const bool operator!=(const string& s) const noexcept {
return !(*this == s);
}
const bool operator==(const char* s) const {
inline const bool operator==(const char* const s) const noexcept {
if (buf == s)
return true;
return strcmp(buf, s) == 0;
}
const bool operator!=(const char* s) const {
inline const bool operator!=(const char* const s) const noexcept {
return !(*this == s);
}
const bool operator<(const string& s) const {
inline const bool operator<(const string& s) const noexcept {
const size_t n = len < s.len? len : s.len;
const int c = memcmp(buf, s.buf, n);
if (c < 0)
@ -161,9 +138,9 @@ public:
return false;
}
const bool operator>(const string& s) const {
inline const bool operator>(const string& s) const noexcept {
const size_t n = len < s.len? len : s.len;
int c = memcmp(buf, s.buf, n);
const int c = memcmp(buf, s.buf, n);
if (c > 0)
return true;
if (c == 0)
@ -176,91 +153,137 @@ private:
friend class odebugstream;
#endif
friend class ostringstream;
friend const string operator+(const string& a, const string& b);
friend const string operator+(const string& a, const char* b);
friend const size_t length(const string& s);
friend const char* c_str(const string& s);
friend const size_t find(const string& s1, const char* s2, const size_t start);
friend const string substr(const string& s, const size_t pos, const size_t n);
friend const string operator+(const string& a, const string& b) noexcept;
friend const string operator+(const string& a, const char* const b) noexcept;
friend const string operator+(const string& a, const char c) noexcept;
friend const size_t length(const string& s) noexcept;
friend const char* const c_str(const string& s) noexcept;
friend const size_t find(const string& s1, const char* const s2, const size_t start) noexcept;
friend const string substr(const string& s, const size_t pos, const size_t n) noexcept;
friend const bool setstring(string& target, const string& s);
size_t len;
char* buf;
const size_t len;
const char* const buf;
const char* const mkbuf(const size_t n) {
if (n == 0)
return stringEmptyBuffer;
char* const b = gc_cnew(n + 1);
b[n] = '\0';
return b;
}
const char* const mksbuf(const char* const s, const size_t n) {
if (n == 0)
return stringEmptyBuffer;
char* const b = gc_cnew(n + 1);
string_memcpy(b, s, n);
b[n] = '\0';
return b;
}
const char* const mksbuf(const char* const s, const size_t n, const bool copy) {
if (!copy)
return s;
if (n == 0)
return stringEmptyBuffer;
char* const b = gc_cnew(n + 1);
string_memcpy(b, s, n);
b[n] = '\0';
return b;
}
const char* const mkcbuf(const char c, const size_t n) {
if (n == 0)
return stringEmptyBuffer;
char* const b = gc_cnew(n + 1);
memset(b, c, n);
b[n] = '\0';
return b;
}
};
/**
* Adds two strings.
*/
const string operator+(const string& a, const string& b) {
string s;
s.len = a.len + b.len;
s.buf = gc_cnew(s.len + 1);
string_memcpy(s.buf, a.buf, a.len);
string_memcpy(s.buf + a.len, b.buf, b.len);
s.buf[s.len] = '\0';
return s;
inline const string operator+(const string& sa, const string& sb) noexcept {
const size_t n = sa.len + sb.len;
char* const b = gc_cnew(n + 1);
string_memcpy(b, sa.buf, sa.len);
string_memcpy(b + sa.len, sb.buf, sb.len);
b[n] = '\0';
return string(b, n, false);
}
const string operator+(const string& a, const char* b) {
string s;
const size_t blen = strlen(b);
s.len = a.len + blen;
s.buf = gc_cnew(s.len + 1);
string_memcpy(s.buf, a.buf, a.len);
string_memcpy(s.buf + a.len, b, blen);
s.buf[s.len] = '\0';
return s;
inline const string operator+(const string& sa, const char* const sb) noexcept {
const size_t bn = strlen(sb);
const size_t n = sa.len + bn;
char* const b = gc_cnew(n + 1);
string_memcpy(b, sa.buf, sa.len);
string_memcpy(b + sa.len, sb, bn);
b[n] = '\0';
return string(b, n, false);
}
inline const string operator+(const string& sa, const char c) noexcept {
const size_t n = sa.len + 1;
char* const b = gc_cnew(n + 1);
string_memcpy(b, sa.buf, sa.len);
b[n - 1] = c;
b[n] = '\0';
return string(b, n, false);
}
/**
* Returns the length of a string.
*/
const size_t length(const string& s) {
inline const size_t length(const string& s) noexcept {
return s.len;
}
/**
* Returns a string as a C zero terminated string.
*/
const char* c_str(const string& s) {
inline const char* const c_str(const string& s) noexcept {
return s.buf;
}
/**
* Find the first occurrence of string s2 in s1, starting at the given position.
*/
const size_t find(const string& s1, const char* s2, const size_t start) {
inline const size_t find(const string& s1, const char* const s2, const size_t start) noexcept {
if (start >= s1.len)
return s1.len;
const char *f = strstr(s1.buf + start, s2);
const char* const f = strstr(s1.buf + start, s2);
if (f == NULL)
return s1.len;
return f - s1.buf;
}
const size_t find(const string& s1, const char* s2) {
inline const size_t find(const string& s1, const char* const s2) noexcept {
return find(s1, s2, 0);
}
/**
* Return true if string s1 contains s2.
*/
const bool contains(const string& s1, const char* s2) {
inline const bool contains(const string& s1, const char* const s2) noexcept {
return find(s1, s2) != length(s1);
}
/**
* Find the first occurence of any character from a string in a string.
*/
const size_t find_first_of(const string& s1, const string& s2) {
inline const size_t find_first_of(const string& s1, const string& s2) noexcept {
return strcspn(c_str(s1), c_str(s2));
}
/**
* Find the first occurence of a character in a string.
*/
const size_t find(const string& s, const char c) {
const char* cs = c_str(s);
const char* f = strchr(cs, c);
inline const size_t find(const string& s, const char c) noexcept {
const char* const cs = c_str(s);
const char* const f = strchr(cs, c);
if (f == NULL)
return length(s);
return f - cs;
@ -269,9 +292,9 @@ const size_t find(const string& s, const char c) {
/**
* Find the last occurence of a character in a string.
*/
const size_t find_last(const string& s, const char c) {
const char* cs = c_str(s);
const char* f = strrchr(cs, c);
inline const size_t find_last(const string& s, const char c) noexcept {
const char* const cs = c_str(s);
const char* const f = strrchr(cs, c);
if (f == NULL)
return length(s);
return f - cs;
@ -280,7 +303,7 @@ const size_t find_last(const string& s, const char c) {
/**
* Return a substring of a string.
*/
const string substr(const string& s, const size_t pos, const size_t n) {
inline const string substr(const string& s, const size_t pos, const size_t n) noexcept {
if (pos >= s.len)
return string();
if (pos + n > s.len)
@ -288,17 +311,29 @@ const string substr(const string& s, const size_t pos, const size_t n) {
return string(s.buf + pos, n);
}
const string substr(const string& s, const size_t pos) {
inline const string substr(const string& s, const size_t pos) noexcept {
return substr(s, pos, length(s));
}
/**
* Set a string. Use with moderation.
*/
/*
inline const bool setstring(string& target, const string& s) {
if (&target == &s)
return true;
memcpy((void*)&target.len, (void*)&s.len, sizeof(size_t));
memcpy((void*)&target.buf, (void*)&s.buf, sizeof(char*));
return true;
}
*/
/**
* Common string constants.
*/
string trueString("true");
string falseString("false");
string emptyString("");
const string trueString("true");
const string falseString("false");
const string emptyString("");
}

View file

@ -38,14 +38,14 @@ namespace tuscany {
/**
* Make a tree from a leaf and two branches.
*/
template<typename T> const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) {
template<typename T> inline const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) {
return mklist<T>(e, left, right);
}
/**
* Find a leaf with the given key in a tree.
*/
template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) {
template<typename T> inline const list<T> assoctree(const T& k, const list<T>& tree) {
if (isNil(tree))
return tree;
if (k == car<T>(car(tree)))
@ -58,7 +58,7 @@ template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) {
/**
* Construct a new tree from a leaf and a tree.
*/
template<typename T> const list<T> constree(const T& e, const list<T>& tree) {
template<typename T> inline const list<T> constree(const T& e, const list<T>& tree) {
if (isNil(tree))
return mktree(e, list<T>(), list<T>());
if (e == car(tree))
@ -71,7 +71,7 @@ template<typename T> const list<T> constree(const T& e, const list<T>& tree) {
/**
* Make a tree from an unordered list of leaves.
*/
template<typename T> const list<T> mktree(const list<T>& l) {
template<typename T> inline const list<T> mktree(const list<T>& l) {
if (isNil(l))
return l;
return constree(car(l), mktree(cdr(l)));
@ -80,7 +80,7 @@ template<typename T> const list<T> mktree(const list<T>& l) {
/**
* Convert a tree to an ordered list of leaves.
*/
template<typename T> const list<T> flatten(const list<T>& tree) {
template<typename T> inline const list<T> flatten(const list<T>& tree) {
if (isNil(tree))
return tree;
return append<T>(flatten<T>(cadr(tree)), cons<T>(car(tree), flatten<T>(caddr(tree))));
@ -89,14 +89,14 @@ template<typename T> const list<T> flatten(const list<T>& tree) {
/**
* Sort a list.
*/
template<typename T> const list<T> sort(const list<T>& l) {
template<typename T> inline const list<T> sort(const list<T>& l) {
return flatten(mktree(l));
}
/**
* Make a balanced tree from an ordered list of leaves.
*/
template<typename T> const list<T> btreeHelper(const list<T>& elements, const size_t n) {
template<typename T> inline const list<T> btreeHelper(const list<T>& elements, const size_t n) {
if (n == 0)
return cons<T>(list<T>(), elements);
const size_t leftSize = (n - 1) / 2; {
@ -116,7 +116,7 @@ template<typename T> const list<T> btreeHelper(const list<T>& elements, const si
}
}
template<typename T> const list<T> mkbtree(const list<T>& elements) {
template<typename T> inline const list<T> mkbtree(const list<T>& elements) {
return car(btreeHelper<T>(elements, length(elements)));
}

View file

@ -50,16 +50,16 @@ long int countEValues = 0;
long int countCValues = 0;
long int countVValues = 0;
bool resetValueCounters() {
inline const bool resetValueCounters() {
countValues = countEValues = countCValues = countVValues = 0;
return true;
}
bool checkValueCounters() {
inline const bool checkValueCounters() {
return countValues == 0;
}
bool printValueCounters() {
inline const bool printValueCounters() {
cout << "countValues " << countValues << endl;
cout << "countEValues " << countEValues << endl;
cout << "countCValues " << countCValues << endl;
@ -92,7 +92,28 @@ bool printValueCounters() {
#endif
/**
* Common value constants.
*/
class value;
extern const value nilValue;
extern const list<value> nilListValue;
extern const list<value> nilPairValue;
extern const value emptyStringValue;
extern const value trueValue;
extern const value falseValue;
/**
* Common value-based lambda types.
*/
typedef lambda<const value(const list<value>&)> lvvlambda;
typedef lambda<const value(const value&)> vvlambda;
typedef lambda<const bool(const value&)> vblambda;
typedef lambda<const value()> vlambda;
/**
* Generic value type class.
*/
class value {
public:
@ -101,346 +122,309 @@ public:
Nil, Symbol, String, List, Number, Bool, Lambda, Ptr
};
value() : type(value::Nil) {
typedef union {
const void* mix;
const gc_ptr<list<value> > lst;
const string str;
const lvvlambda func;
const gc_ptr<value> ptr;
const double num;
const bool boo;
} ValueMix;
inline value() noexcept : type(value::Nil) {
debug_inc(countValues);
debug_inc(countEValues);
debug_watchValue();
}
value(const value& v) {
inline value(const value& v) noexcept : type(v.type) {
debug_inc(countValues);
debug_inc(countCValues);
type = v.type;
switch(type) {
case value::List:
lst() = v.lst();
case value::Lambda:
func() = v.func();
case value::Symbol:
str() = v.str();
case value::String:
str() = v.str();
case value::Number:
num() = v.num();
case value::Bool:
boo() = v.boo();
case value::Ptr:
ptr() = v.ptr();
default:
break;
}
memcpy((void*)&mix, (void*)&v.mix, sizeof(ValueMix));
#ifdef WANT_MAINTAINER_WATCH
watch = v.watch;
#endif
}
virtual ~value() {
inline value(const gc_mutable_ref<value>& r) noexcept : type(((value*)r)->type) {
debug_inc(countValues);
debug_inc(countCValues);
memcpy((void*)&mix, (void*)&(((value*)r)->mix), sizeof(ValueMix));
#ifdef WANT_MAINTAINER_WATCH
watch = v.watch;
#endif
}
inline virtual ~value() noexcept {
debug_dec(countValues);
}
value(const lambda<value(const list<value>&)>& func) : type(value::Lambda), data(vdata(func)) {
inline value(const lvvlambda& f) noexcept : type(value::Lambda), func(f) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const string& str) : type(value::String), data(vdata(result(str))) {
inline value(const string& s) noexcept : type(value::String), str(s) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const char* str) : type(value::Symbol), data(vdata(result(string(str)))) {
inline value(const char* s) noexcept : type(value::Symbol), str(s) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const list<value>& lst) : type(value::List), data(vdata(result(lst))) {
inline value(const list<value>& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(l)) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const list<list<value> >& l) : type(value::List), data(vdata(result(listOfValues(l)))) {
inline value(const list<list<value> >& l) noexcept : type(value::List), lst(new (gc_new<list<value> >()) list<value>(listOfValues(l))) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const double num) : type(value::Number), data(vdata(result(num))) {
inline value(const double d) noexcept : type(value::Number), num(d) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const int num) : type(value::Number), data(vdata(result((double)num))) {
inline value(const int i) noexcept : type(value::Number), num((double)i) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const bool boo) : type(value::Bool), data(vdata(result(boo))) {
inline value(const bool b) noexcept : type(value::Bool), boo(b) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) {
inline value(const gc_ptr<value> p) noexcept : type(value::Ptr), ptr(p) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const failable<value>& m) : type(value::List),
data(vdata(result(hasContent(m)? mklist<value>(content(m)) : rcode(m) == 1? mklist<value>(value(), reason(m)) : mklist<value>(value(), reason(m), rcode(m))))) {
inline value(const failable<value>& m) noexcept : type(value::List),
lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(content(m)) :
rcode(m) == 1? mklist<value>(nilValue, reason(m)) : mklist<value>(nilValue, reason(m), rcode(m)))) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
value(const maybe<value>& m) : type(value::List),
data(vdata(result(hasContent(m)? mklist<value>(content(m)) : list<value>()))) {
inline value(const maybe<value>& m) noexcept : type(value::List),
lst(new (gc_new<list<value> >()) list<value>(hasContent(m)? mklist<value>(content(m)) : nilListValue)) {
debug_inc(countValues);
debug_inc(countVValues);
debug_watchValue();
}
const value& operator=(const value& v) {
if(this == &v)
return *this;
type = v.type;
switch(type) {
case value::List:
lst() = v.lst();
case value::Lambda:
func() = v.func();
case value::Symbol:
str() = v.str();
case value::String:
str() = v.str();
case value::Number:
num() = v.num();
case value::Bool:
boo() = v.boo();
case value::Ptr:
ptr() = v.ptr();
default:
break;
}
#ifdef WANT_MAINTAINER_WATCH
watch = v.watch;
#endif
return *this;
}
value& operator=(const value& v) = delete;
const bool operator!=(const value& v) const {
inline const bool operator!=(const value& v) const noexcept {
return !this->operator==(v);
}
const bool operator==(const value& v) const {
inline const bool operator==(const value& v) const noexcept {
if(this == &v)
return true;
switch(type) {
case value::Nil:
return v.type == value::Nil;
case value::List:
return v.type == value::List && lst()() == v.lst()();
return v.type == value::List && *lst == *v.lst;
case value::Lambda:
return v.type == value::Lambda && func() == v.func();
return v.type == value::Lambda && func == v.func;
case value::Symbol:
case value::String:
return str()() == (string)v;
return (v.type == value::Symbol || v.type == value::String) && str == v.str;
case value::Number:
return num()() == (double)v;
return v.type == value::Number && num == v.num;
case value::Bool:
return boo()() == (bool)v;
return v.type == value::Bool && boo == v.boo;
case value::Ptr:
return v.type == value::Ptr && ptr()() == v.ptr()();
return v.type == value::Ptr && ptr == v.ptr;
default:
return false;
}
}
const bool operator<(const value& v) const {
inline const bool operator<(const value& v) const noexcept {
if(this == &v)
return false;
switch(type) {
case value::List:
return v.type == value::List && lst()() < v.lst()();
return v.type == value::List && *lst < *v.lst;
case value::Symbol:
case value::String:
return str()() < (string)v;
return (v.type == value::Symbol || v.type == value::String) && str < v.str;
case value::Bool:
return boo()() < (bool)v;
return v.type == value::Bool && boo < v.boo;
case value::Number:
return num()() < (double)v;
return v.type == value::Number && num < v.num;
default:
return false;
}
}
const bool operator>(const value& v) const {
inline const bool operator>(const value& v) const noexcept {
if(this == &v)
return false;
switch(type) {
case value::List:
return v.type == value::List && lst()() > v.lst()();
return v.type == value::List && *lst > *v.lst;
case value::Symbol:
case value::String:
return str()() > (string)v;
return (v.type == value::Symbol || v.type == value::String) && str > v.str;
case value::Bool:
return boo()() > (bool)v;
return v.type == value::Bool && boo > v.boo;
case value::Number:
return num()() > (double)v;
return v.type == value::Number && num > v.num;
default:
return false;
}
}
const value operator()(const list<value>& args) const {
return func()(args);
inline const value operator()(const list<value>& args) const noexcept {
return func(args);
}
operator const string() const {
inline operator const string() const noexcept {
switch(type) {
case value::Symbol:
case value::String:
return str()();
return str;
case value::Number: {
ostringstream os;
os << num()();
os << num;
return tuscany::str(os);
}
case value::Bool:
return boo()()? trueString : falseString;
return boo? trueString : falseString;
default:
return emptyString;
}
}
operator const double() const {
inline operator const double() const noexcept {
switch(type) {
case value::Symbol:
case value::String:
return atof(c_str(str()()));
return atof(c_str(str));
case value::Number:
return (double)num()();
return (double)num;
case value::Bool:
return boo()()? 1.0 : 0.0;
return boo? 1.0 : 0.0;
default:
return 0.0;
}
}
operator const int() const {
inline operator const int() const noexcept {
switch(type) {
case value::Symbol:
case value::String:
return atoi(c_str(str()()));
return atoi(c_str(str));
case value::Number:
return (int)num()();
return (int)num;
case value::Bool:
return boo()()? 1 : 0;
return boo? 1 : 0;
default:
return 0;
}
}
operator const bool() const {
inline operator const bool() const noexcept {
switch(type) {
case value::Symbol:
case value::String:
return str()() == string("true");
return str == trueString;
case value::Number:
return (int)num()() != 0;
return num != 0.0;
case value::Bool:
return boo()();
return boo;
default:
return 0;
return false;
}
}
operator const gc_ptr<value>() const {
return ptr()();
inline operator const gc_ptr<value>() const noexcept {
return ptr;
}
operator const list<value>() const {
return lst()();
inline operator const list<value>() const noexcept {
return *lst;
}
operator const list<list<value> >() const {
return listOfListOfValues(lst()());
inline operator const list<list<value> >() const noexcept {
return listOfListOfValues(*lst);
}
operator const lambda<value(const list<value>&)>() const {
return func();
inline operator const lvvlambda() const noexcept {
return func;
}
private:
template<typename T> lambda<T>& vdata() const {
return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data));
}
template<typename T> const lambda<char()>& vdata(const T& v) const {
return *reinterpret_cast<const lambda<char()> *> (&v);
}
lambda<double()>& num() const {
return vdata<double()> ();
}
lambda<bool()>& boo() const {
return vdata<bool()> ();
}
lambda<gc_ptr<value>()>& ptr() const {
return vdata<gc_ptr<value>()> ();
}
lambda<string()>& str() const {
return vdata<string()> ();
}
lambda<list<value>()>& lst() const {
return vdata<list<value>()> ();
}
lambda<value(const list<value>&)>& func() const {
return vdata<value(const list<value>&)> ();
}
const list<value> listOfValues(const list<list<value> >& l) const {
inline const list<value> listOfValues(const list<list<value> >& l) const noexcept {
if (isNil(l))
return list<value>();
return nilListValue;
return cons<value>(car(l), listOfValues(cdr(l)));
}
const list<list<value> > listOfListOfValues(const list<value>& l) const {
inline const list<list<value> > listOfListOfValues(const list<value>& l) const noexcept {
if (isNil(l))
return list<list<value> >();
return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l)));
return cons<list<value> >(car(l).type == value::List? list<value>(car(l)) : nilPairValue, listOfListOfValues(cdr(l)));
}
friend ostream& operator<<(ostream&, const value&);
friend const value::ValueType type(const value& v);
friend ostream& operator<<(ostream&, const value&) noexcept;
friend const value::ValueType type(const value& v) noexcept;
friend const bool setvalue(value& target, const value& v);
#ifdef WANT_MAINTAINER_WATCH
friend const string watchValue(const value& v);
string watch;
#endif
ValueType type;
lambda<char()> data;
const ValueType type;
union {
void* mix;
const gc_ptr<list<value> > lst;
const string str;
const lvvlambda func;
const gc_ptr<value> ptr;
const double num;
const bool boo;
};
};
/**
* Common value constants.
*/
const value nilValue;
const list<value> nilListValue = list<value>();
const list<value> nilPairValue = mklist<value>(nilValue, nilValue);
const value emptyStringValue(emptyString);
const value trueValue(true);
const value falseValue(false);
#ifdef WANT_MAINTAINER_WATCH
/**
* Debug utility used to write the contents of a value to a string, easier
* to watch than the value itself in a debugger.
*/
const string watchValue(const value& v) {
inline const string watchValue(const value& v) {
if (v.type == value::List)
return watchList<value>(v);
odebugstream os;
@ -453,7 +437,7 @@ const string watchValue(const value& v) {
/**
* Write an escape string to a buffer.
*/
const char* escapestr(const char* s, char* buf) {
inline const char* escapestr(const char* const s, char* const buf) noexcept {
if (*s == '\0') {
*buf = '\0';
return buf;
@ -470,7 +454,7 @@ const char* escapestr(const char* s, char* buf) {
/**
* Write an escaped string value to a stream.
*/
ostream& escvwrite(const string& str, ostream& out) {
inline ostream& escvwrite(const string& str, ostream& out) noexcept {
char* buf = gc_cnew(length(str) * 2 + 1);
escapestr(c_str(str), buf);
out << buf;
@ -480,30 +464,29 @@ ostream& escvwrite(const string& str, ostream& out) {
/**
* Write a value to a stream.
*/
ostream& operator<<(ostream& out, const value& v) {
inline ostream& operator<<(ostream& out, const value& v) noexcept {
switch(v.type) {
case value::List:
return out << v.lst()();
return out << *v.lst;
case value::Lambda:
return out << "lambda::" << v.func();
return out << "lambda::" << v.func;
case value::Symbol:
return out << v.str()();
return out << v.str;
case value::String:
out << '\"';
escvwrite(v.str()(), out);
escvwrite(v.str, out);
return out << '\"';
case value::Number:
return out << v.num()();
return out << v.num;
case value::Bool:
if(v.boo()())
return out << "true";
if(v.boo)
return out << trueString;
else
return out << "false";
return out << falseString;
case value::Ptr: {
const gc_ptr<value> p = v.ptr()();
if (p == gc_ptr<value>(NULL))
if (v.ptr == gc_ptr<value>(NULL))
return out << "gc_ptr::null";
return out << "gc_ptr::" << p;
return out << "gc_ptr::" << v.ptr;
}
default:
return out << "nil";
@ -513,70 +496,70 @@ ostream& operator<<(ostream& out, const value& v) {
/**
* Returns the type of a value.
*/
const value::ValueType type(const value& v) {
inline const value::ValueType type(const value& v) noexcept {
return v.type;
}
/**
* Returns true if a value is nil.
*/
const bool isNil(const value& v) {
inline const bool isNil(const value& v) noexcept {
return type(v) == value::Nil;
}
/**
* Returns true if a value is a lambda.
*/
const bool isLambda(const value& v) {
inline const bool isLambda(const value& v) noexcept {
return type(v) == value::Lambda;
}
/**
* Returns true if a value is a string.
*/
const bool isString(const value& v) {
inline const bool isString(const value& v) noexcept {
return type(v) == value::String;
}
/**
* Returns true if a value is a symbol.
*/
const bool isSymbol(const value& v) {
inline const bool isSymbol(const value& v) noexcept {
return type(v) == value::Symbol;
}
/**
* Returns true if a value is a list.
*/
const bool isList(const value& v) {
inline const bool isList(const value& v) noexcept {
return type(v) == value::List;
}
/**
* Returns true if a value is a number.
*/
const bool isNumber(const value& v) {
inline const bool isNumber(const value& v) noexcept {
return type(v) == value::Number;
}
/**
* Returns true if a value is a boolean.
*/
const bool isBool(const value& v) {
inline const bool isBool(const value& v) noexcept {
return type(v) == value::Bool;
}
/**
* Returns true if a value is a pointer.
*/
const bool isPtr(const value& v) {
inline const bool isPtr(const value& v) noexcept {
return type(v) == value::Ptr;
}
/**
* Returns true if a value is a tagged list.
*/
const bool isTaggedList(const value& exp, value tag) {
inline const bool isTaggedList(const value& exp, const value& tag) noexcept {
if(isList(exp) && !isNil((list<value>)exp))
return car((list<value>)exp) == tag;
return false;
@ -585,16 +568,16 @@ const bool isTaggedList(const value& exp, value tag) {
/**
* Make a list of values from a list of other things.
*/
template<typename T> const list<value> mkvalues(const list<T>& l) {
template<typename T> inline const list<value> mkvalues(const list<T>& l) noexcept {
if (isNil(l))
return list<value>();
return nilListValue;
return cons<value>(car(l), mkvalues(cdr(l)));
}
/**
* Convert a list of values to a list of other things.
*/
template<typename T> const list<T> convertValues(const list<value>& l) {
template<typename T> inline const list<T> convertValues(const list<value>& l) noexcept {
if (isNil(l))
return list<T>();
return cons<T>(car(l), convertValues<T>(cdr(l)));
@ -603,7 +586,7 @@ template<typename T> const list<T> convertValues(const list<value>& l) {
/**
* Convert a path string value to a list of values.
*/
const list<string> pathTokens(const char* p) {
inline const list<string> pathTokens(const char* const p) noexcept {
if (p == NULL || p[0] == '\0')
return list<string>();
if (p[0] == '/')
@ -611,23 +594,23 @@ const list<string> pathTokens(const char* p) {
return tokenize("/", p);
}
const list<value> pathValues(const value& p) {
inline const list<value> pathValues(const value& p) noexcept {
return mkvalues(pathTokens(c_str(p)));
}
/**
* Convert a path represented as a list of values to a string value.
*/
const value path(const list<value>& p) {
inline const value path(const list<value>& p) noexcept {
if (isNil(p))
return "";
return string("/") + car(p) + path(cdr(p));
return emptyString;
return string("/") + (string)car(p) + (string)path(cdr(p));
}
/**
* Make a uuid value.
*/
const value mkuuid() {
inline const value mkuuid() noexcept {
apr_uuid_t id;
apr_uuid_get(&id);
char buf[APR_UUID_FORMATTED_LENGTH];
@ -638,19 +621,33 @@ const value mkuuid() {
/**
* Make a random alphanumeric value.
*/
const int intrand() {
inline const int intrand() noexcept {
const apr_uint64_t now = apr_time_now();
srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff));
return rand() & 0x0FFFF;
}
const value mkrand() {
inline const value mkrand() noexcept {
char buf[32];
const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
const char* const an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (int i =0; i < 32; i++)
buf[i] = an[intrand() % 62];
return value(string(buf, 32));
}
/**
* Set a value. Use with moderation.
*/
inline const bool setvalue(value& target, const value& v) {
if (&target == &v)
return true;
#ifdef WANT_MAINTAINER_WATCH
memcpy(&target.watch, &v.watch, sizeof(string));
#endif
memcpy((void*)&target.type, (void*)&v.type, sizeof(value::ValueType));
memcpy((void*)&target.mix, (void*)&v.mix, sizeof(value::ValueMix));
return true;
}
}
#endif /* tuscany_value_hpp */

View file

@ -1,235 +0,0 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test XML handling functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "element.hpp"
#include "xml.hpp"
namespace tuscany {
const string currencyXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" targetNamespace=\"http://services\" name=\"currency\">\n"
" <component name=\"CurrencyConverterWebService\">\n"
" <implementation.java class=\"services.CurrencyConverterImpl\"/>\n"
" <service name=\"CurrencyConverter\">\n"
" <binding.ws/>\n"
" </service>\n"
" </component>\n"
" <component name=\"CurrencyConverterWebService2\">\n"
" <implementation.java class=\"services.CurrencyConverterImpl2\"/>\n"
" <service name=\"CurrencyConverter2\">\n"
" <binding.atom/>\n"
" </service>\n"
" <property name=\"currency\">US</property>\n"
" </component>\n"
"</composite>\n";
const string customerXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<customer>\n"
" <name>jdoe</name>\n"
" <address>\n"
" <city>san francisco</city>\n"
" <state>ca</state>\n"
" </address>\n"
" <account>\n"
" <id>1234</id>\n"
" <balance>1000</balance>\n"
" </account>\n"
" <account>\n"
" <id>6789</id>\n"
" <balance>2000</balance>\n"
" </account>\n"
" <account>\n"
" <id>4567</id>\n"
" <balance>3000</balance>\n"
" </account>\n"
"</customer>\n";
const string abcXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<a>\n"
" <m>abc</m>\n"
" <m>def</m>\n"
" <m>xyz</m>\n"
" <m>tuv</m>\n"
"</a>\n";
const string xyzXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<a>\n"
" <m>\n"
" <id>123</id>\n"
" <name>abc</name>\n"
" </m>\n"
" <m>\n"
" <id>234</id>\n"
" <name>def</name>\n"
" </m>\n"
" <m>\n"
" <id>345</id>\n"
" <name>xyz</name>\n"
" </m>\n"
" <m>\n"
" <id>456</id>\n"
" <name>tuv</name>\n"
" </m>\n"
"</a>\n";
const bool isName(const value& token) {
return isTaggedList(token, attribute) && attributeName(token) == "name";
}
bool testReadXML() {
{
istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
}
{
istringstream is(currencyXML);
const list<value> c = readXML(streamList(is));
const value composite = car(c);
assert(isTaggedList(composite, element));
assert(elementName(composite) == "composite");
assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency"));
}
return true;
}
ostream* xmlWriter(const string& s, ostream* os) {
(*os) << s;
return os;
}
bool testWriteXML() {
{
istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, c);
assert(str(os) == customerXML);
}
{
istringstream is(currencyXML);
const list<value> c = readXML(streamList(is));
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, c);
assert(str(os) == currencyXML);
}
return true;
}
bool testElements() {
{
const list<value> ad = mklist<value>(mklist<value>("city", string("san francisco")), mklist<value>("state", string("ca")));
const list<value> ac1 = mklist<value>(mklist<value>("id", string("1234")), mklist<value>("balance", 1000));
const list<value> ac2 = mklist<value>(mklist<value>("id", string("6789")), mklist<value>("balance", 2000));
const list<value> ac3 = mklist<value>(mklist<value>("id", string("4567")), mklist<value>("balance", 3000));
{
const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3))));
const list<value> e = valuesToElements(c);
const list<value> v = elementsToValues(e);
assert(v == c);
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
{
const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3)));
const list<value> e = valuesToElements(c);
const list<value> v = elementsToValues(e);
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
}
{
istringstream is(abcXML);
const list<value> c = readXML(streamList(is));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, e);
assert(str(os) == abcXML);
}
{
istringstream is(xyzXML);
const list<value> c = readXML(streamList(is));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, e);
assert(str(os) == xyzXML);
}
{
istringstream is(customerXML);
const list<value> c = readXML(streamList(is));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeXML<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
return true;
}
bool testValues() {
{
const list<value> l = mklist<value>(list<value>() + "ns1:echoString" + (list<value>() + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (list<value>() + "text" + string("Hello World!")));
const list<value> e = valuesToElements(l);
const failable<list<string> > lx = writeXML(e);
ostringstream os;
write(content(lx), os);
istringstream is(str(os));
const list<value> x = readXML(streamList(is));
const list<value> v = elementsToValues(x);
assert(v == l);
}
return true;
}
}
int main() {
tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::testReadXML();
tuscany::testWriteXML();
tuscany::testElements();
tuscany::testValues();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

View file

@ -15,5 +15,5 @@
# specific language governing permissions and limitations
# under the License.
SUBDIRS = scheme atom rss js json scdl http server python opencl java openid oauth wsgi
SUBDIRS = xml json scheme atom rss js scdl http server python opencl java openid oauth wsgi

View file

@ -38,100 +38,100 @@ ostream* writer(const string& s, ostream* os) {
const string itemEntry(
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
" <author>\n"
" <email>jane@example.com</email>\n"
" </author>\n"
" <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n"
" <content type=\"application/xml\">\n"
" <item>\n"
" <name>Apple</name>\n"
" <price>$2.99</price>\n"
" </item>\n"
" </content>\n"
" <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
"<author>"
"<email>jane@example.com</email>"
"</author>"
"<updated>Fri Jan 01 08:11:36 PDT 2012</updated>"
"<content type=\"application/xml\">"
"<item>"
"<name>Apple</name>"
"<price>$2.99</price>"
"</item>"
"</content>"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
"</entry>\n");
const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
" <author>\n"
" <email>jane@example.com</email>\n"
" </author>\n"
" <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n"
" <content type=\"text\">Apple</content>\n"
" <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
"<author>"
"<email>jane@example.com</email>"
"</author>"
"<updated>Fri Jan 01 08:11:36 PDT 2012</updated>"
"<content type=\"text\">Apple</content>"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
"</entry>\n");
const string itemNoContentEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
" <author>\n"
" <name>jane</name>\n"
" </author>\n"
" <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n"
" <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
"<author>"
"<name>jane</name>"
"</author>"
"<updated>Fri Jan 01 08:11:36 PDT 2012</updated>"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
"</entry>\n");
const string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title>item</title>\n"
" <content type=\"text/xml\">\n"
" <Item xmlns=\"http://services/\">\n"
" <name xmlns=\"\">Orange</name>\n"
" <price xmlns=\"\">3.55</price>\n"
" </Item>\n"
" </content>\n"
"<title>item</title>"
"<content type=\"text/xml\">"
"<Item xmlns=\"http://services/\">"
"<name xmlns=\"\">Orange</name>"
"<price xmlns=\"\">3.55</price>"
"</Item>"
"</content>"
"</entry>\n");
const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id></id>\n"
" <content type=\"application/xml\">\n"
" <Item xmlns=\"http://services/\">\n"
" <name xmlns=\"\">Orange</name>\n"
" <price xmlns=\"\">3.55</price>\n"
" </Item>\n"
" </content>\n"
" <link href=\"\"/>\n"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id></id>"
"<content type=\"application/xml\">"
"<Item xmlns=\"http://services/\">"
"<name xmlns=\"\">Orange</name>"
"<price xmlns=\"\">3.55</price>"
"</Item>"
"</content>"
"<link href=\"\"/>"
"</entry>\n");
bool testEntry() {
const bool testEntry() {
{
const list<value> i = list<value>() + element + value("item")
+ value(list<value>() + element + value("name") + value(string("Apple")))
+ value(list<value>() + element + value("price") + value(string("$2.99")));
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("item")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("author") + value(string("jane@example.com")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(list<value>() + element + value("content") + value(i)));
const list<value> i = nilListValue + element + value("item")
+ value(nilListValue + element + value("name") + value(string("Apple")))
+ value(nilListValue + element + value("price") + value(string("$2.99")));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("item")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("author") + value(string("jane@example.com")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(nilListValue + element + value("content") + value(i)));
ostringstream os;
writeATOMEntry<ostream*>(writer, &os, a);
assert(str(os) == itemEntry);
}
{
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("item")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("author") + value(string("jane@example.com")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(list<value>() + element + value("content") + value(string("Apple"))));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("item")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("author") + value(string("jane@example.com")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(nilListValue + element + value("content") + value(string("Apple"))));
ostringstream os;
writeATOMEntry<ostream*>(writer, &os, a);
assert(str(os) == itemTextEntry);
}
{
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("item")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("author") + value(string("jane")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("item")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("author") + value(string("jane")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))));
ostringstream os;
writeATOMEntry<ostream*>(writer, &os, a);
assert(str(os) == itemNoContentEntry);
@ -164,54 +164,54 @@ bool testEntry() {
}
const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">Feed</title>\n"
" <id>1234</id>\n"
"<feed xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">Feed</title>"
"<id>1234</id>"
"</feed>\n");
const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<feed xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">Feed</title>\n"
" <id>1234</id>\n"
" <entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>\n"
" <author>\n"
" <email>jane@example.com</email>\n"
" </author>\n"
" <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n"
" <content type=\"application/xml\">\n"
" <item>\n"
" <name>Apple</name>\n"
" <price>$2.99</price>\n"
" </item>\n"
" </content>\n"
" <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>\n"
" </entry>\n"
" <entry xmlns=\"http://www.w3.org/2005/Atom\">\n"
" <title type=\"text\">item</title>\n"
" <id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>\n"
" <author>\n"
" <email>jane@example.com</email>\n"
" </author>\n"
" <updated>Fri Jan 01 08:11:36 PDT 2012</updated>\n"
" <content type=\"application/xml\">\n"
" <item>\n"
" <name>Orange</name>\n"
" <price>$3.55</price>\n"
" </item>\n"
" </content>\n"
" <link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>\n"
" </entry>\n"
"<feed xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">Feed</title>"
"<id>1234</id>"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</id>"
"<author>"
"<email>jane@example.com</email>"
"</author>"
"<updated>Fri Jan 01 08:11:36 PDT 2012</updated>"
"<content type=\"application/xml\">"
"<item>"
"<name>Apple</name>"
"<price>$2.99</price>"
"</item>"
"</content>"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
"</entry>"
"<entry xmlns=\"http://www.w3.org/2005/Atom\">"
"<title type=\"text\">item</title>"
"<id>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</id>"
"<author>"
"<email>jane@example.com</email>"
"</author>"
"<updated>Fri Jan 01 08:11:36 PDT 2012</updated>"
"<content type=\"application/xml\">"
"<item>"
"<name>Orange</name>"
"<price>$3.55</price>"
"</item>"
"</content>"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c\"/>"
"</entry>"
"</feed>\n");
bool testFeed() {
const bool testFeed() {
{
const list<value> a = list<value>() + (list<value>() + element + value("feed")
+ value(list<value>() + element + value("title") + value(string("Feed")))
+ value(list<value>() + element + value("id") + value(string("1234")))
+ value(list<value>() + element + value("author") + value(string("jane@example.com")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))));
const list<value> a = nilListValue + (nilListValue + element + value("feed")
+ value(nilListValue + element + value("title") + value(string("Feed")))
+ value(nilListValue + element + value("id") + value(string("1234")))
+ value(nilListValue + element + value("author") + value(string("jane@example.com")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012"))));
ostringstream os;
writeATOMFeed<ostream*>(writer, &os, a);
assert(str(os) == emptyFeed);
@ -223,31 +223,31 @@ bool testFeed() {
assert(str(os) == emptyFeed);
}
{
const list<value> i1 = list<value>() + element + "item"
+ (list<value>() + element + "name" + "Apple")
+ (list<value>() + element + "price" + "$2.99");
const list<value> i1 = nilListValue + element + "item"
+ (nilListValue + element + "name" + "Apple")
+ (nilListValue + element + "price" + "$2.99");
const list<value> i2 = list<value>() + element + "item"
+ (list<value>() + element + "name" + "Orange")
+ (list<value>() + element + "price" + "$3.55");
const list<value> i2 = nilListValue + element + "item"
+ (nilListValue + element + "name" + "Orange")
+ (nilListValue + element + "price" + "$3.55");
const list<value> i = list<value>()
+ value(list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("item")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("author") + value(string("jane@example.com")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(list<value>() + element + value("content") + value(i1)))
+ value(list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("item")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+ value(list<value>() + element + value("author") + value(string("jane@example.com")))
+ value(list<value>() + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(list<value>() + element + value("content") + value(i2)));
const list<value> i = nilListValue
+ value(nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("item")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("author") + value(string("jane@example.com")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(nilListValue + element + value("content") + value(i1)))
+ value(nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("item")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+ value(nilListValue + element + value("author") + value(string("jane@example.com")))
+ value(nilListValue + element + value("updated") + value(string("Fri Jan 01 08:11:36 PDT 2012")))
+ value(nilListValue + element + value("content") + value(i2)));
const list<value> a = list<value>() + (append<value>(list<value>() + element + value("feed")
+ value(list<value>() + element + value("title") + value(string("Feed")))
+ value(list<value>() + element + value("id") + value("1234")),
const list<value> a = nilListValue + (append<value>(nilListValue + element + value("feed")
+ value(nilListValue + element + value("title") + value(string("Feed")))
+ value(nilListValue + element + value("id") + value("1234")),
i));
ostringstream os;
@ -273,7 +273,7 @@ bool testFeed() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::atom::testEntry();

View file

@ -30,7 +30,7 @@
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "xml.hpp"
#include "../xml/xml.hpp"
namespace tuscany {
namespace atom {
@ -46,24 +46,24 @@ const value entry("entry");
*/
const list<value> entryElementValues(const list<value>& e) {
const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e);
const list<value> t = list<value>() + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt)));
const list<value> t = nilListValue + element + value("title") + (isNil(lt)? value(emptyString) : elementValue(car(lt)));
const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e);
const list<value> i = list<value>() + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li)));
const list<value> i = nilListValue + element + value("id") + (isNil(li)? value(emptyString) : elementValue(car(li)));
const list<value> la = filter<value>(selector(mklist<value>(element, "author")), e);
const list<value> lan = isNil(la)? list<value>() : filter<value>(selector(mklist<value>(element, "name")), car(la));
const list<value> lae = isNil(la)? list<value>() : filter<value>(selector(mklist<value>(element, "email")), car(la));
const list<value> lan = isNil(la)? nilListValue : filter<value>(selector(mklist<value>(element, "name")), car(la));
const list<value> lae = isNil(la)? nilListValue : filter<value>(selector(mklist<value>(element, "email")), car(la));
const list<value> laa = isNil(lan)? lae : lan;
const list<value> a = isNil(laa)? list<value>() : mklist<value>(list<value>() + element + value("author") + elementValue(car(laa)));
const list<value> a = isNil(laa)? nilListValue : mklist<value>(nilListValue + element + value("author") + elementValue(car(laa)));
const list<value> lu = filter<value>(selector(mklist<value>(element, "updated")), e);
const list<value> u = isNil(lu)? list<value>() : mklist<value>(list<value>() + element + value("updated") + elementValue(car(lu)));
const list<value> u = isNil(lu)? nilListValue : mklist<value>(nilListValue + element + value("updated") + elementValue(car(lu)));
const list<value> lc = filter<value>(selector(mklist<value>(element, "content")), e);
const list<value> c = isNil(lc)? list<value>() : mklist<value>(list<value>() + element + value("content") + elementValue(car(lc)));
const list<value> c = isNil(lc)? nilListValue : mklist<value>(nilListValue + element + value("content") + elementValue(car(lc)));
return append<value>(append<value>(append<value>(list<value>() + element + entry + value(t) + value(i), a), u), c);
return append<value>(append<value>(append<value>(nilListValue + element + entry + value(t) + value(i), a), u), c);
}
/**
@ -79,7 +79,7 @@ const list<value> entriesElementValues(const list<value>& e) {
* Return true if a list of strings contains an ATOM feed.
*/
const bool isATOMFeed(const list<string>& ls) {
if (!isXML(ls))
if (!xml::isXML(ls))
return false;
return contains(car(ls), "<feed") && contains(car(ls), "=\"http://www.w3.org/2005/Atom\"");
}
@ -88,7 +88,7 @@ const bool isATOMFeed(const list<string>& ls) {
* Return true if a list of strings contains an ATOM entry.
*/
const bool isATOMEntry(const list<string>& ls) {
if (!isXML(ls))
if (!xml::isXML(ls))
return false;
return contains(car(ls), "<entry") && !contains(car(ls), "<feed") && contains(car(ls), "=\"http://www.w3.org/2005/Atom\"");
}
@ -97,7 +97,7 @@ const bool isATOMEntry(const list<string>& ls) {
* Convert a list of strings to a list of values representing an ATOM entry.
*/
const failable<list<value> > readATOMEntry(const list<string>& ilist) {
const list<value> e = readXML(ilist);
const list<value> e = content(xml::readElements(ilist));
if (isNil(e))
return mkfailure<list<value> >("Empty entry");
return mklist<value>(entryElementValues(car(e)));
@ -107,32 +107,25 @@ const failable<list<value> > readATOMEntry(const list<string>& ilist) {
* Convert a list of strings to a list of values representing an ATOM feed.
*/
const failable<list<value> > readATOMFeed(const list<string>& ilist) {
const list<value> f = readXML(ilist);
const list<value> f = content(xml::readElements(ilist));
if (isNil(f))
return mkfailure<list<value> >("Empty feed");
const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(f));
const list<value> i = filter<value>(selector(mklist<value>(element, "id")), car(f));
const list<value> e = filter<value>(selector(mklist<value>(element, entry)), car(f));
return mklist<value>(append<value>(list<value>() + element + feed
+ value(list<value>() + element + value("title") + elementValue(car(t)))
+ value(list<value>() + element + value("id") + elementValue(car(i))),
return mklist<value>(append<value>(nilListValue + element + feed
+ value(nilListValue + element + value("title") + elementValue(car(t)))
+ value(nilListValue + element + value("id") + elementValue(car(i))),
entriesElementValues(e)));
}
/**
* Returns children of an ATOM content element.
*/
struct filterContentElementChildren {
const value type;
filterContentElementChildren() : type("type") {
}
const bool operator()(const value& v) const {
return !(isAttribute(v) && attributeName((list<value>)v) == type);
}
};
const list<value> contentElementChildren(const value& content) {
return filter<value>(filterContentElementChildren(), elementChildren(content));
return filter<value>([](const value& v) {
return !(isAttribute(v) && attributeName((list<value>)v) == "type");
}, elementChildren(content));
}
/**
@ -146,18 +139,18 @@ const list<value> entryElement(const list<value>& l) {
const value updated = elementChild("updated", l);
const value content = elementChild("content", l);
const bool text = isNil(content)? false : elementHasValue(content);
return list<value>()
+ element + entry + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+ (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + elementValue(title))
+ (list<value>() + element + "id" + elementValue(id))
+ (isNil(author)? list<value>() : (list<value>() + element + "author" +
(email? (list<value>() + element + "email" + elementValue(author)) : (list<value>() + element + "name" + elementValue(author)))))
+ (isNil(updated)? list<value>() : (list<value>() + element + "updated" + elementValue(updated)))
return nilListValue
+ element + entry + (nilListValue + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+ (nilListValue + element + "title" + (nilListValue + attribute + "type" + "text") + elementValue(title))
+ (nilListValue + element + "id" + elementValue(id))
+ (isNil(author)? nilListValue : (nilListValue + element + "author" +
(email? (nilListValue + element + "email" + elementValue(author)) : (nilListValue + element + "name" + elementValue(author)))))
+ (isNil(updated)? nilListValue : (nilListValue + element + "updated" + elementValue(updated)))
+ (isNil(content)?
list<value>() :
append<value>(list<value>() + element + "content" + (list<value>() + attribute + "type" + (text? "text" : "application/xml")),
nilListValue :
append<value>(nilListValue + element + "content" + (nilListValue + attribute + "type" + (text? "text" : "application/xml")),
text? mklist<value>(elementValue(content)) : contentElementChildren(content)))
+ (list<value>() + element + "link" + (list<value>() + attribute + "href" + elementValue(id)));
+ (nilListValue + element + "link" + (nilListValue + attribute + "href" + elementValue(id)));
}
/**
@ -172,9 +165,9 @@ const list<value> entriesElements(const list<value>& l) {
/**
* Convert a list of element values representing an ATOM entry to an ATOM entry.
*/
template<typename R> const failable<R> writeATOMEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
template<typename R> const failable<R> writeATOMEntry(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
return xml::writeElements<R>(reduce, initial, mklist<value>(entryElement(l)));
}
const failable<list<string> > writeATOMEntry(const list<value>& l) {
@ -187,31 +180,31 @@ const failable<list<string> > writeATOMEntry(const list<value>& l) {
/**
* Convert a list of element values representing an ATOM feed to an ATOM feed.
*/
template<typename R> const failable<R> writeATOMFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
template<typename R> const failable<R> writeATOMFeed(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l);
const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l);
const value i = isNil(li)? value(emptyString) : elementValue(car(li));
const list<value> f = list<value>()
+ element + feed + (list<value>() + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+ (list<value>() + element + "title" + (list<value>() + attribute + "type" + "text") + t)
+ (list<value>() + element + "id" + i);
const list<value> f = nilListValue
+ element + feed + (nilListValue + attribute + "xmlns" + "http://www.w3.org/2005/Atom")
+ (nilListValue + element + "title" + (nilListValue + attribute + "type" + "text") + t)
+ (nilListValue + element + "id" + i);
// Write ATOM entries
const list<value> le = filter<value>(selector(mklist<value>(element, entry)), l);
if (isNil(le))
return writeXML<R>(reduce, initial, mklist<value>(f));
return xml::writeElements<R>(reduce, initial, mklist<value>(f));
// Write a single ATOM entry element with a list of values
if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) {
const list<value> fe = append(f, entriesElements(caddr<value>(car(le))));
return writeXML<R>(reduce, initial, mklist<value>(fe));
return xml::writeElements<R>(reduce, initial, mklist<value>(fe));
}
// Write separate ATOM entry elements
const list<value> fe = append(f, entriesElements(le));
return writeXML<R>(reduce, initial, mklist<value>(fe));
return xml::writeElements<R>(reduce, initial, mklist<value>(fe));
}
/**

View file

@ -37,78 +37,78 @@ ostream* writer(const string& s, ostream* os) {
}
const string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<item>\n"
" <title>fruit</title>\n"
" <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
" <description>\n"
" <item>\n"
" <name>Apple</name>\n"
" <price>$2.99</price>\n"
" </item>\n"
" </description>\n"
"<item>"
"<title>fruit</title>"
"<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
"<description>"
"<item>"
"<name>Apple</name>"
"<price>$2.99</price>"
"</item>"
"</description>"
"</item>\n");
const string itemTextEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<item>\n"
" <title>fruit</title>\n"
" <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
" <description>Apple</description>\n"
"<item>"
"<title>fruit</title>"
"<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
"<description>Apple</description>"
"</item>\n");
const string itemNoDescriptionEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<item>\n"
" <title>fruit</title>\n"
" <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
"<item>"
"<title>fruit</title>"
"<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
"</item>\n");
const string incompleteEntry("<item>\n"
" <title>fruit</title>\n"
" <description>\n"
" <Item xmlns=\"http://services/\">\n"
" <name xmlns=\"\">Orange</name>\n"
" <price xmlns=\"\">3.55</price>\n"
" </Item>\n"
" </description>\n"
"<title>fruit</title>"
"<description>"
"<Item xmlns=\"http://services/\">"
"<name xmlns=\"\">Orange</name>"
"<price xmlns=\"\">3.55</price>"
"</Item>"
"</description>"
"</item>");
const string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<item>\n"
" <title>fruit</title>\n"
" <link></link>\n"
" <description>\n"
" <Item xmlns=\"http://services/\">\n"
" <name xmlns=\"\">Orange</name>\n"
" <price xmlns=\"\">3.55</price>\n"
" </Item>\n"
" </description>\n"
"<item>"
"<title>fruit</title>"
"<link></link>"
"<description>"
"<Item xmlns=\"http://services/\">"
"<name xmlns=\"\">Orange</name>"
"<price xmlns=\"\">3.55</price>"
"</Item>"
"</description>"
"</item>\n");
bool testEntry() {
const bool testEntry() {
{
const list<value> i = list<value>() + element + value("item")
+ value(list<value>() + element + value("name") + value(string("Apple")))
+ value(list<value>() + element + value("price") + value(string("$2.99")));
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("fruit")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("content") + value(i)));
const list<value> i = nilListValue + element + value("item")
+ value(nilListValue + element + value("name") + value(string("Apple")))
+ value(nilListValue + element + value("price") + value(string("$2.99")));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("fruit")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("content") + value(i)));
ostringstream os;
writeRSSEntry<ostream*>(writer, &os, a);
assert(str(os) == itemEntry);
}
{
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("fruit")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("content") + value(string("Apple"))));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("fruit")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("content") + value(string("Apple"))));
ostringstream os;
writeRSSEntry<ostream*>(writer, &os, a);
assert(str(os) == itemTextEntry);
}
{
const list<value> a = list<value>() + (list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("fruit")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))));
const list<value> a = nilListValue + (nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("fruit")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"))));
ostringstream os;
writeRSSEntry<ostream*>(writer, &os, a);
assert(str(os) == itemNoDescriptionEntry);
@ -141,48 +141,48 @@ bool testEntry() {
}
const string emptyFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<rss version=\"2.0\">\n"
" <channel>\n"
" <title>Feed</title>\n"
" <link>1234</link>\n"
" <description>Feed</description>\n"
" </channel>\n"
"<rss version=\"2.0\">"
"<channel>"
"<title>Feed</title>"
"<link>1234</link>"
"<description>Feed</description>"
"</channel>"
"</rss>\n");
const string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<rss version=\"2.0\">\n"
" <channel>\n"
" <title>Feed</title>\n"
" <link>1234</link>\n"
" <description>Feed</description>\n"
" <item>\n"
" <title>fruit</title>\n"
" <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>\n"
" <description>\n"
" <item>\n"
" <name>Apple</name>\n"
" <price>$2.99</price>\n"
" </item>\n"
" </description>\n"
" </item>\n"
" <item>\n"
" <title>fruit</title>\n"
" <link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>\n"
" <description>\n"
" <item>\n"
" <name>Orange</name>\n"
" <price>$3.55</price>\n"
" </item>\n"
" </description>\n"
" </item>\n"
" </channel>\n"
"<rss version=\"2.0\">"
"<channel>"
"<title>Feed</title>"
"<link>1234</link>"
"<description>Feed</description>"
"<item>"
"<title>fruit</title>"
"<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b</link>"
"<description>"
"<item>"
"<name>Apple</name>"
"<price>$2.99</price>"
"</item>"
"</description>"
"</item>"
"<item>"
"<title>fruit</title>"
"<link>cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c</link>"
"<description>"
"<item>"
"<name>Orange</name>"
"<price>$3.55</price>"
"</item>"
"</description>"
"</item>"
"</channel>"
"</rss>\n");
bool testFeed() {
const bool testFeed() {
{
const list<value> a = list<value>() + (list<value>() + element + value("feed")
+ value(list<value>() + element + value("title") + value(string("Feed")))
+ value(list<value>() + element + value("id") + value(string("1234"))));
const list<value> a = nilListValue + (nilListValue + element + value("feed")
+ value(nilListValue + element + value("title") + value(string("Feed")))
+ value(nilListValue + element + value("id") + value(string("1234"))));
ostringstream os;
writeRSSFeed<ostream*>(writer, &os, a);
assert(str(os) == emptyFeed);
@ -194,27 +194,27 @@ bool testFeed() {
assert(str(os) == emptyFeed);
}
{
const list<value> i1 = list<value>() + element + "item"
+ (list<value>() + element + "name" + "Apple")
+ (list<value>() + element + "price" + "$2.99");
const list<value> i1 = nilListValue + element + "item"
+ (nilListValue + element + "name" + "Apple")
+ (nilListValue + element + "price" + "$2.99");
const list<value> i2 = list<value>() + element + "item"
+ (list<value>() + element + "name" + "Orange")
+ (list<value>() + element + "price" + "$3.55");
const list<value> i2 = nilListValue + element + "item"
+ (nilListValue + element + "name" + "Orange")
+ (nilListValue + element + "price" + "$3.55");
const list<value> i = list<value>()
+ value(list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("fruit")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(list<value>() + element + value("content") + value(i1)))
+ value(list<value>() + element + value("entry")
+ value(list<value>() + element + value("title") + value(string("fruit")))
+ value(list<value>() + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+ value(list<value>() + element + value("content") + value(i2)));
const list<value> i = nilListValue
+ value(nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("fruit")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b")))
+ value(nilListValue + element + value("content") + value(i1)))
+ value(nilListValue + element + value("entry")
+ value(nilListValue + element + value("title") + value(string("fruit")))
+ value(nilListValue + element + value("id") + value(string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c")))
+ value(nilListValue + element + value("content") + value(i2)));
const list<value> a = list<value>() + (append<value>(list<value>() + element + value("feed")
+ value(list<value>() + element + value("title") + value(string("Feed")))
+ value(list<value>() + element + value("id") + value("1234")),
const list<value> a = nilListValue + (append<value>(nilListValue + element + value("feed")
+ value(nilListValue + element + value("title") + value(string("Feed")))
+ value(nilListValue + element + value("id") + value("1234")),
i));
ostringstream os;
@ -240,7 +240,7 @@ bool testFeed() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::rss::testEntry();

View file

@ -30,7 +30,7 @@
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "xml.hpp"
#include "../xml/xml.hpp"
namespace tuscany {
namespace rss {
@ -50,10 +50,10 @@ const list<value> entryElementValues(const list<value>& e) {
const list<value> li = filter<value>(selector(mklist<value>(element, "link")), e);
const value i = isNil(li)? value(emptyString) : elementValue(car(li));
const list<value> ld = filter<value>(selector(mklist<value>(element, "description")), e);
return append<value>(list<value>() + element + entry
+ value(list<value>() + element + value("title") + t)
+ value(list<value>() + element + value("id") + i),
isNil(ld)? list<value>() : mklist<value>(value(list<value>() + element + value("content") + elementValue(car(ld)))));
return append<value>(nilListValue + element + entry
+ value(nilListValue + element + value("title") + t)
+ value(nilListValue + element + value("id") + i),
isNil(ld)? nilListValue : mklist<value>(value(nilListValue + element + value("content") + elementValue(car(ld)))));
}
/**
@ -69,7 +69,7 @@ const list<value> entriesElementValues(const list<value>& e) {
* Return true if a list of strings contains an RSS feed.
*/
const bool isRSSFeed(const list<string>& ls) {
if (!isXML(ls))
if (!xml::isXML(ls))
return false;
return contains(car(ls), "<rss");
}
@ -78,7 +78,7 @@ const bool isRSSFeed(const list<string>& ls) {
* Convert a list of strings to a list of values representing an RSS entry.
*/
const failable<list<value> > readRSSEntry(const list<string>& ilist) {
const list<value> e = readXML(ilist);
const list<value> e = content(xml::readElements(ilist));
if (isNil(e))
return mkfailure<list<value> >("Empty entry");
return mklist<value>(entryElementValues(car(e)));
@ -88,16 +88,16 @@ const failable<list<value> > readRSSEntry(const list<string>& ilist) {
* Convert a list of strings to a list of values representing an RSS feed.
*/
const failable<list<value> > readRSSFeed(const list<string>& ilist) {
const list<value> f = readXML(ilist);
const list<value> f = content(xml::readElements(ilist));
if (isNil(f))
return mkfailure<list<value> >("Empty feed");
const list<value> c = filter<value>(selector(mklist<value>(element, "channel")), car(f));
const list<value> t = filter<value>(selector(mklist<value>(element, "title")), car(c));
const list<value> i = filter<value>(selector(mklist<value>(element, "link")), car(c));
const list<value> e = filter<value>(selector(mklist<value>(element, "item")), car(c));
return mklist<value>(append<value>(list<value>() + element + feed
+ value(list<value>() + element + value("title") + elementValue(car(t)))
+ value(list<value>() + element + value("id") + elementValue(car(i))),
return mklist<value>(append<value>(nilListValue + element + feed
+ value(nilListValue + element + value("title") + elementValue(car(t)))
+ value(nilListValue + element + value("id") + elementValue(car(i))),
entriesElementValues(e)));
}
@ -109,13 +109,13 @@ const list<value> entryElement(const list<value>& l) {
const value id = elementValue(elementChild("id", l));
const value content = elementChild("content", l);
const bool text = isNil(content)? false : elementHasValue(content);
return append<value>(list<value>()
return append<value>(nilListValue
+ element + "item"
+ (list<value>() + element + "title" + title)
+ (list<value>() + element + "link" + id),
+ (nilListValue + element + "title" + title)
+ (nilListValue + element + "link" + id),
isNil(content)?
list<value>() :
mklist<value>(append<value>(list<value>() + element + "description",
nilListValue :
mklist<value>(append<value>(nilListValue + element + "description",
text? mklist<value>(elementValue(content)) : elementChildren(content))));
}
@ -132,9 +132,9 @@ const list<value> entriesElements(const list<value>& l) {
* Convert a list of values representing an RSS entry to an RSS entry.
* The first two values in the list are the entry id and title.
*/
template<typename R> const failable<R> writeRSSEntry(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
template<typename R> const failable<R> writeRSSEntry(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
return xml::writeElements<R>(reduce, initial, mklist<value>(entryElement(l)));
}
const failable<list<string> > writeRSSEntry(const list<value>& l) {
@ -148,41 +148,41 @@ const failable<list<string> > writeRSSEntry(const list<value>& l) {
* Convert a list of values representing an RSS feed to an RSS feed.
* The first two values in the list are the feed id and title.
*/
template<typename R> const failable<R> writeRSSFeed(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
template<typename R> const failable<R> writeRSSFeed(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& ll) {
const list<value> l = isNil(ll)? ll : (list<value>)car(ll);
const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), l);
const value t = isNil(lt)? value(emptyString) : elementValue(car(lt));
const list<value> li = filter<value>(selector(mklist<value>(element, "id")), l);
const value i = isNil(li)? value(emptyString) : elementValue(car(li));
const list<value> c = list<value>()
+ (list<value>() + element + "title" + t)
+ (list<value>() + element + "link" + i)
+ (list<value>() + element + "description" + t);
const list<value> c = nilListValue
+ (nilListValue + element + "title" + t)
+ (nilListValue + element + "link" + i)
+ (nilListValue + element + "description" + t);
// Write RSS entries
const list<value> le = filter<value>(selector(mklist<value>(element, entry)), l);
if (isNil(le)) {
const list<value> fe = list<value>()
+ element + "rss" + (list<value>() + attribute + "version" + "2.0")
+ append(list<value>() + element + "channel", c);
return writeXML<R>(reduce, initial, mklist<value>(fe));
const list<value> fe = nilListValue
+ element + "rss" + (nilListValue + attribute + "version" + "2.0")
+ append(nilListValue + element + "channel", c);
return xml::writeElements<R>(reduce, initial, mklist<value>(fe));
}
// Write a single RSS entry element with a list of values
if (!isNil(le) && !isNil(car(le)) && isList(car<value>(caddr<value>(car(le))))) {
const list<value> ce = append(c, entriesElements(caddr<value>(car(le))));
const list<value> fe = list<value>()
+ element + "rss" + (list<value>() + attribute + "version" + "2.0")
+ append(list<value>() + element + "channel", ce);
return writeXML<R>(reduce, initial, mklist<value>(fe));
const list<value> fe = nilListValue
+ element + "rss" + (nilListValue + attribute + "version" + "2.0")
+ append(nilListValue + element + "channel", ce);
return xml::writeElements<R>(reduce, initial, mklist<value>(fe));
}
// Write separate RSS entry elements
const list<value> ce = append(c, entriesElements(le));
const list<value> fe = list<value>()
+ element + "rss" + (list<value>() + attribute + "version" + "2.0")
+ append(list<value>() + element + "channel", ce);
return writeXML<R>(reduce, initial, mklist<value>(fe));
const list<value> fe = nilListValue
+ element + "rss" + (nilListValue + attribute + "version" + "2.0")
+ append(nilListValue + element + "channel", ce);
return xml::writeElements<R>(reduce, initial, mklist<value>(fe));
}
/**

View file

@ -33,15 +33,15 @@
namespace tuscany {
namespace scdl {
bool testComposite() {
const bool testComposite() {
ifstream is("test.composite");
const list<value> c = readXML(streamList(is));
const list<value> c = content(xml::readElements(streamList(is)));
return true;
}
bool testComponents() {
const bool testComponents() {
ifstream is("test.composite");
const list<value> c = components(readXML(streamList(is)));
const list<value> c = components(content(xml::readElements(streamList(is))));
assert(length(c) == 4);
const value store = car(c);
@ -58,9 +58,9 @@ bool testComponents() {
return true;
}
bool testServices() {
const bool testServices() {
ifstream is("test.composite");
const list<value> c = components(readXML(streamList(is)));
const list<value> c = components(content(xml::readElements(streamList(is))));
const value store = car(c);
assert(length(services(store)) == 1);
@ -74,9 +74,9 @@ bool testServices() {
return true;
}
bool testReferences() {
const bool testReferences() {
ifstream is("test.composite");
const list<value> c = components(readXML(streamList(is)));
const list<value> c = components(content(xml::readElements(streamList(is))));
const value store = car(c);
assert(length(references(store)) == 3);
@ -86,7 +86,7 @@ bool testReferences() {
assert(length(bindings(catalog)) == 1);
const value binding = car(bindings(catalog));
assert(uri(binding) == value());
assert(uri(binding) == nilValue);
assert(bindingType(binding) == "binding.jsonrpc");
const list<value> t = mkbtree(sort(referenceToTargetAssoc(references(store))));
@ -94,9 +94,9 @@ bool testReferences() {
return true;
}
bool testProperties() {
const bool testProperties() {
ifstream is("test.composite");
const list<value> c = components(readXML(streamList(is)));
const list<value> c = components(content(xml::readElements(streamList(is))));
const value catalog = named(string("Catalog"), c);
assert(length(properties(catalog)) == 1);
@ -110,7 +110,7 @@ bool testProperties() {
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::scdl::testComposite();

View file

@ -30,7 +30,7 @@
#include "list.hpp"
#include "value.hpp"
#include "monad.hpp"
#include "xml.hpp"
#include "../modules/xml/xml.hpp"
namespace tuscany {
namespace scdl {
@ -82,33 +82,26 @@ const list<value> nameToElementAssoc(const list<value>& l) {
/**
* Returns the scdl declaration with the given name.
*/
struct filterName {
const value n;
filterName(const value& n) : n(n) {
}
const bool operator()(const value& v) const {
const value named(const value& n, const value& l) {
const vblambda filterName = [n](const value& v) -> const bool {
return name(v) == n;
}
};
const value named(const value& name, const value& l) {
const list<value> c = filter<value>(filterName(name), l);
};
const list<value> c = filter<value>(filterName, l);
if (isNil(c))
return value();
return nilValue;
return car(c);
}
/**
* Returns the implementation of a component.
*/
const bool filterImplementation(const value& v) {
return isElement(v) && contains(string(cadr<value>(v)), "implementation.");
}
const value implementation(const value& l) {
const vblambda filterImplementation = [](const value& v) -> const bool {
return isElement(v) && contains(string(cadr<value>(v)), "implementation.");
};
const list<value> n = filter<value>(filterImplementation, l);
if (isNil(n))
return value();
return nilValue;
return car(n);
}
@ -156,7 +149,7 @@ const list<value> bindings(const value& l) {
*/
const value bindingsTarget(const list<value>& l) {
if (isNil(l))
return value();
return nilValue;
const value u = uri(car(l));
if (!isNil(u))
return u;

View file

@ -30,18 +30,18 @@ value_element_LDFLAGS =
element_value_SOURCES = element-value.cpp
element_value_LDFLAGS =
xml_value_SOURCES = xml-value.cpp
xml_value_LDFLAGS = -lxml2
xml_element_SOURCES = xml-element.cpp
xml_element_LDFLAGS = -lxml2
value_xml_SOURCES = value-xml.cpp
value_xml_LDFLAGS = -lxml2
element_xml_SOURCES = element-xml.cpp
element_xml_LDFLAGS = -lxml2
json_value_SOURCES = json-value.cpp
json_value_LDFLAGS = -lmozjs
json_value_LDFLAGS = -ljansson
value_json_SOURCES = value-json.cpp
value_json_LDFLAGS = -lmozjs
value_json_LDFLAGS = -ljansson
noinst_PROGRAMS = scheme-test
mod_PROGRAMS = scheme-shell element-value value-element xml-value value-xml json-value value-json
mod_PROGRAMS = scheme-shell element-value value-element xml-element element-xml json-value value-json
TESTS = scheme-test

View file

@ -55,7 +55,7 @@ const bool userPrint(const value val, ostream& out) {
const value evalDriverLoop(istream& in, ostream& out, Env& env) {
promptForInput(evalInputPrompt, out);
value input = readValue(in);
const value input = content(readValue(in));
if (isNil(input))
return input;
const value output = evalExpr(input, env);

View file

@ -31,9 +31,9 @@
namespace tuscany {
namespace scheme {
int elementValue() {
const value v = elementsToValues(readValue(cin));
cout << writeValue(v);
const int elementValue() {
const value v = elementsToValues(content(readValue(cin)));
write(content(writeValue(v)), cout);
return 0;
}

View file

@ -25,15 +25,15 @@
#include "fstream.hpp"
#include "string.hpp"
#include "xml.hpp"
#include "element.hpp"
#include "../xml/xml.hpp"
#include "eval.hpp"
namespace tuscany {
namespace scheme {
int valueXML() {
failable<list<string> > s = writeXML(readValue(cin));
const int valueXML() {
const failable<list<string> > s = xml::writeElements(content(readValue(cin)));
if (!hasContent(s)) {
cerr << reason(s) << " : " << rcode(s);
return 1;

View file

@ -45,7 +45,7 @@ const value setSymbol("set!");
const value dotSymbol(".");
const Env theEmptyEnvironment() {
return list<value>();
return nilListValue;
}
const bool isDefinition(const value& exp) {
@ -68,11 +68,11 @@ const gc_ptr<Frame> firstFrame(const Env& env) {
return car(env);
}
list<value> frameVariables(const Frame& frame) {
const list<value> frameVariables(const Frame& frame) {
return car((list<value> )frame);
}
list<value> frameValues(const Frame& frame) {
const list<value> frameValues(const Frame& frame) {
return cdr((list<value> )frame);
}
@ -103,8 +103,7 @@ const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, c
}
const gc_ptr<Frame> makeFrame(const list<value>& variables, const list<value> values) {
gc_ptr<Frame> frame = new (gc_new<Frame>()) Frame();
*frame = value(makeBinding(cons(value(list<value>()), list<value>()), variables, values));
const gc_ptr<Frame> frame = new (gc_new<Frame>()) Frame(makeBinding(cons(value(nilListValue), nilListValue), variables, values));
return frame;
}
@ -120,7 +119,7 @@ const value definitionValue(const value& exp) {
const list<value> exps(exp);
if(isSymbol(car(cdr(exps)))) {
if (isNil(cdr(cdr(exps))))
return value();
return nilValue;
return car(cdr(cdr(exps)));
}
const list<value> lexps(car(cdr(exps)));
@ -140,7 +139,8 @@ const Frame addBindingToFrame(const value& var, const value& val, const Frame& f
}
const bool defineVariable(const value& var, const value& val, Env& env) {
*firstFrame(env) = addBindingToFrame(var, val, *firstFrame(env));
const Frame newFrame = addBindingToFrame(var, val, *firstFrame(env));
setvalue(*firstFrame(env), addBindingToFrame(var, val, *firstFrame(env)));
return true;
}
@ -168,7 +168,7 @@ const value lookupEnvScan(const value& var, const list<value>& vars, const list<
const value lookupEnvLoop(const value& var, const Env& env) {
if(env == theEmptyEnvironment()) {
logStream() << "Unbound variable " << var << endl;
return value();
return nilValue;
}
return lookupEnvScan(var, frameVariables(*firstFrame(env)), frameValues(*firstFrame(env)), env);
}

View file

@ -147,7 +147,7 @@ const value applyProcedure(const value& procedure, list<value>& arguments) {
return evalSequence(procedureBody(procedure), env);
}
logStream() << "Unknown procedure type " << procedure << endl;
return value();
return nilValue;
}
const value sequenceToExp(const list<value> exps) {
@ -209,16 +209,16 @@ const value expandClauses(const list<value>& clauses) {
if(isNil(rest))
return sequenceToExp(condActions(first));
logStream() << "else clause isn't last " << clauses << endl;
return value();
return nilValue;
}
return makeIf(condPredicate(first), sequenceToExp(condActions(first)), expandClauses(rest));
}
value condToIf(const value& exp) {
const value condToIf(const value& exp) {
return expandClauses(condClauses(exp));
}
value evalIf(const value& exp, Env& env) {
const value evalIf(const value& exp, Env& env) {
if(isTrue(evalExpr(ifPredicate(exp), env)))
return evalExpr(ifConsequent(exp), env);
return evalExpr(ifAlternative(exp), env);
@ -255,7 +255,7 @@ const value evalExpr(const value& exp, Env& env) {
return applyProcedure(evalExpr(operat(exp), env), operandValues);
}
logStream() << "Unknown expression type " << exp << endl;
return value();
return nilValue;
}
const list<value> quotedParameters(const list<value>& p) {

View file

@ -37,39 +37,38 @@
namespace tuscany {
namespace scheme {
const value rightParenthesis(mklist<value>(")"));
const value leftParenthesis(mklist<value>("("));
const value comment(mklist<value>(";"));
const value rightParenthesis(")");
const value leftParenthesis("(");
const double stringToNumber(const string& str) {
inline const double stringToNumber(const string& str) {
return atof(c_str(str));
}
const bool isWhitespace(const char ch) {
inline const bool isWhitespace(const char ch) {
return ch != -1 && isspace(ch);
}
const bool isIdentifierStart(const char ch) {
inline const bool isIdentifierStart(const char ch) {
return ch != -1 && !isspace(ch) && !isdigit(ch);
}
const bool isIdentifierPart(const char ch) {
inline const bool isIdentifierPart(const char ch) {
return ch != -1 && !isspace(ch) && ch != '(' && ch != ')';
}
const bool isDigit(const char ch) {
inline const bool isDigit(const char ch) {
return isdigit(ch) || ch == '.';
}
const bool isLeftParenthesis(const value& token) {
inline const bool isLeftParenthesis(const value& token) {
return leftParenthesis == token;
}
const bool isRightParenthesis(const value& token) {
inline const bool isRightParenthesis(const value& token) {
return rightParenthesis == token;
}
const char readChar(istream& in) {
inline const char readChar(istream& in) {
if(in.eof()) {
return -1;
}
@ -77,14 +76,14 @@ const char readChar(istream& in) {
return c;
}
const char peekChar(istream& in) {
inline const char peekChar(istream& in) {
if(eof(in))
return -1;
char c = (char)peek(in);
return c;
}
const bool isQuote(const value& token) {
inline const bool isQuote(const value& token) {
return token == quoteSymbol;
}
@ -93,9 +92,9 @@ const value readQuoted(istream& in);
const value readIdentifier(const char chr, istream& in);
const value readString(istream& in);
const value readNumber(const char chr, istream& in);
const value readValue(istream& in);
const failable<value> readValue(istream& in);
const failable<value> readToken(istream& in) {
inline const failable<value> readToken(istream& in) {
const char firstChar = readChar(in);
if(isWhitespace(firstChar))
return readToken(in);
@ -119,18 +118,19 @@ const failable<value> readToken(istream& in) {
return readToken(in);
}
const failable<value> skipComment(istream& in) {
const char nextChar = readChar(in);
if (nextChar == '\n')
return readToken(in);
return skipComment(in);
inline const failable<value> skipComment(istream& in) {
while(true) {
const char nextChar = readChar(in);
if (nextChar == '\n')
return readToken(in);
}
}
const value readQuoted(istream& in) {
return mklist(quoteSymbol, readValue(in));
inline const value readQuoted(istream& in) {
return mklist(quoteSymbol, content(readValue(in)));
}
const list<value> readList(const list<value>& listSoFar, istream& in) {
inline const list<value> readList(const list<value>& listSoFar, istream& in) {
const failable<value> ftoken = readToken(in);
if (!hasContent(ftoken))
return reverse(listSoFar);
@ -142,95 +142,97 @@ const list<value> readList(const list<value>& listSoFar, istream& in) {
return readList(cons(token, listSoFar), in);
}
const string listToString(const list<char>& l) {
if(isNil(l))
return "";
const char buf[1] = { car(l) };
return string(buf, 1) + listToString(cdr(l));
inline const string readIdentifierHelper(const char chr, istream& in) {
ostringstream buf;
buf << chr;
while(true) {
const char nextChar = peekChar(in);
if(!isIdentifierPart(nextChar))
return str(buf);
buf << readChar(in);
}
}
const 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, istream& in) {
const value val = c_str(listToString(readIdentifierHelper(mklist(chr), in)));
inline const value readIdentifier(const char chr, istream& in) {
const value val = c_str(readIdentifierHelper(chr, in));
if (val == "false")
return value((bool)false);
if (val == "true")
return value((bool)true);
if (val == "nil")
return value();
return nilValue;
return val;
}
const list<char> readStringHelper(const list<char>& listSoFar, istream& in) {
const char nextChar = readChar(in);
if(nextChar == -1 || nextChar == '"')
return reverse(listSoFar);
if (nextChar == '\\') {
const char escapedChar = readChar(in);
if (escapedChar == -1)
return reverse(listSoFar);
return readStringHelper(cons(escapedChar, listSoFar), in);
inline const value readString(istream& in) {
ostringstream buf;
while(true) {
const char nextChar = readChar(in);
if(nextChar == -1 || nextChar == '"')
return (value)str(buf);
if (nextChar == '\\') {
const char escapedChar = readChar(in);
if (escapedChar == -1)
return (value)str(buf);
buf << escapedChar;
}
buf << nextChar;
}
return readStringHelper(cons(nextChar, listSoFar), in);
}
const value readString(istream& in) {
return listToString(readStringHelper(list<char>(), in));
inline const value readNumber(const char chr, istream& in) {
ostringstream buf;
buf << chr;
while(true) {
const char nextChar = peekChar(in);
if(!isDigit(nextChar))
return stringToNumber(str(buf));
buf << readChar(in);
}
}
const list<char> readNumberHelper(const list<char>& listSoFar, istream& in) {
const char nextChar = peekChar(in);
if(isDigit(nextChar))
return readNumberHelper(cons(readChar(in), listSoFar), in);
return reverse(listSoFar);
}
const value readNumber(const char chr, istream& in) {
return stringToNumber(listToString(readNumberHelper(mklist(chr), in)));
}
const value readValue(istream& in) {
inline const failable<value> readValue(istream& in) {
const failable<value> fnextToken = readToken(in);
if (!hasContent(fnextToken))
return value();
return nilValue;
const value nextToken = content(fnextToken);
if(isLeftParenthesis(nextToken))
return readList(list<value>(), in);
return (value)readList(nilListValue, in);
return nextToken;
}
const value readValue(const string s) {
inline const failable<value> readValue(const string& s) {
istringstream in(s);
const failable<value> fnextToken = readToken(in);
if (!hasContent(fnextToken))
return value();
return nilValue;
const value nextToken = content(fnextToken);
if(isLeftParenthesis(nextToken))
return readList(list<value>(), in);
return (value)readList(nilListValue, in);
return nextToken;
}
const bool writeValue(const value& val, ostream& out) {
out << val;
return true;
inline const failable<value> readValue(const list<string>& l) {
ostringstream os;
write(l, os);
return readValue(str(os));
}
const string writeValue(const value& val) {
inline const failable<ostream&> writeValue(const value& val, ostream& out) {
out << val;
return out;
}
inline const failable<list<string> > writeValue(const value& val) {
ostringstream out;
out << val;
return str(out);
return mklist<string>(str(out));
}
const value readScript(istream& in) {
const value val = readValue(in);
inline const value readScript(istream& in) {
const value val = content(readValue(in));
if (isNil(val))
return list<value>();
return nilListValue;
return cons(val, (list<value>)readScript(in));
}

View file

@ -40,7 +40,7 @@ const value quoteSymbol("'");
const value lambdaSymbol("lambda");
#ifdef WANT_THREADS
perthread_ptr<ostream> displayOutStream;
const perthread_ptr<ostream> displayOutStream;
#else
ostream* displayOutStream = NULL;
#endif
@ -51,49 +51,49 @@ perthread_ptr<ostream> logOutStream;
ostream* logOutStream = NULL;
#endif
const bool setupDisplay(ostream& out) {
inline const bool setupDisplay(ostream& out) {
displayOutStream = &out;
return true;
}
ostream& displayStream() {
inline ostream& displayStream() {
if (displayOutStream == NULL)
return cout;
return *displayOutStream;
}
const bool setupLog(ostream& out) {
inline const bool setupLog(ostream& out) {
logOutStream = &out;
return true;
}
ostream& logStream() {
inline ostream& logStream() {
if (logOutStream == NULL)
return cerr;
return *logOutStream;
}
const value carProc(const list<value>& args) {
inline const value carProc(const list<value>& args) {
return car((list<value> )car(args));
}
const value cdrProc(const list<value>& args) {
inline const value cdrProc(const list<value>& args) {
return cdr((list<value> )car(args));
}
const value consProc(const list<value>& args) {
inline const value consProc(const list<value>& args) {
return cons(car(args), (list<value> )cadr(args));
}
const value listProc(const list<value>& args) {
inline const value listProc(const list<value>& args) {
return args;
}
const value assocProc(const list<value>& args) {
inline const value assocProc(const list<value>& args) {
return assoc(car(args), (list<list<value> >)cadr(args));
}
const value nulProc(const list<value>& args) {
inline const value nulProc(const list<value>& args) {
const value v(car(args));
if (isNil(v))
return true;
@ -102,31 +102,31 @@ const value nulProc(const list<value>& args) {
return false;
}
const value equalProc(const list<value>& args) {
inline const value equalProc(const list<value>& args) {
return (bool)(car(args) == cadr(args));
}
const value addProc(const list<value>& args) {
inline const value addProc(const list<value>& args) {
if (isNil(cdr(args)))
return (double)car(args);
return (double)car(args) + (double)cadr(args);
}
const value subProc(const list<value>& args) {
inline const value subProc(const list<value>& args) {
if (isNil(cdr(args)))
return (double)0 - (double)car(args);
return (double)car(args) - (double)cadr(args);
}
const value mulProc(const list<value>& args) {
inline const value mulProc(const list<value>& args) {
return (double)car(args) * (double)cadr(args);
}
const value divProc(const list<value>& args) {
inline const value divProc(const list<value>& args) {
return (double)car(args) / (double)cadr(args);
}
const value displayProc(const list<value>& args) {
inline const value displayProc(const list<value>& args) {
if (isNil(args)) {
displayStream() << endl;
return true;
@ -135,7 +135,7 @@ const value displayProc(const list<value>& args) {
return displayProc(cdr(args));
}
const value logProc(const list<value>& args) {
inline const value logProc(const list<value>& args) {
if (isNil(args)) {
logStream() << endl;
return true;
@ -144,52 +144,52 @@ const value logProc(const list<value>& args) {
return logProc(cdr(args));
}
const value uuidProc(unused const list<value>& args) {
inline const value uuidProc(unused const list<value>& args) {
return mkuuid();
}
const value cadrProc(const list<value>& args) {
inline const value cadrProc(const list<value>& args) {
return cadr((list<value> )car(args));
}
const value caddrProc(const list<value>& args) {
inline const value caddrProc(const list<value>& args) {
return caddr((list<value> )car(args));
}
const value cadddrProc(const list<value>& args) {
inline const value cadddrProc(const list<value>& args) {
return cadddr((list<value> )car(args));
}
const value cddrProc(const list<value>& args) {
inline const value cddrProc(const list<value>& args) {
return cddr((list<value> )car(args));
}
const value cdddrProc(const list<value>& args) {
inline const value cdddrProc(const list<value>& args) {
return cdddr((list<value> )car(args));
}
const value appendProc(const list<value>& args) {
inline const value appendProc(const list<value>& args) {
return append((list<value> )car(args), (list<value>)cadr(args));
}
const value startProc(unused const list<value>& args) {
return lambda<value(const list<value>&)>();
inline const value startProc(unused const list<value>& args) {
return lvvlambda();
}
const value stopProc(unused const list<value>& args) {
return lambda<value(const list<value>&)>();
inline const value stopProc(unused const list<value>& args) {
return lvvlambda();
}
const value applyPrimitiveProcedure(const value& proc, list<value>& args) {
const lambda<value(const list<value>&)> func(cadr((list<value>)proc));
inline const value applyPrimitiveProcedure(const value& proc, list<value>& args) {
const lvvlambda func(cadr((list<value>)proc));
return func(args);
}
const bool isPrimitiveProcedure(const value& proc) {
inline const bool isPrimitiveProcedure(const value& proc) {
return isTaggedList(proc, primitiveSymbol);
}
const bool isSelfEvaluating(const value& exp) {
inline const bool isSelfEvaluating(const value& exp) {
if(isNil(exp))
return true;
if(isNumber(exp))
@ -203,15 +203,15 @@ const bool isSelfEvaluating(const value& exp) {
return false;
}
const value primitiveImplementation(const list<value>& proc) {
inline const value primitiveImplementation(const list<value>& proc) {
return car(cdr(proc));
}
template<typename F> const value primitiveProcedure(const F& f) {
return mklist<value>(primitiveSymbol, (lambda<value(const list<value>&)>)f);
template<typename F> inline const value primitiveProcedure(const F& f) {
return mklist<value>(primitiveSymbol, (lvvlambda)f);
}
const list<value> primitiveProcedureNames() {
inline const list<value> primitiveProcedureNames() {
return mklist<value>("car")
+ "cdr"
+ "cons"
@ -237,7 +237,7 @@ const list<value> primitiveProcedureNames() {
+ "stop";
}
const list<value> primitiveProcedureObjects() {
inline const list<value> primitiveProcedureObjects() {
return mklist(primitiveProcedure(carProc))
+ primitiveProcedure(cdrProc)
+ primitiveProcedure(consProc)
@ -263,23 +263,23 @@ const list<value> primitiveProcedureObjects() {
+ primitiveProcedure(stopProc);
}
const bool isFalse(const value& exp) {
inline const bool isFalse(const value& exp) {
return (bool)exp == false;
}
const bool isTrue(const value& exp) {
inline const bool isTrue(const value& exp) {
return (bool)exp == true;
}
const bool isQuoted(const value& exp) {
inline const bool isQuoted(const value& exp) {
return isTaggedList(exp, quoteSymbol);
}
const value textOfQuotation(const value& exp) {
inline const value textOfQuotation(const value& exp) {
return car(cdr((list<value> )exp));
}
const value makeLambda(const list<value>& parameters, const list<value>& body) {
inline const value makeLambda(const list<value>& parameters, const list<value>& body) {
return cons(lambdaSymbol, cons<value>(parameters, body));
}

View file

@ -30,7 +30,7 @@
#include "driver.hpp"
int main() {
tuscany::gc_scoped_pool pool;
const tuscany::gc_scoped_pool pool;
tuscany::scheme::evalDriverRun(tuscany::cin, tuscany::cout);
return 0;
}

View file

@ -26,14 +26,16 @@
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "perf.hpp"
#include "driver.hpp"
#include "scheme-test.hpp"
namespace tuscany {
namespace scheme {
bool testEnv() {
gc_scoped_pool pool;
Env globalEnv = list<value>();
const bool testEnv() {
const gc_scoped_pool pool;
Env globalEnv = nilListValue;
Env env = extendEnvironment(mklist<value>("a"), mklist<value>(1), globalEnv);
defineVariable("x", env, env);
assert(lookupVariableValue(value("x"), env) == env);
@ -41,7 +43,7 @@ bool testEnv() {
return true;
}
bool testEnvGC() {
const bool testEnvGC() {
resetLambdaCounters();
resetListCounters();
resetValueCounters();
@ -52,49 +54,49 @@ bool testEnvGC() {
return true;
}
bool testRead() {
const bool testRead() {
istringstream is("abcd");
assert(readValue(is) == "abcd");
assert(content(readValue(is)) == "abcd");
istringstream is2("123");
assert(readValue(is2) == value(123));
assert(content(readValue(is2)) == value(123));
istringstream is3("(abcd)");
assert(readValue(is3) == mklist(value("abcd")));
assert(content(readValue(is3)) == mklist(value("abcd")));
istringstream is4("(abcd xyz)");
assert(readValue(is4) == mklist<value>("abcd", "xyz"));
assert(content(readValue(is4)) == mklist<value>("abcd", "xyz"));
istringstream is5("(abcd (xyz tuv))");
assert(readValue(is5) == mklist<value>("abcd", mklist<value>("xyz", "tuv")));
assert(content(readValue(is5)) == mklist<value>("abcd", mklist<value>("xyz", "tuv")));
return true;
}
bool testWrite() {
const bool testWrite() {
{
const list<value> i = list<value>()
+ (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
+ (list<value>() + "item"
+ (list<value>() + "name" + "Apple")
+ (list<value>() + "price" + "$2.99")))
+ (list<value>() + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
+ (list<value>() + "item"
+ (list<value>() + "name" + "Orange")
+ (list<value>() + "price" + "$3.55")));
const list<value> i = nilListValue
+ (nilListValue + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
+ (nilListValue + "item"
+ (nilListValue + "name" + "Apple")
+ (nilListValue + "price" + "$2.99")))
+ (nilListValue + "item" + "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
+ (nilListValue + "item"
+ (nilListValue + "name" + "Orange")
+ (nilListValue + "price" + "$3.55")));
const list<value> a = cons<value>("Feed", cons<value>("feed-1234", i));
ostringstream os;
writeValue(a, os);
istringstream is(str(os));
assert(readValue(is) == a);
assert(content(readValue(is)) == a);
}
{
const list<value> i = mklist<value>("x", value());
const list<value> i = mklist<value>("x", nilValue);
const list<value> a = mklist<value>(i);
ostringstream os;
writeValue(a, os);
istringstream is(str(os));
assert(readValue(is) == a);
assert(content(readValue(is)) == a);
}
return true;
}
@ -147,8 +149,8 @@ const string evalOutput(const string& scm) {
return str(os);
}
bool testEval() {
gc_scoped_pool pool;
const bool testEval() {
const gc_scoped_pool pool;
assert(contains(evalOutput(testSchemeNumber), "testNumber ok"));
assert(contains(evalOutput(testSchemeString), "testString ok"));
assert(contains(evalOutput(testSchemeDefinition), "testDefinition ok"));
@ -161,8 +163,8 @@ bool testEval() {
return true;
}
bool testEvalExpr() {
gc_scoped_pool pool;
const bool testEvalExpr() {
const gc_scoped_pool pool;
const value exp = mklist<value>("+", 2, 3);
Env env = setupEnvironment();
const value r = evalExpr(exp, env);
@ -170,8 +172,8 @@ bool testEvalExpr() {
return true;
}
bool testEvalRun() {
gc_scoped_pool pool;
const bool testEvalRun() {
const gc_scoped_pool pool;
evalDriverRun(cin, cout);
return true;
}
@ -188,8 +190,8 @@ const string testReturnLambda(
const string testCallLambda(
"(define (testCallLambda l x y) (l x y))");
bool testEvalLambda() {
gc_scoped_pool pool;
const bool testEvalLambda() {
const gc_scoped_pool pool;
Env env = setupEnvironment();
const value trl = mklist<value>("testReturnLambda");
@ -208,7 +210,18 @@ bool testEvalLambda() {
return true;
}
bool testEvalGC() {
const bool testEvalScript() {
const gc_scoped_pool pool;
Env env = setupEnvironment();
ifstream is("test.scm");
const value script = readScript(is);
const value expr = mklist<value>("echo", string("x"));
const value res = evalScript(expr, script, env);
assert(res == string("x"));
return true;
}
const bool testEvalGC() {
resetLambdaCounters();
resetListCounters();
resetValueCounters();
@ -221,11 +234,55 @@ bool testEvalGC() {
return true;
}
const string testCustomer = "((customer (@name \"jdoe\") (account (id \"1234\") (@balance 1000)) (address (@city \"san francisco\") (@state \"ca\"))))";
const bool testReadWrite() {
const gc_scoped_pool pool;
istringstream is(testCustomer);
const value r = content(readValue(is));
ostringstream os;
writeValue(r, os);
//assert(str(os) == testCustomer);
return true;
}
const bool testReadWritePerf() {
const gc_scoped_pool pool;
const blambda rwl = blambda(testReadWrite);
cout << "Scheme read + write test " << time(rwl, 5, 200) << " ms" << endl;
return true;
}
const bool testReadWriteBigDoc() {
const gc_scoped_pool pool;
istringstream is(testBigDoc);
const value r = content(readValue(is));
ostringstream os;
writeValue(r, os);
//assert(str(os) == testBigDoc);
return true;
}
const bool testReadWriteBigDocPerf() {
const gc_scoped_pool pool;
const blambda rwl = blambda(testReadWriteBigDoc);
cout << "Scheme big doc read + write test " << time(rwl, 5, 200) << " ms" << endl;
return true;
}
}
}
int main() {
tuscany::gc_scoped_pool p;
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::scheme::testEnv();
@ -235,7 +292,10 @@ int main() {
tuscany::scheme::testEval();
tuscany::scheme::testEvalExpr();
tuscany::scheme::testEvalLambda();
tuscany::scheme::testEvalScript();
tuscany::scheme::testEvalGC();
tuscany::scheme::testReadWritePerf();
tuscany::scheme::testReadWriteBigDocPerf();
tuscany::cout << "OK" << tuscany::endl;
return 0;

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,44 @@
; Licensed to the Apache Software Foundation (ASF) under one
; or more contributor license agreements. See the NOTICE file
; distributed with this work for additional information
; regarding copyright ownership. The ASF licenses this file
; to you under the Apache License, Version 2.0 (the
; "License"); you may not use this file except in compliance
; with the License. You may obtain a copy of the License at
;
; http://www.apache.org/licenses/LICENSE-2.0
;
; Unless required by applicable law or agreed to in writing,
; software distributed under the License is distributed on an
; "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
; KIND, either express or implied. See the License for the
; specific language governing permissions and limitations
; under the License.
; JSON-RPC test case
(define (echo x) x)
; ATOMPub test case
(define (get id)
(if (nul id)
'((feed (title "Sample Feed") (id "123456789") (entry
(((title "Item") (id "111") (content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))
((title "Item") (id "222") (content (item (name "Orange") (currencyCode "USD") (currencySymbol "$") (price 3.55))))
((title "Item") (id "333") (content (item (name "Pear") (currencyCode "USD") (currencySymbol "$") (price 1.55))))))))
(list (list 'entry '(title "Item") (list 'id (car id)) '(content (item (name "Apple") (currencyCode "USD") (currencySymbol "$") (price 2.99))))))
)
(define (post collection item)
'("123456789")
)
(define (put id item)
true
)
(define (delete id)
true
)

View file

@ -31,9 +31,9 @@
namespace tuscany {
namespace scheme {
int valueElement() {
const value v = valuesToElements(readValue(cin));
cout << writeValue(v);
const int valueElement() {
const value v = valuesToElements(content(readValue(cin)));
write(content(writeValue(v)), cout);
return 0;
}

View file

@ -25,16 +25,16 @@
#include "fstream.hpp"
#include "string.hpp"
#include "xml.hpp"
#include "element.hpp"
#include "../xml/xml.hpp"
#include "eval.hpp"
namespace tuscany {
namespace scheme {
int xmlValue() {
const value v = readXML(streamList(cin));
cout << writeValue(v);
const int xmlValue() {
const value v = content(xml::readElements(streamList(cin)));
write(content(writeValue(v)), cout);
return 0;
}

View file

@ -0,0 +1,29 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
incl_HEADERS = *.hpp
incldir = $(prefix)/include/modules/xml
xml_test_SOURCES = xml-test.cpp
xml_test_LDFLAGS = -lxml2
xsd_test_SOURCES = xsd-test.cpp
xsd_test_LDFLAGS = -lxml2
noinst_PROGRAMS = xml-test xsd-test
TESTS = xml-test

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,373 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/* $Rev$ $Date$ */
/**
* Test XML handling functions.
*/
#include <assert.h>
#include "stream.hpp"
#include "string.hpp"
#include "list.hpp"
#include "value.hpp"
#include "element.hpp"
#include "perf.hpp"
#include "xml.hpp"
#include "xml-test.hpp"
namespace tuscany {
namespace xml {
const string currencyXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200912\" targetNamespace=\"http://services\" name=\"currency\">"
"<component name=\"CurrencyConverterWebService\">"
"<implementation.java class=\"services.CurrencyConverterImpl\"/>"
"<service name=\"CurrencyConverter\">"
"<binding.ws/>"
"</service>"
"</component>"
"<component name=\"CurrencyConverterWebService2\">"
"<implementation.java class=\"services.CurrencyConverterImpl2\"/>"
"<service name=\"CurrencyConverter2\">"
"<binding.atom/>"
"</service>"
"<property name=\"currency\">US</property>"
"</component>"
"</composite>\n";
const string customerXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<customer>"
"<name>jdoe</name>"
"<address>"
"<city>san francisco</city>"
"<state>ca</state>"
"</address>"
"<account>"
"<id>1234</id>"
"<balance>1000</balance>"
"</account>"
"<account>"
"<id>6789</id>"
"<balance>2000</balance>"
"</account>"
"<account>"
"<id>4567</id>"
"<balance>3000</balance>"
"</account>"
"</customer>\n";
const string abcXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<a>"
"<m>abc</m>"
"<m>def</m>"
"<m>xyz</m>"
"<m>tuv</m>"
"</a>\n";
const string xyzXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<a>"
"<m>"
"<id>123</id>"
"<name>abc</name>"
"</m>"
"<m>"
"<id>234</id>"
"<name>def</name>"
"</m>"
"<m>"
"<id>345</id>"
"<name>xyz</name>"
"</m>"
"<m>"
"<id>456</id>"
"<name>tuv</name>"
"</m>"
"</a>\n";
const string boolXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<x>true</x>\n";
const string numberXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<x>123.4</x>\n";
const bool isName(const value& token) {
return isTaggedList(token, attribute) && attributeName(token) == "name";
}
const bool testReadXML() {
{
istringstream is(customerXML);
const list<value> c = content(readElements(streamList(is)));
}
{
istringstream is(currencyXML);
const list<value> c = content(readElements(streamList(is)));
const value composite = car(c);
assert(isTaggedList(composite, element));
assert(elementName(composite) == "composite");
assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == string("currency"));
}
{
istringstream is(boolXML);
const list<value> c = content(readElements(streamList(is)));
assert(caddr<value>(car(c)) == value(true));
}
{
istringstream is(numberXML);
const list<value> c = content(readElements(streamList(is)));
assert(caddr<value>(car(c)) == value(123.4));
}
return true;
}
ostream* xmlWriter(const string& s, ostream* os) {
(*os) << s;
return os;
}
const bool testWriteXML() {
{
istringstream is(customerXML);
const list<value> c = content(readElements(streamList(is)));
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, c);
assert(str(os) == customerXML);
}
{
istringstream is(currencyXML);
const list<value> c = content(readElements(streamList(is)));
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, c);
assert(str(os) == currencyXML);
}
return true;
}
const bool testElements() {
{
const list<value> ad = mklist<value>(mklist<value>("city", string("san francisco")), mklist<value>("state", string("ca")));
const list<value> ac1 = mklist<value>(mklist<value>("id", string("1234")), mklist<value>("balance", 1000));
const list<value> ac2 = mklist<value>(mklist<value>("id", string("6789")), mklist<value>("balance", 2000));
const list<value> ac3 = mklist<value>(mklist<value>("id", string("4567")), mklist<value>("balance", 3000));
{
const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3))));
const list<value> e = valuesToElements(c);
const list<value> v = elementsToValues(e);
assert(v == c);
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
{
const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3)));
const list<value> e = valuesToElements(c);
const list<value> v = elementsToValues(e);
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
}
{
istringstream is(abcXML);
const list<value> c = content(readElements(streamList(is)));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, e);
assert(str(os) == abcXML);
}
{
istringstream is(xyzXML);
const list<value> c = content(readElements(streamList(is)));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, e);
assert(str(os) == xyzXML);
}
{
istringstream is(customerXML);
const list<value> c = content(readElements(streamList(is)));
const list<value> v = elementsToValues(c);
const list<value> e = valuesToElements(v);
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, e);
assert(str(os) == customerXML);
}
return true;
}
const bool testValues() {
{
const list<value> l = mklist<value>(nilListValue + "ns1:echoString" + (nilListValue + "@xmlns:ns1" + string("http://ws.apache.org/axis2/services/echo")) + (nilListValue + "text" + string("Hello World!")));
const list<value> e = valuesToElements(l);
const failable<list<string> > lx = writeElements(e);
ostringstream os;
write(content(lx), os);
istringstream is(str(os));
const list<value> x = content(readElements(streamList(is)));
const list<value> v = elementsToValues(x);
assert(v == l);
}
return true;
}
const bool testReadWrite() {
const gc_scoped_pool pool;
istringstream is(customerXML);
const list<string> il = streamList(is);
const list<value> r = elementsToValues(content(readElements(il)));
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, valuesToElements(r));
//assert(str(os) == customerXML);
return true;
}
const bool testReadWritePerf() {
const gc_scoped_pool pool;
const blambda rwl = blambda(testReadWrite);
cout << "XML read + write test " << time(rwl, 5, 200) << " ms" << endl;
return true;
}
const bool testReadWriteBigDoc() {
const gc_scoped_pool pool;
istringstream is(testBigDoc);
const list<string> il = streamList(is);
const list<value> r = elementsToValues(content(readElements(il)));
ostringstream os;
writeElements<ostream*>(xmlWriter, &os, valuesToElements(r));
//assert(str(os) == testBigDoc);
return true;
}
const bool testReadWriteBigDocPerf() {
const gc_scoped_pool pool;
const blambda rwl = blambda(testReadWriteBigDoc);
cout << "XML big doc read + write test " << time(rwl, 5, 200) << " ms" << endl;
return true;
}
const string customersXML =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<customers>"
"<customer>"
"<name>jane doe</name>"
"<address>"
"<city>san francisco</city>"
"<state>ca</state>"
"</address>"
"<account>"
"<id>1234</id>"
"<balance>1000</balance>"
"</account>"
"<account>"
"<id>6789</id>"
"<balance>4000</balance>"
"</account>"
"</customer>"
"<customer>"
"<name>john doe</name>"
"<address>"
"<city>new york</city>"
"<state>ny</state>"
"</address>"
"<account>"
"<id>5678</id>"
"<balance>2000</balance>"
"</account>"
"<account>"
"<id>4321</id>"
"<balance>1000</balance>"
"</account>"
"</customer>"
"</customers>\n";
const bool testQuery() {
{
const gc_scoped_pool pool;
// Read XML doc containing customers
istringstream is(customersXML);
const list<value> c = content(readElements(streamList(is)));
//cout << c << endl;
// Map list of customers to a list of (customer name, customer balance) pairs
const list<value> nb = map<value, value>([](value e) -> const value {
// Map list of accounts to a list of balances
list<value> bals = map<value, value>([](value e) -> const value {
return (double)elementValue(elementChild("balance", e));
}, elementChildren("account", e));
// Reduce list of balances to compute customer balance
value total = reduce<value, value>([](value accum, value v) -> const value {
return (double)accum + (double)v;
}, value(0), bals);
// Return (customer name, customer balance) pair
return mklist<value>(elementValue(elementChild("name", e)), total);
}, elementChildren("customer", elementChild("customers", c)));
// The resulting list of (customer name, customer balance) pairs
//cout << nb << endl;
assert(nb == mklist<value>(mklist<value>("jane doe", 5000), mklist<value>("john doe", 3000)));
}
return true;
}
}
}
int main() {
const tuscany::gc_scoped_pool p;
tuscany::cout << "Testing..." << tuscany::endl;
tuscany::xml::testReadXML();
tuscany::xml::testWriteXML();
tuscany::xml::testElements();
tuscany::xml::testValues();
tuscany::xml::testReadWritePerf();
tuscany::xml::testReadWriteBigDocPerf();
tuscany::xml::testQuery();
tuscany::cout << "OK" << tuscany::endl;
return 0;
}

File diff suppressed because one or more lines are too long

View file

@ -38,24 +38,20 @@
#include "monad.hpp"
namespace tuscany {
/**
* APR-based memory management functions.
*/
namespace xml {
/**
* Initializes the libxml2 library.
*/
class XMLParser {
public:
XMLParser() {
inline XMLParser() {
debug("xml::XMLParser");
xmlMemSetup(gc_pool_free, gc_pool_malloc, gc_pool_realloc, gc_pool_strdup);
xmlInitParser();
}
~XMLParser() {
inline ~XMLParser() {
}
} xmlParser;
@ -68,30 +64,19 @@ public:
None = 0, Element = 1, Attribute = 2, Text = 3, EndElement = 15, Identifier = 100, End = 101
};
XMLReader(xmlTextReaderPtr xml) : xml(xml), owner(true), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) {
inline XMLReader(xmlTextReaderPtr xml) : xml(xml), owner(true), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) {
debug("xml::XMLReader::xml");
xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1);
xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1);
}
XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) {
inline XMLReader(const XMLReader& r) : xml(r.xml), owner(false), tokenType(r.tokenType), isEmptyElement(r.isEmptyElement), hasValue(r.hasValue), hasAttributes(r.hasAttributes) {
debug("xml::XMLReader::copy");
}
const XMLReader& operator=(const XMLReader& r) {
debug("xml::XMLReader::operator=");
if(this == &r)
return *this;
xml = r.xml;
owner = false;
tokenType = r.tokenType;
isEmptyElement = r.isEmptyElement;
hasValue = r.hasValue;
hasAttributes = r.hasAttributes;
return *this;
}
XMLReader& operator=(const XMLReader& r) = delete;
~XMLReader() {
inline ~XMLReader() {
if (!owner)
return;
xmlTextReaderClose(xml);
@ -101,7 +86,7 @@ public:
/**
* Read the next XML token and return its type.
*/
int read() {
inline const int read() {
if (tokenType == End)
return tokenType;
if (tokenType == Element) {
@ -120,13 +105,13 @@ public:
return tokenType = xmlTextReaderNodeType(xml);
}
operator xmlTextReaderPtr() const {
inline operator xmlTextReaderPtr() const {
return xml;
}
private:
xmlTextReaderPtr xml;
bool owner;
const xmlTextReaderPtr xml;
const bool owner;
int tokenType;
bool isEmptyElement;
bool hasValue;
@ -139,38 +124,56 @@ private:
const value endElement("<");
const value startElement(">");
/**
* Read a value from a text string, automatically detects a boolean or number value.
*/
const value readTextValue(const char* const val) {
if (!strcmp("true", val))
return value(true);
if (!strcmp("false", val))
return value(false);
char e[2];
double d;
const int n = sscanf(val, "%lg%1s", &d, e);
if (n == 1)
return value(d);
return value(string(val));
}
/**
* Read an XML identifier.
*/
const value readIdentifier(XMLReader& reader) {
const char* name = (const char*)xmlTextReaderConstName(reader);
inline const value readIdentifier(XMLReader& reader) {
const char* const name = (const char*)xmlTextReaderConstName(reader);
return name;
}
/**
* Read XML text.
*/
const value readText(XMLReader& reader) {
const char *val = (const char*)xmlTextReaderConstValue(reader);
return string(val);
inline const value readText(XMLReader& reader) {
const char* const val = (const char*)xmlTextReaderConstValue(reader);
return readTextValue(val);
}
/**
* Read an XML attribute.
*/
const value readAttribute(XMLReader& reader) {
const char *name = (const char*)xmlTextReaderConstName(reader);
const char *val = (const char*)xmlTextReaderConstValue(reader);
return mklist<value>(attribute, name, string(val));
inline const value readAttribute(XMLReader& reader) {
const char* const name = (const char*)xmlTextReaderConstName(reader);
const char* const val = (const char*)xmlTextReaderConstValue(reader);
return mklist<value>(attribute, name, readTextValue(val));
}
/**
* Read an XML token.
*/
const value readToken(XMLReader& reader) {
inline const value readToken(XMLReader& reader) {
const int tokenType = reader.read();
if (tokenType == XMLReader::None || tokenType == XMLReader::End)
return value();
return nilValue;
if (tokenType == XMLReader::Element)
return startElement;
if (tokenType == XMLReader::Identifier)
@ -187,7 +190,7 @@ const value readToken(XMLReader& reader) {
/**
* Read a list of values from XML tokens.
*/
const list<value> readList(const list<value>& listSoFar, XMLReader& reader) {
inline const list<value> readList(const list<value>& listSoFar, XMLReader& reader) {
const value token = readToken(reader);
if(isNil(token) || endElement == token)
return reverse(listSoFar);
@ -199,11 +202,11 @@ const list<value> readList(const list<value>& listSoFar, XMLReader& reader) {
/**
* Read a list of values from a libxml2 XML reader.
*/
const list<value> read(XMLReader& reader) {
value nextToken = readToken(reader);
inline const list<value> read(XMLReader& reader) {
const value nextToken = readToken(reader);
if (startElement == nextToken)
return mklist<value>(readList(mklist(element), reader));
return list<value>();
return nilListValue;
}
/**
@ -211,17 +214,18 @@ const list<value> read(XMLReader& reader) {
*/
class XMLReadContext {
public:
XMLReadContext(const list<string>& ilist) : ilist(ilist) {
inline XMLReadContext(const list<string>& ilist) : ilist(ilist) {
}
list<string> ilist;
gc_mutable_ref<list<string> > ilist;
};
/**
* Callback function called by libxml2 to read XML.
*/
int readCallback(void *context, char* buffer, int len) {
XMLReadContext& rc = *static_cast<XMLReadContext*>(context);
if (isNil(rc.ilist))
inline int readCallback(void *context, char* buffer, int len) {
XMLReadContext& rc = *(XMLReadContext*)context;
if (isNil((const list<string>)rc.ilist))
return 0;
const list<string> f(fragment(rc.ilist, len));
const string s(car(f));
@ -233,7 +237,7 @@ int readCallback(void *context, char* buffer, int len) {
/**
* Return true if a list of strings contains an XML document.
*/
const bool isXML(const list<string>& ls) {
inline const bool isXML(const list<string>& ls) {
if (isNil(ls))
return false;
return substr(car(ls), 0, 5) == "<?xml";
@ -242,12 +246,12 @@ const bool isXML(const list<string>& ls) {
/**
* Read a list of values from a list of strings representing an XML document.
*/
const list<value> readXML(const list<string>& ilist) {
debug(ilist, "xml::readXML");
inline const failable<list<value> > readElements(const list<string>& ilist) {
debug(ilist, "xml::readElements");
XMLReadContext cx(ilist);
xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT);
const xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET | XML_PARSE_NODICT);
if (xml == NULL)
return list<value>();
return nilListValue;
XMLReader reader(xml);
return read(reader);
}
@ -255,19 +259,19 @@ const list<value> readXML(const list<string>& ilist) {
/**
* Default encoding used to write XML documents.
*/
const char* encoding = "UTF-8";
const char* const encoding = "UTF-8";
/**
* Write a list of XML element or attribute tokens.
*/
const list<value> expandElementValues(const value& n, const list<value>& l) {
inline const list<value> expandElementValues(const value& n, const list<value>& l) {
if (isNil(l))
return l;
return cons<value>(value(cons<value>(element, cons<value>(n, isList(car(l))? (list<value>)car(l) : mklist(car(l))))), expandElementValues(n, cdr(l)));
}
const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) {
inline const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml) {
if (isNil(l))
return true;
@ -331,7 +335,7 @@ const failable<bool> writeList(const list<value>& l, const xmlTextWriterPtr xml)
/**
* Write a list of values to a libxml2 XML writer.
*/
const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, bool xmlTag) {
inline const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, bool xmlTag) {
if (xmlTag) {
if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0)
return mkfailure<bool>("xmlTextWriterStartDocument failed");
@ -353,17 +357,18 @@ const failable<bool> write(const list<value>& l, const xmlTextWriterPtr xml, boo
*/
template<typename R> class XMLWriteContext {
public:
XMLWriteContext(const lambda<R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
inline XMLWriteContext(const lambda<const R(const string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
const lambda<R(const string&, const R)> reduce;
R accum;
const lambda<const R(const string&, const R)> reduce;
gc_mutable_ref<R> accum;
};
/**
* Callback function called by libxml2 to write XML out.
*/
template<typename R> int writeCallback(void *context, const char* buffer, int len) {
XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context);
template<typename R> inline int writeCallback(void *context, const char* buffer, int len) {
XMLWriteContext<R>& cx = *(XMLWriteContext<R>*)context;
cx.accum = cx.reduce(string(buffer, len), cx.accum);
return len;
}
@ -371,7 +376,7 @@ template<typename R> int writeCallback(void *context, const char* buffer, int le
/**
* Convert a list of values to an XML document.
*/
template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const bool xmlTag) {
template<typename R> inline const failable<R> writeElements(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& l, const bool xmlTag) {
XMLWriteContext<R> cx(reduce, initial);
xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL);
if (out == NULL)
@ -379,34 +384,35 @@ template<typename R> const failable<R> writeXML(const lambda<R(const string&, co
xmlTextWriterPtr xml = xmlNewTextWriter(out);
if (xml == NULL)
return mkfailure<R>("xmlNewTextWriter failed");
xmlTextWriterSetIndent(xml, 1);
xmlTextWriterSetIndent(xml, 0);
const failable<bool> w = write(l, xml, xmlTag);
xmlFreeTextWriter(xml);
if (!hasContent(w)) {
return mkfailure<R>(w);
}
return cx.accum;
return (R)cx.accum;
}
template<typename R> const failable<R> writeXML(const lambda<R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
return writeXML(reduce, initial, l, true);
template<typename R> inline const failable<R> writeElements(const lambda<const R(const string&, const R)>& reduce, const R& initial, const list<value>& l) {
return writeElements(reduce, initial, l, true);
}
/**
* Convert a list of values to a list of strings representing an XML document.
*/
const failable<list<string> > writeXML(const list<value>& l, const bool xmlTag) {
debug(l, "xml::writeXML");
const failable<list<string> > ls = writeXML<list<string> >(rcons<string>, list<string>(), l, xmlTag);
inline const failable<list<string> > writeElements(const list<value>& l, const bool xmlTag) {
debug(l, "xml::writeElements");
const failable<list<string> > ls = writeElements<list<string> >(rcons<string>, list<string>(), l, xmlTag);
if (!hasContent(ls))
return ls;
return reverse(list<string>(content(ls)));
}
const failable<list<string> > writeXML(const list<value>& l) {
return writeXML(l, true);
inline const failable<list<string> > writeElements(const list<value>& l) {
return writeElements(l, true);
}
}
}
#endif /* tuscany_xml_hpp */

View file

@ -30,11 +30,11 @@
namespace tuscany {
bool printNode(xmlTextReaderPtr reader) {
const bool printNode(xmlTextReaderPtr reader) {
const xmlChar* name = xmlTextReaderConstName(reader);
if(name == NULL)
name = (xmlChar *)"<unknown>";
const xmlChar* value = xmlTextReaderConstValue(reader);
const xmlChar* const value = xmlTextReaderConstValue(reader);
cerr << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " "
<< xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader);
if(value == NULL)
@ -53,7 +53,7 @@ int xmlClose(void *context) {
return 0;
}
bool readFile(const char*xsdfilename, const char *filename) {
const bool readFile(const char* const xsdfilename, const char* const filename) {
cout << "Loading schema " << xsdfilename << endl;
const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET);
const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc);
@ -61,7 +61,7 @@ bool readFile(const char*xsdfilename, const char *filename) {
const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd);
cout << "Reading file " << filename << endl;
FILE* file = fopen(filename, "r");
FILE* const file = fopen(filename, "r");
if (file != NULL) {
const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET);
xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1);
@ -93,7 +93,7 @@ bool readFile(const char*xsdfilename, const char *filename) {
}
int main(int argc, char **argv) {
int main(const int argc, const char** const argv) {
tuscany::cout << "Testing..." << tuscany::endl;
if(argc != 3)
return 1;