summaryrefslogtreecommitdiffstats
path: root/ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h')
-rw-r--r--ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h101
1 files changed, 101 insertions, 0 deletions
diff --git a/ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h b/ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h
new file mode 100644
index 0000000..a8f7be2
--- /dev/null
+++ b/ext/sqlite_modern_cpp/sqlite_modern_cpp/log.h
@@ -0,0 +1,101 @@
+#include "errors.h"
+
+#include <sqlite3.h>
+
+#include <utility>
+#include <tuple>
+#include <type_traits>
+
+namespace sqlite {
+ namespace detail {
+ template<class>
+ using void_t = void;
+ template<class T, class = void>
+ struct is_callable : std::false_type {};
+ template<class Functor, class ...Arguments>
+ struct is_callable<Functor(Arguments...), void_t<decltype(std::declval<Functor>()(std::declval<Arguments>()...))>> : std::true_type {};
+ template<class Functor, class ...Functors>
+ class FunctorOverload: public Functor, public FunctorOverload<Functors...> {
+ public:
+ template<class Functor1, class ...Remaining>
+ FunctorOverload(Functor1 &&functor, Remaining &&... remaining):
+ Functor(std::forward<Functor1>(functor)),
+ FunctorOverload<Functors...>(std::forward<Remaining>(remaining)...) {}
+ using Functor::operator();
+ using FunctorOverload<Functors...>::operator();
+ };
+ template<class Functor>
+ class FunctorOverload<Functor>: public Functor {
+ public:
+ template<class Functor1>
+ FunctorOverload(Functor1 &&functor):
+ Functor(std::forward<Functor1>(functor)) {}
+ using Functor::operator();
+ };
+ template<class Functor>
+ class WrapIntoFunctor: public Functor {
+ public:
+ template<class Functor1>
+ WrapIntoFunctor(Functor1 &&functor):
+ Functor(std::forward<Functor1>(functor)) {}
+ using Functor::operator();
+ };
+ template<class ReturnType, class ...Arguments>
+ class WrapIntoFunctor<ReturnType(*)(Arguments...)> {
+ ReturnType(*ptr)(Arguments...);
+ public:
+ WrapIntoFunctor(ReturnType(*ptr)(Arguments...)): ptr(ptr) {}
+ ReturnType operator()(Arguments... arguments) { return (*ptr)(std::forward<Arguments>(arguments)...); }
+ };
+ inline void store_error_log_data_pointer(std::shared_ptr<void> ptr) {
+ static std::shared_ptr<void> stored;
+ stored = std::move(ptr);
+ }
+ template<class T>
+ std::shared_ptr<typename std::decay<T>::type> make_shared_inferred(T &&t) {
+ return std::make_shared<typename std::decay<T>::type>(std::forward<T>(t));
+ }
+ }
+ template<class Handler>
+ typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception&)>::value>::type
+ error_log(Handler &&handler);
+ template<class Handler>
+ typename std::enable_if<detail::is_callable<Handler(const sqlite_exception&)>::value>::type
+ error_log(Handler &&handler);
+ template<class ...Handler>
+ typename std::enable_if<sizeof...(Handler)>=2>::type
+ error_log(Handler &&...handler) {
+ return error_log(detail::FunctorOverload<detail::WrapIntoFunctor<typename std::decay<Handler>::type>...>(std::forward<Handler>(handler)...));
+ }
+ template<class Handler>
+ typename std::enable_if<!detail::is_callable<Handler(const sqlite_exception&)>::value>::type
+ error_log(Handler &&handler) {
+ return error_log(std::forward<Handler>(handler), [](const sqlite_exception&) {});
+ }
+ template<class Handler>
+ typename std::enable_if<detail::is_callable<Handler(const sqlite_exception&)>::value>::type
+ error_log(Handler &&handler) {
+ auto ptr = detail::make_shared_inferred([handler = std::forward<Handler>(handler)](int error_code, const char *errstr) mutable {
+ switch(error_code & 0xFF) {
+#define SQLITE_MODERN_CPP_ERROR_CODE(NAME,name,derived) \
+ case SQLITE_ ## NAME: switch(error_code) { \
+ derived \
+ default: handler(errors::name(errstr, "", error_code)); \
+ };break;
+#define SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED(BASE,SUB,base,sub) \
+ case SQLITE_ ## BASE ## _ ## SUB: \
+ handler(errors::base ## _ ## sub(errstr, "", error_code)); \
+ break;
+#include "lists/error_codes.h"
+#undef SQLITE_MODERN_CPP_ERROR_CODE_EXTENDED
+#undef SQLITE_MODERN_CPP_ERROR_CODE
+ default: handler(sqlite_exception(errstr, "", error_code)); \
+ }
+ });
+
+ sqlite3_config(SQLITE_CONFIG_LOG, (void(*)(void*,int,const char*))[](void *functor, int error_code, const char *errstr) {
+ (*static_cast<decltype(ptr.get())>(functor))(error_code, errstr);
+ }, ptr.get());
+ detail::store_error_log_data_pointer(std::move(ptr));
+ }
+}