C function to Python

Question:

Can someone help to make Python version of function.
Thanks

unsigned char asap_xor(unsigned char *msg, int len) {
    unsigned char xor_val = 0;
    int i;
    xor_val = msg[0];
    for (i = 1; i < len; i++) {
        xor_val ^= msg[i];
    }
    xor_val = 13 ^ xor_val;
    xor_val = xor_val | 0x40;
    return (xor_val);
}

my python version but error

def asap_xor(msg, len):
    xor_val = msg[0]
    for i in range(1, len):
        xor_val ^= msg[i]
    xor_val = byte(13 ^ xor_val)
    xor_val = byte(xor_val | 0x40)
    return (xor_val)

TypeError: unsupported operand type(s) for ^=: ‘str’ and ‘str’

Asked By: bit

||

Answers:

Not sure what version of python you are on, but for python 3.5+ or so, this should work:

def asap_xor(msg):        
    xor_val = msg[0]
    for m in msg[1:]:
        xor_val ^= m
    xor_val = (13 ^ xor_val)
    xor_val = (xor_val | 0x40)

    return xor_val

print(asap_xor("test".encode('utf8')))
print(asap_xor(b"test"))
Answered By: th33lf

If your task is to "translate" code from C to Python line by line @th33lf‘s answer is perfectly fine.

However, you can use built-in features of Python which allows you to implement same logic in one-liner (suggested in this comment):

13 ^ reduce(xor, msg) | 0x40

reduce() iterates over iterable and applies provided function (we used xor()) to every item using result of previous step as first argument.

So pythonic version of your C function is:

from functools import reduce
from operator import xor

def asap_xor(msg):
    return 13 ^ reduce(xor, msg) | 0x40

Note that msg should be an iterable of int values (already said in this comment). If your input value is string you can use str.encode() to convert str to bytes.

If you need to keep len argument (as you’ve said in this comment) you can pass sliced msg to reduce() (check this comment). I’d set default length argument value to 0 and use islice() only if some non-zero length passed to function.

from functools import reduce
from operator import xor
from itertools import islice

def asap_xor(msg, length=0):
    return 13 ^ reduce(xor, islice(msg, length) if length else msg) | 0x40

Usage:

asap_xor("message".encode())                     # 102
asap_xor("message".encode(), 6)                  # 67
asap_xor(b"message")                             # 102
asap_xor(b"message", 6)                          # 67
asap_xor([109, 101, 115, 115, 97, 103, 101])     # 102
asap_xor([109, 101, 115, 115, 97, 103, 101], 6)  # 67

Answered By: Olvin Roght
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.