auxiliary.hpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* Luwra
  2. * Minimal-overhead Lua wrapper for C++
  3. *
  4. * Copyright (C) 2015, Ole Krüger <ole@vprsm.de>
  5. */
  6. #ifndef LUWRA_AUXILIARY_H_
  7. #define LUWRA_AUXILIARY_H_
  8. #include "common.hpp"
  9. #include "types.hpp"
  10. #include <vector>
  11. #include <utility>
  12. LUWRA_NS_BEGIN
  13. /**
  14. * Check if two values are equal.
  15. * \param state Lua state
  16. * \param index1 Index of left-hand side value
  17. * \param index2 Index of right-hand side value
  18. */
  19. static inline
  20. bool equal(State* state, int index1, int index2) {
  21. #if LUA_VERSION_NUM <= 501
  22. return lua_equal(state, index1, index2);
  23. #else
  24. return lua_compare(state, index1, index2, LUA_OPEQ);
  25. #endif
  26. }
  27. /**
  28. * Set a registered metatable for the value on top of the stack.
  29. * \param state Lua state
  30. * \param name Metatable name
  31. */
  32. static inline
  33. void setMetatable(State* state, const char* name) {
  34. #if LUA_VERSION_NUM <= 501
  35. luaL_getmetatable(state, name);
  36. lua_setmetatable(state, -2);
  37. #else
  38. luaL_setmetatable(state, name);
  39. #endif
  40. }
  41. /**
  42. * Register a value as a global.
  43. * \param state Lua state
  44. * \param name Global name
  45. * \param value Global value
  46. */
  47. template <typename V> static inline
  48. void setGlobal(State* state, const std::string& name, V value) {
  49. assert(1 == push(state, value));
  50. lua_setglobal(state, name.c_str());
  51. }
  52. /**
  53. * Retrieve a global value.
  54. * \param state Lua state
  55. * \param name Global name
  56. * \returns Value associated with the given name
  57. */
  58. template <typename V> static inline
  59. V getGlobal(State* state, const std::string& name) {
  60. lua_getglobal(state, name.c_str());
  61. V instance = read<V>(state, -1);
  62. lua_pop(state, 1);
  63. return instance;
  64. }
  65. namespace internal {
  66. template <typename K, typename V, typename... R>
  67. struct EntryPusher {
  68. static inline
  69. void push(State* state, int index, K&& key, V&& value, R&&... rest) {
  70. EntryPusher<K, V>::push(state, index, std::forward<K>(key), std::forward<V>(value));
  71. EntryPusher<R...>::push(state, index, std::forward<R>(rest)...);
  72. }
  73. };
  74. template <typename K, typename V>
  75. struct EntryPusher<K, V> {
  76. static inline
  77. void push(State* state, int index, K&& key, V&& value) {
  78. assert(1 == luwra::push(state, key));
  79. assert(1 == luwra::push(state, value));
  80. lua_rawset(state, index < 0 ? index - 2 : index);
  81. }
  82. };
  83. }
  84. /**
  85. * Set multiple fields at once. Allows you to provide multiple key-value pairs.
  86. * \param state Lua state
  87. * \param index Table index
  88. * \param args Key-value pairs
  89. */
  90. template <typename... R> static inline
  91. void setFields(State* state, int index, R&&... args) {
  92. static_assert(sizeof...(R) % 2 == 0, "Field parameters must appear in pairs");
  93. internal::EntryPusher<R...>::push(state, index, std::forward<R>(args)...);
  94. }
  95. /**
  96. * A collection of key-value pairs.
  97. */
  98. using FieldVector = std::vector<std::pair<Pushable, Pushable>>;
  99. /**
  100. * Apply key-value pairs to a table.
  101. * \param state Lua state
  102. * \param index Table index
  103. * \param fields Table fields
  104. */
  105. static inline
  106. void setFields(State* state, int index, const FieldVector& fields) {
  107. if (index < 0)
  108. index = lua_gettop(state) + (index + 1);
  109. for (const auto& pair: fields) {
  110. pair.first.push(state);
  111. pair.second.push(state);
  112. lua_rawset(state, index);
  113. }
  114. }
  115. template <>
  116. struct Value<FieldVector> {
  117. /**
  118. * Pushing a FieldVector will create a new table with the given fields.
  119. */
  120. static inline
  121. size_t push(State* state, const FieldVector& fields) {
  122. lua_newtable(state);
  123. setFields(state, -1, fields);
  124. return 1;
  125. }
  126. };
  127. /**
  128. * Retrieve a field from a table.
  129. */
  130. template <typename V, typename K> static inline
  131. V getField(State* state, int index, K key) {
  132. if (index < 0)
  133. index = lua_gettop(state) + (index + 1);
  134. assert(push<K>(state, key) == 1);
  135. lua_rawget(state, index);
  136. V value = read<V>(state, -1);
  137. lua_pop(state, 1);
  138. return value;
  139. }
  140. LUWRA_NS_END
  141. #endif