stack.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. /* Luwra
  2. * Minimal-overhead Lua wrapper for C++
  3. *
  4. * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
  5. */
  6. #ifndef LUWRA_STACK_H_
  7. #define LUWRA_STACK_H_
  8. #include "common.hpp"
  9. #include "types.hpp"
  10. #include <cassert>
  11. #include <utility>
  12. #include <functional>
  13. #include <string>
  14. LUWRA_NS_BEGIN
  15. namespace internal {
  16. template <typename T>
  17. struct Layout {
  18. static_assert(
  19. sizeof(T) == -1,
  20. "Parameter to Layout is not a valid signature"
  21. );
  22. };
  23. template <typename R>
  24. struct Layout<R()> {
  25. using ReturnType = R;
  26. template <typename F, typename... A> static inline
  27. R direct(State*, int, F&& hook, A&&... args) {
  28. return hook(
  29. std::forward<A>(args)...
  30. );
  31. }
  32. };
  33. template <typename R, typename T>
  34. struct Layout<R(T)> {
  35. using ReturnType = R;
  36. template <typename F, typename... A> static inline
  37. R direct(State* state, int n, F&& hook, A&&... args) {
  38. return hook(
  39. std::forward<A>(args)...,
  40. Value<T>::read(state, n)
  41. );
  42. }
  43. };
  44. template <typename R, typename T1, typename... TR>
  45. struct Layout<R(T1, TR...)> {
  46. using ReturnType = R;
  47. template <typename F, typename... A> static inline
  48. R direct(State* state, int n, F&& hook, A&&... args) {
  49. return Layout<R(TR...)>::direct(
  50. state,
  51. n + 1,
  52. std::forward<F>(hook),
  53. std::forward<A>(args)...,
  54. Value<T1>::read(state, n)
  55. );
  56. }
  57. };
  58. }
  59. /**
  60. * Retrieve values from the stack and invoke a `Callable` with them.
  61. *
  62. * \tparam S Signature in the form of `R(A...)` where `A` is a sequence of types, which shall be
  63. * retrieved from the stack, and `R` the return type of `hook`
  64. * \tparam F An instance of `Callable` which accepts parameters `X..., A...` and returns `R`
  65. * (this parameter should be inferable and can be omitted)
  66. * \tparam X Extra argument types
  67. *
  68. * \param state Lua state instance
  69. * \param pos Index of the first value
  70. * \param hook Callable value
  71. * \param args Extra arguments which shall be be passed to `hook` before the stack values
  72. *
  73. * \returns Result of calling `hook`
  74. */
  75. template <typename S, typename F, typename... X> static inline
  76. typename internal::Layout<S>::ReturnType direct(State* state, int pos, F&& hook, X&&... args) {
  77. return internal::Layout<S>::direct(
  78. state,
  79. pos,
  80. std::forward<F>(hook),
  81. std::forward<X>(args)...
  82. );
  83. }
  84. /**
  85. * Same as `direct(state, 1, hook)`.
  86. */
  87. template <typename S, typename F, typename... A> static inline
  88. typename internal::Layout<S>::ReturnType direct(State* state, F&& hook, A&&... args) {
  89. return internal::Layout<S>::direct(
  90. state,
  91. 1,
  92. std::forward<F>(hook),
  93. std::forward<A>(args)...
  94. );
  95. }
  96. /**
  97. * Synonym for [direct](@ref direct) with a function pointer which lets you omit all template parameters.
  98. * The stack layout will be inferred using the signature of the given function pointer.
  99. */
  100. template <typename R, typename... A> static inline
  101. R apply(State* state, int pos, R (* fun)(A...)) {
  102. return direct<R(A...)>(state, pos, fun);
  103. }
  104. /**
  105. * Same as `apply(state, 1, fun)`.
  106. */
  107. template <typename R, typename... A> static inline
  108. R apply(State* state, R (* fun)(A...)) {
  109. return apply(state, 1, fun);
  110. }
  111. /**
  112. * Synonym for [direct](@ref direct) with a function object which lets you omit all template parameters.
  113. * The stack layout will be inferred using the template parameter to your `std::function` object.
  114. */
  115. template <typename R, typename... A> static inline
  116. R apply(State* state, int pos, const std::function<R(A...)>& fun) {
  117. return internal::Layout<R(A...)>::direct(state, pos, fun);
  118. }
  119. /**
  120. * Same as `apply(state, 1, fun)`.
  121. */
  122. template <typename R, typename... A> static inline
  123. R apply(State* state, const std::function<R(A...)>& fun) {
  124. return apply(state, 1, fun);
  125. }
  126. namespace internal {
  127. template <typename T>
  128. struct LayoutMapper {
  129. static_assert(
  130. sizeof(T) == -1,
  131. "Parameter to LayoutMapper is not a valid signature"
  132. );
  133. };
  134. template <typename... A>
  135. struct LayoutMapper<void (A...)> {
  136. template <typename F, typename... X> static inline
  137. size_t map(State* state, int n, F&& hook, X&&... args) {
  138. direct<void (A...)>(
  139. state,
  140. n,
  141. std::forward<F>(hook),
  142. std::forward<X>(args)...
  143. );
  144. return 0;
  145. }
  146. };
  147. template <typename R, typename... A>
  148. struct LayoutMapper<R (A...)> {
  149. template <typename F, typename... X> static inline
  150. size_t map(State* state, int n, F&& hook, X&&... args) {
  151. return push(
  152. state,
  153. direct<R (A...)>(
  154. state,
  155. n,
  156. std::forward<F>(hook),
  157. std::forward<X>(args)...
  158. )
  159. );
  160. }
  161. };
  162. }
  163. /**
  164. * Similiar to [direct](@ref direct) but pushes the result of the given `Callable` onto the stack.
  165. * \returns Number of values pushed
  166. */
  167. template <typename S, typename F, typename... A> static inline
  168. size_t map(State* state, int pos, F&& hook, A&&... args) {
  169. return internal::LayoutMapper<S>::map(
  170. state,
  171. pos,
  172. std::forward<F>(hook),
  173. std::forward<A>(args)...
  174. );
  175. }
  176. /**
  177. * Same as `map(state, 1, hook)`.
  178. */
  179. template <typename S, typename F, typename... A> static inline
  180. size_t map(State* state, F&& hook, A&&... args) {
  181. return internal::LayoutMapper<S>::map(
  182. state,
  183. 1,
  184. std::forward<F>(hook),
  185. std::forward<A>(args)...
  186. );
  187. }
  188. LUWRA_NS_END
  189. #endif