Bytes Object is Comma Separated Decimal Values (Python 3) - python-3.x

A machine I interface with at my work returns its frequency as a bytes object like this:
b'192,232,206,0'
This little-endian (I think that's right, I'm not great at remembering which is which) bytes object is supposed to translate to a hex bytes object \x00\xCE\xE8\xC0 which translates into decimal as 13560000. I have found that Python has int.from_bytes() which takes the hex bytes object and turns it to a nice integer, but when I apply that to my comma-separated bytes object where each bytes is a decimal value, I get an astronomically large number (3816634650710199623094969186609 to be exact). Can anyone help me out here?

It's a bit convoluted but you can convert the decimal numbers to hex strings and combine their byte values to assemble a number:
freq = b'192,232,206,0'
freq_bytes = b''
for decimal in freq.split(b','):
hex_str = hex(int(decimal))
if hex_str == '0x0':
hex_str += '0' # otherwise it won't convert
freq_bytes += bytes.fromhex(hex_str[2:]) # remove the 0x part
freq_int = int.from_bytes(freq_bytes, 'little')
gives 13560000

Related

How to convert a byte to the correct decimal representation?

I have a function that checks a bit in a specific index of a string (converted to byte representation):
fn check_bit(s: String) -> bool {
let bytes = s.as_bytes(); // converts string to bytes
let byte = s[0]; // pick first byte
// byte here seems to be in decimal representation
byte | 0xf7 == 0xff // therefore this returns incorrect value
}
after printing and doing arithmetic operations on the byte variable, I noticed that byte is a decimal number. For example, for the ASCII value of char b (0x98), byte stores 98 as decimal, which results in an incorrect value when doing bitwise operations on them. How can I convert this decimal value to correct hex, binary or decimal representation? (for 0x98 I am expecting to get decimal value of 152)
noticed that byte is a decimal number
An integer has no intrinsic base, it is just a bit pattern in memory. You can write them out in a string as a decimal, binary, octal, etc., but the value in memory is the same.
In other words, integers are not stored in memory as strings.
For example, for ascii value of char b (0x98), byte simply stores 98 as decimal
ASCII b is not 0x98, it is 98, which is 0x62:
assert_eq!(98, 0x62);
assert_eq!(98, "b".as_bytes()[0]);
assert_eq!(98, 'b' as i32);
How can I convert this decimal value to correct hex, binary or decimal representation?
Such a conversion does not make sense because integers are not stored as strings as explained above.

Binary Formatting Variables in TCL

I am trying to create a binary message to send over a socket, but I'm having trouble with the way TCL treats all variables as strings. I need to calculate the length of a string and know its value in binary.
set length [string length $message]
set binaryMessagePart [binary format s* { $length 0 }]
However, when I run this I get the error 'expected integer but got "$length"'. How do I get this to work and return the value for the integer 5 and not the char 5?
To calculate the length of a string, use string length. To calculate the length of a string in a particular encoding, convert the string to that encoding and use string length:
set enc "utf-8"; # Or whatever; you need to know this ahead of time for sanity's sake
set encoded [encoding convertto $enc $message]
set length [string length $encoded]
Note that with the encoded length, this will be in bytes whereas the length prior to encoding is in characters. For some messages and some encodings, the difference can be substantial.
To compose a binary message with the length and the body of the message (a fairly common binary format), use binary format like this:
# Assumes the length is big-endian; for little-endian, use i instead of I
set binPart [binary format "Ia*" $length $encoded]
What you were doing wrong was using s* which consumes a list of integers and produces a sequence of little-endian short integer binary values in the output string, and yet were feeding the list that was literally $length 0; and the string $length is not an integer as those don't start with $. We could have instead done [list $length 0] to produce the argument to s* and that would have worked, but that doesn't seem quite right for the context of the question.
In binary format, these are the common formats (there are many more):
a is for string data (mnemonically “ASCII”); this is binary string data, and you need to encode it first.
i and I are for 32-bit numbers (mnemonically “int” like in many programming languages, but especially C). Upper case is big-endian, lower case is little-endian.
s and S are for 16-bit numbers (mnemonically “short”).
c is for 8-bit numbers (mnemonically “char” from C).
w and W are for 64-bit numbers (mnemonically “wide integers”).
f and d are for IEEE binary floating point numbers (mnemonically “float” and “double” respectively, so 4 and 8 bytes).
All can be followed by an optional length, either a number or a *. For the number ones, instead of inserting a single number they insert a list of them (and so consume a list); numbers give fixed lengths, and * does “all the list”. For the string format indicator, a number uses a fixed number of bytes in the message (truncating or padding with zero bytes as necessary) and * does “all the string” (never truncating or padding).

Python bytes representation

I'm writing a hex viewer on python for examining raw packet bytes. I use dpkt module.
I supposed that one hex byte may have value between 0x00 and 0xFF. However, I've noticed that python bytes representation looks differently:
b'\x8a\n\x1e+\x1f\x84V\xf2\xca$\xb1'
I don't understand what do these symbols mean. How can I translate these symbols to original 1-byte values which could be shown in hex viewer?
The \xhh indicates a hex value of hh. i.e. it is the Python 3 way of encoding 0xhh.
See https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
The b at the start of the string is an indication that the variables should be of bytes type rather than str. The above link also covers that. The \n is a newline character.
You can use bytearray to store and access the data. Here's an example using the byte string in your question.
example_bytes = b'\x8a\n\x1e+\x1f\x84V\xf2\xca$\xb1'
encoded_array = bytearray(example_bytes)
print(encoded_array)
>>> bytearray(b'\x8a\n\x1e+\x1f\x84V\xf2\xca$\xb1')
# Print the value of \x8a which is 138 in decimal.
print(encoded_array[0])
>>> 138
# Encode value as Hex.
print(hex(encoded_array[0]))
>>> 0x8a
Hope this helps.

Trying to pack binary bits represented by bytes into a byte in python

I have a string that contains a string of hex values that represent binary bits, so 0x00 = binary 0 and 0x01 = binary 1. How can I pack eight of these hex values into a byte?
For example, the string = '\x01\x01\x00\x01\x00\x01\x00\x01' and from that I want 0b11010101.
The end goal is to extract several bytes worth of binary from a long string.
How can this be done? I've not seen any instance so far of using struct.pack to do this. Any help would be appreciated!
3>> int('\x01\x01\x00\x01\x00\x01\x00\x01'.translate({0: '0', 1: '1'}), 2)
213

How do I convert string of hex digits to value it represents in Lua

I'm reading in a lot of lines of hex data. They come in as strings and I parse them for line_codes which tell me what to do with the rest of the data. One line sets a most significant word of an address (MSW), another line sets the least significant (LSW).
I then need to concatenate those together such that if MSW = "00ff" and LSW = "f10a"
address would be 00fff10a.
This all went fine, but then I was supposed to check if address was between a certain set of values:
if address <= "007FFFh" and address >= "000200h" then
print "I'm in"
end
As you all probably know, Lua is not a fan of this as it gives me an error using <= and >= with strings.
If there a way I can convert the string into hex, such that "FFFF" would become 0xFFFF?
You use tonumber:
local someHexString = "03FFACB"
local someNumber = tonumber(someHexString, 16)
Note that numbers are not in hexadecimal. Nor are they in decimal, octal, or anything else. They're just numbers. The number 0xFF is the same number as 255. "FF" and "255" are string representations of the same number.

Resources