API cleanup for binarywave (loadibw->load, move checksum to util, ...).
[igor.git] / igor / util.py
1 # Copyright
2
3 "Utility functions for handling buffers"
4
5 import sys as _sys
6
7 import numpy as _numpy
8
9
10 def hex_bytes(buffer, spaces=None):
11     r"""Pretty-printing for binary buffers.
12
13     >>> hex_bytes(buffer('\x00\x01\x02\x03\x04'))
14     '0001020304'
15     >>> hex_bytes(buffer('\x00\x01\x02\x03\x04'), spaces=1)
16     '00 01 02 03 04'
17     >>> hex_bytes(buffer('\x00\x01\x02\x03\x04'), spaces=2)
18     '0001 0203 04'
19     >>> hex_bytes(buffer('\x00\x01\x02\x03\x04\x05\x06'), spaces=2)
20     '0001 0203 0405 06'
21     >>> hex_bytes(buffer('\x00\x01\x02\x03\x04\x05\x06'), spaces=3)
22     '000102 030405 06'
23     """
24     hex_bytes = ['{:02x}'.format(ord(x)) for x in buffer]
25     if spaces is None:
26         return ''.join(hex_bytes)
27     elif spaces is 1:
28         return ' '.join(hex_bytes)
29     for i in range(len(hex_bytes)//spaces):
30         hex_bytes.insert((spaces+1)*(i+1)-1, ' ')
31     return ''.join(hex_bytes)
32
33 def assert_null(buffer, strict=True):
34     r"""Ensure an input buffer is entirely zero.
35
36     >>> import sys
37     >>> assert_null(buffer(''))
38     >>> assert_null(buffer('\x00\x00'))
39     >>> assert_null(buffer('\x00\x01\x02\x03'))
40     Traceback (most recent call last):
41       ...
42     ValueError: 00 01 02 03
43     >>> stderr = sys.stderr
44     >>> sys.stderr = sys.stdout
45     >>> assert_null(buffer('\x00\x01\x02\x03'), strict=False)
46     warning: post-data padding not zero: 00 01 02 03
47     >>> sys.stderr = stderr
48     """
49     if buffer and ord(max(buffer)) != 0:
50         hex_string = hex_bytes(buffer, spaces=1)
51         if strict:
52             raise ValueError(hex_string)
53         else:
54             _sys.stderr.write(
55                 'warning: post-data padding not zero: {}\n'.format(hex_string))
56
57 # From ReadWave.c
58 def byte_order(needToReorderBytes):
59     little_endian = _sys.byteorder == 'little'
60     if needToReorderBytes:
61         little_endian = not little_endian
62     if little_endian:
63         return '<'  # little-endian
64     return '>'  # big-endian    
65
66 # From ReadWave.c
67 def checksum(buffer, byte_order, oldcksum, numbytes):
68     x = _numpy.ndarray(
69         (numbytes/2,), # 2 bytes to a short -- ignore trailing odd byte
70         dtype=_numpy.dtype(byte_order+'h'),
71         buffer=buffer)
72     oldcksum += x.sum()
73     if oldcksum > 2**31:  # fake the C implementation's int rollover
74         oldcksum %= 2**32
75         if oldcksum > 2**31:
76             oldcksum -= 2**31
77     return oldcksum & 0xffff