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:
parent
1f3796522a
commit
ae0b7c0063
55 changed files with 2977 additions and 2270 deletions
6
sca-cpp/trunk/.gitignore
vendored
6
sca-cpp/trunk/.gitignore
vendored
|
|
@ -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
25
sca-cpp/trunk/etc/callgrind
Executable 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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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("");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
34
sca-cpp/trunk/modules/scheme/scheme-test.hpp
Normal file
34
sca-cpp/trunk/modules/scheme/scheme-test.hpp
Normal file
File diff suppressed because one or more lines are too long
44
sca-cpp/trunk/modules/scheme/test.scm
Normal file
44
sca-cpp/trunk/modules/scheme/test.scm
Normal 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
|
||||
)
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
29
sca-cpp/trunk/modules/xml/Makefile.am
Normal file
29
sca-cpp/trunk/modules/xml/Makefile.am
Normal 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
|
||||
|
||||
2
sca-cpp/trunk/modules/xml/test.xml
Normal file
2
sca-cpp/trunk/modules/xml/test.xml
Normal file
File diff suppressed because one or more lines are too long
373
sca-cpp/trunk/modules/xml/xml-test.cpp
Normal file
373
sca-cpp/trunk/modules/xml/xml-test.cpp
Normal 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;
|
||||
}
|
||||
33
sca-cpp/trunk/modules/xml/xml-test.hpp
Normal file
33
sca-cpp/trunk/modules/xml/xml-test.hpp
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -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 */
|
||||
|
|
@ -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;
|
||||
Loading…
Add table
Add a link
Reference in a new issue