#include "errors.h" #include #include #include #include namespace sqlite { namespace detail { template using void_t = void; template struct is_callable : std::false_type { }; template struct is_callable()(std::declval()...))>> : std::true_type { }; template class FunctorOverload : public Functor, public FunctorOverload { public: template FunctorOverload(Functor1 &&functor, Remaining &&...remaining) : Functor(std::forward(functor)), FunctorOverload(std::forward(remaining)...) { } using Functor::operator(); using FunctorOverload::operator(); }; template class FunctorOverload : public Functor { public: template FunctorOverload(Functor1 &&functor) : Functor(std::forward(functor)) { } using Functor::operator(); }; template class WrapIntoFunctor : public Functor { public: template WrapIntoFunctor(Functor1 &&functor) : Functor(std::forward(functor)) { } using Functor::operator(); }; template class WrapIntoFunctor { ReturnType (*ptr)(Arguments...); public: WrapIntoFunctor(ReturnType (*ptr)(Arguments...)) : ptr(ptr) { } ReturnType operator()(Arguments... arguments) { return (*ptr)(std::forward(arguments)...); } }; inline void store_error_log_data_pointer(std::shared_ptr ptr) { static std::shared_ptr stored; stored = std::move(ptr); } template std::shared_ptr::type> make_shared_inferred(T &&t) { return std::make_shared::type>(std::forward(t)); } } // namespace detail template typename std::enable_if::value>::type error_log( Handler &&handler); template typename std::enable_if::value>::type error_log( Handler &&handler); template typename std::enable_if= 2>::type error_log(Handler &&...handler) { return error_log(detail::FunctorOverload::type>...>( std::forward(handler)...)); } template typename std::enable_if::value>::type error_log( Handler &&handler) { return error_log(std::forward(handler), [](const sqlite_exception &) {}); } template typename std::enable_if::value>::type error_log( Handler &&handler) { auto ptr = detail::make_shared_inferred( [handler = std::forward(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(functor))(error_code, errstr); }, ptr.get()); detail::store_error_log_data_pointer(std::move(ptr)); } } // namespace sqlite