@@ -8,32 +8,75 @@ class CSAReadError(Exception):
8
8
pass
9
9
10
10
11
- def read (fileobj ):
12
- ''' Read CSA header from fileobj
11
+ def read (csa_str ):
12
+ ''' Read CSA header from string `csa_str`
13
13
14
14
Parameters
15
15
----------
16
- fileobj : file-like
17
- file-like object implementing ``read, seek, tell`. The data is
18
- taken to start at position 0 and end at the end of the file.
16
+ csa_str : str
17
+ byte string containing CSA header information
19
18
20
19
Returns
21
20
-------
22
21
header : dict
23
22
header information
24
- tags : sequence
25
- sequence of tags from header
26
23
'''
27
- fileobj .seek (0 )
28
- hdr_id = fileobj .read (4 )
29
- hdr = {}
30
- tags = []
24
+ hdr_id = csa_str [:4 ]
25
+ csa_len = len (csa_str )
26
+ csa_dict = {'tags' : {}}
31
27
if hdr_id != 'SV10' :
32
- hdr ['type' ] = 1
33
- hdr ['n_tags' ], = unpack ('<i' , hdr_id )
28
+ csa_dict ['type' ] = 1
29
+ csa_dict ['n_tags' ], = unpack ('<i' , hdr_id )
30
+ ptr = 4
34
31
else :
35
- hdr ['type' ] = 2
36
- hdr ['unused1' ] = fileobj .read (4 )
37
- hdr ['n_tags' ], = unpack ('<I' , fileobj .read (4 ))
38
- hdr ['unused3' ], = unpack ('<I' , fileobj .read (4 ))
39
- return hdr , tags
32
+ csa_dict ['type' ] = 2
33
+ csa_dict ['unused0' ] = csa_str [4 :8 ]
34
+ csa_dict ['n_tags' ], = unpack ('<I' , csa_str [8 :12 ])
35
+ ptr = 12
36
+ csa_dict ['check' ], = unpack ('<I' , csa_str [ptr :ptr + 4 ])
37
+ ptr += 4
38
+ for tag_no in range (csa_dict ['n_tags' ]):
39
+ name , vm , vr , syngodt , n_items , xx = \
40
+ unpack ('<64sI4sIII' ,csa_str [ptr :ptr + 84 ])
41
+ name = nt_str (name )
42
+ tag = {'pointer' : ptr ,
43
+ 'n_items' : n_items ,
44
+ 'last3' : xx }
45
+ ptr += 84
46
+ assert n_items < 100
47
+ for item_no in range (n_items ):
48
+ tag ['pointer' ] = ptr
49
+ x0 ,x1 ,x2 ,x3 = unpack ('<4i' ,csa_str [ptr :ptr + 16 ])
50
+ tag ['xx' ] = [x0 ,x1 ,x2 ,x3 ]
51
+ ptr += 16
52
+ item_len = x1
53
+ if (ptr + item_len ) > csa_len :
54
+ raise CSAReadError ('Item is too long, aborting read' )
55
+ format = '<%ds' % item_len
56
+ tag ['value' ] = unpack (format ,csa_str [ptr :ptr + item_len ])
57
+ plus4 = item_len % 4
58
+ if plus4 != 0 :
59
+ ptr += item_len + (4 - plus4 )
60
+ else :
61
+ ptr += item_len
62
+ tag ['end_pointer' ] = ptr
63
+ csa_dict ['tags' ][name ] = tag
64
+ return csa_dict
65
+
66
+
67
+ def nt_str (s ):
68
+ ''' Strip string to first null
69
+
70
+ Parameters
71
+ ----------
72
+ s : str
73
+
74
+ Returns
75
+ -------
76
+ sdash : str
77
+ s stripped to first occurence of null (0)
78
+ '''
79
+ zero_pos = s .find (chr (0 ))
80
+ if zero_pos == - 1 :
81
+ return s
82
+ return s [:zero_pos ]
0 commit comments