2013-08-14 14:17:44 +02:00
/***************************************************************************
* Copyright ( C ) 2013 by Chris Mitchell *
2014-08-15 02:11:43 -07:00
* Copyright ( C ) 2014 by Ahmed Charles - acharles @ outlook . com *
2023-02-20 21:46:15 +00:00
* Copyright ( C ) 2020 , 2023 by Stephen Lyons - slysven @ virginmedia . com *
2013-08-14 14:17:44 +02:00
* *
* This program is free software ; you can redistribute it and / or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation ; either version 2 of the License , or *
* ( at your option ) any later version . *
* *
* This program is distributed in the hope that it will be useful , *
* but WITHOUT ANY WARRANTY ; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the *
* GNU General Public License for more details . *
* *
* You should have received a copy of the GNU General Public License *
* along with this program ; if not , write to the *
* Free Software Foundation , Inc . , *
* 59 Temple Place - Suite 330 , Boston , MA 02111 - 1307 , USA . *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2021-04-17 14:48:23 -04:00
# include <QDebug>
2013-08-14 14:17:44 +02:00
# include "LuaInterface.h"
# include "VarUnit.h"
2021-12-07 06:21:39 +01:00
# include "utils.h"
2014-08-15 02:11:43 -07:00
2018-08-30 13:48:42 +02:00
# include <csetjmp>
2014-08-15 02:11:43 -07:00
2021-04-17 14:48:23 -04:00
extern " C " {
2025-05-17 22:34:05 +01:00
# if defined(INCLUDE_VERSIONED_LUA_HEADERS)
# include <lua5.1/lauxlib.h>
# include <lua5.1/lua.h>
# include <lua5.1/lualib.h>
# else
# include <lauxlib.h>
# include <lua.h>
# include <lualib.h>
# endif
2021-04-17 14:48:23 -04:00
}
2013-08-14 14:17:44 +02:00
static jmp_buf buf ;
2021-04-17 14:48:23 -04:00
LuaInterface : : LuaInterface ( lua_State * L )
2025-09-25 09:26:12 +02:00
: mL ( L )
2013-08-14 14:17:44 +02:00
{
2014-09-29 04:08:18 -07:00
varUnit . reset ( new VarUnit ( ) ) ;
2013-08-14 14:17:44 +02:00
//set our panic function
2021-04-17 14:48:23 -04:00
lua_atpanic ( L , & onPanic ) ;
2013-08-14 14:17:44 +02:00
}
2018-06-05 06:50:40 +02:00
LuaInterface : : ~ LuaInterface ( ) = default ;
2014-09-29 04:08:18 -07:00
2017-04-27 03:55:38 -07:00
int LuaInterface : : onPanic ( lua_State * L )
2013-08-14 14:17:44 +02:00
{
QString error = " Lua Panic, No error information " ;
2017-04-27 03:55:38 -07:00
if ( lua_isstring ( L , - 1 ) ) {
2020-10-11 13:26:59 +02:00
error = lua_tostring ( L , - 1 ) ;
2023-02-27 08:15:54 +01:00
qDebug ( ) < < " Lua panic: " < < error ;
2013-08-14 14:17:44 +02:00
}
2023-02-27 08:15:54 +01:00
2013-08-14 14:17:44 +02:00
longjmp ( buf , 1 ) ;
return 1 ;
}
2017-04-27 03:55:38 -07:00
VarUnit * LuaInterface : : getVarUnit ( )
{
2014-09-29 04:08:18 -07:00
return varUnit . data ( ) ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
QStringList LuaInterface : : varName ( TVar * var )
{
2013-08-14 14:17:44 +02:00
QStringList names ;
2023-04-15 06:38:39 +02:00
if ( var - > getName ( ) = = qsl ( " _G " ) ) {
2013-08-14 14:17:44 +02:00
names < < " " ;
return names ;
}
names < < var - > getName ( ) ;
2023-05-11 07:44:16 +02:00
TVar * pParent = var - > getParent ( ) ;
while ( pParent & & pParent - > getName ( ) ! = qsl ( " _G " ) ) {
names . insert ( 0 , pParent - > getName ( ) ) ;
pParent = pParent - > getParent ( ) ;
2013-08-14 14:17:44 +02:00
}
return names ;
}
2025-12-24 10:04:10 +00:00
std : : pair < bool , QString > LuaInterface : : validMove ( QTreeWidgetItem * pWidget )
2017-04-27 03:55:38 -07:00
{
2023-05-11 07:44:16 +02:00
TVar * pNewParent = varUnit - > getWVar ( pWidget ) ;
if ( pNewParent & & pNewParent - > getValueType ( ) ! = LUA_TTABLE ) {
2025-12-24 10:04:10 +00:00
//: Error message shown when user tries to drag a variable onto a non-table variable
return { false , QObject : : tr ( " Cannot move variable here - the target is not a table " ) } ;
2017-06-26 16:46:54 +02:00
}
2025-12-24 10:04:10 +00:00
return { true , QString ( ) } ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : getAllChildren ( TVar * var , QList < TVar * > * list )
{
QListIterator < TVar * > it ( var - > getChildren ( true ) ) ;
2017-06-26 16:46:54 +02:00
if ( varUnit - > isSaved ( var ) | | var - > saved ) {
2013-08-14 14:17:44 +02:00
list - > append ( var ) ;
2017-06-26 16:46:54 +02:00
}
2017-04-27 03:55:38 -07:00
while ( it . hasNext ( ) ) {
TVar * child = it . next ( ) ;
2017-06-26 16:46:54 +02:00
if ( child - > getValueType ( ) = = LUA_TTABLE ) {
2017-04-27 03:55:38 -07:00
getAllChildren ( child , list ) ;
2017-06-26 16:46:54 +02:00
} else if ( varUnit - > isSaved ( child ) | | var - > saved ) {
2013-08-14 14:17:44 +02:00
list - > append ( child ) ;
2017-06-26 16:46:54 +02:00
}
2013-08-14 14:17:44 +02:00
}
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : loadKey ( lua_State * L , TVar * var )
{
if ( setjmp ( buf ) = = 0 ) {
2023-05-14 15:06:15 +02:00
const int keyType = var - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( var - > isReference ( ) ) {
2013-08-14 14:17:44 +02:00
lua_rawgeti ( L , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-27 08:15:54 +01:00
if ( keyType = = LUA_TNUMBER ) {
2013-08-14 14:17:44 +02:00
lua_pushnumber ( L , var - > getName ( ) . toInt ( ) ) ;
2023-02-27 08:15:54 +01:00
} else if ( keyType = = LUA_TTABLE ) {
} else if ( keyType = = LUA_TBOOLEAN ) {
2017-04-27 03:55:38 -07:00
lua_pushboolean ( L , var - > getName ( ) . toLower ( ) = = " true " ? 1 : 0 ) ;
} else {
2018-01-26 04:07:28 +01:00
lua_pushstring ( L , var - > getName ( ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
}
}
2023-02-27 08:15:54 +01:00
return lua_type ( L , - 1 ) = = keyType ;
2013-08-14 14:17:44 +02:00
}
2023-02-27 08:15:54 +01:00
2013-08-14 14:17:44 +02:00
return false ;
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : loadValue ( lua_State * L , TVar * var , int index )
{
2013-08-14 14:17:44 +02:00
//puts a value on stack
2017-04-27 03:55:38 -07:00
if ( setjmp ( buf ) = = 0 ) {
if ( loadKey ( L , var ) ) {
2013-08-14 14:17:44 +02:00
//everything is tabled in lua, we need to just find what table
//we're using, if index == 0, we iterate to the closest table
2017-06-26 16:46:54 +02:00
if ( index ) {
2025-11-18 03:49:49 -05:00
// Validate stack before attempting table access
const int stackTop = lua_gettop ( L ) ;
const int actualIndex = ( index < 0 ) ? stackTop + index + 1 : index ;
2026-01-03 16:00:41 +01:00
2025-11-18 03:49:49 -05:00
if ( actualIndex < = 0 | | actualIndex > stackTop ) {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::loadValue() - Invalid stack index " < < index < < " for variable \" " < < var - > getName ( ) < < " \" . Stack size: " < < stackTop
< < " , resolved index: " < < actualIndex < < " . " ;
2025-11-18 03:49:49 -05:00
return false ;
}
2026-01-03 16:00:41 +01:00
2025-11-18 03:49:49 -05:00
if ( ! lua_istable ( L , index ) ) {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::loadValue() - Value at stack index " < < index < < " is not a table for variable \" " < < var - > getName ( )
< < " \" . Got type: " < < lua_typename ( L , lua_type ( L , index ) ) < < " . " ;
2025-11-18 03:49:49 -05:00
return false ;
}
2026-01-03 16:00:41 +01:00
2013-08-14 14:17:44 +02:00
lua_gettable ( L , index ) ;
2017-06-26 16:46:54 +02:00
} else {
2025-11-18 03:49:49 -05:00
// Find the closest table on the stack
bool foundTable = false ;
2017-04-27 03:55:38 -07:00
for ( int j = 1 ; j < = lua_gettop ( L ) ; j + + ) {
if ( lua_type ( L , j * - 1 ) = = LUA_TTABLE ) {
lua_gettable ( L , j * - 1 ) ;
2025-11-18 03:49:49 -05:00
foundTable = true ;
break ;
2013-08-14 14:17:44 +02:00
}
}
2025-11-18 03:49:49 -05:00
if ( ! foundTable ) {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::loadValue() - No table found on stack for variable \" " < < var - > getName ( ) < < " \" when index=0. Stack size: " < < lua_gettop ( L )
< < " . " ;
2025-11-18 03:49:49 -05:00
return false ;
}
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
} else {
2013-08-14 14:17:44 +02:00
return false ;
2017-04-27 03:55:38 -07:00
}
if ( lua_gettop ( L ) ) {
2014-09-15 16:59:25 -04:00
return lua_type ( L , - 1 ) = = var - > getValueType ( ) ;
2017-04-27 03:55:38 -07:00
}
2014-09-15 16:59:25 -04:00
return false ;
2013-08-14 14:17:44 +02:00
}
return false ;
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : reparentCVariable ( TVar * from , TVar * to , TVar * curVar )
{
2013-08-14 14:17:44 +02:00
//get the old parent on the stack
2017-04-27 03:55:38 -07:00
if ( setjmp ( buf ) = = 0 ) {
if ( ! from | | ! to | | ( from = = to ) ) {
// moving from global to global or nowhere
2013-08-14 14:17:44 +02:00
return true ;
2017-04-27 03:55:38 -07:00
}
2023-05-14 15:06:15 +02:00
const int stackSize = lua_gettop ( mL ) ;
const bool isSaved = varUnit - > isSaved ( curVar ) ;
2017-04-27 03:55:38 -07:00
if ( isSaved ) {
QList < TVar * > list ;
2013-08-14 14:17:44 +02:00
getAllChildren ( curVar , & list ) ;
2017-04-27 03:55:38 -07:00
QListIterator < TVar * > it ( list ) ;
while ( it . hasNext ( ) ) {
TVar * t = it . next ( ) ;
2013-08-14 14:17:44 +02:00
varUnit - > removeSavedVar ( t ) ;
}
}
2017-04-27 03:55:38 -07:00
QList < TVar * > vars = varOrder ( curVar ) ;
2023-02-20 21:46:15 +00:00
lua_getglobal ( mL , ( vars [ 0 ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
int i = 1 ;
for ( ; i < vars . size ( ) ; i + + ) {
2023-02-20 21:46:15 +00:00
if ( ! loadValue ( mL , vars [ i ] , - 2 ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
}
//redo the parenting in TVar
from - > removeChild ( curVar ) ;
curVar - > setParent ( to ) ;
to - > addChild ( curVar ) ;
vars = varOrder ( curVar ) ;
//do the actual reparenting part
2017-04-27 03:55:38 -07:00
if ( to = = varUnit - > getBase ( ) ) {
2013-08-14 14:17:44 +02:00
//we're going global
2023-02-20 21:46:15 +00:00
lua_setglobal ( mL , curVar - > getName ( ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_getglobal ( mL , ( vars [ 0 ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
i = 1 ;
for ( ; i < vars . size ( ) - 1 ; i + + ) {
2023-02-20 21:46:15 +00:00
if ( ! loadValue ( mL , vars [ i ] , - 2 ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_remove ( mL , - 2 ) ;
2013-08-14 14:17:44 +02:00
}
2023-02-20 21:46:15 +00:00
lua_insert ( mL , - 2 ) ;
if ( ! loadKey ( mL , curVar ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_insert ( mL , - 2 ) ;
if ( ! lua_istable ( mL , - 3 ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_settable ( mL , - 3 ) ;
lua_pop ( mL , 1 ) ;
2013-08-14 14:17:44 +02:00
}
//delete the old copy
2017-04-27 03:55:38 -07:00
if ( from = = varUnit - > getBase ( ) ) {
2023-02-20 21:46:15 +00:00
lua_pushnil ( mL ) ;
lua_setglobal ( mL , curVar - > getName ( ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
if ( ! loadKey ( mL , curVar ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_pushnil ( mL ) ;
if ( ! lua_istable ( mL , - 3 ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_settable ( mL , - 3 ) ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
if ( isSaved ) {
QList < TVar * > list ;
2013-08-14 14:17:44 +02:00
list . append ( to ) ;
getAllChildren ( curVar , & list ) ;
2017-04-27 03:55:38 -07:00
QListIterator < TVar * > it ( list ) ;
while ( it . hasNext ( ) ) {
TVar * t = it . next ( ) ;
2013-08-14 14:17:44 +02:00
varUnit - > addSavedVar ( t ) ;
}
}
2023-02-20 21:46:15 +00:00
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return true ;
}
2014-01-10 21:41:20 -05:00
return false ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : reparentVariable ( QTreeWidgetItem * newP , QTreeWidgetItem * cItem , QTreeWidgetItem * oldP )
{
2013-08-14 14:17:44 +02:00
//if oldParent doesn't exist:
//this means we were moved to a table from the global namespace
//if newParent doesn't exist:
//we were moved to the global namespace
//if both exist:
//this means we were moved from inside a table to inside another table
//and in both instances, this table was not _G
2019-08-13 10:27:54 +02:00
TVar * curVar = varUnit - > getWVar ( cItem ) ;
if ( ! curVar ) {
return false ;
}
2021-04-17 14:48:23 -04:00
2017-04-27 03:55:38 -07:00
TVar * newParent = varUnit - > getWVar ( newP ) ;
TVar * oldParent = varUnit - > getWVar ( oldP ) ;
TVar * from = oldParent ;
TVar * to = newParent ;
if ( newParent & & newParent - > getValueType ( ) ! = LUA_TTABLE ) {
2014-01-10 21:41:20 -05:00
//FIXME: report why this fails to user
2013-08-14 14:17:44 +02:00
return false ;
}
2020-06-01 17:35:35 +01:00
2017-04-27 03:55:38 -07:00
if ( ! newParent & & ! oldParent ) {
2013-08-14 14:17:44 +02:00
//happens when we move from _G to _G
return false ;
2020-06-01 17:35:35 +01:00
}
if ( ! oldParent ) {
2013-08-14 14:17:44 +02:00
from = varUnit - > getBase ( ) ;
2020-06-01 17:35:35 +01:00
// newParent cannot be a nullptr here as we would have returned in
// previous if - so to won't be either:
2013-08-14 14:17:44 +02:00
to = newParent ;
2017-04-27 03:55:38 -07:00
} else if ( ! newParent ) {
2020-06-01 17:35:35 +01:00
// oldParent cannot be a nullptr here as we would have returned in
// previous if - so from won't be either:
2013-08-14 14:17:44 +02:00
from = oldParent ;
to = varUnit - > getBase ( ) ;
}
2020-06-01 17:35:35 +01:00
// one of from and to must not be a nullptr here - so prior test for BOTH
// being a nullptr here and returning false in that case was dead code.
2017-04-27 03:55:38 -07:00
return reparentCVariable ( from , to , curVar ) ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
QList < TVar * > LuaInterface : : varOrder ( TVar * var )
{
QList < TVar * > vars ;
2023-04-15 06:38:39 +02:00
if ( var - > getName ( ) = = qsl ( " _G " ) ) {
2013-08-14 14:17:44 +02:00
return vars ;
}
vars < < var ;
2023-05-11 07:44:16 +02:00
TVar * pParent = var - > getParent ( ) ;
while ( pParent & & pParent - > getName ( ) ! = qsl ( " _G " ) ) {
vars . insert ( 0 , pParent ) ;
pParent = pParent - > getParent ( ) ;
2013-08-14 14:17:44 +02:00
}
return vars ;
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : createVar ( TVar * var )
{
setValue ( var ) ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : setCValue ( QList < TVar * > vars )
{
2013-08-14 14:17:44 +02:00
//make the new stack
2017-04-27 03:55:38 -07:00
TVar * var = vars . back ( ) ;
if ( setjmp ( buf ) = = 0 ) {
2023-05-14 15:06:15 +02:00
const int stackSize = lua_gettop ( mL ) ;
2023-02-20 21:46:15 +00:00
lua_getglobal ( mL , ( vars [ 0 ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
int i = 1 ;
for ( ; i < vars . size ( ) - 1 ; i + + ) {
2023-02-20 21:46:15 +00:00
if ( ! loadValue ( mL , vars [ i ] , - 2 ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
}
//push our value onto the stack
2017-04-27 03:55:38 -07:00
switch ( var - > getValueType ( ) ) {
2013-08-14 14:17:44 +02:00
case LUA_TSTRING :
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , var - > getValue ( ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TNUMBER :
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , var - > getValue ( ) . toInt ( ) ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TBOOLEAN :
2023-02-20 21:46:15 +00:00
lua_pushboolean ( mL , var - > getValue ( ) . toLower ( ) = = " true " ? 1 : 0 ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TTABLE :
2023-02-20 21:46:15 +00:00
lua_newtable ( mL ) ;
2013-08-14 14:17:44 +02:00
break ;
default :
2023-02-20 21:46:15 +00:00
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
//set it up
2023-02-20 21:46:15 +00:00
if ( lua_type ( mL , - 1 ) ! = var - > getValueType ( ) ) {
lua_settop ( mL , stackSize ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2023-02-20 21:46:15 +00:00
lua_settable ( mL , - 3 ) ;
2013-08-14 14:17:44 +02:00
}
2014-01-10 21:41:20 -05:00
return false ;
2013-08-14 14:17:44 +02:00
}
2018-01-26 04:07:28 +01:00
// sets the value of a Lua variable by running dynamically-generated Lua code
2017-04-27 03:55:38 -07:00
bool LuaInterface : : setValue ( TVar * var )
{
2013-08-14 14:17:44 +02:00
//This function assumes the var has been modified and then called
2021-04-17 14:48:23 -04:00
2013-08-14 14:17:44 +02:00
2017-04-27 03:55:38 -07:00
QList < TVar * > vars = varOrder ( var ) ;
2018-01-26 04:07:28 +01:00
QString variableChangeCode = vars [ 0 ] - > getName ( ) ;
2017-04-27 03:55:38 -07:00
for ( int i = 1 ; i < vars . size ( ) ; i + + ) {
2017-06-26 16:46:54 +02:00
if ( vars [ i ] - > isReference ( ) ) {
2017-04-27 03:55:38 -07:00
return setCValue ( vars ) ;
2017-06-26 16:46:54 +02:00
}
2017-04-27 03:55:38 -07:00
if ( vars [ i ] - > getKeyType ( ) = = LUA_TNUMBER ) {
2021-12-07 06:21:39 +01:00
variableChangeCode . append ( qsl ( " [%1] " ) . arg ( vars . at ( i ) - > getName ( ) ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2021-12-07 06:21:39 +01:00
variableChangeCode . append ( qsl ( R " ([ " % 1 " ]) " ) . arg ( vars . at ( i ) - > getName ( ) ) ) ;
2013-08-14 14:17:44 +02:00
}
}
2017-04-27 03:55:38 -07:00
switch ( var - > getValueType ( ) ) {
2013-08-14 14:17:44 +02:00
case LUA_TSTRING :
2021-12-07 06:21:39 +01:00
variableChangeCode . append ( qsl ( " = [[%1]] " ) . arg ( var - > getValue ( ) ) ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TNUMBER :
2021-12-07 06:21:39 +01:00
variableChangeCode . append ( qsl ( " = %1 " ) . arg ( var - > getValue ( ) ) ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TBOOLEAN :
2021-12-07 06:21:39 +01:00
variableChangeCode . append ( qsl ( " = %1 " ) . arg ( var - > getValue ( ) ) ) ;
2013-08-14 14:17:44 +02:00
break ;
case LUA_TTABLE :
2018-01-26 04:07:28 +01:00
variableChangeCode . append ( QLatin1String ( " = {} " ) ) ;
2013-08-14 14:17:44 +02:00
break ;
default :
return false ;
}
2023-02-20 21:46:15 +00:00
int error = luaL_loadstring ( mL , variableChangeCode . toUtf8 ( ) . constData ( ) ) ;
2020-06-01 17:35:35 +01:00
if ( error ) {
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::setValue(...) WARNING - Internal Lua (parsing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" " < < variableChangeCode < < " \" . " ;
return false ;
}
2023-02-20 21:46:15 +00:00
error = lua_pcall ( mL , 0 , LUA_MULTRET , 0 ) ;
2017-04-27 03:55:38 -07:00
if ( error ) {
2020-06-01 17:35:35 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::setValue(...) WARNING - Internal Lua (executing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" " < < variableChangeCode < < " \" . " ;
2013-08-14 14:17:44 +02:00
return false ;
}
return true ;
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : deleteVar ( TVar * var )
{
QList < TVar * > vars = varOrder ( var ) ;
2013-08-14 14:17:44 +02:00
QString oldName = vars [ 0 ] - > getName ( ) ;
2017-04-27 03:55:38 -07:00
for ( int i = 1 ; i < vars . size ( ) ; i + + ) {
if ( vars [ i ] - > getKeyType ( ) = = LUA_TNUMBER ) {
2021-12-07 06:21:39 +01:00
oldName . append ( qsl ( " [%1] " ) . arg ( vars [ i ] - > getName ( ) ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2021-12-07 06:21:39 +01:00
oldName . append ( qsl ( R " ([ " % 1 " ]) " ) . arg ( vars [ i ] - > getName ( ) ) ) ;
2013-08-14 14:17:44 +02:00
}
}
//delete it
2021-12-07 06:21:39 +01:00
oldName . append ( qsl ( " = nil " ) ) ;
2023-02-20 21:46:15 +00:00
int error = luaL_loadstring ( mL , oldName . toUtf8 ( ) . constData ( ) ) ;
2020-06-01 17:35:35 +01:00
if ( error ) {
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::deleteVar(...) WARNING - Internal Lua (parsing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" " < < oldName < < " \" . " ;
return ;
}
2023-02-20 21:46:15 +00:00
error = lua_pcall ( mL , 0 , LUA_MULTRET , 0 ) ;
2017-04-27 03:55:38 -07:00
if ( error ) {
2020-06-01 17:35:35 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::deleteVar(...) WARNING - Internal Lua (executing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" " < < oldName < < " \" . " ;
2013-08-14 14:17:44 +02:00
}
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : renameCVar ( QList < TVar * > vars )
{
2013-08-14 14:17:44 +02:00
//uses C Api to rename a variable.
//dangerous function since you can get an api panic
//and trash the stack
2021-04-17 14:48:23 -04:00
2017-04-27 03:55:38 -07:00
TVar * var = vars . back ( ) ;
2013-08-14 14:17:44 +02:00
//make the new stack
2023-02-20 21:46:15 +00:00
lua_getglobal ( mL , ( vars [ 0 ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
if ( setjmp ( buf ) = = 0 ) {
int i = 1 ;
int pushCount = 0 ;
2013-08-14 14:17:44 +02:00
int kType ;
2017-04-27 03:55:38 -07:00
for ( ; i < vars . size ( ) - 1 ; i + + ) {
2013-08-14 14:17:44 +02:00
kType = vars [ i ] - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , QString ( vars [ i ] - > getName ( ) ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , vars [ i ] - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( vars [ i ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
}
2023-02-20 21:46:15 +00:00
lua_gettable ( mL , - 2 ) ;
if ( lua_isnil ( mL , - 1 ) ) {
2013-08-14 14:17:44 +02:00
//value didn't exist, make it
2023-02-20 21:46:15 +00:00
lua_pop ( mL , - 1 ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , QString ( vars [ i ] - > getName ( ) ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE | | kType = = LUA_TFUNCTION ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , vars [ i ] - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( vars [ i ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
}
2023-02-20 21:46:15 +00:00
lua_newtable ( mL ) ;
lua_settable ( mL , - 3 ) ;
2017-04-27 03:55:38 -07:00
i - - ; //decrement since we want to reput this table on the stack on next iteration
2013-08-14 14:17:44 +02:00
}
}
kType = var - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getNewName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , var - > getNewName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameCVar() - Unsupported key type: " < < lua_typename ( mL , kType ) < < " for variable \" " < < var - > getName ( )
< < " \" . Expected string, number, or table. " ;
2013-08-14 14:17:44 +02:00
return ;
}
//put the old value on the stack
2023-02-20 21:46:15 +00:00
lua_getglobal ( mL , ( vars [ 0 ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
i = 1 ;
for ( ; i < vars . size ( ) - 1 ; i + + ) {
2013-08-14 14:17:44 +02:00
kType = vars [ i ] - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , QString ( vars [ i ] - > getName ( ) ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE | | kType = = LUA_TFUNCTION ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , vars [ i ] - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( vars [ i ] - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
}
2023-02-20 21:46:15 +00:00
lua_gettable ( mL , - 2 ) ;
2013-08-14 14:17:44 +02:00
pushCount + + ;
}
kType = var - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE | | kType = = LUA_TFUNCTION ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameCVar() - Unsupported key type when retrieving old value: " < < lua_typename ( mL , kType ) < < " for variable \" " < < var - > getName ( )
< < " \" . Expected string, number, table, or function. " ;
2013-08-14 14:17:44 +02:00
return ;
}
2023-02-20 21:46:15 +00:00
lua_gettable ( mL , - 2 ) ;
2013-08-14 14:17:44 +02:00
pushCount + + ;
//old value is @ -1 now
//we want to put our new named key @ -2
kType = var - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getNewName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , var - > getNewName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameCVar() - Unsupported key type when setting new key: " < < lua_typename ( mL , kType ) < < " for variable \" " < < var - > getName ( )
< < " \" . Expected string, number, or table. " ;
2013-08-14 14:17:44 +02:00
return ;
}
pushCount + + ;
2023-02-20 21:46:15 +00:00
lua_insert ( mL , - 2 ) ;
lua_settable ( mL , - 3 - pushCount ) ;
2013-08-14 14:17:44 +02:00
//key & value popped
//delete it, so we put the old key back on the stack and set to nil
kType = var - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE | | kType = = LUA_TFUNCTION ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameCVar() - Unsupported key type when deleting old key: " < < lua_typename ( mL , kType ) < < " for variable \" " < < var - > getName ( )
< < " \" . Expected string, number, table, or function. " ;
2013-08-14 14:17:44 +02:00
return ;
}
2023-02-20 21:46:15 +00:00
lua_pushnil ( mL ) ;
lua_settable ( mL , - 3 ) ;
2013-08-14 14:17:44 +02:00
var - > clearNewName ( ) ;
}
}
2017-04-27 03:55:38 -07:00
bool LuaInterface : : loadVar ( TVar * var )
{
2013-08-14 14:17:44 +02:00
//puts the value of a variable on the -1 position of the stack
2017-04-27 03:55:38 -07:00
if ( setjmp ( buf ) = = 0 ) {
2023-05-14 15:06:15 +02:00
const int kType = var - > getKeyType ( ) ;
const int vType = var - > getValueType ( ) ;
2017-04-27 03:55:38 -07:00
if ( vType = = LUA_TTABLE ) {
if ( kType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , QString ( var - > getName ( ) ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE ) {
2023-02-20 21:46:15 +00:00
lua_rawgeti ( mL , LUA_REGISTRYINDEX , var - > getName ( ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2013-08-14 14:17:44 +02:00
}
2023-02-20 21:46:15 +00:00
if ( lua_istable ( mL , - 2 ) ) {
lua_gettable ( mL , - 2 ) ;
2013-08-14 14:17:44 +02:00
return true ;
2017-04-27 03:55:38 -07:00
} else {
2023-02-20 21:46:15 +00:00
lua_pop ( mL , 1 ) ;
2013-08-14 14:17:44 +02:00
return false ;
}
2017-04-27 03:55:38 -07:00
} else if ( vType = = LUA_TNUMBER ) {
2023-02-20 21:46:15 +00:00
lua_pushnumber ( mL , QString ( var - > getValue ( ) ) . toInt ( ) ) ;
2017-04-27 03:55:38 -07:00
} else if ( vType = = LUA_TBOOLEAN ) {
2023-02-20 21:46:15 +00:00
lua_pushboolean ( mL , var - > getValue ( ) . toLower ( ) = = " true " ? 1 : 0 ) ;
2017-04-27 03:55:38 -07:00
} else if ( vType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
lua_pushstring ( mL , QString ( var - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2013-08-14 14:17:44 +02:00
return false ;
2017-04-27 03:55:38 -07:00
}
} else {
2026-01-03 16:00:41 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::loadVar() - Lua panic occurred while loading variable \" " < < var - > getName ( ) < < " \" with key type " < < lua_typename ( mL , var - > getKeyType ( ) )
< < " and value type " < < lua_typename ( mL , var - > getValueType ( ) ) < < " . " ;
2013-08-14 14:17:44 +02:00
return false ;
}
2013-08-19 12:25:26 +02:00
return true ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : renameVar ( TVar * var )
{
2013-08-14 14:17:44 +02:00
//this assumes anything like reparenting has been done
2021-04-17 14:48:23 -04:00
2017-04-27 03:55:38 -07:00
QList < TVar * > vars = varOrder ( var ) ;
2018-09-22 08:49:52 +02:00
QString oldVariable = vars . at ( 0 ) - > getName ( ) ;
2013-08-14 14:17:44 +02:00
QString newName ;
2017-06-26 16:46:54 +02:00
if ( vars . size ( ) > 1 ) {
2013-08-14 14:17:44 +02:00
newName = vars [ 0 ] - > getName ( ) ;
2017-06-26 16:46:54 +02:00
}
2020-06-01 17:35:35 +01:00
2017-04-27 03:55:38 -07:00
for ( int i = 1 ; i < vars . size ( ) ; i + + ) {
2023-05-14 15:06:15 +02:00
const int kType = vars [ i ] - > getKeyType ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TNUMBER ) {
2021-12-07 06:21:39 +01:00
oldVariable . append ( qsl ( " [%1] " ) . arg ( vars . at ( i ) - > getName ( ) ) ) ;
2017-06-26 16:46:54 +02:00
if ( i < vars . size ( ) - 1 ) {
2021-12-07 06:21:39 +01:00
newName . append ( qsl ( " [%1] " ) . arg ( vars [ i ] - > getName ( ) ) ) ;
2017-06-26 16:46:54 +02:00
}
2020-06-01 17:35:35 +01:00
2017-04-27 03:55:38 -07:00
} else if ( kType = = LUA_TTABLE ) {
2013-08-14 14:17:44 +02:00
renameCVar ( vars ) ;
return ;
2020-06-01 17:35:35 +01:00
}
// That leaves LUA_TSTRING:
2021-12-07 06:21:39 +01:00
oldVariable . append ( qsl ( R " ([ " % 1 " ]) " ) . arg ( vars . at ( i ) - > getName ( ) ) ) ;
2020-06-01 17:35:35 +01:00
if ( i < vars . size ( ) - 1 ) {
2021-12-07 06:21:39 +01:00
newName . append ( qsl ( R " ([ " % 1 " ]) " ) . arg ( vars . at ( i ) - > getName ( ) ) ) ;
2013-08-14 14:17:44 +02:00
}
}
2018-09-22 08:49:52 +02:00
if ( vars . size ( ) < = 1 ) {
// this variable is at root level on _G
2021-12-07 06:21:39 +01:00
newName . append ( qsl ( " _G[ \" %1 \" ] " ) . arg ( vars . last ( ) - > getNewName ( ) ) ) ;
2017-04-27 03:55:38 -07:00
} else {
2018-09-22 08:49:52 +02:00
// this variable is nested in a table
if ( var - > getNewKeyType ( ) = = LUA_TNUMBER ) {
2021-12-07 06:21:39 +01:00
newName . append ( qsl ( " [%1] " ) . arg ( vars . last ( ) - > getNewName ( ) ) ) ;
2018-09-22 08:49:52 +02:00
} else {
2021-12-07 06:21:39 +01:00
newName . append ( qsl ( R " ([ " % 1 " ]) " ) . arg ( vars . last ( ) - > getNewName ( ) ) ) ;
2018-09-22 08:49:52 +02:00
}
2017-04-27 03:55:38 -07:00
}
2018-09-22 08:49:52 +02:00
2021-12-07 06:21:39 +01:00
auto renameCode = qsl ( " %1 = %2 " ) . arg ( newName , oldVariable ) ;
2023-02-20 21:46:15 +00:00
int error = luaL_loadstring ( mL , renameCode . toUtf8 ( ) . constData ( ) ) ;
2020-06-01 17:35:35 +01:00
if ( error ) {
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameVar(...) WARNING - In copying (first) stage, internal Lua (parsing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" " < < renameCode
< < " \" . " ;
var - > clearNewName ( ) ;
return ;
}
2023-02-20 21:46:15 +00:00
error = lua_pcall ( mL , 0 , LUA_MULTRET , 0 ) ;
2017-04-27 03:55:38 -07:00
if ( error ) {
2020-06-01 17:35:35 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameVar(...) WARNING - In copying (first) stage, internal Lua (executing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" "
< < renameCode < < " \" . " ;
2013-08-14 14:17:44 +02:00
var - > clearNewName ( ) ;
return ;
}
2020-06-01 17:35:35 +01:00
2013-08-14 14:17:44 +02:00
//delete it
2023-02-20 21:46:15 +00:00
error = luaL_loadstring ( mL , oldVariable . append ( QLatin1String ( " = nil " ) ) . toUtf8 ( ) . constData ( ) ) ;
2020-06-01 17:35:35 +01:00
if ( error ) {
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameVar(...) WARNING - In deleting (second) stage, internal Lua (parsing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" "
< < renameCode < < " \" . " ;
var - > clearNewName ( ) ;
return ;
}
2023-02-20 21:46:15 +00:00
error = lua_pcall ( mL , 0 , LUA_MULTRET , 0 ) ;
2017-04-27 03:55:38 -07:00
if ( error ) {
2020-06-01 17:35:35 +01:00
qWarning ( ) . noquote ( ) . nospace ( ) < < " LuaInterface::renameVar(...) WARNING - In deleting (second) stage, internal Lua (executing) error: \" " < < lua_tostring ( mL , - 1 ) < < " \" in code: \n \" "
< < renameCode < < " \" . " ;
2013-08-14 14:17:44 +02:00
}
var - > clearNewName ( ) ;
}
2023-02-27 08:15:54 +01:00
// returns the value for a string/number/boolean datatype, or an empty string otherwise
2017-04-27 03:55:38 -07:00
QString LuaInterface : : getValue ( TVar * var )
{
if ( setjmp ( buf ) = = 0 ) {
2023-05-14 15:06:15 +02:00
QList < TVar * > const vars = varOrder ( var ) ;
2017-06-26 16:46:54 +02:00
if ( vars . empty ( ) ) {
2023-02-27 08:15:54 +01:00
return { } ;
2017-06-26 16:46:54 +02:00
}
2023-05-14 15:06:15 +02:00
const int pCount = vars . size ( ) ; //how many things we need to pop from the stack at the end
2013-08-14 14:17:44 +02:00
//load from _G first
2023-02-27 08:15:54 +01:00
auto firstVariable = vars . constFirst ( ) ;
if ( firstVariable - > getKeyType ( ) = = LUA_TSTRING ) {
lua_getglobal ( mL , ( firstVariable - > getName ( ) ) . toUtf8 ( ) . constData ( ) ) ;
} else if ( firstVariable - > getKeyType ( ) = = LUA_TNUMBER ) {
lua_rawgeti ( mL , LUA_GLOBALSINDEX , firstVariable - > getName ( ) . toInt ( ) ) ;
}
if ( lua_isnoneornil ( mL , lua_gettop ( mL ) ) ) {
2023-05-14 15:06:15 +02:00
qDebug ( ) < < " LuaInterface::getValue: Couldn't put root value " < < firstVariable - > getName ( ) < < " onto the Lua stack in order to get value of " < < var - > getName ( )
2023-02-27 08:15:54 +01:00
< < " , perhaps the key type isn't supported? " ;
return { } ;
}
2017-04-27 03:55:38 -07:00
for ( int i = 1 ; i < vars . size ( ) ; i + + ) {
2023-02-27 08:15:54 +01:00
if ( ! loadValue ( mL , vars . at ( i ) , - 2 ) ) {
return { } ;
2017-06-26 16:46:54 +02:00
}
2013-08-14 14:17:44 +02:00
}
2023-05-14 15:06:15 +02:00
const int valueType = lua_type ( mL , - 1 ) ;
2018-01-26 04:07:28 +01:00
QString value ;
2023-02-27 08:15:54 +01:00
if ( valueType = = LUA_TBOOLEAN ) {
2023-02-20 21:46:15 +00:00
value = lua_toboolean ( mL , - 1 ) = = 0 ? QLatin1String ( " false " ) : QLatin1String ( " true " ) ;
2023-02-27 08:15:54 +01:00
} else if ( valueType = = LUA_TNUMBER | | valueType = = LUA_TSTRING ) {
2023-02-20 21:46:15 +00:00
value = lua_tostring ( mL , - 1 ) ;
2017-06-26 16:46:54 +02:00
}
2023-02-20 21:46:15 +00:00
lua_pop ( mL , pCount ) ;
2013-08-14 14:17:44 +02:00
return value ;
}
2023-02-27 08:15:54 +01:00
return { } ;
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : iterateTable ( lua_State * L , int index , TVar * tVar , bool hide )
{
2013-08-14 14:17:44 +02:00
depth + + ;
2017-04-27 03:55:38 -07:00
while ( lua_next ( L , index ) ) {
2023-05-14 15:06:15 +02:00
const int vType = lua_type ( L , - 1 ) ;
const int kType = lua_type ( L , - 2 ) ;
2017-04-27 03:55:38 -07:00
lua_pushvalue ( L , - 2 ) ; //we do this because extracting the key with tostring changes it
2013-08-14 14:17:44 +02:00
QString keyName ;
QString valueName ;
2017-04-09 19:49:02 +02:00
auto var = new TVar ( ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TTABLE ) {
keyName = QString : : number ( luaL_ref ( L , LUA_REGISTRYINDEX ) ) ; //this function pops the top item
2013-08-14 14:17:44 +02:00
lrefs . append ( keyName . toInt ( ) ) ;
var - > setReference ( true ) ;
2017-04-27 03:55:38 -07:00
} else {
2020-10-11 13:26:59 +02:00
keyName = lua_tostring ( L , - 1 ) ;
2017-04-27 03:55:38 -07:00
if ( kType = = LUA_TFUNCTION & & keyName . isEmpty ( ) ) {
2013-08-14 14:17:44 +02:00
//we lost the reference
keyName = QString : : number ( luaL_ref ( L , LUA_REGISTRYINDEX ) ) ;
lrefs . append ( keyName . toInt ( ) ) ;
var - > setReference ( true ) ;
2017-04-27 03:55:38 -07:00
} else {
2013-08-14 14:17:44 +02:00
lua_pop ( L , 1 ) ;
2017-04-27 03:55:38 -07:00
}
2013-08-14 14:17:44 +02:00
}
2017-04-27 03:55:38 -07:00
if ( keyName = = " package " & & depth = = 1 ) { //don't load in the 'package' table
2013-08-14 14:17:44 +02:00
lua_pop ( L , 1 ) ;
tVar - > removeChild ( var ) ;
delete var ;
continue ;
}
var - > setName ( keyName , kType ) ;
var - > setValueType ( vType ) ;
var - > setParent ( tVar ) ;
var - > hidden = hide ;
tVar - > addChild ( var ) ;
2023-05-11 07:44:16 +02:00
const void * pKey = lua_topointer ( L , - 1 ) ;
var - > pKey = pKey ;
const void * pValue = lua_topointer ( L , - 2 ) ;
var - > pValue = pValue ;
2023-04-15 06:38:39 +02:00
if ( varUnit - > varExists ( var ) | | keyName = = qsl ( " _G " ) ) {
2013-08-14 14:17:44 +02:00
lua_pop ( L , 1 ) ;
tVar - > removeChild ( var ) ;
delete var ;
continue ;
}
varUnit - > addVariable ( var ) ;
2023-05-11 07:44:16 +02:00
varUnit - > addPointer ( pKey ) ;
2013-08-14 14:17:44 +02:00
2023-05-11 07:44:16 +02:00
varUnit - > addPointer ( pValue ) ;
2017-04-27 03:55:38 -07:00
if ( vType = = LUA_TTABLE ) {
if ( depth < = 99 & & lua_checkstack ( L , 3 ) ) { //depth is historical now
2013-08-14 14:17:44 +02:00
//put the table on top
lua_pushnil ( L ) ;
var - > setValue ( " {} " , LUA_TTABLE ) ;
iterateTable ( L , - 2 , var , hide ) ;
depth - - ;
}
2017-04-27 03:55:38 -07:00
} else if ( vType = = LUA_TSTRING | | vType = = LUA_TNUMBER ) {
lua_pushvalue ( L , - 1 ) ;
2020-10-11 13:26:59 +02:00
valueName = lua_tostring ( L , - 1 ) ;
2013-08-14 14:17:44 +02:00
var - > setValue ( valueName ) ;
2017-04-27 03:55:38 -07:00
lua_pop ( L , 1 ) ;
} else if ( vType = = LUA_TBOOLEAN ) {
2013-08-14 14:17:44 +02:00
valueName = lua_toboolean ( L , - 1 ) = = 0 ? " false " : " true " ;
var - > setValue ( valueName ) ;
2017-04-27 03:55:38 -07:00
} else if ( vType = = LUA_TFUNCTION
& & ( ! keyName . toLower ( ) . startsWith ( " alias " ) & & ! keyName . toLower ( ) . startsWith ( " trigger " ) & & ! keyName . toLower ( ) . startsWith ( " action " ) & & ! keyName . toLower ( ) . startsWith ( " timer " )
& & ! keyName . toLower ( ) . startsWith ( " key " ) ) ) {
2013-08-14 14:17:44 +02:00
//functions are compiled to bytecode so there is no reference
var - > setValue ( " function " ) ;
2017-04-27 03:55:38 -07:00
} else {
2013-08-14 14:17:44 +02:00
tVar - > removeChild ( var ) ;
varUnit - > removeVariable ( var ) ;
delete var ;
}
lua_pop ( L , 1 ) ;
}
}
2017-04-27 03:55:38 -07:00
void LuaInterface : : getVars ( bool hide )
{
2013-08-14 14:17:44 +02:00
//returns the base item
2020-11-26 20:54:01 +00:00
// QElapsedTimer t;
// t.start();
2023-02-20 21:46:15 +00:00
lua_pushnil ( mL ) ;
2013-08-14 14:17:44 +02:00
depth = 0 ;
2023-05-11 07:44:16 +02:00
auto global = new TVar ( ) ;
global - > setName ( " _G " , LUA_TSTRING ) ;
global - > setValue ( " {} " , LUA_TTABLE ) ;
2013-08-14 14:17:44 +02:00
QListIterator < int > it ( lrefs ) ;
2017-04-27 03:55:38 -07:00
while ( it . hasNext ( ) ) {
2023-05-14 15:06:15 +02:00
const int ref = it . next ( ) ;
2023-02-20 21:46:15 +00:00
luaL_unref ( mL , LUA_REGISTRYINDEX , ref ) ;
2013-08-14 14:17:44 +02:00
}
2025-10-21 21:00:25 +01:00
lrefs . clear ( ) ;
2013-08-14 14:17:44 +02:00
varUnit - > clear ( ) ;
2023-05-11 07:44:16 +02:00
varUnit - > setBase ( global ) ;
varUnit - > addVariable ( global ) ;
iterateTable ( mL , LUA_GLOBALSINDEX , global , hide ) ;
2020-11-26 20:54:01 +00:00
// FIXME: possible to keep and report? qDebug()<<"took"<<t.elapsed()<<"to get variables in";
2013-08-14 14:17:44 +02:00
}