stack.hpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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 <utility>
  11. #include <functional>
  12. LUWRA_NS_BEGIN
  13. namespace internal {
  14. template <typename>
  15. struct Layout;
  16. template <typename R, typename T>
  17. struct Layout<R(T)> {
  18. template <typename F, typename... A> static inline
  19. R direct(State* state, int n, F hook, A&&... args) {
  20. return hook(
  21. std::forward<A>(args)...,
  22. Value<T>::read(state, n)
  23. );
  24. }
  25. };
  26. template <typename R, typename T1, typename... TR>
  27. struct Layout<R(T1, TR...)> {
  28. template <typename F, typename... A> static inline
  29. R direct(State* state, int n, F hook, A&&... args) {
  30. return Layout<R(TR...)>::direct(
  31. state,
  32. n + 1,
  33. hook,
  34. std::forward<A>(args)...,
  35. Value<T1>::read(state, n)
  36. );
  37. }
  38. };
  39. }
  40. /**
  41. * Assuming a stack layout as follows (where A = A0, A1 ... An):
  42. *
  43. * Position | Parameter
  44. * ----------+-----------
  45. * pos + n | An xn
  46. * ... | ...
  47. * pos + 1 | A1 x1
  48. * pos + 0 | A0 x0
  49. * ... | ...
  50. *
  51. * Given a function `R f(A0, A1, ... An)` you are able to map over
  52. * the values on the stack on the stack like so:
  53. *
  54. * R my_result = apply(lua_state, pos, f);
  55. *
  56. * which is equivalent to
  57. *
  58. * R my_result = f(x0, x1, ... xn);
  59. *
  60. * where x0, x1, ... xn are the values on the stack.
  61. */
  62. template <typename R, typename... A> static inline
  63. R apply(State* state, int pos, R (*function_pointer)(A...)) {
  64. return internal::Layout<R(A...)>::direct(state, pos, function_pointer);
  65. }
  66. /**
  67. * Same as `apply(state, 1, function_pointer)`.
  68. */
  69. template <typename R, typename... A> static inline
  70. R apply(State* state, R (*function_pointer)(A...)) {
  71. return apply(state, 1, function_pointer);
  72. }
  73. /**
  74. * Specialization of `apply` which works for `std::function`.
  75. */
  76. template <typename R, typename... A> static inline
  77. R apply(State* state, int pos, std::function<R(A...)> function_object) {
  78. return internal::Layout<R(A...)>::direct(state, pos, function_object);
  79. }
  80. /**
  81. * Same as `apply(state, 1, function_object)`.
  82. */
  83. template <typename R, typename... A> static inline
  84. R apply(State* state, std::function<R(A...)> function_object) {
  85. return apply(state, 1, function_object);
  86. }
  87. /**
  88. * Check if two values are equal.
  89. */
  90. static inline
  91. bool equal(State* state, int index1, int index2) {
  92. #if LUA_VERSION_NUM <= 501
  93. return lua_equal(state, index1, index2);
  94. #else
  95. return lua_compare(state, index1, index2, LUA_OPEQ);
  96. #endif
  97. }
  98. /**
  99. * Register a value as a global.
  100. */
  101. template <typename T> static inline
  102. void register_global(State* state, const char* name, T value) {
  103. Value<T>::push(state, value);
  104. lua_setglobal(state, name);
  105. }
  106. LUWRA_NS_END
  107. #endif