commit 250ba75ea88e017af4e19b7f52dbe76ff33efd1e
parent dc31a93cdc5221d5c4ea72906368afd936d4db79
Author: cfillion <cfillion@users.noreply.github.com>
Date: Thu, 4 Apr 2019 02:40:02 -0400
refactor reascript vararg wrappers without preprocessing
Diffstat:
8 files changed, 103 insertions(+), 71 deletions(-)
diff --git a/src/action.hpp b/src/action.hpp
@@ -43,7 +43,8 @@ private:
class ActionList {
public:
- template<class... Args> Action *add(Args&&... args) {
+ template<typename... Args> Action *add(Args&&... args)
+ {
auto action = std::make_unique<Action>(args...);
m_list.emplace(action->id(), std::move(action));
diff --git a/src/api.cpp b/src/api.cpp
@@ -17,28 +17,33 @@
#include "api.hpp"
-#include <cstdio>
+#include <string>
#include <reaper_plugin_functions.h>
-APIDef::APIDef(const APIFunc *func)
- : m_func(func)
+using namespace std::string_literals;
+
+#define KEY(prefix) (prefix "_ReaPack_"s + m_func->name)
+
+APIReg::APIReg(const APIFunc *func)
+ : m_func(func),
+ m_impl(KEY("API")), m_vararg(KEY("APIvararg")), m_help(KEY("APIdef"))
{
- plugin_register(m_func->cKey, m_func->cImpl);
- plugin_register(m_func->reascriptKey, m_func->reascriptImpl);
- plugin_register(m_func->definitionKey, m_func->definition);
+ registerFunc();
}
-APIDef::~APIDef()
+APIReg::~APIReg()
{
- unregister(m_func->cKey, m_func->cImpl);
- unregister(m_func->reascriptKey, m_func->reascriptImpl);
- unregister(m_func->definitionKey, m_func->definition);
+ m_impl.insert(m_impl.begin(), '-');
+ m_vararg.insert(m_vararg.begin(), '-');
+ m_help.insert(m_help.begin(), '-');
+
+ registerFunc();
}
-void APIDef::unregister(const char *key, void *ptr)
+void APIReg::registerFunc() const
{
- char buf[255];
- snprintf(buf, sizeof(buf), "-%s", key);
- plugin_register(buf, ptr);
+ plugin_register(m_impl.c_str(), m_func->cImpl);
+ plugin_register(m_vararg.c_str(), m_func->reascriptImpl);
+ plugin_register(m_help.c_str(), m_func->definition);
}
diff --git a/src/api.hpp b/src/api.hpp
@@ -18,27 +18,30 @@
#ifndef REAPACK_API_HPP
#define REAPACK_API_HPP
+#include <string>
+
struct APIFunc {
- const char *cKey;
+ const char *name;
void *cImpl;
-
- const char *reascriptKey;
void *reascriptImpl;
-
- const char *definitionKey;
void *definition;
};
-class APIDef {
+class APIReg {
public:
- APIDef(const APIFunc *);
- APIDef(const APIDef &) = delete;
- ~APIDef();
+ APIReg(const APIFunc *);
+ APIReg(const APIReg &) = delete;
+ ~APIReg();
private:
- void unregister(const char *key, void *ptr);
+ void registerFunc() const;
const APIFunc *m_func;
+
+ // plugin_register requires these to not be temporaries
+ std::string m_impl;
+ std::string m_vararg;
+ std::string m_help;
};
namespace API {
diff --git a/src/api_helper.hpp b/src/api_helper.hpp
@@ -18,48 +18,69 @@
#ifndef REAPACK_API_HELPER_HPP
#define REAPACK_API_HELPER_HPP
-#include <boost/mpl/aux_/preprocessor/token_equal.hpp>
+#include <tuple>
+
#include <boost/preprocessor.hpp>
-#define API_PREFIX "ReaPack_"
+template<typename T>
+struct ReaScriptAPI;
+
+template<typename R, typename... Args>
+struct ReaScriptAPI<R(*)(Args...)>
+{
+ static void *applyVarArg(R(*fn)(Args...), void **argv, int argc)
+ {
+ if(static_cast<size_t>(argc) < sizeof...(Args))
+ return nullptr;
+
+ const auto &voidArgs = makeTuple(argv, std::index_sequence_for<Args...>{});
+ const auto &args = *reinterpret_cast<const std::tuple<Args...> *>(&voidArgs);
+
+ if constexpr (std::is_void_v<R>) {
+ std::apply(fn, args);
+ return nullptr;
+ }
+ else {
+ // cast integers to have the same size as a pointer to avoid warnings
+ using IntPtrR = std::conditional_t<std::is_integral_v<R>, intptr_t, R>;
+ const auto value = static_cast<IntPtrR>(std::apply(fn, args));
+ return reinterpret_cast<void *>(value);
+ }
+ }
+
+private:
+ template<size_t... I>
+ static auto makeTuple(void **argv, std::index_sequence<I...>)
+ {
+ return std::make_tuple(argv[I]...);
+ }
+};
-#define BOOST_MPL_PP_TOKEN_EQUAL_void(x) x
-#define BOOST_MPL_PP_TOKEN_EQUAL_bool(x) x
-#define BOOST_MPL_PP_TOKEN_EQUAL_int(x) x
-#define IS_VOID(type) BOOST_MPL_PP_TOKEN_EQUAL(type, void)
-#define IS_BOOL(type) BOOST_MPL_PP_TOKEN_EQUAL(type, bool)
-#define IS_INT(type) BOOST_MPL_PP_TOKEN_EQUAL(type, int)
+template<auto fn>
+void *InvokeReaScriptAPI(void **argv, int argc)
+{
+ return ReaScriptAPI<decltype(fn)>::applyVarArg(fn, argv, argc);
+}
#define ARG_TYPE(arg) BOOST_PP_TUPLE_ELEM(2, 0, arg)
#define ARG_NAME(arg) BOOST_PP_TUPLE_ELEM(2, 1, arg)
-// produce an appropriate conversion from void* to any type
-#define VOIDP_TO(type, val) \
- BOOST_PP_IF(IS_BOOL(type), val != 0, \
- (type) BOOST_PP_EXPR_IF(IS_INT(type), (intptr_t)) val)
-
#define DEFARGS(r, data, i, arg) BOOST_PP_COMMA_IF(i) ARG_TYPE(arg) ARG_NAME(arg)
-#define CALLARGS(r, data, i, arg) \
- BOOST_PP_COMMA_IF(i) VOIDP_TO(ARG_TYPE(arg), argv[i])
#define DOCARGS(r, macro, i, arg) \
BOOST_PP_EXPR_IF(i, ",") BOOST_PP_STRINGIZE(macro(arg))
-#define DEFINE_API(type, name, args, help, ...) \
- namespace API_##name { \
- static type cImpl(BOOST_PP_SEQ_FOR_EACH_I(DEFARGS, _, args)) __VA_ARGS__ \
- static void *reascriptImpl(void **argv, int argc) { \
- BOOST_PP_EXPR_IF(BOOST_PP_NOT(IS_VOID(type)), return (void *)(intptr_t)) \
- cImpl(BOOST_PP_SEQ_FOR_EACH_I(CALLARGS, _, args)); \
- BOOST_PP_EXPR_IF(IS_VOID(type), return nullptr;) \
- } \
- static const char *definition = #type "\0" \
- BOOST_PP_SEQ_FOR_EACH_I(DOCARGS, ARG_TYPE, args) "\0" \
- BOOST_PP_SEQ_FOR_EACH_I(DOCARGS, ARG_NAME, args) "\0" help; \
- }; \
- APIFunc API::name = {\
- "API_" API_PREFIX #name, (void *)&API_##name::cImpl, \
- "APIvararg_" API_PREFIX #name, (void *)&API_##name::reascriptImpl, \
- "APIdef_" API_PREFIX #name, (void *)API_##name::definition, \
+#define DEFINE_API(type, name, args, help, ...) \
+ static type API_##name(BOOST_PP_SEQ_FOR_EACH_I(DEFARGS, _, args)) __VA_ARGS__ \
+ \
+ APIFunc API::name { #name, \
+ reinterpret_cast<void *>(&API_##name), \
+ reinterpret_cast<void *>(&InvokeReaScriptAPI<API_##name>), \
+ reinterpret_cast<void *>(const_cast<char *>( \
+ #type "\0" \
+ BOOST_PP_SEQ_FOR_EACH_I(DOCARGS, ARG_TYPE, args) "\0" \
+ BOOST_PP_SEQ_FOR_EACH_I(DOCARGS, ARG_NAME, args) "\0" \
+ help \
+ )) \
}
#endif
diff --git a/src/event.hpp b/src/event.hpp
@@ -26,15 +26,16 @@
#include <optional>
#include <vector>
-template<class T>
+template<typename T>
class Event;
-template<class R, class... Args>
+template<typename R, typename... Args>
class Event<R(Args...)> {
public:
- typedef std::function<R(Args...)> Handler;
- typedef typename std::conditional<
- std::is_void<R>::value, void, std::optional<R>>::type ReturnType;
+ using Handler = std::function<R(Args...)>;
+ using ReturnType = std::conditional_t<
+ std::is_void_v<R>, void, std::optional<R>
+ >;
Event() = default;
Event(const Event &) = delete;
@@ -50,7 +51,7 @@ public:
ReturnType operator()(Args... args) const
{
- if constexpr (std::is_void<R>::value) {
+ if constexpr (std::is_void_v<R>) {
for(const auto &func : m_handlers)
func(std::forward<Args>(args)...);
}
@@ -67,7 +68,7 @@ private:
};
namespace AsyncEventImpl {
- typedef std::function<void ()> MainThreadFunc;
+ using MainThreadFunc = std::function<void ()>;
class Loop {
public:
@@ -97,10 +98,10 @@ namespace AsyncEventImpl {
};
};
-template<class T>
+template<typename T>
class AsyncEvent;
-template<class R, class... Args>
+template<typename R, typename... Args>
class AsyncEvent<R(Args...)> : public Event<R(Args...)> {
public:
using typename Event<R(Args...)>::ReturnType;
@@ -112,7 +113,7 @@ public:
// don't wait until the next timer tick to return nothing if there are no
// handlers currently subscribed to the event
if(!*this) {
- if constexpr (std::is_void<R>::value)
+ if constexpr (std::is_void_v<R>)
promise->set_value();
else
promise->set_value(std::nullopt);
@@ -121,7 +122,7 @@ public:
}
m_emitter.runInMainThread([=] {
- if constexpr (std::is_void<R>::value) {
+ if constexpr (std::is_void_v<R>) {
Event<R(Args...)>::operator()(args...);
promise->set_value();
}
diff --git a/src/reapack.hpp b/src/reapack.hpp
@@ -86,7 +86,7 @@ private:
UseRootPath m_useRootPath;
Config m_config;
ActionList m_actions;
- std::list<APIDef> m_api;
+ std::list<APIReg> m_api;
Transaction *m_tx;
std::unique_ptr<About> m_about;
diff --git a/src/string.hpp b/src/string.hpp
@@ -33,8 +33,9 @@ namespace String {
std::string indent(const std::string &);
- template<typename T, typename = std::enable_if_t<std::is_arithmetic<T>::value>>
- std::string number(const T v) {
+ template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<T>>>
+ std::string number(const T v)
+ {
std::ostringstream stream;
ImplDetail::imbueStream(stream);
stream << v;
diff --git a/vendor/vcpkg-deps.txt b/vendor/vcpkg-deps.txt
@@ -1 +1 @@
-boost-algorithm boost-core boost-lexical-cast boost-logic boost-mpl boost-preprocessor boost-range catch2 curl sqlite3
+boost-algorithm boost-core boost-lexical-cast boost-logic boost-preprocessor boost-range catch2 curl sqlite3