types.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* Luwra
  2. * Minimal-overhead Lua wrapper for C++
  3. *
  4. * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
  5. */
  6. #ifndef LUWRA_TYPES_H_
  7. #define LUWRA_TYPES_H_
  8. #include "common.hpp"
  9. #include <utility>
  10. #include <tuple>
  11. #include <string>
  12. LUWRA_NS_BEGIN
  13. /* Lua types */
  14. using Integer = lua_Integer;
  15. using Number = lua_Number;
  16. using State = lua_State;
  17. using CFunction = lua_CFunction;
  18. /**
  19. * A value on the stack
  20. */
  21. template <typename T>
  22. struct Value {
  23. static_assert(sizeof(T) == -1, "You must not use an unspecialized version of Value");
  24. /**
  25. * Retrieve the value at position `n`.
  26. */
  27. static
  28. T read(State*, int);
  29. /**
  30. * Push the value onto the stack.
  31. */
  32. static
  33. int push(State*, T);
  34. };
  35. /**
  36. * Define a template specialization of `Value` for `type` with a `retrf(State*, int)` which
  37. * extracts it from the stack and a `pushf(State*, type)` which pushes the value on the stack again.
  38. * This assumes that only one value will be pushed onto the stack.
  39. */
  40. #define LUWRA_DEF_VALUE(type, retrf, pushf) \
  41. template <> \
  42. struct Value<type> { \
  43. static inline \
  44. type read(State* state, int n) { \
  45. return retrf(state, n); \
  46. } \
  47. \
  48. static inline \
  49. int push(State* state, type value) { \
  50. pushf(state, value); \
  51. return 1; \
  52. } \
  53. }
  54. #ifndef luaL_checkboolean
  55. /**
  56. * Check if the value at index `n` is a boolean and retrieve its value.
  57. */
  58. #define luaL_checkboolean(state, n) \
  59. (luaL_checktype(state, n, LUA_TBOOLEAN), lua_toboolean(state, n))
  60. #endif
  61. #ifndef luaL_pushstdstring
  62. /**
  63. * Push a `std::string` as string onto the stack.
  64. */
  65. #define luaL_pushstdstring(state, stdstring) \
  66. (lua_pushstring(state, stdstring.c_str()))
  67. #endif
  68. /* Lua-dependent types */
  69. LUWRA_DEF_VALUE(Integer, luaL_checkinteger, lua_pushinteger);
  70. LUWRA_DEF_VALUE(Number, luaL_checknumber, lua_pushnumber);
  71. /* C/C++ types */
  72. LUWRA_DEF_VALUE(bool, luaL_checkboolean, lua_pushboolean);
  73. LUWRA_DEF_VALUE(const char*, luaL_checkstring, lua_pushstring);
  74. LUWRA_DEF_VALUE(std::string, luaL_checkstring, luaL_pushstdstring);
  75. #undef LUWRA_DEF_VALUE
  76. /**
  77. * An arbitrary value on an execution stack.
  78. * Note: this value is only available as long as it exists on its originating stack.
  79. */
  80. struct Arbitrary {
  81. State* state;
  82. int index;
  83. };
  84. template <>
  85. struct Value<Arbitrary> {
  86. static inline
  87. Arbitrary read(State* state, int index) {
  88. if (index < 0)
  89. index = lua_gettop(state) + (index + 1);
  90. return Arbitrary {state, index};
  91. }
  92. static inline
  93. int push(State* state, const Arbitrary& value) {
  94. lua_pushvalue(value.state, value.index);
  95. if (value.state != state)
  96. lua_xmove(value.state, state, 1);
  97. return 1;
  98. }
  99. };
  100. namespace internal {
  101. template <typename>
  102. struct StackPusher;
  103. template <size_t I>
  104. struct StackPusher<std::index_sequence<I>> {
  105. template <typename T> static inline
  106. void push(State* state, const T& package) {
  107. Value<typename std::tuple_element<I, T>::type>::push(state, std::get<I>(package));
  108. }
  109. };
  110. template <size_t I, size_t... Is>
  111. struct StackPusher<std::index_sequence<I, Is...>> {
  112. template <typename T> static inline
  113. void push(State* state, const T& package) {
  114. Value<typename std::tuple_element<I, T>::type>::push(state, std::get<I>(package));
  115. StackPusher<std::index_sequence<Is...>>::push(state, package);
  116. }
  117. };
  118. }
  119. /**
  120. * Allows you to use multiple return values.
  121. */
  122. template <typename... A>
  123. struct Value<std::tuple<A...>> {
  124. static inline
  125. std::tuple<A...> read(State*, int) {
  126. static_assert(sizeof(std::tuple<A...>) == -1, "std::tuples cannot be read from the stack");
  127. }
  128. static inline
  129. int push(State* state, const std::tuple<A...>& value) {
  130. internal::StackPusher<std::make_index_sequence<sizeof...(A)>>::push(state, value);
  131. return sizeof...(A);
  132. }
  133. };
  134. LUWRA_NS_END
  135. #endif