I am new to Lua, and I am building a custom dissector for Wireshark. My situation is this:
The wireshark data consists of hex numbers such as 4321 8765 CBA9. What I would like to wind up with is (after it has been dissected) : CBA9 8765 4321.
What I have done so far is create a small function in Lua that will take these numbers individually, convert them to strings, and places them in the correct order.
function ReverseOrder3Numbers(hex_1, hex_2, hex_3)
local hex_1_int = hex_1:uint()
local hex_2_int = hex_2:uint()
local hex_3_int = hex_3:uint()
word1 = string.format("%04X", hex_1_int)
word2 = string.format("%04X", hex_2_int)
word3 = string.format("%04X", hex_3_int)
combined_string = "0x" .. word3 .. word2 .. word1
output = combined_string
return output
end
However, once I go to add this bunch to the tree, I get an error saying Lua Error: ...: calling 'add' on bad self (userdata expected, got string).
How can I get around this? Do I need a different approach entirely? I am not looking for anything complex or fancy. All I need to do is what I described. Any help would be appreciated.
There's nothing really wrong with ReverseOrder3Numbers (other than perhaps some missing local qualifiers). You should update your question to include the code that invokes add.
You might've accidentally used tree.add( ... ) instead of tree:add( ... ) (note the colon after tree).
Call tree:add() will send to the object 'tree' the direct link to 'tree' itself as first implicitly argument. And no matter how much args you will attach to this call or no one at all. Use tree.add() sintax if your 'add' method doesn't support self-link. In this case 'self' should be linked to the 'tree' object inside the 'add' method.
It's not clear what you pass to the function ReverseOrder3Numbers. But since you access theses parameeters with the uint method I assume that the parameters are tvb:range(x,y) results. If you want to change the order of the digits inside the individual values, you can use the endianess-aware methods:
function ReverseOrder3Numbers(hex_1, hex_2, hex_3)
local hex_1_int = hex_1:le_uint()
local hex_2_int = hex_2:le_uint()
local hex_3_int = hex_3:le_uint()
...
end
If you want to change the endianess of data that is added to the tree you should use the endianess-aware version of the add method.
tree:le_add(f_MyProtoField, tvb:range(x,y), ReverseOrder3Numbers(...))
I don't know the reason why le is suffix in the one case and a prefix in the other.
Related
i'm trying to do something like that:
get_num_of_ones = "('1'):rep(%d)"
print(get_num_of_ones:format(24))
but i get the following result: ('1'):rep(24) and not 24 times the number 1.
how can I do it in this way so that i will get 111...11 (24 times the number 1) ?
The simplest, most straightforward, efficient and readable way to achieve what you want is simply to pass your number directly to string.rep; there is no need to format source code here:
get_num_of_ones = ('1'):rep(24)
print(get_num_of_ones)
If there is the artificial constraint that it needs to be achieved by formatting a source code template, you need to use load/loadstring:
get_num_of_ones = "return ('1'):rep(%d)" -- you need the "return" to make it a valid chunk, and to be able to get the result out
local source = get_num_of_ones:format(24) -- formatted source code
local chunk = assert(load(source)) -- load the source code; gives us a "chunk" (function) if there was no syntax error
local retval = chunk()
print(retval)
I am fairly new to Puppet and Ruby. Most likely this question has been asked before but I am not able to find any relevant information.
In my puppet code I will have a string variable retrieved from the fact hostname.
$n="$facts['hostname'].ex-ample.com"
I am expecting to get the values like these
DEV-123456-02B.ex-ample.com,
SCC-123456-02A.ex-ample.com,
DEV-123456-03B.ex-ample.com,
SCC-999999-04A.ex-ample.com
I want to perform the following action. Change the string to lowercase and then replace the
-02, -03 or -04 to -01.
So my output would be like
dev-123456-01b.ex-ample.com,
scc-123456-01a.ex-ample.com,
dev-123456-01b.ex-ample.com,
scc-999999-01a.ex-ample.com
I figured I would need to use .downcase on $n to make everything lowercase. But I am not sure how to replace the digits. I was thinking of .gsub or split but not sure how. I would prefer to make this happen in a oneline code.
If you really want a one-liner, you could run this against each string:
str
.downcase
.split('-')
.map
.with_index { |substr, i| i == 2 ? substr.gsub(/0[0-9]/, '01') : substr }
.join('-')
Without knowing what format your input list is taking, I'm not sure how to advise on how to iterate through it, but maybe you have that covered already. Hope it helps.
Note that Puppet and Ruby are entirely different languages and the other answers are for Ruby and won't work in Puppet.
What you need is:
$h = downcase(regsubst($facts['hostname'], '..(.)$', '01\1'))
$n = "${h}.ex-ample.com"
notice($n)
Note:
The downcase and regsubst functions come from stdlib.
I do a regex search and replace using the regsubst function and replace ..(.)$ - 2 characters followed by another one that I capture at the end of the string and replace that with 01 and the captured string.
All of that is then downcased.
If the -01--04 part is always on the same string index you could use that to replace the content.
original = 'DEV-123456-02B.ex-ample.com'
# 11 -^
string = original.downcase # creates a new downcased string
string[11, 2] = '01' # replace from index 11, 2 characters
string #=> "dev-123456-01b.ex-ample.com"
I was trying to convert a match object to a string in perl6. The method Str on a match object is defined as:
method Str(Match:D: --> Str:D)
I would think I could use Str($match) to accomplish this. And it seems to convert it to a string, but I'm getting an error using the string with the following code:
my $searchme = "rudolph";
my $match = $searchme ~~ /.*dol.*/;
say $match.WHAT;
my $test1 = Str($match);
say $test1.WHAT;
say $test1;
With the output:
(Match)
(Str)
With the error:
Cannot find method 'gist': no method cache and no .^find_method in
block at .code.tio line 6
However, if I run:
my $searchme = "rudolph";
my $match = $searchme ~~ /.*dol.*/;
say $match.WHAT;
my $test1 = $match.Str;
say $test1.WHAT;
say $test1;
I get no error and the result:
(Match)
(Str)
rudolph
Is this a bug or me misunderstanding how it works?
Thanks for reading.
I'm writing this up as an answer even though it's actually an incomplete discussion of a bug, so not at all normal SO fare. The alternative of lots of comments doesn't seem better.
It's a bug. Perhaps you just golfed this.
dd $test1; instead of say $test1; is helpful in that it displays BOOTStr $test1 = (BOOTStr without .perl method).
Based on that I searched the rakudo repo for BOOTStr and that led to the above issue.
Golfing it further leads to:
say $ = Str(Match.new);
Note that these are all fine:
say Str(Match.new);
say $ = Int(Match.new);
say $ = Str(Date.new: '2015-12-31');
It appears to be a combination of leaking some implementation details regarding how Rakudo/NQP/MoarVM bootstrap; Match being an NQP object; Str() on that being wonky; and assigning it to a Scalar container (the $ is an anonymous one) making that wonkiness visible.
I'll add more when/if I figure it out.
I am doing 2player game and when I get informations from server, it's in format "topic;arg1;arg2" so if I am sending positions it's "PlayerPos;x;y".
I then use split method with character ";".
But then... I even tried to write it on screen "PlayerPos" was written right, but it cannot be gained through if.
This is how I send info on server:
server.write("PlayerPos;"+player1.x+";"+player1.y);
And how I accept it on client:
String Get=client.readString();
String [] Getted = split(Get, ';');
fill(0);
text(Get,20,20);
text(Getted[0],20,40);
if(Getted[0]=="PlayerPos"){
text("HERE",20,100);
player1.x=parseInt(Getted[1]);
player1.x=parseInt(Getted[2]);
}
It writes me "PlayerPos;200;200" on screen, even "PlayerPos" under it. But it never writes "HERE" and it never makes it into the if.
Where is my mistake?
Don't use == when comparing String values. Use the equals() function instead:
if(Getted[0].equals("PlayerPos")){
From the Processing reference:
To compare the contents of two Strings, use the equals() method, as in if (a.equals(b)), instead of if (a == b). A String is an Object, so comparing them with the == operator only compares whether both Strings are stored in the same memory location. Using the equals() method will ensure that the actual contents are compared. (The troubleshooting reference has a longer explanation.)
I am currently attempting to parse data that is sent from an outside source serially. An example is as such:
DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_
This data can come in many different lengths, but the first few pieces are all the same. Each "piece" originally comes in with CRLF after, so I've replaced them with string.gsub(input,"\r\n","|") so that is why my input looks the way it does.
The part I would like to parse is:
4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_
The "4" tells me that there will be four lines total to create this file. I'm using this as a means to set the amount of passes in the loop.
The 7x5 is the font height.
The 1 is the xpos.
The 25 is the ypos.
The variable data (172-24 in this case) is the text at these parameters.
As you can see, it should continue to loop this pattern throughout the input string received. Now the "4" can actually be any variable > 0; with each number equaling a set of four variables to capture.
Here is what I have so far. Please excuse the loop variable, start variable, and print commands. I'm using Linux to run this function to try to troubleshoot.
function loop_input(input)
var = tonumber(string.match(val, "DATA|0|(%d*).*"))
loop = string.match(val, "DATA|0|")
start = string.match(val, loop.."(%d*)|.*")
for obj = 1, var do
for i = 1, 4 do
if i == 1 then
i = "font" -- want the first group to be set to font
elseif i == 2 then
i = "xpos" -- want the second group to be set to xpos
elseif i == 3 then
i = "ypos" -- want the third group to be set to ypos
else
i = "txt" -- want the fourth group to be set to text
end
obj = font..xpos..ypos..txt
--print (i)
end
objects = objects..obj -- concatenate newly created obj variables with each pass
end
end
val = "DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_"
print(loop_input(val))
Ideally, I want to create a loop that, depending on the var variable, will plug in the captured variables between the pipe deliminators and then I can use them freely as I wish. When trying to troubleshoot with parenthesis around my four variables (like I have above), I receive the full list of four variables four times in a row. Now I'm having difficulty actually cycling through the input string and actually grabbing them out as the loop moves down the data string. I was thinking that using the pipes as a means to delineate variables from one another would help. Am I wrong? If it doesn't matter and I can keep the [/r/n]+ instead of each "|" then I am definitely all for that.
I've searched around and found some threads that I thought would help but I'm not sure if tables or splitting the inputs would be advisable. Like these threads:
Setting a variable in a for loop (with temporary variable) Lua
How do I make a dynamic variable name in Lua?
Most efficient way to parse a file in Lua
I'm fairly new to programming and trying to teach myself. So please excuse my beginner thread. I have both the "Lua Reference Manual" and "Programming in Lua" books in paperback which is how I've tried to mock my function(s) off of. But I'm having a problem making the connection.
I thank you all for any input or guidance you can offer!
Cheers.
Try this:
val = "DATA|0|4|7x5|1|25|174-24|7x5|1|17|TERW|7x5|1|9|08MN|7x5|1|1|_"
val = val .. "|"
data = val:match("DATA|0|%d+|(.*)$")
for fh,xpos,ypos,text in data:gmatch("(.-)|(.-)|(.-)|(.-)|") do
print(fh,xpos,ypos,text)
end