issue with struct.unpack
Alexander Blinne
news at blinne.net
Sun Aug 26 08:53:28 EDT 2012
On 26.08.2012 01:31, Dennis Lee Bieber wrote:
> The struct module relies upon the user knowing the format of the data.
> If your problem is that you have some null-terminated string data in a
> variable width field, you will have to locate the position of the null
> FIRST, and specify the appropriate "count" for the s format.
This gave me the idea of an Enhancement of the Struct class with an
additional format character (perhaps 'n') which corresponds to a
null-terminated string:
-----
# -*- coding: utf-8 -*-
import struct
class Nstr(object):
def __init__(self, ncount):
self.ncount = ncount
def unpack(self, s):
s = s.split('\0')
return s[:self.ncount], '\0'.join(s[self.ncount:])
def pack(self, *s):
if len(s)!=self.ncount:
raise ValueError
for st in s:
if '\0' in st:
raise ValueError
return '\0'.join(s)+'\0'
def __repr__(self):
return 'Nstr('+repr(self.ncount)+')'
class NStruct(object):
def __init__(self, format):
self.format = format
if format[0] in '!=<>@':
self.endianness = format[0]
format = format[1:]
else:
self.endianness = ''
self.chunks = []
while len(format)>0:
j = format.find('n')
if j > -1:
k = j-1
while format[k].isdigit():
k-=1
chunkformat, ncount, format = format[:k+1],\
format[k+1:j], format[j+1:]
ncount = 1 if len(ncount)==0 else int(ncount)
else:
chunkformat, ncount, format = format, '', ''
ncount = 0
stru = struct.Struct(self.endianness+chunkformat)
l = len(stru.unpack("0"*stru.size))
self.chunks.append((stru, l))
if ncount > 0:
self.chunks.append((Nstr(ncount), ncount))
def unpack(self, data):
res = []
for sth, n in self.chunks:
if isinstance(sth, struct.Struct):
chunk, data = data[:sth.size], data[sth.size:]
res.extend(sth.unpack(chunk))
elif isinstance(sth, Nstr):
chunk, data = sth.unpack(data)
res.extend(chunk)
return res
def pack(self, *data):
res = []
for sth, n in self.chunks:
chunk, data = data[:n], data[n:]
res.append(sth.pack(*chunk))
return ''.join(res)
def __repr__(self):
return 'NStruct('+repr(self.format)+')'
if __name__=="__main__":
a = NStruct('h b 2n 2h')
print repr(a)
d = 'asdblah blah\0haha\0asdf'
r = a.unpack(d)
assert r == [29537, 100, 'blah blah', 'haha', 29537, 26212]
print repr(d), repr(r)
dd = a.pack(*r)
print r, repr(dd)
assert dd == d
-----
beware of bugs in the above code, i haven't testet it much yet.
Alex
More information about the Python-list
mailing list