Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Decoding Binary to Boolean

I'm trying to receive some data with sockets, and then unpack the data to work on it.

In input, i have a binary string : "MsgID - Sender - Size - Time1 - Time2 - Resrv - bool1 - bool2"

Here is the format : "H - H - L - f - I - L - 'bool' - 'bool'"

When I receive the data, I have to unpack it with this line :

messageEnaKill = struct.unpack('!HHLfIL??', messageEnaKill_raw)

And then I have to work on the boolean values (the last 2 ones). The fact is I don't know the format for boolean values, is it a char ('c') or something ?

My second problem is that I have to check the binary boolean if it is True or False. How can I do that ? is this code true :

if msg[0] == bin(True):

considering "msg[0]" the boolean data from the "unpack".

Thanks for the support !

like image 283
tutur29 Avatar asked Sep 20 '26 02:09

tutur29


2 Answers

from struct documentation:

The '?' conversion code corresponds to the _Bool type defined by C99. If this type is not available, it is simulated using a char. In standard mode, it is always represented by one byte.

The ? type will be unpacked as a bool type:

>>> type(struct.unpack('?','c')[0])
<type 'bool'>

Any value other than null character ('\0') will be True. So you can follow the suggestion from Jan Vlcinsky. Your solution depends on what data you receive. If a null byte means False and other byte True, then you can continue using ? unpacking as a simplest solution.

So to check if your first boolean in a message is true use this test:

messageEnaKill = struct.unpack('!HHLfIL??', messageEnaKill_raw)
if(messageEnaKill[7]==True):
    # do something
like image 97
nio Avatar answered Sep 22 '26 14:09

nio


You may decide to put multiple bits into one integer and pack/unpack that integer

To convert list of booleans, following functions might be of help:

def encode_booleans(bool_lst):
    res = 0
    for i, bval in enumerate(bool_lst):
        res += int(bval) << i
    return res

def decode_booleans(intval, bits):
    res = []
    for bit in xrange(bits):
        mask = 1 << bit
        res.append((intval & mask) == mask)
    return res

To test it:

>>> blst = [True, False, True]
>>> encode_booleans(blst)
5
>>> decode_booleans(5, 3)
[True, False, True]
>>> decode_booleans(5, 10)
[True, False, True, False, False, False, False, False, False, False]

Encoding

Encoding is then done in two steps

  1. turn set of booleans into an integer
  2. create resulting structure to pack using all the other types plus newly created integer

Decoding

Decoding goes also in two steps, just in oposite order

  1. unpack into expected structure, booleans being represented s single integer
  2. decode the integer into set of booleans

This assumes, you have encoding part under control.

Full example

Assuming import struct was done and the two functions above are defined:

>>> packform = "!HHLfILB"
>>> msg_id = 101
>>> sender = 22
>>> size = 1000
>>> time1 = 123.45
>>> time2 = 222
>>> bool1 = True
>>> bool2 = False
>>> bools_enc = encode_booleans([bool1, bool2])
>>> bools_enc
1
>>> resrv = 55
>>> msg_lst = [msg_id, sender, size, time1, time2, resrv, bools_enc]
>>> enc = struct.pack(packform, *msg_lst)
>>> enc
'\x00e\x00\x16\x00\x00\x03\xe8B\xf6\xe6f\x00\x00\x00\xde\x00\x00\x007\x01'
>>> decoded = struct.unpack(packform, enc)
>>> decoded
(101, 22, 1000, 123.44999694824219, 222, 55, 1)
>>> msg_lst
[101, 22, 1000, 123.45, 222, 55, 1]
>>> new_msg_id, new_sender, new_size, new_time1, new_time2, new_resrv, new_bools_enc = decoded
>>> new_bool1, new_bool2 = decode_booleans(new_bools_enc, 2)
>>> new_bool1
True
>>> new_bool2
False
like image 30
Jan Vlcinsky Avatar answered Sep 22 '26 14:09

Jan Vlcinsky