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