diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2018-03-06 21:37:39 +0000 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2018-03-06 21:37:39 +0000 |
commit | ba25f019012b632f6af9f5addee5058ba6a4e077 (patch) | |
tree | f9e5bc70a9fb075e43f11ca4a02493147e4b3d50 /service | |
parent | Add basic site setup (diff) | |
download | mirrorsearch-ba25f019012b632f6af9f5addee5058ba6a4e077.tar.bz2 mirrorsearch-ba25f019012b632f6af9f5addee5058ba6a4e077.tar.xz mirrorsearch-ba25f019012b632f6af9f5addee5058ba6a4e077.zip |
Wrap support for making unique ptrs from functions
Diffstat (limited to 'service')
-rw-r--r-- | service/api.ice | 4 | ||||
-rw-r--r-- | service/apiImpl.cpp | 44 | ||||
-rw-r--r-- | service/test.cpp | 5 | ||||
-rw-r--r-- | service/uptr.cpp | 26 | ||||
-rw-r--r-- | service/uptr.h | 38 |
5 files changed, 97 insertions, 20 deletions
diff --git a/service/api.ice b/service/api.ice index c207c3d..64edfe7 100644 --- a/service/api.ice +++ b/service/api.ice @@ -10,8 +10,8 @@ module MirrorSearch { interface Search { idempotent SearchServices getServices(); - idempotent SearchHits getMatches(string filename); - idempotent optional(0) string feelingLucky(string filename); + idempotent SearchHits getMatches(string filename) throws XmlError; + idempotent optional(0) string feelingLucky(string filename) throws XmlError; }; }; diff --git a/service/apiImpl.cpp b/service/apiImpl.cpp index 588d360..1de31cb 100644 --- a/service/apiImpl.cpp +++ b/service/apiImpl.cpp @@ -1,8 +1,9 @@ #include "apiImpl.h" +#include "uptr.h" #include <sql/getServices.sql.h> #include <buffer.h> -#include <memory> +#include <compileTimeFormatter.h> #include <libxml/xpath.h> #include <libxml/xpathInternals.h> @@ -21,35 +22,42 @@ namespace MirrorSearch { return fetch<SearchServices>(sql::getServices); } - typedef std::shared_ptr<xmlDoc> xmlDocSPtr; - typedef std::shared_ptr<xmlXPathContext> xmlXPathContextSPtr; - typedef std::shared_ptr<xmlXPathObject> xmlXPathObjectSPtr; + template<typename Fmt, typename ... P> + void + libxmlErrorHandler(const std::string & fn, const P & ... p) + { + throw XmlError(Fmt::get(fn, xmlGetLastError()->message, p...)); + } + template<typename Fmt, typename ... P> + auto lEHB(const P & ... p) + { + return std::bind(&libxmlErrorHandler<Fmt, P...>, std::placeholders::_1, p...); + } + typedef UPtr<xmlDoc> xmlDocSPtr; + typedef UPtr<xmlXPathContext> xmlXPathContextSPtr; + typedef UPtr<xmlXPathObject> xmlXPathObjectSPtr; + + AdHocFormatter(Read, "Failed to read in %? (%?) [%?, %?]"); static auto getDoc(const ::std::string & url, int flags) { - if (auto doc = xmlDocSPtr(htmlReadFile(url.c_str(), NULL, flags), xmlFreeDoc)) { - return doc; - } - throw XmlError("Failed to open " + url); + return make_unique(htmlReadFile, xmlFreeDoc, lEHB<Read>(url, flags), url.c_str(), (const char*)NULL, flags); } + AdHocFormatter(XPathCtx, "Failed to create xpath context in %? (%?)"); static auto getXPathCxt(const xmlDocSPtr & doc) { - if (auto xpathCtx = xmlXPathContextSPtr(xmlXPathNewContext(doc.get()), xmlXPathFreeContext)) { - return xpathCtx; - } - throw XmlError("Failed to create xpath context"); + return make_unique(xmlXPathNewContext, xmlXPathFreeContext, lEHB<XPathCtx>(), doc.get()); } + AdHocFormatter(XPathEval, "Failed to evaluate xpath in %? (%?) [%?]"); static auto getXPathObj(const ::std::string & xpath, const xmlXPathContextSPtr & ctx, xmlXPathObjectType type) { - if (auto xpathObj = xmlXPathObjectSPtr(xmlXPathEvalExpression(BAD_CAST xpath.c_str(), ctx.get()), xmlXPathFreeObject)) { - if (xpathObj->type != type) { - throw XmlError("Xpath evaluates to wrong type " + xpath); - } - return xpathObj; + auto xpathObj = make_unique(xmlXPathEvalExpression, xmlXPathFreeObject, lEHB<XPathEval>(xpath), BAD_CAST xpath.c_str(), ctx.get()); + if (xpathObj->type != type) { + throw XmlError("Xpath evaluates to wrong type " + xpath); } - throw XmlError("Failed to evaluate xpath " + xpath); + return xpathObj; } void SearchImpl::callService(const ::std::string & fn, const SearchServicePtr & s, SearchHits & sh) const diff --git a/service/test.cpp b/service/test.cpp index c115712..8b93cf8 100644 --- a/service/test.cpp +++ b/service/test.cpp @@ -47,6 +47,11 @@ BOOST_AUTO_TEST_CASE(getServices) BOOST_CHECK(!ss.front()->urlxpath.empty()); } +BOOST_AUTO_TEST_CASE(getMatches_failure) +{ + BOOST_REQUIRE_THROW(s->getMatches("no.fixture"), MirrorSearch::XmlError); +} + BOOST_AUTO_TEST_CASE(getMatches_zstd_notfound) { auto ms = s->getMatches("zstd-1.3.3.tar.gz"); diff --git a/service/uptr.cpp b/service/uptr.cpp new file mode 100644 index 0000000..1669a69 --- /dev/null +++ b/service/uptr.cpp @@ -0,0 +1,26 @@ +#include "uptr.h" +#include <execinfo.h> +#include <boost/assert.hpp> +#include <string> +#include <stdlib.h> +#include <exception> + +namespace MirrorSearch { + + std::string + failingFunction(void * const func) + { + char ** fn = backtrace_symbols(&func, 1); + BOOST_ASSERT(fn); + BOOST_ASSERT(*fn); + std::string funcName(*fn); + free(fn); + return funcName; + } + + void + defaultErrorHandler(const std::string & fn) + { + throw std::runtime_error("Fatal error in " + fn); + } +} diff --git a/service/uptr.h b/service/uptr.h new file mode 100644 index 0000000..1de1f99 --- /dev/null +++ b/service/uptr.h @@ -0,0 +1,38 @@ +#ifndef MIRRORSEARCH_UPTR_H +#define MIRRORSEARCH_UPTR_H + +#include <memory> +#include <functional> + +namespace MirrorSearch { + typedef std::function<void(const std::string &)> OnError; + + std::string + failingFunction(void * const func); + + void + defaultErrorHandler(const std::string &); + + template<typename O> using UPtr = std::unique_ptr<O, void(*)(O*)>; + + template<typename R, typename ... P, typename ... A> + R * + make_unique(R * (*func)(P...), OnError onError, A ... p) + { + if (auto obj = func(p...)) { + return obj; + } + onError(failingFunction((void * const)func)); + throw std::runtime_error("Error handler did not throw"); + } + + template<typename R, typename ... P, typename ... A> + UPtr<R> + make_unique(R*(*get)(P...), void(*release)(R*), OnError onError, A ... p) + { + return std::unique_ptr<R, void(*)(R*)>(make_unique(get, onError, p...), release); + } +} + +#endif + |