diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-16 06:00:12 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2009-11-16 06:00:12 +0000 |
commit | ec5f59dac8d5eca3504ec5fe205dcb7d8fd382a6 (patch) | |
tree | 41edf192475639ca342a84efc3e1d94bf0a65672 | |
parent | 24842067f999efb5e62f1dd3cde017df1381c0a3 (diff) |
Fixed support for nested elements and lists. Improved failure/error reporting monad. Minor code cleanup.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@880598 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | cpp/sca/kernel/element.hpp | 85 | ||||
-rw-r--r-- | cpp/sca/kernel/kernel-test.cpp | 3 | ||||
-rw-r--r-- | cpp/sca/kernel/list.hpp | 9 | ||||
-rw-r--r-- | cpp/sca/kernel/monad.hpp | 81 | ||||
-rw-r--r-- | cpp/sca/kernel/value.hpp | 44 | ||||
-rw-r--r-- | cpp/sca/kernel/xml.hpp | 26 | ||||
-rw-r--r-- | cpp/sca/modules/atom/atom.hpp | 10 | ||||
-rw-r--r-- | cpp/sca/modules/http/curl.hpp | 58 | ||||
-rw-r--r-- | cpp/sca/modules/json/json.hpp | 15 |
9 files changed, 255 insertions, 76 deletions
diff --git a/cpp/sca/kernel/element.hpp b/cpp/sca/kernel/element.hpp index d93e90742b..2b5336ba5c 100644 --- a/cpp/sca/kernel/element.hpp +++ b/cpp/sca/kernel/element.hpp @@ -39,6 +39,24 @@ const value attribute("attribute"); const value element("element"); /** + * Returns true if a value is an element. + */ +bool isElement(const value& v) { + if (!isList(v) || isNil(v) || element != car<value>(v)) + return false; + return true; +} + +/** + * Returns true if a value is an attribute. + */ +bool isAttribute(const value& v) { + if (!isList(v) || isNil(v) || attribute != car<value>(v)) + return false; + return true; +} + +/** * Returns the name of an attribute. */ const value attributeName(const list<value>& l) { @@ -99,9 +117,7 @@ const bool elementToValueIsList(const value& v) { if (!isList(v)) return false; const list<value> l = v; - if(isNil(l)) - return true; - return isList(car(l)); + return (isNil(l) || !isSymbol(car(l))); } const value elementToValue(const value& t) { @@ -150,12 +166,10 @@ const bool elementToValueIsSymbol(const value& v) { } const list<value> elementToValueGroupValues(const value& v, const list<value>& l) { - if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) { + if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) return cons(v, l); - } - if (car<value>(car(l)) != car<value>(v)) { + if (car<value>(car(l)) != car<value>(v)) return cons(v, l); - } if (!elementToValueIsList(cadr<value>(car(l)))) { const value g = mklist<value>(car<value>(v), mklist<value>(cdr<value>(v), cdr<value>(car(l)))); return elementToValueGroupValues(g, cdr(l)); @@ -167,9 +181,7 @@ const list<value> elementToValueGroupValues(const value& v, const list<value>& l const list<value> elementsToValues(const list<value>& e) { if (isNil(e)) - return list<value>(); - const value v = elementToValue(car(e)); - const list<value> n = elementsToValues(cdr(e)); + return e; return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); } @@ -207,7 +219,7 @@ const value valueToElement(const value& t) { */ const list<value> valuesToElements(const list<value>& l) { if (isNil(l)) - return list<value>(); + return l; return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l))); } @@ -219,19 +231,19 @@ struct selectorLambda { const list<value> select; selectorLambda(const list<value>& s) : select(s) { } - const bool evalExpr(const list<value>& s, const list<value> v) const { + 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 evalExpr(cdr(s), cdr(v)); + return evalSelect(cdr(s), cdr(v)); } const bool operator()(const value& v) const { if (!isList(v)) return false; - return evalExpr(select, v); + return evalSelect(select, v); } }; @@ -239,5 +251,50 @@ const lambda<bool(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)); + if (isNil(f)) + return value(); + 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)); +} + +/** + * Return the child element with the given name. + */ +const value elementChild(const value& name, const value& l) { + const list<value> f = elementChildren(name, l); + if (isNil(f)) + return value(); + return car(f); +} + } #endif /* tuscany_element_hpp */ diff --git a/cpp/sca/kernel/kernel-test.cpp b/cpp/sca/kernel/kernel-test.cpp index 0234f6eb3e..9346e31b71 100644 --- a/cpp/sca/kernel/kernel-test.cpp +++ b/cpp/sca/kernel/kernel-test.cpp @@ -650,7 +650,8 @@ bool testFailableMonad() { assert((m >> success<int, std::string>()) == m); assert(m >> failableF >> failableG == m >> failableH); - failable<int, std::string> ooops("ooops"); + failable<int, std::string> ooops = mkfailure<int, std::string>("ooops"); + assert(reason(ooops) == "ooops"); assert(ooops >> failableF >> failableG == ooops); return true; } diff --git a/cpp/sca/kernel/list.hpp b/cpp/sca/kernel/list.hpp index deb4414d98..c21efe173b 100644 --- a/cpp/sca/kernel/list.hpp +++ b/cpp/sca/kernel/list.hpp @@ -175,17 +175,10 @@ template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) { } /** - * Construct a list from a single value. - */ -template<typename T> const list<T> cons(const T& car) { - return list<T> (car, result(list<T> ())); -} - -/** * Construct a list of one value. */ template<typename T> const list<T> mklist(const T& car) { - return cons<T>(car); + return list<T> (car, result(list<T> ())); } /** diff --git a/cpp/sca/kernel/monad.hpp b/cpp/sca/kernel/monad.hpp index 9fefbb9f60..98eb3799c0 100644 --- a/cpp/sca/kernel/monad.hpp +++ b/cpp/sca/kernel/monad.hpp @@ -68,6 +68,14 @@ private: }; /** + * Write an identity monad to a stream. + */ +template<typename V> std::ostream& operator<<(std::ostream& out, const id<V>& m) { + out << (V)m; + return out; +} + +/** * Return an identity monad from a value. */ template<typename V> const id<V> mkunit(const V& v) { @@ -134,6 +142,18 @@ private: }; /** + * Write a maybe monad to a stream. + */ +template<typename V> std::ostream& operator<<(std::ostream& out, const maybe<V>& m) { + if (!hasValue(m)) { + out << "nothing"; + return out; + } + out << (V)m; + return out; +} + +/** * Return a maybe monad with a value in it. */ template<typename V> const maybe<V> mkjust(const V& v) { @@ -174,20 +194,23 @@ template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, co */ template<typename V, typename F> class failable { public: + failable() : hasv(false) { + } + failable(const V& v) : hasv(true), v(v) { } - failable(const F& f) : hasv(false), f(f) { + failable(const failable<V, F>& m) : hasv(m.hasv) { + if (hasv) + v = m.v; + else + f = m.f; } operator const V() const { return v; } - operator const F() const { - return f; - } - const failable<V, F>& operator=(const failable<V, F>& m) { if(this == &m) return *this; @@ -212,14 +235,32 @@ public: } private: - const bool hasv; + bool hasv; V v; F f; + failable(const bool hasv, const F& f) : hasv(hasv), f(f) { + } + template<typename A, typename B> friend const bool hasValue(const failable<A, B>& m); + template<typename A, typename B> friend const B reason(const failable<A, B>& m); + template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f); }; /** + * Write a failable monad to a stream. + */ +template<typename V, typename F> std::ostream& operator<<(std::ostream& out, const failable<V, F>& m) { + if (!hasValue(m)) { + out << reason(m); + return out; + } + const V v = m; + out << v; + return out; +} + +/** * Returns a failable monad with a success value in it. */ template<typename V, typename F> const failable<V, F> mksuccess(const V& v) { @@ -231,6 +272,17 @@ template<typename V, typename F> const lambda<failable<V, F>(V)> success() { } /** + * Returns a failable monad with a failure in it. + */ +template<typename V, typename F> const failable<V, F> mkfailure(const F& f) { + return failable<V, F>(false, f); +} + +template<typename V, typename F> const lambda<failable<V, F>(V)> failure() { + return mkfailure<V, F>; +} + +/** * Returns true if the monad contains a value. */ template<typename V, typename F> const bool hasValue(const failable<V, F>& m) { @@ -238,6 +290,13 @@ template<typename V, typename F> const bool hasValue(const failable<V, F>& m) { } /** + * Returns the reason for failure of a failable monad. + */ +template<typename V, typename F> const F reason(const failable<V, F>& m) { + return m.f; +} + +/** * Bind a function to a failable monad. Passes the success value in the monad to the function * if present, or does nothing if there's no value and a failure instead. */ @@ -330,6 +389,16 @@ private: }; /** + * Write a state monad to a stream. + */ +template<typename S, typename V> std::ostream& operator<<(std::ostream& out, const state<S, V>& m) { + const S s = m; + const V v = m; + out << '(' << s << ' ' << v << ')'; + return out; +} + +/** * Return a state monad carrying a result value. */ template<typename S, typename V> struct returnState { diff --git a/cpp/sca/kernel/value.hpp b/cpp/sca/kernel/value.hpp index 618bd7b622..d602b30623 100644 --- a/cpp/sca/kernel/value.hpp +++ b/cpp/sca/kernel/value.hpp @@ -362,7 +362,9 @@ private: }; - +/** + * Write a value to a stream. + */ std::ostream& operator<<(std::ostream& out, const value& v) { switch(v.type) { case value::List: @@ -399,46 +401,86 @@ std::ostream& operator<<(std::ostream& out, const value& v) { } } +/** + * Returns the type of a value. + */ const value::ValueType type(const value& v) { return v.type; } +/** + * Returns true if a value is nil. + */ const bool isNil(const value& value) { return value.type == value::Undefined; } +/** + * Returns true if a value is a lambda. + */ +const bool isLambda(const value& value) { + return value.type == value::Lambda; +} + +/** + * Returns true if a value is a string. + */ const bool isString(const value& value) { return value.type == value::String; } +/** + * Returns true if a value is a symbol. + */ const bool isSymbol(const value& value) { return value.type == value::Symbol; } +/** + * Returns true if a value is a list. + */ const bool isList(const value& value) { return value.type == value::List; } +/** + * Returns true if a value is a number. + */ const bool isNumber(const value& value) { return value.type == value::Number; } +/** + * Returns true if a value is a boolean. + */ const bool isBool(const value& value) { return value.type == value::Bool; } +/** + * Returns true if a value is a character. + */ const bool isChar(const value& value) { return value.type == value::Char; } +/** + * Returns true if a value is a pointer. + */ const bool isPtr(const value& value) { return value.type == value::Ptr; } +/** + * Returns true if a value is a pooled pointer. + */ const bool isPoolPtr(const value& value) { return value.type == value::PoolPtr; } +/** + * Returns true if a value is a tagged list. + */ const bool isTaggedList(const value& exp, value tag) { if(isList(exp) && !isNil((list<value>)exp)) return car((list<value>)exp) == tag; diff --git a/cpp/sca/kernel/xml.hpp b/cpp/sca/kernel/xml.hpp index b7611b8477..8d561557ca 100644 --- a/cpp/sca/kernel/xml.hpp +++ b/cpp/sca/kernel/xml.hpp @@ -144,7 +144,7 @@ const value readAttribute(XMLReader& reader) { */ const value readToken(XMLReader& reader) { const int tokenType = reader.read(); - if (tokenType == XMLReader::End) + if (tokenType == XMLReader::None || tokenType == XMLReader::End) return value(); if (tokenType == XMLReader::Element) return startElement; @@ -228,7 +228,7 @@ const char* encoding = "UTF-8"; */ const list<value> expandElementValues(const value& n, const list<value>& l) { if (isNil(l)) - return list<value>(); + return l; return cons<value>(value(cons<value>(element, cons<value>(n, (list<value>)car(l)))), expandElementValues(n, cdr(l))); } @@ -240,7 +240,7 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW const value token(car(l)); if (isTaggedList(token, attribute)) { if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)std::string(attributeName(token)).c_str(), (const xmlChar*)std::string(attributeValue(token)).c_str()) < 0) - return std::string("xmlTextWriterWriteAttribute failed"); + return mkfailure<bool, std::string>("xmlTextWriterWriteAttribute failed"); } else if (isTaggedList(token, element)) { @@ -257,7 +257,7 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW // Write an element with a single value if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0) - return std::string("xmlTextWriterStartElement failed"); + return mkfailure<bool, std::string>("xmlTextWriterStartElement failed"); // Write its children const failable<bool, std::string> w = writeList(elementChildren(token), xml); @@ -265,14 +265,14 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW return w; if (xmlTextWriterEndElement(xml) < 0) - return std::string("xmlTextWriterEndElement failed"); + return mkfailure<bool, std::string>("xmlTextWriterEndElement failed"); } } else { // Write an element if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0) - return std::string("xmlTextWriterStartElement failed"); + return mkfailure<bool, std::string>("xmlTextWriterStartElement failed"); // Write its children const failable<bool, std::string> w = writeList(elementChildren(token), xml); @@ -280,13 +280,13 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW return w; if (xmlTextWriterEndElement(xml) < 0) - return std::string("xmlTextWriterEndElement failed"); + return mkfailure<bool, std::string>("xmlTextWriterEndElement failed"); } } else { // Write XML text if (xmlTextWriterWriteString(xml, (const xmlChar*)std::string(token).c_str()) < 0) - return std::string("xmlTextWriterWriteString failed"); + return mkfailure<bool, std::string>("xmlTextWriterWriteString failed"); } @@ -299,14 +299,14 @@ const failable<bool, std::string> writeList(const list<value>& l, const xmlTextW */ const failable<bool, std::string> write(const list<value>& l, const xmlTextWriterPtr xml) { if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0) - return std::string("xmlTextWriterStartDocument failed"); + return mkfailure<bool, std::string>("xmlTextWriterStartDocument failed"); const failable<bool, std::string> w = writeList(l, xml); if (!hasValue(w)) return w; if (xmlTextWriterEndDocument(xml) < 0) - return std::string("xmlTextWriterEndDocument failed"); + return mkfailure<bool, std::string>("xmlTextWriterEndDocument failed"); return true; } @@ -337,15 +337,15 @@ template<typename R> const failable<R, std::string> writeXML(const lambda<R(std: XMLWriteContext<R> cx(reduce, initial); xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL); if (out == NULL) - return std::string("xmlOutputBufferCreateIO failed"); + return mkfailure<R, std::string>("xmlOutputBufferCreateIO failed"); xmlTextWriterPtr xml = xmlNewTextWriter(out); if (xml == NULL) - return std::string("xmlNewTextWriter failed"); + return mkfailure<R, std::string>("xmlNewTextWriter failed"); const failable<bool, std::string> w = write(l, xml); xmlFreeTextWriter(xml); if (!hasValue(w)) { - return std::string(w); + return mkfailure<R, std::string>(reason(w)); } return cx.accum; } diff --git a/cpp/sca/modules/atom/atom.hpp b/cpp/sca/modules/atom/atom.hpp index 2077081320..5054c635a0 100644 --- a/cpp/sca/modules/atom/atom.hpp +++ b/cpp/sca/modules/atom/atom.hpp @@ -52,7 +52,7 @@ const list<value> entryValue(const list<value>& e) { */ const list<value> entriesValues(const list<value>& e) { if (isNil(e)) - return list<value>(); + return e; return cons<value>(entryValue(car(e)), entriesValues(cdr(e))); } @@ -62,7 +62,7 @@ const list<value> entriesValues(const list<value>& e) { const failable<list<value>, std::string> readEntry(const list<std::string>& ilist) { const list<value> e = readXML(ilist); if (isNil(e)) - return std::string("Empty entry"); + return mkfailure<list<value>, std::string>("Empty entry"); return entryValue(car(e)); } @@ -72,7 +72,7 @@ const failable<list<value>, std::string> readEntry(const list<std::string>& ilis const failable<list<value>, std::string> readFeed(const list<std::string>& ilist) { const list<value> f = readXML(ilist); if (isNil(f)) - return std::string("Empty feed"); + return mkfailure<list<value>, std::string>("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)); @@ -99,7 +99,7 @@ const list<value> entryElement(const list<value>& l) { */ const list<value> entriesElements(const list<value>& l) { if (isNil(l)) - return list<value>(); + return l; return cons<value>(entryElement(car(l)), entriesElements(cdr(l))); } @@ -156,7 +156,7 @@ const list<value> entryValuesToElements(const list<value> val) { */ const list<value> feedValuesToElementsLoop(const list<value> val) { if (isNil(val)) - return list<value>(); + return val; return cons<value>(entryValuesToElements(car(val)), feedValuesToElementsLoop(cdr(val))); } diff --git a/cpp/sca/modules/http/curl.hpp b/cpp/sca/modules/http/curl.hpp index c0d79cef13..5ee3a090b0 100644 --- a/cpp/sca/modules/http/curl.hpp +++ b/cpp/sca/modules/http/curl.hpp @@ -137,13 +137,13 @@ template<typename R> size_t headerCallback(void *ptr, size_t size, size_t nmemb, * Apply an HTTP verb to a list containing a list of headers and a list of content, and * a reduce function used to process the response. */ -curl_slist* headers(curl_slist* cl, const list<std::string> h) { +curl_slist* headers(curl_slist* cl, const list<std::string>& h) { if (isNil(h)) return cl; return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h)); } -template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> > req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLHandle& ch) { // Init the curl session curl_easy_reset(ch); @@ -190,13 +190,13 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< // Return the HTTP return code or content if (rc) - return std::string(curl_easy_strerror(rc)); + return mkfailure<list<R>, std::string>(curl_easy_strerror(rc)); long httprc; curl_easy_getinfo (ch, CURLINFO_RESPONSE_CODE, &httprc); if (httprc != 200 && httprc != 201) { std::ostringstream es; es << "HTTP code " << httprc; - return es.str(); + return mkfailure<list<R>, std::string>(es.str()); } return mklist<R>(hcx.accum, wcx.accum); } @@ -204,13 +204,13 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list< /** * Evaluate an expression remotely, at the given URL. */ -const failable<value, std::string> evalExpr(const value expr, const std::string& url, CURLHandle& ch) { +const failable<value, std::string> evalExpr(const value& expr, const std::string& url, const CURLHandle& ch) { // Convert expression to a JSON-RPC request json::JSONContext cx; const failable<list<std::string>, std::string> jsreq = jsonRequest(1, car<value>(expr), cdr<value>(expr), cx); if (!hasValue(jsreq)) - return std::string(jsreq); + return mkfailure<value, std::string>(reason(jsreq)); if (logContent) { std::cout<< "content: " << std::endl; @@ -223,7 +223,7 @@ const failable<value, std::string> evalExpr(const value expr, const std::string const list<std::string> h = mklist<std::string>("Content-Type: application/json-rpc"); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(mklist<list<std::string> >(h, jsreq), rcons<std::string>, list<std::string>(), url, "POST", ch); if (!hasValue(res)) - return std::string(res); + return mkfailure<value, std::string>(reason(res)); // Return result if (logContent) { @@ -238,7 +238,7 @@ const failable<value, std::string> evalExpr(const value expr, const std::string /** * HTTP GET, return the resource at the given URL. */ -template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, CURLHandle& ch) { +template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLHandle& ch) { const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); return apply(req, reduce, initial, url, "GET", ch); } @@ -246,17 +246,17 @@ template<typename R> const failable<list<R>, std::string> get(const lambda<R(std /** * HTTP GET, return a list of values representing the resource at the given URL. */ -const failable<value, std::string> get(const std::string& url, CURLHandle& ch) { +const failable<value, std::string> get(const std::string& url, const CURLHandle& ch) { // Get the contents of the resource at the given URL const failable<list<list<std::string> >, std::string> res = get<list<std::string> >(rcons<std::string>, list<std::string>(), url, ch); if (!hasValue(res)) - return std::string(res); + return mkfailure<value, std::string>(reason(res)); const list<list<std::string> > ls = res; - // TODO Return an ATOM feed const std::string ct; if (ct.find("application/atom+xml") != std::string::npos) { + // TODO Return an ATOM feed } // Return the content as a string value @@ -268,12 +268,12 @@ const failable<value, std::string> get(const std::string& url, CURLHandle& ch) { /** * HTTP POST. */ -const failable<value, std::string> post(const value& val, const std::string& url, CURLHandle& ch) { +const failable<value, std::string> post(const value& val, const std::string& url, const CURLHandle& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasValue(entry)) - return std::string(entry); + return mkfailure<value, std::string>(reason(entry)); if (logContent) { std::cout << "content:" << std::endl; write(list<std::string>(entry), std::cout); @@ -285,45 +285,63 @@ const failable<value, std::string> post(const value& val, const std::string& url const list<list<std::string> > req = mklist<list<std::string> >(h, entry); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "POST", ch); if (!hasValue(res)) - return std::string(res); + return mkfailure<value, std::string>(reason(res)); return value(true); } /** * HTTP PUT. */ -const failable<value, std::string> put(const value& val, const std::string& url, CURLHandle& ch) { +const failable<value, std::string> put(const value& val, const std::string& url, const CURLHandle& ch) { // Convert value to an ATOM entry const failable<list<std::string>, std::string> entry = atom::writeATOMEntry(atom::entryValuesToElements(val)); if (!hasValue(entry)) - return std::string(entry); + return mkfailure<value, std::string>(reason(entry)); if (logContent) { std::cout << "content:" << std::endl; write(list<std::string>(entry), std::cout); std::cout << std::endl; } - // POST it to the URL + // PUT it to the URL const list<std::string> h = mklist<std::string>("Content-Type: application/atom+xml"); const list<list<std::string> > req = mklist<list<std::string> >(h, entry); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "PUT", ch); if (!hasValue(res)) - return std::string(res); + return mkfailure<value, std::string>(reason(res)); return value(true); } /** * HTTP DELETE. */ -const failable<value, std::string> del(const std::string& url, CURLHandle& ch) { +const failable<value, std::string> del(const std::string& url, const CURLHandle& ch) { const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>()); const failable<list<list<std::string> >, std::string> res = apply<list<std::string> >(req, rcons<std::string>, list<std::string>(), url, "DELETE", ch); if (!hasValue(res)) - return std::string(res); + return mkfailure<value, std::string>(reason(res)); return value(true); } +/** + * HTTP client proxy function. + */ +struct proxy { + proxy(const std::string& url, const CURLHandle& ch) : url(url), ch(ch) { + } + + const value operator()(const list<value>& args) const { + failable<value, std::string> val = evalExpr(args, url, ch); + if (!hasValue(val)) + return value(); + return val; + } + + const std::string url; + const CURLHandle& ch; +}; + } } diff --git a/cpp/sca/modules/json/json.hpp b/cpp/sca/modules/json/json.hpp index 0d21cfe359..f6c8eb5fe8 100644 --- a/cpp/sca/modules/json/json.hpp +++ b/cpp/sca/modules/json/json.hpp @@ -200,7 +200,7 @@ failable<bool, std::string> consume(JSONParser* parser, const list<std::string>& return true; JSString* jstr = JS_NewStringCopyZ(cx, car(ilist).c_str()); if(!JS_ConsumeJSONText(cx, parser, JS_GetStringChars(jstr), JS_GetStringLength(jstr))) - return "JS_ConsumeJSONText failed"; + return mkfailure<bool, std::string>("JS_ConsumeJSONText failed"); return consume(parser, cdr(ilist), cx); } @@ -211,14 +211,14 @@ const failable<list<value>, std::string> readJSON(const list<std::string>& ilist jsval val; JSONParser* parser = JS_BeginJSONParse(cx, &val); if(parser == NULL) - return std::string("JS_BeginJSONParse failed"); + return mkfailure<list<value>, std::string>("JS_BeginJSONParse failed"); const failable<bool, std::string> consumed = consume(parser, ilist, cx); if(!JS_FinishJSONParse(cx, parser, JSVAL_NULL)) - return std::string("JS_FinishJSONParse failed"); + return mkfailure<list<value>, std::string>("JS_FinishJSONParse failed"); if(!hasValue(consumed)) - return std::string(consumed); + return mkfailure<list<value>, std::string>(reason(consumed)); return list<value>(jsValToValue(val, cx)); } @@ -357,11 +357,11 @@ template<typename R> const failable<R, std::string> writeJSON(const lambda<R(std jsval val = OBJECT_TO_JSVAL(o); const failable<bool, std::string> w = writeList(l, o, cx); if (!hasValue(w)) - return std::string(w); + return mkfailure<R, std::string>(reason(w)); WriteContext<R> wcx(reduce, initial, cx); if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx)) - return std::string("JS_Stringify failed"); + return mkfailure<R, std::string>("JS_Stringify failed"); return wcx.accum; } @@ -380,8 +380,7 @@ const failable<list<std::string>, std::string> writeJSON(const list<value>& l, c */ const failable<list<std::string>, std::string> jsonRequest(const value& id, const value& func, const value& params, json::JSONContext& cx) { const list<value> r = mklist<value>(mklist<value>("id", id), mklist<value>("method", func), mklist<value>("params", params)); - failable<list<std::string>, std::string> ls = writeJSON(valuesToElements(r), cx); - return ls; + return writeJSON(valuesToElements(r), cx); } /** |