Avoiding ASCII conversion in serial communication using luars232 - lua

I am using luars233 library for serial communication using Lua. I need to send data bytes without converting them in ASCII form, but the write function of luars232 is converting the data into ASCII before transmission even if I pass it to the function as a number(data type). Please provide possible assistance

I have worked-around the issue by using escape sequence in String datatype e.g. '\2' would pass 0x02 on to the serial port using write function of luars232. But this restricts performing mathematical operations on the data before transmission. Further suggestions are welcomed.

The library takes the data argument and coerces it to a string via luaL_checklstring using standard Lua rules. So, if you want complete control over the data, you should pass a string. A Lua string is a counted sequence of bytes.
Certainly, as you have found, a literal escaped character sequence will work.
You can also use the string.char(...) function, which takes a list of zero or more values 0-255 and creates string with those byte values.
If you have a table sequence of bytes, you can unpack them into a list:
local bytes = { 27, 76, 117, 97 }
port:write(string.char(table.unpack(bytes)))
So, yes, you do have to convert to a string. But, you can defer that until just before the write call.

Related

How to cast hex string as hex integer?

I'm using BLE plugin, which requires to present the values as list of hex number(e.g. [0x20,0x11,0x06,0x6D]).
I was able to get a list of hex strings using int.toRadixString (['0x20','0x11','0x06','0x6D']), but didn't find a way to convert those strings into hex integers.
I'm looking for something like int demicalToHex(int demical) or similar function.
Thanks in advance.
There's no such thing as a hex number. What it needs is a list of integers (List<int>).
In the same way that you have [0x20,0x11,0x06,0x6D] you could equally write that as [32, 17, 6, 109]. Sometimes, it's convenient to think about integers in their decimal representation or their hex representation (or octal, or binary...), but as far as the compiler is concerned, they are just integers.
Just use an array of integers (not strings).

Lua bit library

Right now I have made my own funcs to do bitwise and + not but then I saw the bit library and tried to use it but it doesn't work how I imagined, it returns a large decimal instead of the binary bit and so my question is actually a few.
First: how to do bitwise AND on binary number using the bit32 library.
10110111
11000100 = 10000100
Second: How to calculate the ipv4 broadcast address by adding the network address and the wildcard mask in binary form using the bit32 library
192.168.1.0 + 31 = 192.168.1.31
11000000.10100000.00000001.00000000
00000000.00000000.00000000.00011111 = 11000000.10100000.00000001.00011111
I am assuming that your bitwise and / not functions take string arguments.
Numbers can be represented in multiple ways.
The number 110101, which is in base two, has the same value as 53, which is in base 10.
When you say
x=123
Lua converts 123 into its binary representation, 1111011, which it then stores in memory as bits.
When you say
print(x)
Lua goes into memory, grabs x, which is 1111011, and then converts it into its more human-readable base 10 representation, and you see
123
The bitwise functions you wrote performs bit operations on strings which display the binary representation of a number like "1111011". the bit32 library performs bit operations on numbers, which display the decimal representation of a number like 123.
In Lua, "1001001" is a string, but if arithmatic operations are performed on it, it treats it as if it were a number written in base 10. So when you do
bit32.band("101","110")
the bit32.band function interprets its arguments as one-hundred-one and one-hundred-ten.
You must first convert your binary strings into numbers:
bit32.band(tonumber("101",2), tonumber("110",2))

Operation on Hexadecimal DELPHI

My application has to do operation on Hexadecimal values.
For example,
If the input given by user is '0010F750', then my application will tell you the user which is the nearest value (from some set of pre defined values) and will give next value by adding '0000E500'.
How we can perform Hexa Decimal operations Find nearest, Add, Subtract from DELPHI?
Performing operations on hexadecimal values does not really mean anything. Numbers are numbers. Hexadecimal is merely a representation using base 16.
All you need to do is convert these hex strings to integers and you can use standard arithmetic operations.
function HexStrToInt(const str: string): Integer;
begin
Result := StrToInt('$' + str);
end;
Add and subtract using + and -. Use IntToHex to express values as their hex representations.
Your application does not and cannot "do operation on Hexadecimal values". Rather, it operates on binary values stored in chunks of data organized as bytes.
What the USER sees and what the PROGRAM works with are two completely unrelated things.
The number one (1) in binary is 00000001, in hex is 01, in decimal is 1, and in ASCII has the hexadecimal value of 31. Try printing the value of Ord('1').
You need to convert the external representation of your data, in Hex, to an internal representation as an Integer. That's what David was pointing to earlier.
Then you'd need to apply your "rounding" to the numeric value, then convert it back to a Hex string for the user to see.
Search around for examples that let you implement a simple calculator and you'll understand better.

Can BitConverter be used to reliably extract multi-byte values from an IL byte stream (as returned by MethodBody.GetILAsByteArray)?

I am working on some code that parses IL byte arrays as returned by MethodBody.GetILAsByteArray.
Lets say I want to read a metadata token or a 32-bit integer constant from such an IL byte stream. At first I thought using BitConverter.ToInt32(byteArray, offset) would make this easy. However I'm now worried that this won't work on big-endian machines.
As far as I know, IL always uses little-endian encoding for multi-byte values:
"All argument numbers are encoded least-significant-byte-at-smallest-address (a pattern commonly termed 'little-endian')." — The Common Language Infrastructure Annotated Standard, Partition III, ch. 1.2 (p. 482).
Since BitConverter's conversion methods honour the computer architecture's endianness (which can be discovered through BitConverter.IsLittleEndian), I conclude that BitConverter should not be used to extract multi-byte values from an IL byte stream, because this would give wrong results on big-endian machines.
Is this conclusion correct?
If yes: Is there any way to tell BitConverter which endianness to use for conversions, or is there any other class in the BCL that offers this functionality, or do I have to write my own conversion code?
If no: Where am I wrong? What is the proper way of extracting e.g. a Int32 operand value from an IL byte array?
You should always do this on a little endian array before passing it:
// Array is little. Are we on big?
if (!BitConverter.IsLittleEndian)
{
// Then flip it
Array.Reverse(array);
}
int val = BitConverter.ToInt32(...);
However as you mention an IL stream. The bytecode is this (AFAIK):
(OPCODE:(1|2):little) (VARIABLES:x:little)
So I would read a byte, check its opcode, then read the appropriate bytes and flip the array if necessary using the above code. Can I ask what you are doing?

Why does Delphi warn when assigning ShortString to string?

I'm converting some legacy code to Delphi 2010.
There are a fair number of old ShortStrings, like string[25]
Why does the assignment below:
type
S: String;
ShortS: String[25];
...
S := ShortS;
cause the compiler to generate this warning:
W1057 Implicit string cast from 'ShortString' to 'string'.
There's no data loss that is occurring here. In what circumstances would this warning be helpful information to me?
Thanks!
Tomw
It's because your code is implicitly converting a single-byte character string to a UnicodeString. It's warning you in case you might have overlooked it, since that can cause problems if you do it by mistake.
To make it go away, use an explicit conversion:
S := string(ShortS);
The ShortString type has not changed. It continues to be, in effect, an array of AnsiChar.
By assigning it to a string type, you are taking what is a group of AnsiChars (one byte) and putting it into a group of WideChars (two bytes). The compiler can do that just fine, and is smart enough not to lose data, but the warning is there to let you know that such a conversion has taken place.
The warning is very important because you may lose data. The conversion is done using the current Windows 8-bit character set, and some character sets do not define all values between 0 and 255, or are multi-byte character sets, and thus cannot convert all byte values.
The data loss can occur on a standard computer in a country with specific standard character sets, or on a computer in USA that has been set up for a different locale, because the user communicates a lot with people in other languages.
For instance, if the local code page is 932, the byte values 129 and 130 will both convert to the same value in the Unicode string.
In addition to this, the conversion involves a Windows API call, which is an expensive operation. If you do a lot of these, it can slow down your application.
It's safe ( as long as you're using the ShortString for its intended purpose: to hold a string of characters and not a collection of bytes, some of which may be 0 ), but may have performance implications if you do it a lot. As far as I know, Delphi has to allocate memory for the new unicode string, extract the characters from the ShortString into a null-terminated string (that's why it's important that it's a properly-formed string) and then call something like the Windows API MultiByteToWideChar() function. Not rocket science, but not a trivial operation either.
ShortStrings don't have a code page associated with them, AnsiStrings do (since D2009).
The conversion from ShortString to UnicodeString can only be done on the assumption that ShortStrings are encoded in the default ANSI encoding which is not a safe assumption.
I don't really know Delphi, but if I remember correctly, the Shortstrings are essentially a sequence of characters on the stack, whereas a regular string (AnsiString) is actually a reference to a location on the heap. This may have different implications.
Here's a good article on the different string types:
http://www.codexterity.com/delphistrings.htm
I think there might also be a difference in terms of encoding but I'm not 100% sure.

Resources