1#!/usr/bin/env python3
2
3"""Binary manipulation functions."""
4
5import logging
6import struct
7import sys
8
9logger = logging.getLogger()
10
11
12def unpack_uint8(buff, position):
13 """Retrieve an 8 bit uint from a buffer."""
14 res = buff[position]
15 return res
16
17
18def unpack_uint16_be(buff, position):
19 """Retrieve a 16 bit big endian int from a buffer."""
20 try:
21 return (buff[position] << 8) + buff[position + 1]
22 except IndexError as e:
23 raise IndexError('Cannot read 16 bits from position {p} in buffer len {l}'.format(
24 p=position, l=len(buff)))
25
26
27def unpack_uint24_be(buff, position):
28 """Retrieve a 24 bit big endian unsigned int from a buffer."""
29 return (buff[position] << 16) + (buff[position +1 ] << 8) + buff[position + 2]
30
31
32def unpack_uint22_be(buff, position):
33 """Retrieve the 22 MSB from `position` in `buffer`."""
34 return unpack_uint24_be(buff, position) >> 2
35
36
37def unpack_uint32_be(buff, position):
38 """Retrieve a 32 bit big endian unsigned int from a buffer."""
39 return ((buff[position] << 24) +
40 (buff[position + 1] << 16) +
41 (buff[position + 2] << 8) +
42 buff[position + 3])
43
44
45def unpack_int32_be(buff, position):
46 """Retrieve a 32 bit big endian int from a buffer."""
47 return struct.unpack_from('>i', buff, position)[0]
48
49
50def unpack_uint40_be(buff, position):
51 """Retrieve a 32 bit big endian int from a buffer."""
52 return ((buff[position] << 40) +
53 (buff[position + 1] << 32) +
54 (buff[position + 2] << 24) +
55 (buff[position + 3] << 16) +
56 (buff[position + 4] << 8) +
57 buff[position + 5])
58
59
60def unpack_uint64_be(buff, position):
61 """Retrieve a 64 bit big endian int from a buffer."""
62 return ((buff[position] << 56) +
63 (buff[position + 1] << 48) +
64 (buff[position + 2] << 40) +
65 (buff[position + 3] << 32) +
66 (buff[position + 4] << 24) +
67 (buff[position + 5] << 16) +
68 (buff[position + 6] << 8) +
69 buff[position + 7])
70
71
72def unpack_float64_be(buff, position):
73 """(slowly) decode a big endian double precision float from binary"""
74 return struct.unpack('>d', buff[position:position + 8])[0]
75
76
77def unpack_float32_be(buff, position):
78 """(slowly) decode a big endian single precision float from binary"""
79 return struct.unpack('>f', buff[position:position + 4])[0]
80
81
82def pack_uint16_be(buff, position, value):
83 """Store a 16 bit big endian int into a buffer."""
84 buff[position] = value >> 8
85 buff[position + 1] = value & 0xff
86
87
88def pack_uint32_be(buff, position, value):
89 """Store a 32 bit big endian int into a buffer."""
90 buff[position] = value >> 24
91 buff[position + 1] = (value >> 16) & 0xff
92 buff[position + 2] = (value >> 8) & 0xff
93 buff[position + 3] = value & 0xff