Mercurial > hgrepos > Python > apps > py-cutils
comparison 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 |
comparison
equal
deleted
inserted
replaced
| 254:655f9e4bc6f2 | 255:d852559df523 |
|---|---|
| 1 # -*- coding: utf-8 -*- | |
| 2 # :- | |
| 3 # :Copyright: (c) 2025 Franz Glasner | |
| 4 # :License: BSD-3-Clause | |
| 5 # :- | |
| 6 r"""Wrap :func:`zlib.crc32` into a :mod:`hashlib` compatible interface. | |
| 7 | |
| 8 """ | |
| 9 | |
| 10 from __future__ import print_function, absolute_import | |
| 11 | |
| 12 | |
| 13 __all__ = ["crc32"] | |
| 14 | |
| 15 | |
| 16 import struct | |
| 17 import zlib | |
| 18 | |
| 19 from . import PY2 | |
| 20 | |
| 21 | |
| 22 try: | |
| 23 long | |
| 24 except NameError: | |
| 25 INT_TYPES = (int, ) | |
| 26 else: | |
| 27 INT_TYPES = (int, long) # noqa: F821 long is undefined | |
| 28 | |
| 29 | |
| 30 class crc32(object): | |
| 31 | |
| 32 __slots__ = ["_crc"] | |
| 33 | |
| 34 zlib_crc32 = zlib.crc32 | |
| 35 | |
| 36 def __init__(self, data=b""): | |
| 37 self._crc = self.zlib_crc32(data) | |
| 38 | |
| 39 def update(self, data): | |
| 40 self._crc = self.zlib_crc32(data, self._crc) | |
| 41 | |
| 42 def digest(self): | |
| 43 return struct.pack(">I", self._get_crc_as_uint32()) | |
| 44 | |
| 45 def hexdigest(self): | |
| 46 return "{:08X}".format(self._get_crc_as_uint32()) | |
| 47 | |
| 48 def copy(self): | |
| 49 copied_crc = crc32() | |
| 50 copied_crc._crc = self._crc | |
| 51 return copied_crc | |
| 52 | |
| 53 def __eq__(self, other): | |
| 54 if isinstance(other, crc32): | |
| 55 return self._crc == other._crc | |
| 56 elif isinstance(other, INT_TYPES): | |
| 57 return self._get_crc_as_uint32() == self.as_uint32(other) | |
| 58 else: | |
| 59 return NotImplemented | |
| 60 | |
| 61 def __ne__(self, other): | |
| 62 equal = self.__eq__(other) | |
| 63 return equal if equal is NotImplemented else not equal | |
| 64 | |
| 65 def _get_crc_as_uint32(self): | |
| 66 """Get the current CRC always as positive number with the same bit | |
| 67 pattern because Python2 yields negative numbers also. | |
| 68 | |
| 69 :return: The current CRC value as positive number on all Python | |
| 70 versions | |
| 71 :rtype: int | |
| 72 | |
| 73 """ | |
| 74 if PY2: | |
| 75 if self._crc < 0: | |
| 76 # Return the bitpattern as unsigned 32-bit number | |
| 77 return (~self._crc ^ 0xFFFFFFFF) | |
| 78 else: | |
| 79 return self._crc | |
| 80 else: | |
| 81 return self._crc | |
| 82 | |
| 83 @staticmethod | |
| 84 def as_uint32(i): | |
| 85 if i < 0: | |
| 86 if i < -2147483648: | |
| 87 raise OverflowError("") | |
| 88 return (~i ^ 0xFFFFFFFF) | |
| 89 else: | |
| 90 return i |
