You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
159 lines
4.5 KiB
159 lines
4.5 KiB
#include <AP_HAL/AP_HAL.h> |
|
#include "lua_boxed_numerics.h" |
|
#include <AP_Scripting/lua_generated_bindings.h> |
|
|
|
|
|
extern const AP_HAL::HAL& hal; |
|
|
|
uint32_t coerce_to_uint32_t(lua_State *L, int arg) { |
|
{ // userdata |
|
const uint32_t * ud = static_cast<uint32_t *>(luaL_testudata(L, arg, "uint32_t")); |
|
if (ud != nullptr) { |
|
return *ud; |
|
} |
|
} |
|
{ // integer |
|
|
|
// if this assert fails, you will need to add an upper bounds |
|
// check that ensures the value isn't greater then UINT32_MAX |
|
static_assert(sizeof(lua_Number) == sizeof(uint32_t), "32 bit integers are only supported"); |
|
|
|
int success; |
|
const lua_Integer v = lua_tointegerx(L, arg, &success); |
|
if (success && v >= 0) { |
|
return static_cast<uint32_t>(v); |
|
} |
|
} |
|
{ // float |
|
int success; |
|
const lua_Number v = lua_tonumberx(L, arg, &success); |
|
if (success && v >= 0 && v <= float(UINT32_MAX)) { |
|
return static_cast<uint32_t>(v); |
|
} |
|
} |
|
// failure |
|
return luaL_argerror(L, arg, "Unable to coerce to uint32_t"); |
|
} |
|
|
|
// the exposed constructor to lua calls to create a uint32_t |
|
int lua_new_uint32_t(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args > 1) { |
|
return luaL_argerror(L, args, "too many arguments"); |
|
} |
|
|
|
*static_cast<uint32_t *>(lua_newuserdata(L, sizeof(uint32_t))) = (args == 1) ? coerce_to_uint32_t(L, 1) : 0; |
|
luaL_getmetatable(L, "uint32_t"); |
|
lua_setmetatable(L, -2); |
|
return 1; |
|
} |
|
|
|
#define UINT32_T_BOX_OP(name, sym) \ |
|
int uint32_t___##name(lua_State *L) { \ |
|
const int args = lua_gettop(L); \ |
|
if (args > 2) { \ |
|
return luaL_argerror(L, args, "too many arguments"); \ |
|
} else if (args < 2) { \ |
|
return luaL_argerror(L, args, "too few arguments"); \ |
|
} \ |
|
\ |
|
uint32_t v1 = coerce_to_uint32_t(L, 1); \ |
|
uint32_t v2 = coerce_to_uint32_t(L, 2); \ |
|
\ |
|
new_uint32_t(L); \ |
|
*static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = v1 sym v2; \ |
|
return 1; \ |
|
} |
|
|
|
UINT32_T_BOX_OP(add, +) |
|
UINT32_T_BOX_OP(sub, -) |
|
UINT32_T_BOX_OP(mul, *) |
|
UINT32_T_BOX_OP(div, /) |
|
UINT32_T_BOX_OP(mod, %) |
|
UINT32_T_BOX_OP(idiv, /) |
|
UINT32_T_BOX_OP(band, &) |
|
UINT32_T_BOX_OP(bor, |) |
|
UINT32_T_BOX_OP(bxor, ^) |
|
UINT32_T_BOX_OP(shl, <<) |
|
UINT32_T_BOX_OP(shr, >>) |
|
|
|
#define UINT32_T_BOX_OP_BOOL(name, sym) \ |
|
int uint32_t___##name(lua_State *L) { \ |
|
const int args = lua_gettop(L); \ |
|
luaL_checkstack(L, 1, "Out of stack"); \ |
|
if (args > 2) { \ |
|
return luaL_argerror(L, args, "too many arguments"); \ |
|
} else if (args < 2) { \ |
|
return luaL_argerror(L, args, "too few arguments"); \ |
|
} \ |
|
\ |
|
uint32_t v1 = coerce_to_uint32_t(L, 1); \ |
|
uint32_t v2 = coerce_to_uint32_t(L, 2); \ |
|
\ |
|
lua_pushboolean(L, v1 sym v2); \ |
|
return 1; \ |
|
} |
|
|
|
UINT32_T_BOX_OP_BOOL(eq, ==) |
|
UINT32_T_BOX_OP_BOOL(lt, <) |
|
UINT32_T_BOX_OP_BOOL(le, <=) |
|
|
|
#define UINT32_T_BOX_OP_UNARY(name, sym) \ |
|
int uint32_t___##name(lua_State *L) { \ |
|
const int args = lua_gettop(L); \ |
|
luaL_checkstack(L, 1, "Out of stack"); \ |
|
if (args != 1) { \ |
|
return luaL_argerror(L, args, "Expected 1 argument"); \ |
|
} \ |
|
\ |
|
uint32_t v1 = coerce_to_uint32_t(L, 1); \ |
|
\ |
|
new_uint32_t(L); \ |
|
*static_cast<uint32_t *>(luaL_checkudata(L, -1, "uint32_t")) = sym v1; \ |
|
return 1; \ |
|
} |
|
|
|
// DO NOT SUPPORT UNARY NEGATION |
|
UINT32_T_BOX_OP_UNARY(bnot, ~) |
|
|
|
int uint32_t_toint(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 1) { |
|
return luaL_argerror(L, args, "Expected 1 argument"); |
|
} |
|
|
|
uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t")); |
|
|
|
lua_pushinteger(L, static_cast<lua_Integer>(v)); |
|
|
|
return 1; |
|
} |
|
|
|
int uint32_t_tofloat(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 1) { |
|
return luaL_argerror(L, args, "Expected 1 argument"); |
|
} |
|
|
|
uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t")); |
|
|
|
lua_pushnumber(L, static_cast<lua_Number>(v)); |
|
|
|
return 1; |
|
} |
|
|
|
int uint32_t___tostring(lua_State *L) { |
|
const int args = lua_gettop(L); |
|
if (args != 1) { |
|
return luaL_argerror(L, args, "Expected 1 argument"); |
|
} |
|
|
|
uint32_t v = *static_cast<uint32_t *>(luaL_checkudata(L, 1, "uint32_t")); |
|
|
|
char buf[32]; |
|
hal.util->snprintf(buf, ARRAY_SIZE(buf), "%u", (unsigned)v); |
|
|
|
lua_pushstring(L, buf); |
|
|
|
return 1; |
|
}
|
|
|