Lua: Proper Scoping with Buffer Manipulation - lua

I'm trying to create a buffer that is built with an input. This buffer would then send the captured strings to another function in the file that would manipulate the strings and utilize it later in other function(s). The first capture is parsed as expected and is fine. I'm having an issue clearing the buffer for new string captures when new data is received. Instead, it is adding the new strings onto the original ones, leaving me unable to properly manipulate it. Here is an example of what I'm trying to do:
local buffer = ""
function action(input)
buffer = buffer..input
parse_data(buffer)
end
function parse_data(data)
obj = ""
obj_var = buffer:match("(%d).*")
if obj_var == 1 then
obj = do_some_function()
else
obj = do_some_other_function()
end
buffer = ""
end
function do_some_function()
some action
end
function do_some_other_function()
some chunk
end
I do not know where to plug a command or function to clear the file's buffer variable prior to each new send. I know that this is very very simplistic code. But I hope I conveyed what I'm trying to get done with the buffer variable. This is a plugin file that will receive the input at it's main function to build each buffer. Then depending on the input, it will report to that specific function. I've tried to place buffer = "" at the end of each function and no go. I've also tried to change the variable call in function string(buffer) to another variable but that still doesn't clear the buffer. I guess I'm more so getting confused as to the lexical scoping of the buffer and how it would be best to clear it.
Thanks for all the help.

Related

uint64 to hex in lua 5.1

Hey I am not able to make this conversion correctly. I use below code
RawGUID=17379524724484210731 --It's impossible to store variable this way, it will always convert into test3 eventually. Stored as userdata I cannot change
test1="17379524724484210731"
test2="1.7379524724484e+019"
test3=1.7379524724484e+019
function tohex(num)
local charset = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"}
local tmp = {}
repeat
table.insert(tmp,1,charset[num%16+1])
num = math.floor(num/16)
until num==0
return table.concat(tmp)
end
RawGUID is an example of what I need to convert into hex string, the rest of the variables is just conversion of the same number.
The code works well for anything that's below 64bits.
To be honest, to achieve my goal I need a string in hex to make the rest of my code work
The result I am getting: F13079A800000000
The result I want: F13079A80000002B

Lua callback function does not work with table

I am trying to change Xadow's baudrate of Uart and trying to do same thing on software PDF but everytime i get errors. I just need to know how should I write the syntax.
Here is the guide of the lua software on xadow's writer
config={}
config["bit"]=9
config["par"]=0
config["stop"]=1
config["bdr"]=9600
function uartData(uart_id,len,data)
print(data)
end
uart_id=uart.create(1,uartData(config))
uart_id = uart.create(port, cb_func [,param])
Param is an optional Lua table as described in the documentation.
You have to call:
uart_id = uart.create(1, uartData, config)
not
uart_id = uart.create(1, uartData(config))
uartData(config) would pass the return value of uartData (nil) to uart.create instead of the function variable uartData
You can simply wirte config.bit=9 instead of config["bit"]=9 btw.

In Lua, using a boolean variable from another script in the same project ends up with nill value error

This code is for a modding engine, Unitale base on Unity Written in Lua
So I am trying to use a Boolean Variable in my script poseur.lua, so when certain conditions are met so I can pass it to the other script encounter.lua, where a engine Predefined functions is being uses to make actions happens base on the occurring moment.
I tried to read the engine documentation multiple times, follow the exact syntax of Lua's fonction like GetVar(), SetVar(), SetGobal(),GetGlobal().
Searching and google thing about the Language, post on the subreddit and Game Exchange and tried to solve it by myself for hours... I just can't do it and I can't understand why ?
I will show parts of my codes for each.
poseur:
-- A basic monster script skeleton you can copy and modify for your own creations.
comments = {"Smells like the work\rof an enemy stand.",
"Nidhogg_Warrior is posing like his\rlife depends on it.",
"Nidhogg_Warrior's limbs shouldn't\rbe moving in this way."}
commands = {"GREET", "JUMP", "FLIRT", "CRINGE"}
EndDialougue = {" ! ! !","ouiii"}
sprite = "poseur" --Always PNG. Extension is added automatically.
name = "Nidhogg_Warrior"
hp = 99
atk = 1
def = 1
check = "The Nidhogg_Warrior is\rsearching for the Nidhogg"
dialogbubble = "rightlarge" -- See documentation for what bubbles you have available.
canspare = false
cancheck = true
GreetCounter = 5
Berserk = false
encounter:
-- A basic encounter script skeleton you can copy and modify for your own creations.
encountertext = "Nidhogg_Warrior is\rrunning frantically"
nextwaves = {"bullettest_chaserorb"}
wavetimer = 5.0
arenasize = {155, 130}
music = "musAncientGuardian"
enemies = {"poseur"}
require("Monsters.poseur")
enemypositions = {{0, 0}}
-- A custom list with attacks to choose from.
-- Actual selection happens in EnemyDialogueEnding().
-- Put here in case you want to use it.
possible_attacks = {"bullettest_bouncy", "bullettest_chaserorb", "bullettest_touhou"}
function EncounterStarting()
-- If you want to change the game state immediately, this is the place.
Player.lv = 20
Player.hp = 99
Player.name = "Teemies"
poseur.GetVar("Berserk")
end
Thank you for reading.
The answer to my problem was to use SetGobal(), GetGobal().
For some reasons my previous attempt to simply use SetGobal()Resulted in nil value despite writing it like that SetGobal("Berserk",true) gave me a nill value error, as soon as I launch the game.
But I still used them wrong. First I needed to put it SetGobal() at the end of the condition instead of at the start of the the poseur.lua script because the change of value... for some reasons was being overwritten by it first installment.
And to test the variable in the function in my encounter.lua, I needed to write it like that
function EnemyDialogueStarting()
-- Good location for setting monster dialogue depending on how the battle is going.
if GetGlobal("Jimmies") == true then
TEEEST()
end
end
Also any tips an suggestions are still welcome !
Well firstly, in lua simple values like bool and number are copied on assignment:
global={}
a=2
global.a=a--this is a copy
a=4--this change won't affect value in table
print(global.a)--2
print(a)--4
Secondly,
SetGobal and the other mentioned functions are not part of lua language, they must be related to your engine. Probably, they use word 'Global' not as lua 'global' but in a sense defined by engine.
Depending on the engine specifics these functions might as well do a deep copy of any variable they're given (or might as well not work with complicated objects).

How to remove non-ascii char from MQ messages with ESQL

CONCLUSION:
For some reason the flow wouldn't let me convert the incoming message to a BLOB by changing the Message Domain property of the Input Node so I added a Reset Content Descriptor node before the Compute Node with the code from the accepted answer. On the line that parses the XML and creates the XMLNSC Child for the message I was getting a 'CHARACTER:Invalid wire format received' error so I took that line out and added another Reset Content Descriptor node after the Compute Node instead. Now it parses and replaces the Unicode characters with spaces. So now it doesn't crash.
Here is the code for the added Compute Node:
CREATE FUNCTION Main() RETURNS BOOLEAN
BEGIN
DECLARE NonPrintable BLOB X'0001020304050607080B0C0E0F101112131415161718191A1B1C1D1E1F7F808182838485868788898A8B8C8D8E8F909192939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9EAEBECEDEEEFF1F2F3F4F5F6F7F8F9FAFBFCFDFEFF';
DECLARE Printable BLOB X'20202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020';
DECLARE Fixed BLOB TRANSLATE(InputRoot.BLOB.BLOB, NonPrintable, Printable);
SET OutputRoot = InputRoot;
SET OutputRoot.BLOB.BLOB = Fixed;
RETURN TRUE;
END;
UPDATE:
The message is being parsed as XML using XMLNSC. Thought that would cause a problem, but it does not appear to be.
Now I'm using PHP. I've created a node to plug into the legacy flow. Here's the relevant code:
class fixIncompetence {
function evaluate ($output_assembly,$input_assembly) {
$output_assembly->MRM = $input_assembly->MRM;
$output_assembly->MQMD = $input_assembly->MQMD;
$tmp = htmlentities($input_assembly->MRM->VALUE_TO_FIX, ENT_HTML5|ENT_SUBSTITUTE,'UTF-8');
if (!empty($tmp)) {
$output_assembly->MRM->VALUE_TO_FIX = $tmp;
}
// Ensure there are no null MRM fields. MessageBroker is strict.
foreach ($output_assembly->MRM as $key => $val) {
if (empty($val)) {
$output_assembly->MRM->$key = '';
}
}
}
}
Right now I'm getting a vague error about read only messages, but before that it wasn't working either.
Original Question:
For some reason I am unable to impress upon the senders of our MQ
messages that smart quotes, endashes, emdashes, and such crash our XML
parser.
I managed to make a working solution with SQL queries, but it wasted
too many resources. Here's the last thing I tried, but it didn't work
either:
CREATE FUNCTION CLEAN(IN STR CHAR) RETURNS CHAR BEGIN
SET STR = REPLACE('–',STR,'–');
SET STR = REPLACE('—',STR,'—');
SET STR = REPLACE('·',STR,'·');
SET STR = REPLACE('“',STR,'“');
SET STR = REPLACE('”',STR,'”');
SET STR = REPLACE('‘',STR,'&lsqo;');
SET STR = REPLACE('’',STR,'’');
SET STR = REPLACE('•',STR,'•');
SET STR = REPLACE('°',STR,'°');
RETURN STR;
END;
As you can see I'm not very good at this. I have tried reading about
various ESQL string functions without much success.
So in ESQL you can use the TRANSLATE function.
The following is a snippet I use to clean up a BLOB containing non-ASCII low hex values so that it then be cast into a usable character string.
You should be able to modify it to change your undesired characters into something more benign. Basically each hex value in NonPrintable gets translated into its positional equivalent in Printable, in this case always a full-stop i.e. x'2E' in ASCII. You'll need to make your BLOB's long enough to cover the desired range of hex values.
DECLARE NonPrintable BLOB X'000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F';
DECLARE Printable BLOB X'2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E2E';
SET WorkBlob = TRANSLATE(WorkBlob, NonPrintable, Printable);
BTW if messages with invalid characters only come in every now and then I'd probably specify BLOB on the input node and then use something similar to the following to invoke the XMLNSC parser.
CREATE LASTCHILD OF OutputRoot DOMAIN 'XMLNSC'
PARSE(InputRoot.BLOB.BLOB CCSID InputRoot.Properties.CodedCharSetId ENCODING InputRoot.Properties.Encoding);
With the exception terminal wired up you can then correct the BLOB's of any messages containing parser breaking invalid characters before attempting to reparse.
Finally my best wishes as I've had a number of battles over the years with being forced to correct invalid message content in the "Integration Layer" after all that's what it's meant to do.

Passing session between two lua files

I want to call another lua script from my main script say like
session:execute("lua","/path/somefile.lua "..somearg1.." "..somearg2..)
its working fine and somefile.lua is executing but suppose i also want to use session there i.e. i am accessing a database in somefile.lua and want to speak a query result in somefile.lua by using session. (session:speak(queryResult)).
i also tried sending session as one of argument
session:execute("lua","/path/somefile.lua "..session)
but it gives a error "attempt to concatenate global 'session' (a userdata value)"
any advise..??
code of first lua file
session:answer();
session:setAutoHangup(false);
session:set_tts_params("flite","kal");
callerId = session:getVariable("caller_id_number");
session:execute("lua ","/etc/freeswitch/scripts/checkbal.lua "..callerId.." "..session);
session:destroy();
code for 2nd lua file
callerId=argv[1];
session=argv[2];
luasql = require "luasql.postgres";
env=assert(luasql:postgres());
con=assert(env:connect("mydb","postgres","password","127.0.0.1","5432"));
cur=assert(con:execute("select balance from bal where number='"..callerId.."'"));
session:set_tts_params("flite","kal");
row=cur:fetch({},"a");
res=row.balance;
session:speak(res);
Rig your second file to be a module that returns a function or a table of functions. Here is an example that has second file return a "speak" function that you can then re-use as many times as desired:
Code of first Lua file:
session:answer()
session:setAutoHangup(false)
session:set_tts_params("flite","kal")
callerId = session:getVariable("caller_id_number")
speak = require 'checkbal'
speak(session, callerId)
-- session:execute("lua ","/etc/freeswitch/scripts/checkbal.lua "..callerId.." "..session)
session:destroy()
Code for 2nd Lua file:
luasql = require "luasql.postgres"
local env=assert(luasql:postgres())
local con=assert(env:connect("mydb","postgres","password","127.0.0.1","5432"))
local function speak(session, callerId)
local cur = assert(con:execute("select balance from bal where number='"..callerId.."'"))
session:set_tts_params("flite","kal")
row=cur:fetch({},"a")
res=row.balance
session:speak(res)
end
return speak
Note: this is Lua: no need for semicolons.
I would consider making "session" an object (table with methods) with a "speak" method, but this is going beyond scope of this question and is not necessary, may just lead to more maintainable code later.

Resources