* @brief Calls the cached Lua transform function for @p uniqueId under the per-call deadline. */
| 2256 | * @brief Calls the cached Lua transform function for @p uniqueId under the per-call deadline. |
| 2257 | */ |
| 2258 | QVariant DataModel::FrameBuilder::applyTransformLua(TransformEngine& engine, |
| 2259 | int uniqueId, |
| 2260 | const QVariant& rawValue, |
| 2261 | const TransformFrameInfo& info) |
| 2262 | { |
| 2263 | auto refIt = engine.luaRefs.find(uniqueId); |
| 2264 | if (refIt == engine.luaRefs.end()) |
| 2265 | return rawValue; |
| 2266 | |
| 2267 | lua_State* L = engine.luaState; |
| 2268 | const auto& transform = refIt->second; |
| 2269 | const bool acceptsInfo = transform.acceptsInfo; |
| 2270 | engine.luaDeadline.setRemainingTime(kTransformWatchdogMs); |
| 2271 | |
| 2272 | try { |
| 2273 | lua_rawgeti(L, LUA_REGISTRYINDEX, transform.ref); |
| 2274 | if (rawValue.typeId() == QMetaType::Double) { |
| 2275 | lua_pushnumber(L, SerialStudio::toDouble(rawValue)); |
| 2276 | } else { |
| 2277 | const auto utf8 = rawValue.toString().toUtf8(); |
| 2278 | lua_pushlstring(L, utf8.constData(), static_cast<size_t>(utf8.size())); |
| 2279 | } |
| 2280 | |
| 2281 | int argCount = 1; |
| 2282 | if (acceptsInfo) { |
| 2283 | lua_createtable(L, 0, 3); |
| 2284 | lua_pushinteger(L, static_cast<lua_Integer>(info.frameNumber)); |
| 2285 | lua_setfield(L, -2, "frameNumber"); |
| 2286 | lua_pushinteger(L, info.sourceId); |
| 2287 | lua_setfield(L, -2, "sourceId"); |
| 2288 | lua_pushinteger(L, static_cast<lua_Integer>(info.timestampMs)); |
| 2289 | lua_setfield(L, -2, "timestampMs"); |
| 2290 | argCount = 2; |
| 2291 | } |
| 2292 | |
| 2293 | int pcallStatus = LUA_ERRRUN; |
| 2294 | try { |
| 2295 | pcallStatus = lua_pcall(L, argCount, 1, 0); |
| 2296 | } catch (...) { |
| 2297 | qWarning() << "[FrameBuilder] Uncaught exception escaped lua_pcall in transform for" |
| 2298 | << uniqueId; |
| 2299 | try { |
| 2300 | lua_settop(L, 0); |
| 2301 | lua_pushstring(L, "uncaught Lua exception (escaped lua_pcall)"); |
| 2302 | } catch (...) { |
| 2303 | } |
| 2304 | pcallStatus = LUA_ERRRUN; |
| 2305 | } |
| 2306 | engine.luaDeadline = QDeadlineTimer(QDeadlineTimer::Forever); |
| 2307 | |
| 2308 | if (pcallStatus != LUA_OK) [[unlikely]] { |
| 2309 | qWarning() << "[FrameBuilder] Lua transform call failed for dataset" << uniqueId << ":" |
| 2310 | << lua_tostring(L, -1); |
| 2311 | lua_pop(L, 1); |
| 2312 | return rawValue; |
| 2313 | } |
| 2314 | |
| 2315 | if (lua_isnumber(L, -1)) { |
nothing calls this directly
no test coverage detected