LCOV - code coverage report
Current view: top level - AP_Scripting - lua_boxed_numerics.cpp (source / functions) Hit Total Coverage
Test: lcov.info Lines: 75 89 84.3 %
Date: 2026-09-09 11:02:08 Functions: 10 11 90.9 %

          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

Generated by: LCOV version 1.14