Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permanent memory space for a user-defined function #1248

Merged
merged 17 commits into from
Nov 20, 2023
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 14 additions & 45 deletions dev/function.h
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
#pragma once

#include <sqlite3.h>
#include <type_traits> // std::is_member_function_pointer, std::remove_const, std::decay, std::is_same, std::false_type, std::true_type
#include <string> // std::string
#include <tuple> // std::tuple, std::tuple_size, std::tuple_element
#include <functional> // std::function
#include <algorithm> // std::min
#include <utility> // std::move, std::forward

#include "functional/cxx_universal.h"
#include "functional/cxx_type_traits_polyfill.h"
#include "tags.h"

namespace sqlite_orm {

Expand All @@ -21,48 +19,6 @@ namespace sqlite_orm {
class pointer_binding;

namespace internal {

struct udf_proxy_base {
using func_call_fn_t = void (*)(void* udfHandle,
sqlite3_context* context,
int argsCount,
sqlite3_value** values);
using final_call_fn_t = void (*)(void* udfHandle, sqlite3_context* context);

std::string name;
int argumentsCount = 0;
std::function<void*()> create;
xdestroy_fn_t destroy = nullptr;
func_call_fn_t func = nullptr;
final_call_fn_t finalAggregateCall = nullptr;

udf_proxy_base(std::string name,
int argumentsCount,
std::function<void*()> create,
xdestroy_fn_t destroy,
func_call_fn_t run) :
name(std::move(name)),
argumentsCount(argumentsCount), create(std::move(create)), destroy(destroy), func(run) {}

udf_proxy_base(std::string name,
int argumentsCount,
std::function<void*()> create,
xdestroy_fn_t destroy,
func_call_fn_t step,
final_call_fn_t finalCall) :
name(std::move(name)),
argumentsCount(argumentsCount), create(std::move(create)), destroy(destroy), func(step),
finalAggregateCall(finalCall) {}
};

struct scalar_udf_proxy : udf_proxy_base {
using udf_proxy_base::udf_proxy_base;
};

struct aggregate_udf_proxy : udf_proxy_base {
using udf_proxy_base::udf_proxy_base;
};

template<class F>
using scalar_call_function_t = decltype(&F::operator());

Expand Down Expand Up @@ -131,6 +87,10 @@ namespace sqlite_orm {
args_tuple args;
};

template<class T>
SQLITE_ORM_INLINE_VAR constexpr bool
is_operator_argument_v<T, std::enable_if_t<polyfill::is_specialization_of_v<T, function_call>>> = true;

template<class T>
struct unpacked_arg {
using type = T;
Expand Down Expand Up @@ -244,6 +204,10 @@ namespace sqlite_orm {

#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
/** @short Specifies that a type is a user-defined scalar function.
*
* `UDF` must meet the following requirements:
* - `UDF::name()` static function
* - `UDF::operator()()` call operator
*/
template<class UDF>
concept orm_scalar_udf = requires {
Expand All @@ -252,6 +216,11 @@ namespace sqlite_orm {
};

/** @short Specifies that a type is a user-defined aggregate function.
*
* `UDF` must meet the following requirements:
* - `UDF::name()` static function
* - `UDF::step()` member function
* - `UDF::fin()` member function
*/
template<class UDF>
concept orm_aggregate_udf = requires {
Expand Down
14 changes: 14 additions & 0 deletions dev/functional/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
#include <version>
#endif

#ifdef SQLITE_ORM_CONSTEXPR_LAMBDAS_SUPPORTED
#define SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17 constexpr
#else
#define SQLITE_ORM_CONSTEXPR_LAMBDA_CPP17
#endif

#ifdef SQLITE_ORM_INLINE_VARIABLES_SUPPORTED
#define SQLITE_ORM_INLINE_VAR inline
#else
Expand All @@ -24,6 +30,14 @@
#define SQLITE_ORM_NOUNIQUEADDRESS
#endif

#if SQLITE_ORM_HAS_CPP_ATTRIBUTE(likely) >= 201803L
#define SQLITE_ORM_CPP_LIKELY [[likely]]
#define SQLITE_ORM_CPP_UNLIKELY [[unlikely]]
#else
#define SQLITE_ORM_CPP_LIKELY
#define SQLITE_ORM_CPP_UNLIKELY
#endif

#ifdef SQLITE_ORM_CONSTEVAL_SUPPORTED
#define SQLITE_ORM_CONSTEVAL consteval
#else
Expand Down
4 changes: 4 additions & 0 deletions dev/functional/cxx_core_features.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
#define SQLITE_ORM_FOLD_EXPRESSIONS_SUPPORTED
#endif

#if __cpp_constexpr >= 201603L
#define SQLITE_ORM_CONSTEXPR_LAMBDAS_SUPPORTED
#endif

#if __cpp_if_constexpr >= 201606L
#define SQLITE_ORM_IF_CONSTEXPR_SUPPORTED
#endif
Expand Down
2 changes: 0 additions & 2 deletions dev/functional/cxx_functional_polyfill.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#endif
#include <utility> // std::forward

#if __cpp_lib_invoke < 201411L
#include "cxx_type_traits_polyfill.h"
#endif
#include "../member_traits/member_traits.h"

namespace sqlite_orm {
Expand Down
34 changes: 34 additions & 0 deletions dev/functional/cxx_tuple_polyfill.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include <tuple> // std::apply; std::tuple_size
#if __cpp_lib_apply < 201603L
#include <utility> // std::forward, std::index_sequence, std::make_index_sequence
#endif

#include "../functional/cxx_universal.h" // ::size_t
#include "../functional/cxx_functional_polyfill.h" // std::invoke

namespace sqlite_orm {
namespace internal {
namespace polyfill {
#if __cpp_lib_apply >= 201603L
using std::apply;
#else
template<class Callable, class Tpl, size_t... Idx>
decltype(auto) apply(Callable&& callable, Tpl&& tpl, std::index_sequence<Idx...>) {
return polyfill::invoke(std::forward<Callable>(callable), std::get<Idx>(std::forward<Tpl>(tpl))...);
}

template<class Callable, class Tpl>
decltype(auto) apply(Callable&& callable, Tpl&& tpl) {
constexpr size_t size = std::tuple_size<std::remove_reference_t<Tpl>>::value;
return apply(std::forward<Callable>(callable),
std::forward<Tpl>(tpl),
std::make_index_sequence<size>{});
}
#endif
}
}

namespace polyfill = internal::polyfill;
}
Loading