Source code for crccheck.checksum

""" Classes to calculated additive and XOR checksums.

  License::

    Copyright (C) 2015-2021 by Martin Scharrer <martin@scharrer-online.de>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""
from crccheck.base import CrccheckBase, CrccheckError


[docs]class ChecksumBase(CrccheckBase): """ Base class for all checksum classes. Args: initvalue (int): Initial value. If None then the default value for the class is used. byteorder ('big' or 'little'): byte order (endianness) used when reading the input bytes. """ _width = 0 _mask = 0 _check_data = (0xDE, 0xAD, 0xBE, 0xEF, 0xAA, 0x55, 0xC2, 0x8C) _check_result_littleendian = None def __init__(self, initvalue=0, byteorder='big'): super(ChecksumBase, self).__init__(initvalue) self._byteorder = byteorder
[docs] def process(self, data): """ Process given data. Args: data (bytes, bytearray or list of ints [0-255]): input data to process. Returns: self """ dataword = 0 n = 0 bigendian = (self._byteorder == 'big') width = self._width mask = self._mask value = self._value for byte in data: if bigendian: dataword = (dataword << 8) | byte else: dataword |= (byte << n) n += 8 if n == width: value = mask & (value + dataword) dataword = 0 n = 0 self._value = value return self
[docs] @classmethod def selftest(cls, data=None, expectedresult=None, byteorder='big'): """ Selftest method for automated tests. Args: data (bytes, bytearray or list of int [0-255]): data to process expectedresult (int): expected result byteorder ('big' or 'little'): byte order (endianness) used when reading the input bytes. Raises: CrccheckError: if result is not as expected """ if data is None: data = cls._check_data if expectedresult is None: if byteorder == 'big': expectedresult = cls._check_result else: expectedresult = cls._check_result_littleendian result = cls.calc(data, byteorder=byteorder) if result != expectedresult: raise CrccheckError(hex(result))
[docs]class Checksum32(ChecksumBase): """ 32-bit checksum. Calculates 32-bit checksum by adding the input bytes in groups of four. Input data length must be a multiple of four, otherwise the last bytes are not used. """ _width = 32 _mask = 0xFFffFFff _check_result = 0x8903817B _check_result_littleendian = 0x7C810388
[docs]class Checksum16(ChecksumBase): """ 16-bit checksum. Calculates 16-bit checksum by adding the input bytes in groups of two. Input data length must be a multiple of two, otherwise the last byte is not used. """ _width = 16 _mask = 0xFFff _check_result = 0x0A7D _check_result_littleendian = 0x8008
[docs]class Checksum8(ChecksumBase): """ 8-bit checksum. Calculates 8-bit checksum by adding the input bytes. """ _width = 8 _mask = 0xFF _check_result = 0x85 _check_result_littleendian = _check_result
[docs]class ChecksumXorBase(ChecksumBase): """ Base class for all XOR checksum classes. """
[docs] def process(self, data): """ Process given data. Args: data (bytes, bytearray or list of ints [0-255]): input data to process. Returns: self """ dataword = 0 n = 0 bigendian = (self._byteorder == 'big') width = self._width mask = self._mask value = self._value for byte in data: if bigendian: dataword = (dataword << 8) | byte else: dataword |= (byte << n) n += 8 if n == width: value = mask & (value ^ dataword) dataword = 0 n = 0 self._value = value return self
[docs]class ChecksumXor32(ChecksumXorBase): """ 32-bit XOR checksum. Calculates 32-bit checksum by XOR-ing the input bytes in groups of four. Input data length must be a multiple of four, otherwise the last bytes are not used. """ _width = 32 _mask = 0xFFffFFff _check_result = 0x74F87C63 _check_result_littleendian = 0x637CF874
[docs]class ChecksumXor16(ChecksumXorBase): """ 16-bit XOR checksum. Calculates 16-bit checksum by XOR-ing the input bytes in groups of two. Input data length must be a multiple of two, otherwise the last byte is not used. """ _width = 16 _mask = 0xFFff _check_result = 0x089B _check_result_littleendian = 0x9B08
[docs]class ChecksumXor8(ChecksumXorBase): """ 8-bit XOR checksum. Calculates 8-bit checksum by XOR-ing the input bytes. """ _width = 8 _mask = 0xFF _check_result = 0x93 _check_result_littleendian = _check_result
[docs]class Checksum(ChecksumBase): """ General additive checksum. Args: width (int): bit width of checksum. Must be positive and a multiple of 8. initvalue (int): Initial value. If None then the default value for the class is used. byteorder ('big' or 'little'): byte order (endianness) used when reading the input bytes. """ _check_result = None _check_result_littleendian = None def __init__(self, width, initvalue=0, byteorder='big'): super(Checksum, self).__init__(initvalue, byteorder) width = int(width) if width <= 0 or width % 8 != 0: raise ValueError("width must be postive and a multiple of 8") self._width = width self._mask = (1 << width) - 1
[docs]class ChecksumXor(ChecksumXorBase): """ General XOR checksum. Args: width (int): bit width of checksum. Must be positive and a multiple of 8. initvalue (int): Initial value. If None then the default value for the class is used. byteorder ('big' or 'little'): byte order (endianness) used when reading the input bytes. """ _check_result = None _check_result_littleendian = None def __init__(self, width, initvalue=0, byteorder='big'): super(ChecksumXor, self).__init__(initvalue, byteorder) width = int(width) if width <= 0 or width % 8 != 0: raise ValueError("width must be postive and a multiple of 8") self._width = width self._mask = (1 << width) - 1
ALLCHECKSUMCLASSES = ( Checksum8, Checksum16, Checksum32, ChecksumXor8, ChecksumXor16, ChecksumXor32, )