Mercurial > hgrepos > Python > apps > py-cutils
diff cutils/util/crc32.py @ 255:d852559df523
Wrap zlib.crc32 into a hashlib-compatible interface
| author | Franz Glasner <fzglas.hg@dom66.de> |
|---|---|
| date | Sat, 15 Feb 2025 16:36:05 +0100 |
| parents | |
| children | 57057028f13e |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cutils/util/crc32.py Sat Feb 15 16:36:05 2025 +0100 @@ -0,0 +1,90 @@ +# -*- coding: utf-8 -*- +# :- +# :Copyright: (c) 2025 Franz Glasner +# :License: BSD-3-Clause +# :- +r"""Wrap :func:`zlib.crc32` into a :mod:`hashlib` compatible interface. + +""" + +from __future__ import print_function, absolute_import + + +__all__ = ["crc32"] + + +import struct +import zlib + +from . import PY2 + + +try: + long +except NameError: + INT_TYPES = (int, ) +else: + INT_TYPES = (int, long) # noqa: F821 long is undefined + + +class crc32(object): + + __slots__ = ["_crc"] + + zlib_crc32 = zlib.crc32 + + def __init__(self, data=b""): + self._crc = self.zlib_crc32(data) + + def update(self, data): + self._crc = self.zlib_crc32(data, self._crc) + + def digest(self): + return struct.pack(">I", self._get_crc_as_uint32()) + + def hexdigest(self): + return "{:08X}".format(self._get_crc_as_uint32()) + + def copy(self): + copied_crc = crc32() + copied_crc._crc = self._crc + return copied_crc + + def __eq__(self, other): + if isinstance(other, crc32): + return self._crc == other._crc + elif isinstance(other, INT_TYPES): + return self._get_crc_as_uint32() == self.as_uint32(other) + else: + return NotImplemented + + def __ne__(self, other): + equal = self.__eq__(other) + return equal if equal is NotImplemented else not equal + + def _get_crc_as_uint32(self): + """Get the current CRC always as positive number with the same bit + pattern because Python2 yields negative numbers also. + + :return: The current CRC value as positive number on all Python + versions + :rtype: int + + """ + if PY2: + if self._crc < 0: + # Return the bitpattern as unsigned 32-bit number + return (~self._crc ^ 0xFFFFFFFF) + else: + return self._crc + else: + return self._crc + + @staticmethod + def as_uint32(i): + if i < 0: + if i < -2147483648: + raise OverflowError("") + return (~i ^ 0xFFFFFFFF) + else: + return i
