0

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'

5
  • Could you please provide an explanation of what you are trying to do in the function and also expected output and sample input Commented Oct 11, 2022 at 14:34
  • 1
    Please edit to include your attempt so far. Commented Oct 11, 2022 at 14:35
  • Assuming msg is a bytes object you can use 13 ^ reduce(xor, msg) | 0x40. Imports: reduce(), xor(). Example. Commented Oct 11, 2022 at 14:38
  • Not just bytes object, any iterable of int values will fit. Example. Commented Oct 11, 2022 at 14:45
  • @bit, length of your message is 125, you pass 124 which exclude last symbol, that's why results are different. If that's expected behavior, you can implement it using simple slice notation ( reduce(xor, msg[:length]) ) or with islice() ( reduce(xor, islice(msg, length)) ). Updated function. Commented Oct 11, 2022 at 15:21

2 Answers 2

4

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

Sign up to request clarification or add additional context in comments.

3 Comments

whilst I totally sympathise with the link, answers are totally not the place to include links to material entirely irrelevant to the question.
@user438383, that's why I asked one of moderators in Python chat is it okay to add one-line footer.
Loved this answer, indeed is the more 'pythonic' solution!
3

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"))

2 Comments

@bit I assumed you would be passing a string, not byte array. Updated the answer.
msg = msg.encode('utf8') AttributeError: 'bytes' object has no attribute 'encode'

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.