summaryrefslogtreecommitdiff
path: root/include/boost/sqlite/detail/scalar_function.hpp
diff options
context:
space:
mode:
authorJohn Turner <jturner.usa@gmail.com>2025-09-14 00:16:10 -0400
committerJohn Turner <jturner.usa@gmail.com>2025-09-14 00:16:10 -0400
commitefcea3a80da7c4479d5fe168435ecc9fd06bdc72 (patch)
tree5cb0177e17b1b00a177f2e830e809f606334571b /include/boost/sqlite/detail/scalar_function.hpp
downloadsqlite-kv-bench-efcea3a80da7c4479d5fe168435ecc9fd06bdc72.tar.gz
Squashed 'subprojects/boost-sqlite/' content from commit 3378e35
git-subtree-dir: subprojects/boost-sqlite git-subtree-split: 3378e353705271e569cf4ba15c467b840a39798c
Diffstat (limited to 'include/boost/sqlite/detail/scalar_function.hpp')
-rw-r--r--include/boost/sqlite/detail/scalar_function.hpp172
1 files changed, 172 insertions, 0 deletions
diff --git a/include/boost/sqlite/detail/scalar_function.hpp b/include/boost/sqlite/detail/scalar_function.hpp
new file mode 100644
index 0000000..ee16a23
--- /dev/null
+++ b/include/boost/sqlite/detail/scalar_function.hpp
@@ -0,0 +1,172 @@
+// Copyright (c) 2023 Klemens D. Morgenstern
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+#ifndef BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP
+#define BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP
+
+#include <boost/sqlite/detail/config.hpp>
+#include <boost/sqlite/cstring_ref.hpp>
+#include <boost/sqlite/memory.hpp>
+#include <boost/sqlite/result.hpp>
+#include <boost/sqlite/value.hpp>
+
+#include <boost/callable_traits/args.hpp>
+#include <boost/callable_traits/return_type.hpp>
+#include <boost/callable_traits/has_void_return.hpp>
+#include <boost/core/span.hpp>
+
+
+BOOST_SQLITE_BEGIN_NAMESPACE
+
+template<typename ... Args>
+struct context;
+
+namespace detail
+{
+
+template<typename Func, typename ... Args, std::size_t Extent>
+auto create_scalar_function_impl(sqlite3 * db,
+ cstring_ref name,
+ Func && func,
+ int flags,
+ std::tuple<context<Args...>, boost::span<value, Extent>> * ,
+ std::false_type /* void return */,
+ std::false_type /* is pointer */) -> int
+{
+ using func_type = typename std::decay<Func>::type;
+ return sqlite3_create_function_v2(
+ db, name.c_str(),
+ Extent == boost::dynamic_extent ? -1 : static_cast<int>(Extent),
+ SQLITE_UTF8 | flags,
+ new (memory_tag{}) func_type(std::forward<Func>(func)),
+ +[](sqlite3_context* ctx, int len, sqlite3_value** args)
+ {
+ auto cc = context<Args...>(ctx);
+ auto aa = reinterpret_cast<value*>(args);
+ auto &f = *reinterpret_cast<func_type*>(sqlite3_user_data(ctx));
+ boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)};
+
+ execute_context_function(ctx, f, cc, vals);
+ }, nullptr, nullptr,
+ +[](void * ptr) noexcept {delete_(static_cast<func_type*>(ptr));}
+ );
+}
+
+template<typename Func, typename ... Args, std::size_t Extent>
+auto create_scalar_function_impl(sqlite3 * db,
+ cstring_ref name,
+ Func && func, int flags,
+ std::tuple<context<Args...>, boost::span<value, Extent>> * ,
+ std::true_type /* void return */,
+ std::false_type /* is pointer */) -> int
+{
+ using func_type = typename std::decay<Func>::type;
+ return sqlite3_create_function_v2(
+ db,
+ name.c_str(),
+ (Extent == boost::dynamic_extent) ? -1 : static_cast<int>(Extent),
+ SQLITE_UTF8 | flags,
+ new (memory_tag{}) func_type(std::forward<Func>(func)),
+ +[](sqlite3_context* ctx, int len, sqlite3_value** args)
+ {
+ auto cc = context<Args...>(ctx);
+ auto aa = reinterpret_cast<value*>(args);
+ auto &f = *reinterpret_cast<func_type*>(sqlite3_user_data(ctx));
+ boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)};
+
+ execute_context_function(
+ ctx,
+ [&]()
+ {
+ f(cc, vals);
+ return result<void>();
+ });
+
+ }, nullptr, nullptr,
+ +[](void * ptr){delete_(static_cast<func_type*>(ptr));}
+ );
+}
+
+
+template<typename Func, typename ... Args, std::size_t Extent>
+auto create_scalar_function_impl(sqlite3 * db,
+ cstring_ref name,
+ Func * func, int flags,
+ std::tuple<context<Args...>, boost::span<value, Extent>> * ,
+ std::false_type /* void return */,
+ std::true_type /* is pointer */) -> int
+{
+ return sqlite3_create_function_v2(
+ db, name.c_str(),
+ Extent == boost::dynamic_extent ? -1 : static_cast<int>(Extent),
+ SQLITE_UTF8 | flags,
+ reinterpret_cast<void*>(func),
+ +[](sqlite3_context* ctx, int len, sqlite3_value** args)
+ {
+ auto cc = context<Args...>(ctx);
+ auto aa = reinterpret_cast<value*>(args);
+ auto f = reinterpret_cast<Func*>(sqlite3_user_data(ctx));
+
+ boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)};
+
+ execute_context_function(
+ ctx, f, cc, vals);
+ }, nullptr, nullptr, nullptr);
+}
+
+template<typename Func, typename ... Args, std::size_t Extent>
+auto create_scalar_function_impl(sqlite3 * db,
+ cstring_ref name,
+ Func * func, int flags,
+ std::tuple<context<Args...>, boost::span<value, Extent>> * ,
+ std::true_type /* void return */,
+ std::true_type /* is pointer */) -> int
+{
+ return sqlite3_create_function_v2(
+ db,
+ name.c_str(),
+ (Extent == boost::dynamic_extent) ? -1 : static_cast<int>(Extent),
+ SQLITE_UTF8 | flags,
+ reinterpret_cast<void*>(func),
+ +[](sqlite3_context* ctx, int len, sqlite3_value** args)
+ {
+ auto cc = context<Args...>(ctx);
+ auto aa = reinterpret_cast<value*>(args);
+ auto f = *reinterpret_cast<Func*>(sqlite3_user_data(ctx));
+ boost::span<value, Extent> vals{aa, static_cast<std::size_t>(len)};
+ execute_context_function(
+ ctx,
+ [&]()
+ {
+ f(cc, vals);
+ return result<void>();
+ });
+
+ }, nullptr, nullptr, nullptr);
+}
+
+template<typename Func>
+auto create_scalar_function(sqlite3 * db,
+ cstring_ref name,
+ Func && func,
+ int flags)
+ -> decltype(create_scalar_function_impl(
+ db, name, std::forward<Func>(func), flags,
+ static_cast<callable_traits::args_t<Func>*>(nullptr),
+ callable_traits::has_void_return<Func>{},
+ std::is_pointer<typename std::decay<Func>::type>{}
+ ))
+{
+ return create_scalar_function_impl(db, name, std::forward<Func>(func), flags,
+ static_cast<callable_traits::args_t<Func>*>(nullptr),
+ callable_traits::has_void_return<Func>{},
+ std::is_pointer<typename std::decay<Func>::type>{});
+}
+
+
+}
+
+BOOST_SQLITE_END_NAMESPACE
+
+#endif //BOOST_SQLITE_DETAIL_SCALAR_FUNCTION_HPP