14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao"""Implements (a subset of) Sun XDR -- eXternal Data Representation. 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 34adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoSee: RFC 1014 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport struct 84adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry: 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from cStringIO import StringIO as _StringIO 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept ImportError: 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from StringIO import StringIO as _StringIO 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao__all__ = ["Error", "Packer", "Unpacker", "ConversionError"] 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# exceptions 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Error(Exception): 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Exception class for this module. Use: 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except xdrlib.Error, var: 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # var has the Error instance for the exception 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Public ivars: 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao msg -- contains the message 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, msg): 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.msg = msg 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __repr__(self): 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return repr(self.msg) 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __str__(self): 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return str(self.msg) 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass ConversionError(Error): 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Packer: 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Pack various data representations into a buffer.""" 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self): 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.reset() 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def reset(self): 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__buf = _StringIO() 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def get_buffer(self): 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.__buf.getvalue() 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # backwards compatibility 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao get_buf = get_buffer 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_uint(self, x): 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__buf.write(struct.pack('>L', x)) 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_int(self, x): 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__buf.write(struct.pack('>l', x)) 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_enum = pack_int 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_bool(self, x): 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if x: self.__buf.write('\0\0\0\1') 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: self.__buf.write('\0\0\0\0') 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_uhyper(self, x): 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(x>>32 & 0xffffffffL) 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(x & 0xffffffffL) 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_hyper = pack_uhyper 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_float(self, x): 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: self.__buf.write(struct.pack('>f', x)) 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except struct.error, msg: 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ConversionError, msg 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_double(self, x): 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: self.__buf.write(struct.pack('>d', x)) 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except struct.error, msg: 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ConversionError, msg 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_fstring(self, n, s): 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if n < 0: 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError, 'fstring size must be nonnegative' 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = s[:n] 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao n = ((n+3)//4)*4 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = data + (n - len(data)) * '\0' 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__buf.write(data) 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_fopaque = pack_fstring 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_string(self, s): 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao n = len(s) 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(n) 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_fstring(n, s) 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_opaque = pack_string 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_bytes = pack_string 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_list(self, list, pack_item): 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for item in list: 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(1) 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_item(item) 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(0) 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_farray(self, n, list, pack_item): 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(list) != n: 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError, 'wrong array size' 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for item in list: 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pack_item(item) 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pack_array(self, list, pack_item): 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao n = len(list) 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_uint(n) 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.pack_farray(n, list, pack_item) 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass Unpacker: 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Unpacks various data representations from the given buffer.""" 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, data): 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.reset(data) 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def reset(self, data): 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__buf = data 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = 0 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def get_position(self): 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.__pos 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def set_position(self, position): 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = position 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def get_buffer(self): 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.__buf 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def done(self): 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if self.__pos < len(self.__buf): 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise Error('unextracted data remains') 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_uint(self): 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = self.__pos 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = j = i+4 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = self.__buf[i:j] 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(data) < 4: 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise EOFError 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao x = struct.unpack('>L', data)[0] 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return int(x) 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except OverflowError: 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return x 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_int(self): 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = self.__pos 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = j = i+4 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = self.__buf[i:j] 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(data) < 4: 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise EOFError 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return struct.unpack('>l', data)[0] 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao unpack_enum = unpack_int 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_bool(self): 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return bool(self.unpack_int()) 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_uhyper(self): 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hi = self.unpack_uint() 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao lo = self.unpack_uint() 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return long(hi)<<32 | lo 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_hyper(self): 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao x = self.unpack_uhyper() 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if x >= 0x8000000000000000L: 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao x = x - 0x10000000000000000L 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return x 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_float(self): 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = self.__pos 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = j = i+4 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = self.__buf[i:j] 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(data) < 4: 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise EOFError 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return struct.unpack('>f', data)[0] 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_double(self): 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = self.__pos 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = j = i+8 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data = self.__buf[i:j] 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(data) < 8: 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise EOFError 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return struct.unpack('>d', data)[0] 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_fstring(self, n): 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if n < 0: 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError, 'fstring size must be nonnegative' 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao i = self.__pos 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao j = i + (n+3)//4*4 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if j > len(self.__buf): 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise EOFError 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__pos = j 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.__buf[i:i+n] 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao unpack_fopaque = unpack_fstring 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_string(self): 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao n = self.unpack_uint() 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.unpack_fstring(n) 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao unpack_opaque = unpack_string 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao unpack_bytes = unpack_string 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_list(self, unpack_item): 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao list = [] 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao while 1: 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao x = self.unpack_uint() 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if x == 0: break 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if x != 1: 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ConversionError, '0 or 1 expected, got %r' % (x,) 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao item = unpack_item() 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao list.append(item) 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return list 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_farray(self, n, unpack_item): 2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao list = [] 2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for i in range(n): 2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao list.append(unpack_item()) 2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return list 2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def unpack_array(self, unpack_item): 2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao n = self.unpack_uint() 2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return self.unpack_farray(n, unpack_item) 232