auxiliary.hpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  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. */
  16. static inline
  17. bool equal(State* state, int index1, int index2) {
  18. #if LUA_VERSION_NUM <= 501
  19. return lua_equal(state, index1, index2);
  20. #else
  21. return lua_compare(state, index1, index2, LUA_OPEQ);
  22. #endif
  23. }
  24. /**
  25. * Register a value as a global.
  26. */
  27. template <typename V> static inline
  28. void setGlobal(State* state, const std::string& name, V value) {
  29. assert(1 == push(state, value));
  30. lua_setglobal(state, name.c_str());
  31. }
  32. /**
  33. * Retrieve a global value.
  34. */
  35. template <typename V> static inline
  36. V getGlobal(State* state, const std::string& name) {
  37. lua_getglobal(state, name.c_str());
  38. V instance = read<V>(state, -1);
  39. lua_pop(state, 1);
  40. return instance;
  41. }
  42. namespace internal {
  43. template <typename K, typename V, typename... R>
  44. struct EntryPusher {
  45. static inline
  46. void push(State* state, int index, K&& key, V&& value, R&&... rest) {
  47. EntryPusher<K, V>::push(state, index, std::forward<K>(key), std::forward<V>(value));
  48. EntryPusher<R...>::push(state, index, std::forward<R>(rest)...);
  49. }
  50. };
  51. template <typename K, typename V>
  52. struct EntryPusher<K, V> {
  53. static inline
  54. void push(State* state, int index, K&& key, V&& value) {
  55. assert(1 == luwra::push(state, key));
  56. assert(1 == luwra::push(state, value));
  57. lua_rawset(state, index < 0 ? index - 2 : index);
  58. }
  59. };
  60. }
  61. /**
  62. * Set multiple fields at once. Allows you to provide multiple key-value pairs.
  63. */
  64. template <typename... R> static inline
  65. void setFields(State* state, int index, R&&... args) {
  66. static_assert(sizeof...(R) % 2 == 0, "Field parameters must appear in pairs");
  67. internal::EntryPusher<R...>::push(state, index, std::forward<R>(args)...);
  68. }
  69. /**
  70. *
  71. */
  72. using FieldVector = std::vector<std::pair<Pushable, Pushable>>;
  73. /**
  74. *
  75. */
  76. static inline
  77. void setFields(State* state, int index, const FieldVector& fields) {
  78. if (index < 0)
  79. index = lua_gettop(state) + (index + 1);
  80. for (const auto& pair: fields) {
  81. pair.first.push(state);
  82. pair.second.push(state);
  83. lua_rawset(state, index);
  84. }
  85. }
  86. template <>
  87. struct Value<FieldVector> {
  88. static inline
  89. size_t push(State* state, const FieldVector& fields) {
  90. lua_newtable(state);
  91. setFields(state, -1, fields);
  92. return 1;
  93. }
  94. };
  95. /**
  96. * Retrieve a field from a table.
  97. */
  98. template <typename V, typename K> static inline
  99. V getField(State* state, int index, K key) {
  100. if (index < 0)
  101. index = lua_gettop(state) + (index + 1);
  102. assert(push<K>(state, key) == 1);
  103. lua_rawget(state, index);
  104. V value = read<V>(state, -1);
  105. lua_pop(state, 1);
  106. return value;
  107. }
  108. LUWRA_NS_END
  109. #endif