lua_boxed_numerics.cpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. #include <AP_HAL/AP_HAL.h>
  2. #include "lua_boxed_numerics.h"
  3. extern const AP_HAL::HAL& hal;
  4. int new_uint32_t(lua_State *L) {
  5. luaL_checkstack(L, 2, "Out of stack");
  6. *static_cast<uint32_t *>(lua_newuserdata(L, sizeof(uint32_t))) = 0; // allocated memory is already zerod, no need to manipulate this
  7. luaL_getmetatable(L, "uint32_t");
  8. lua_setmetatable(L, -2);
  9. return 1;
  10. }
  11. uint32_t * check_uint32_t(lua_State *L, int arg) {
  12. void *data = luaL_checkudata(L, arg, "uint32_t");
  13. return static_cast<uint32_t *>(data);
  14. }
  15. static uint32_t coerce_to_uint32_t(lua_State *L, int arg) {
  16. { // userdata
  17. const uint32_t * ud = static_cast<uint32_t *>(luaL_testudata(L, arg, "uint32_t"));
  18. if (ud != nullptr) {
  19. return *ud;
  20. }
  21. }
  22. { // integer
  23. // if this assert fails, you will need to add an upper bounds
  24. // check that ensures the value isn't greater then UINT32_MAX
  25. static_assert(sizeof(lua_Number) == sizeof(uint32_t), "32 bit integers are only supported");
  26. int success;
  27. const lua_Integer v = lua_tointegerx(L, arg, &success);
  28. if (success && v >= 0) {
  29. return static_cast<uint32_t>(v);
  30. }
  31. }
  32. { // float
  33. int success;
  34. const lua_Number v = lua_tonumberx(L, arg, &success);
  35. if (success && v >= 0 && v <= UINT32_MAX) {
  36. return static_cast<uint32_t>(v);
  37. }
  38. }
  39. // failure
  40. return luaL_argerror(L, arg, "Unable to coerce to uint32_t");
  41. }
  42. #define UINT32_T_BOX_OP(name, sym) \
  43. static int uint32_t___##name(lua_State *L) { \
  44. const int args = lua_gettop(L); \
  45. if (args > 2) { \
  46. return luaL_argerror(L, args, "too many arguments"); \
  47. } else if (args < 2) { \
  48. return luaL_argerror(L, args, "too few arguments"); \
  49. } \
  50. \
  51. uint32_t v1 = coerce_to_uint32_t(L, 1); \
  52. uint32_t v2 = coerce_to_uint32_t(L, 2); \
  53. \
  54. new_uint32_t(L); \
  55. *static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = v1 sym v2; \
  56. return 1; \
  57. }
  58. UINT32_T_BOX_OP(add, +)
  59. UINT32_T_BOX_OP(sub, -)
  60. UINT32_T_BOX_OP(mul, *)
  61. UINT32_T_BOX_OP(div, /)
  62. UINT32_T_BOX_OP(mod, %)
  63. UINT32_T_BOX_OP(idiv, /)
  64. UINT32_T_BOX_OP(band, &)
  65. UINT32_T_BOX_OP(bor, |)
  66. UINT32_T_BOX_OP(bxor, ^)
  67. UINT32_T_BOX_OP(shl, <<)
  68. UINT32_T_BOX_OP(shr, >>)
  69. #define UINT32_T_BOX_OP_BOOL(name, sym) \
  70. static int uint32_t___##name(lua_State *L) { \
  71. const int args = lua_gettop(L); \
  72. luaL_checkstack(L, 1, "Out of stack"); \
  73. if (args > 2) { \
  74. return luaL_argerror(L, args, "too many arguments"); \
  75. } else if (args < 2) { \
  76. return luaL_argerror(L, args, "too few arguments"); \
  77. } \
  78. \
  79. uint32_t v1 = coerce_to_uint32_t(L, 1); \
  80. uint32_t v2 = coerce_to_uint32_t(L, 2); \
  81. \
  82. lua_pushboolean(L, v1 sym v2); \
  83. return 1; \
  84. }
  85. UINT32_T_BOX_OP_BOOL(eq, =)
  86. UINT32_T_BOX_OP_BOOL(lt, <)
  87. UINT32_T_BOX_OP_BOOL(le, <=)
  88. #define UINT32_T_BOX_OP_UNARY(name, sym) \
  89. static int uint32_t___##name(lua_State *L) { \
  90. const int args = lua_gettop(L); \
  91. luaL_checkstack(L, 1, "Out of stack"); \
  92. if (args != 1) { \
  93. return luaL_argerror(L, args, "Expected 1 argument"); \
  94. } \
  95. \
  96. uint32_t v1 = coerce_to_uint32_t(L, 1); \
  97. \
  98. new_uint32_t(L); \
  99. *static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = sym v1; \
  100. return 1; \
  101. }
  102. // DO NOT SUPPORT UNARY NEGATION
  103. UINT32_T_BOX_OP_UNARY(bnot, ~)
  104. static int uint32_t_toint(lua_State *L) {
  105. const int args = lua_gettop(L);
  106. if (args != 1) {
  107. return luaL_argerror(L, args, "Expected 1 argument");
  108. }
  109. uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t"));
  110. lua_pushinteger(L, static_cast<lua_Integer>(v));
  111. return 1;
  112. }
  113. static int uint32_t_tofloat(lua_State *L) {
  114. const int args = lua_gettop(L);
  115. if (args != 1) {
  116. return luaL_argerror(L, args, "Expected 1 argument");
  117. }
  118. uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t"));
  119. lua_pushnumber(L, static_cast<lua_Number>(v));
  120. return 1;
  121. }
  122. static int uint32_t___tostring(lua_State *L) {
  123. const int args = lua_gettop(L);
  124. if (args != 1) {
  125. return luaL_argerror(L, args, "Expected 1 argument");
  126. }
  127. uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t"));
  128. char buf[32];
  129. hal.util->snprintf(buf, ARRAY_SIZE(buf), "%u", (unsigned)v);
  130. lua_pushstring(L, buf);
  131. return 1;
  132. }
  133. const luaL_Reg uint32_t_meta[] = {
  134. {"__add", uint32_t___add},
  135. {"__sub", uint32_t___sub},
  136. {"__mul", uint32_t___mul},
  137. {"__div", uint32_t___div},
  138. {"__mod", uint32_t___mod},
  139. {"__idiv", uint32_t___idiv},
  140. {"__band", uint32_t___band},
  141. {"__bor", uint32_t___bor},
  142. {"__bxor", uint32_t___bxor},
  143. {"__shl", uint32_t___shl},
  144. {"__shr", uint32_t___shr},
  145. {"__shr", uint32_t___shr},
  146. {"__eq", uint32_t___eq},
  147. {"__lt", uint32_t___lt},
  148. {"__le", uint32_t___le},
  149. {"__bnot", uint32_t___bnot},
  150. {"__tostring", uint32_t___tostring},
  151. {"toint", uint32_t_toint},
  152. {"tofloat", uint32_t_tofloat},
  153. {NULL, NULL}
  154. };
  155. void load_boxed_numerics(lua_State *L) {
  156. luaL_checkstack(L, 5, "Out of stack");
  157. luaL_newmetatable(L, "uint32_t");
  158. luaL_setfuncs(L, uint32_t_meta, 0);
  159. lua_pushstring(L, "__index");
  160. lua_pushvalue(L, -2);
  161. lua_settable(L, -3);
  162. lua_pop(L, 1);
  163. }
  164. void load_boxed_numerics_sandbox(lua_State *L) {
  165. // if there are ever more drivers then move to a table based solution
  166. lua_pushstring(L, "uint32_t");
  167. lua_pushcfunction(L, new_uint32_t);
  168. lua_settable(L, -3);
  169. }