1- # This file reads binary data files.
2- # It is mostly for development purposes, to simplify learning a data
3- # file's format. For final use, reading binary data files should
4- # minimize the number of calls to struct.unpack and file.read because
5- # many calls to these functions (i.e. using the code in this module)
6- # are slow.
71import numpy as np
82from struct import unpack
93from os .path import expanduser
104
11- ics = 0 # This is a holder for the checksum index
125
13-
14- class eofException (Exception ):
15- pass
16-
17- class CheckSumError (Exception ):
18- pass
19-
20- # class checksum(object):
21- # # In that case, it *might* be nice to include functionality for nested
22- # # checksums, but that seems a bit overkill at this point.
23- # def __init__(self, file, val, size, error_behavior='exception'):
24- # """
25- # Value *val* to initialize the checksum with,
26- # and the *size* of the checksum (in bytes, currently this can only be 1,2,4 or 8).
27- # """
28- # self.file = file
29- # self.init(val, size, error_behavior)
30-
31- # def init(self, val, size, error_behavior='exception'):
32- # self._cs = val
33- # self._size = size
34- # self._rem = ''
35- # self._frmt = {1: 'B', 2: 'H', 4: 'L', 8: 'Q'}[size]
36- # self._mask = (2 ** (8 * size) - 1)
37- # ## I'd like to add different behavior for the checksum
38- # self._error_behavior = error_behavior
39-
40- # def error(self, val):
41- # if val == 'rem':
42- # message = 'A remainder exists in the checksum.'
43- # else:
44- # message = 'Checksum failed at %d, with a difference of %d.' % (
45- # self.file.tell(), val)
46- # if self._error_behavior == 'warning':
47- # print('Warning: ' + message)
48- # elif self._error_behavior == 'silent':
49- # pass
50- # else:
51- # raise CheckSumError(message)
52-
53- # def __call__(self, val, remove_val=False):
54- # """
55- # Compare the checksum to *val*.
56- # *remove_val* specifies whether *val* should be removed from
57- # self._cs because it was already added to it.
58- # """
59- # if self._rem:
60- # self.error('rem')
61- # retval = (self._cs - val * remove_val & self._mask) - val
62- # if retval:
63- # self.error(retval)
64- # return retval # returns zero if their is no remainder
65-
66- # def add(self, valcs):
67- # """
68- # Add the data in *valcs* to the checksum.
69- # """
70- # if self._rem: # If the cs remainder is not empty:
71- # lr = self._rem.__len__()
72- # ics = self._size - lr
73- # self._rem, valcs = self._rem + valcs[:ics], valcs[ics:]
74- # if lr == self._size:
75- # self._cs += unpack(self.file.endian + self._frmt, self._rem)[0]
76- # self._rem = ''
77- # if valcs: # If valcs is not empty:
78- # ics = (valcs.__len__() / self._size) * self._size
79- # for v in unpack(self.file.endian + self._frmt * (ics / self._size), valcs[:ics]):
80- # self._cs += v
81- # self._rem += valcs[ics:]
82-
83- # __iadd__ = add
84-
85-
86- class bin_reader (object ):
87- #### I may want to write this class in C at some point, to speed things up.
6+ class bin_reader ():
7+ """
8+ Reads binary data files. It is mostly for development purposes, to
9+ simplify learning a data file's format. Reading binary data files should
10+ minimize the number of calls to struct.unpack and file.read because many
11+ calls to these functions (i.e. using the code in this module) are slow.
12+ """
8813 _size_factor = {'B' : 1 , 'b' : 1 , 'H' : 2 ,
8914 'h' : 2 , 'L' : 4 , 'l' : 4 , 'f' : 4 , 'd' : 8 }
9015 _frmt = {np .uint8 : 'B' , np .int8 : 'b' ,
@@ -98,11 +23,11 @@ class bin_reader(object):
9823 def pos (self ,):
9924 return self .f .tell ()
10025
101- # def __enter__(self,):
102- # return self
26+ def __enter__ (self ,):
27+ return self
10328
104- # def __exit__(self, type, value, traceback):
105- # self.close()
29+ def __exit__ (self , type , value , traceback ):
30+ self .close ()
10631
10732 def __init__ (self , fname , endian = '<' , checksum_size = None , debug_level = 0 ):
10833 """
@@ -116,24 +41,22 @@ def __init__(self, fname, endian='<', checksum_size=None, debug_level=0):
11641 self .fsize = self .tell ()
11742 self .f .seek (0 , 0 )
11843 self .close = self .f .close
119- #if progbar_size is not None:
120- # self.progbar=progress_bar(self.fsize,progbar_size)
12144 if checksum_size :
122- pass # This is never run?
45+ pass
12346 #self.cs = checksum(self, 0, checksum_size)
12447 else :
12548 self .cs = checksum_size
12649 self .debug_level = debug_level
12750
128- def checksum (self ,):
129- """
130- The next byte(s) are the expected checksum. Perform the checksum.
131- """
132- if self .cs :
133- cs = self .read (1 , self .cs ._frmt )
134- self .cs (cs , True )
135- else :
136- raise CheckSumError ('CheckSum not requested for this file' )
51+ # def checksum(self,):
52+ # """
53+ # The next byte(s) are the expected checksum. Perform the checksum.
54+ # """
55+ # if self.cs:
56+ # cs = self.read(1, self.cs._frmt)
57+ # self.cs(cs, True)
58+ # else:
59+ # raise Exception ('CheckSum not requested for this file')
13760
13861 def tell (self ,):
13962 return self .f .tell ()
@@ -158,7 +81,7 @@ def reads(self, n):
15881 def read (self , n , frmt ):
15982 val = self .f .read (n * self ._size_factor [frmt ])
16083 if not val : # If val is empty we are at the end of the file.
161- raise eofException
84+ raise Exception ( 'End of file' )
16285 self .cs and self .cs .add (val )
16386 if n == 1 :
16487 return unpack (self .endian + frmt * n , val )[0 ]
@@ -192,5 +115,67 @@ def read_ui32(self, n):
192115 def read_i32 (self , n ):
193116 return self .read (n , 'l' )
194117
195- # def read_nbytes(self, n):
196- # self.f.read(n)
118+ #ics = 0 # This is a holder for the checksum index
119+ # class checksum():
120+ # # Checksum for TRDI
121+ # def __init__(self, file, val, size, error_behavior='exception'):
122+ # """
123+ # Value *val* to initialize the checksum with,
124+ # and the *size* of the checksum (in bytes, currently this can only be 1,2,4 or 8).
125+ # """
126+ # self.file = file
127+ # self.init(val, size, error_behavior)
128+
129+ # def init(self, val, size, error_behavior='exception'):
130+ # self._cs = val
131+ # self._size = size
132+ # self._rem = ''
133+ # self._frmt = {1: 'B', 2: 'H', 4: 'L', 8: 'Q'}[size]
134+ # self._mask = (2 ** (8 * size) - 1)
135+ # ## I'd like to add different behavior for the checksum
136+ # self._error_behavior = error_behavior
137+
138+ # def error(self, val):
139+ # if val == 'rem':
140+ # message = 'A remainder exists in the checksum.'
141+ # else:
142+ # message = 'Checksum failed at %d, with a difference of %d.' % (
143+ # self.file.tell(), val)
144+ # if self._error_behavior == 'warning':
145+ # print('Warning: ' + message)
146+ # elif self._error_behavior == 'silent':
147+ # pass
148+ # else:
149+ # raise Exception(message)
150+
151+ # def __call__(self, val, remove_val=False):
152+ # """
153+ # Compare the checksum to *val*.
154+ # *remove_val* specifies whether *val* should be removed from
155+ # self._cs because it was already added to it.
156+ # """
157+ # if self._rem:
158+ # self.error('rem')
159+ # retval = (self._cs - val * remove_val & self._mask) - val
160+ # if retval:
161+ # self.error(retval)
162+ # return retval # returns zero if there is no remainder
163+
164+ # def add(self, valcs):
165+ # """
166+ # Add the data in *valcs* to the checksum.
167+ # """
168+ # if self._rem: # If the cs remainder is not empty:
169+ # lr = self._rem.__len__()
170+ # ics = self._size - lr
171+ # self._rem, valcs = self._rem + valcs[:ics], valcs[ics:]
172+ # if lr == self._size:
173+ # self._cs += unpack(self.file.endian + self._frmt, self._rem)[0]
174+ # self._rem = ''
175+ # if valcs: # If valcs is not empty:
176+ # ics = (valcs.__len__() / self._size) * self._size
177+ # for v in unpack(self.file.endian + self._frmt * (ics / self._size), valcs[:ics]):
178+ # self._cs += v
179+ # self._rem += valcs[ics:]
180+
181+ # __iadd__ = add
0 commit comments