1# This file is part of Xpra. 2# Copyright (C) 2012-2021 Antoine Martin <antoine@xpra.org> 3# Xpra is released under the terms of the GNU GPL v2, or, at your option, any 4# later version. See the file COPYING for details. 5 6#cython: wraparound=False, boundscheck=False 7 8from libc.stdint cimport uint32_t, uintptr_t #pylint: disable=syntax-error 9from xpra.buffers.membuf cimport getbuf, MemBuf 10from libc.string cimport memset 11 12 13cdef extern from "Python.h": 14 int PyObject_GetBuffer(object obj, Py_buffer *view, int flags) 15 void PyBuffer_Release(Py_buffer *view) 16 int PyBUF_ANY_CONTIGUOUS 17 18 19def xor_str(a, b): 20 assert len(a)==len(b), "cyxor cannot xor strings of different lengths (%s:%s vs %s:%s)" % (type(a), len(a), type(b), len(b)) 21 cdef Py_buffer py_bufa 22 memset(&py_bufa, 0, sizeof(Py_buffer)) 23 if PyObject_GetBuffer(a, &py_bufa, PyBUF_ANY_CONTIGUOUS): 24 raise Exception("failed to read pixel data from %s" % type(a)) 25 cdef Py_buffer py_bufb 26 memset(&py_bufb, 0, sizeof(Py_buffer)) 27 if PyObject_GetBuffer(b, &py_bufb, PyBUF_ANY_CONTIGUOUS): 28 PyBuffer_Release(&py_bufa) 29 raise Exception("failed to read pixel data from %s" % type(b)) 30 cdef Py_ssize_t alen = py_bufa.len 31 cdef Py_ssize_t blen = py_bufb.len 32 if alen!=blen: 33 PyBuffer_Release(&py_bufa) 34 PyBuffer_Release(&py_bufb) 35 raise Exception("python or cython bug? buffers don't have the same length?") 36 cdef MemBuf out_buf = getbuf(alen) 37 cdef uintptr_t op = <uintptr_t> out_buf.get_mem() 38 cdef unsigned char *acbuf = <unsigned char *> py_bufa.buf 39 cdef unsigned char *bcbuf = <unsigned char *> py_bufb.buf 40 cdef unsigned char *ocbuf = <unsigned char *> op 41 cdef uint32_t *obuf = <uint32_t*> op 42 cdef uint32_t *abuf = <uint32_t*> py_bufa.buf 43 cdef uint32_t *bbuf = <uint32_t*> py_bufb.buf 44 cdef unsigned int i, j, steps, char_steps 45 if (alen % 4)!=0 or (blen % 4)!=0: 46 #unaligned access, use byte at a time slow path: 47 char_steps = alen 48 for 0 <= i < char_steps: 49 ocbuf[i] = acbuf[i] ^ bcbuf[i] 50 else: 51 #do 4 bytes at a time: 52 steps = alen // 4 53 if steps>0: 54 for 0 <= i < steps: 55 obuf[i] = abuf[i] ^ bbuf[i] 56 #bytes at a time again at the end: 57 char_steps = alen % 4 58 if char_steps>0: 59 for 0 <= i < char_steps: 60 j = alen-char_steps+i 61 ocbuf[j] = acbuf[j] ^ bcbuf[j] 62 PyBuffer_Release(&py_bufa) 63 PyBuffer_Release(&py_bufb) 64 return memoryview(out_buf) 65