Line data Source code
1 : #include "AP_Scripting_config.h"
2 :
3 : #if AP_SCRIPTING_ENABLED
4 :
5 : #include <AP_HAL/AP_HAL.h>
6 : #include "lua_boxed_numerics.h"
7 : #include <AP_Scripting/lua_generated_bindings.h>
8 :
9 :
10 : extern const AP_HAL::HAL& hal;
11 :
12 80296 : uint32_t coerce_to_uint32_t(lua_State *L, int arg) {
13 : { // userdata
14 80296 : const uint32_t * ud = static_cast<uint32_t *>(luaL_testudata(L, arg, "uint32_t"));
15 80296 : if (ud != nullptr) {
16 45228 : return *ud;
17 : }
18 : }
19 : { // integer
20 :
21 : // if this assert fails, you will need to add an upper bounds
22 : // check that ensures the value isn't greater then UINT32_MAX
23 : static_assert(sizeof(lua_Number) == sizeof(uint32_t), "32 bit integers are only supported");
24 :
25 : int success;
26 35068 : const lua_Integer v = lua_tointegerx(L, arg, &success);
27 35068 : if (success) {
28 35068 : return static_cast<uint32_t>(v);
29 : }
30 : }
31 : { // float
32 : int success;
33 0 : const lua_Number v = lua_tonumberx(L, arg, &success);
34 0 : if (success && v >= 0 && v <= float(UINT32_MAX)) {
35 0 : return static_cast<uint32_t>(v);
36 : }
37 : }
38 : // failure
39 0 : return luaL_argerror(L, arg, "Unable to coerce to uint32_t");
40 : }
41 :
42 504 : uint64_t coerce_to_uint64_t(lua_State *L, int arg) {
43 : { // uint64_t userdata
44 504 : const uint64_t * ud = static_cast<uint64_t *>(luaL_testudata(L, arg, "uint64_t"));
45 504 : if (ud != nullptr) {
46 312 : return *ud;
47 : }
48 : }
49 : { // integer
50 : int success;
51 192 : const lua_Integer v = lua_tointegerx(L, arg, &success);
52 :
53 : // Lua int maps to int32. However, because of the size difference negatives numbers wont come out correctly as they do for uint32
54 192 : if (success && v >= 0) {
55 156 : return static_cast<uint64_t>(v);
56 : }
57 : }
58 : { // uint32_t userdata
59 36 : const uint32_t * ud = static_cast<uint32_t *>(luaL_testudata(L, arg, "uint32_t"));
60 36 : if (ud != nullptr) {
61 24 : return static_cast<uint64_t>(*ud);
62 : }
63 : }
64 : { // float
65 : int success;
66 12 : const lua_Number v = lua_tonumberx(L, arg, &success);
67 12 : if (success && (v >= 0) && (v <= float(UINT64_MAX))) {
68 12 : return static_cast<uint64_t>(v);
69 : }
70 : }
71 : // failure
72 0 : return luaL_argerror(L, arg, "Unable to coerce to uint64_t");
73 : }
74 :
75 : // the exposed constructor to lua calls to create a uint32_t
76 74 : int lua_new_uint32_t(lua_State *L) {
77 74 : const int args = lua_gettop(L);
78 74 : if (args > 1) {
79 0 : return luaL_argerror(L, args, "too many arguments");
80 : }
81 :
82 74 : *new_uint32_t(L) = (args == 1) ? coerce_to_uint32_t(L, 1) : 0;
83 74 : return 1;
84 : }
85 :
86 : // the exposed constructor to lua calls to create a uint64_t
87 144 : int lua_new_uint64_t(lua_State *L) {
88 144 : const int args = lua_gettop(L);
89 144 : if (args > 2) {
90 0 : return luaL_argerror(L, args, "too many arguments");
91 : }
92 :
93 144 : uint64_t value = 0;
94 144 : switch (args) {
95 12 : case 0:
96 : default:
97 : // No arguments, init to 0
98 12 : break;
99 108 : case 1:
100 : // Single argument
101 108 : value = coerce_to_uint64_t(L, 1);
102 108 : break;
103 :
104 24 : case 2:
105 : // Two uint32 giving high and low half
106 24 : const uint64_t high = coerce_to_uint32_t(L, 1);
107 24 : const uint64_t low = coerce_to_uint32_t(L, 2);
108 24 : value = (high << 32) | low;
109 24 : break;
110 : }
111 :
112 144 : *new_uint64_t(L) = value;
113 144 : return 1;
114 : }
115 :
116 17084 : int uint32_t_toint(lua_State *L) {
117 17084 : binding_argcheck(L, 1);
118 :
119 17084 : const uint32_t v = *check_uint32_t(L, 1);
120 :
121 17084 : lua_pushinteger(L, static_cast<lua_Integer>(v));
122 :
123 17084 : return 1;
124 : }
125 :
126 0 : int uint64_t_toint(lua_State *L) {
127 0 : binding_argcheck(L, 1);
128 :
129 0 : const uint64_t v = *check_uint64_t(L, 1);
130 :
131 0 : if (v > INT32_MAX) {
132 : // uint64_t too large to convert to int return nill rather than giving error
133 0 : return 0;
134 : }
135 :
136 0 : lua_pushinteger(L, static_cast<lua_Integer>(v));
137 :
138 0 : return 1;
139 : }
140 :
141 39239 : int uint32_t_tofloat(lua_State *L) {
142 39239 : binding_argcheck(L, 1);
143 :
144 39239 : const uint32_t v = *check_uint32_t(L, 1);
145 :
146 39239 : lua_pushnumber(L, static_cast<lua_Number>(v));
147 :
148 39239 : return 1;
149 : }
150 :
151 24 : int uint64_t_tofloat(lua_State *L) {
152 24 : binding_argcheck(L, 1);
153 :
154 24 : const uint64_t v = *check_uint64_t(L, 1);
155 :
156 24 : lua_pushnumber(L, static_cast<lua_Number>(v));
157 :
158 24 : return 1;
159 : }
160 :
161 9 : int uint32_t___tostring(lua_State *L) {
162 9 : binding_argcheck(L, 1);
163 :
164 9 : const uint32_t v = *check_uint32_t(L, 1);
165 :
166 : char buf[32];
167 9 : hal.util->snprintf(buf, ARRAY_SIZE(buf), "%lu", (unsigned long)v);
168 :
169 9 : lua_pushstring(L, buf);
170 :
171 9 : return 1;
172 : }
173 :
174 12 : int uint64_t___tostring(lua_State *L) {
175 12 : binding_argcheck(L, 1);
176 :
177 12 : const uint64_t v = *check_uint64_t(L, 1);
178 :
179 : char buf[32];
180 12 : hal.util->snprintf(buf, ARRAY_SIZE(buf), "%llu", (unsigned long long)v);
181 :
182 12 : lua_pushstring(L, buf);
183 :
184 12 : return 1;
185 : }
186 :
187 : // Split uint64 into a high and low uint32
188 24 : int uint64_t_split(lua_State *L) {
189 24 : binding_argcheck(L, 1);
190 :
191 24 : const uint64_t v = *check_uint64_t(L, 1);
192 :
193 : // high
194 24 : *new_uint32_t(L) = v >> 32;
195 :
196 : // low
197 24 : *new_uint32_t(L) = v & 0xFFFFFFFF;
198 :
199 24 : return 2;
200 : }
201 :
202 : #endif // AP_SCRIPTING_ENABLED
|