1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
"""
localzone.util
~~~~~~~~~~~~~~
This module contains general purpose utilities used by localzone.
"""
from itertools import chain, repeat
def group(iterable, n, padvalue=None):
"""
Create n-length sets from an iterable.
:param iterable: An iterable object.
:type iterable: iterable
:param n: The number of items in the set.
:type n: int
:param padvalue: The value used, if necessary, to pad the last set.
:type n: int
:return: An iterable set.
:rtype: iterator
"""
return zip(*[chain(iterable, repeat(padvalue, n - 1))] * n)
def pack(tup):
"""
Packs a tuple of 8-bit integers.
:param tup: Tuple of 8-bit integers.
:type tup: tuple
:return: The packed n-bit value, where n is len(tup) * 8.
:rtype: int
"""
size = len(tup)
result = 0
for i in range(size):
result = tup[i] << (i * 8) | result
return result
def checksum(word, size=32):
"""
Implements Fletcher's checksum to create 16, 32, or 64-bit checksums.
:param word: The data to checksum.
:type word: string
:param size: The checksum's size.
:type size: int
:return: Fletcher's checksum represented as a hexadecimal digest.
:rtype: string
"""
if size not in [16, 32, 64]:
raise ValueError("Valid checksum sizes are 16, 32 and 64")
bits = int(size / 2)
block_size = int(bits / 8)
modulus = int(2 ** bits - 1)
pad = 0
ordinals = map(ord, word)
if size == 16:
blocks = ordinals
else:
blocks = map(pack, group(ordinals, block_size, pad))
a = b = 0
for block in blocks:
a += block
b += a
a %= modulus
b %= modulus
return format((b << bits) | a, "x").zfill(4)
|