1"""Implements (a subset of) Sun XDR -- eXternal Data Representation. 2 3See: RFC 1014 4 5""" 6 7import struct 8try: 9 from cStringIO import StringIO as _StringIO 10except ImportError: 11 from StringIO import StringIO as _StringIO 12 13__all__ = ["Error", "Packer", "Unpacker", "ConversionError"] 14 15# exceptions 16class Error(Exception): 17 """Exception class for this module. Use: 18 19 except xdrlib.Error, var: 20 # var has the Error instance for the exception 21 22 Public ivars: 23 msg -- contains the message 24 25 """ 26 def __init__(self, msg): 27 self.msg = msg 28 def __repr__(self): 29 return repr(self.msg) 30 def __str__(self): 31 return str(self.msg) 32 33 34class ConversionError(Error): 35 pass 36 37 38 39class Packer: 40 """Pack various data representations into a buffer.""" 41 42 def __init__(self): 43 self.reset() 44 45 def reset(self): 46 self.__buf = _StringIO() 47 48 def get_buffer(self): 49 return self.__buf.getvalue() 50 # backwards compatibility 51 get_buf = get_buffer 52 53 def pack_uint(self, x): 54 self.__buf.write(struct.pack('>L', x)) 55 56 def pack_int(self, x): 57 self.__buf.write(struct.pack('>l', x)) 58 59 pack_enum = pack_int 60 61 def pack_bool(self, x): 62 if x: self.__buf.write('\0\0\0\1') 63 else: self.__buf.write('\0\0\0\0') 64 65 def pack_uhyper(self, x): 66 self.pack_uint(x>>32 & 0xffffffffL) 67 self.pack_uint(x & 0xffffffffL) 68 69 pack_hyper = pack_uhyper 70 71 def pack_float(self, x): 72 try: self.__buf.write(struct.pack('>f', x)) 73 except struct.error, msg: 74 raise ConversionError, msg 75 76 def pack_double(self, x): 77 try: self.__buf.write(struct.pack('>d', x)) 78 except struct.error, msg: 79 raise ConversionError, msg 80 81 def pack_fstring(self, n, s): 82 if n < 0: 83 raise ValueError, 'fstring size must be nonnegative' 84 data = s[:n] 85 n = ((n+3)//4)*4 86 data = data + (n - len(data)) * '\0' 87 self.__buf.write(data) 88 89 pack_fopaque = pack_fstring 90 91 def pack_string(self, s): 92 n = len(s) 93 self.pack_uint(n) 94 self.pack_fstring(n, s) 95 96 pack_opaque = pack_string 97 pack_bytes = pack_string 98 99 def pack_list(self, list, pack_item): 100 for item in list: 101 self.pack_uint(1) 102 pack_item(item) 103 self.pack_uint(0) 104 105 def pack_farray(self, n, list, pack_item): 106 if len(list) != n: 107 raise ValueError, 'wrong array size' 108 for item in list: 109 pack_item(item) 110 111 def pack_array(self, list, pack_item): 112 n = len(list) 113 self.pack_uint(n) 114 self.pack_farray(n, list, pack_item) 115 116 117 118class Unpacker: 119 """Unpacks various data representations from the given buffer.""" 120 121 def __init__(self, data): 122 self.reset(data) 123 124 def reset(self, data): 125 self.__buf = data 126 self.__pos = 0 127 128 def get_position(self): 129 return self.__pos 130 131 def set_position(self, position): 132 self.__pos = position 133 134 def get_buffer(self): 135 return self.__buf 136 137 def done(self): 138 if self.__pos < len(self.__buf): 139 raise Error('unextracted data remains') 140 141 def unpack_uint(self): 142 i = self.__pos 143 self.__pos = j = i+4 144 data = self.__buf[i:j] 145 if len(data) < 4: 146 raise EOFError 147 x = struct.unpack('>L', data)[0] 148 try: 149 return int(x) 150 except OverflowError: 151 return x 152 153 def unpack_int(self): 154 i = self.__pos 155 self.__pos = j = i+4 156 data = self.__buf[i:j] 157 if len(data) < 4: 158 raise EOFError 159 return struct.unpack('>l', data)[0] 160 161 unpack_enum = unpack_int 162 163 def unpack_bool(self): 164 return bool(self.unpack_int()) 165 166 def unpack_uhyper(self): 167 hi = self.unpack_uint() 168 lo = self.unpack_uint() 169 return long(hi)<<32 | lo 170 171 def unpack_hyper(self): 172 x = self.unpack_uhyper() 173 if x >= 0x8000000000000000L: 174 x = x - 0x10000000000000000L 175 return x 176 177 def unpack_float(self): 178 i = self.__pos 179 self.__pos = j = i+4 180 data = self.__buf[i:j] 181 if len(data) < 4: 182 raise EOFError 183 return struct.unpack('>f', data)[0] 184 185 def unpack_double(self): 186 i = self.__pos 187 self.__pos = j = i+8 188 data = self.__buf[i:j] 189 if len(data) < 8: 190 raise EOFError 191 return struct.unpack('>d', data)[0] 192 193 def unpack_fstring(self, n): 194 if n < 0: 195 raise ValueError, 'fstring size must be nonnegative' 196 i = self.__pos 197 j = i + (n+3)//4*4 198 if j > len(self.__buf): 199 raise EOFError 200 self.__pos = j 201 return self.__buf[i:i+n] 202 203 unpack_fopaque = unpack_fstring 204 205 def unpack_string(self): 206 n = self.unpack_uint() 207 return self.unpack_fstring(n) 208 209 unpack_opaque = unpack_string 210 unpack_bytes = unpack_string 211 212 def unpack_list(self, unpack_item): 213 list = [] 214 while 1: 215 x = self.unpack_uint() 216 if x == 0: break 217 if x != 1: 218 raise ConversionError, '0 or 1 expected, got %r' % (x,) 219 item = unpack_item() 220 list.append(item) 221 return list 222 223 def unpack_farray(self, n, unpack_item): 224 list = [] 225 for i in range(n): 226 list.append(unpack_item()) 227 return list 228 229 def unpack_array(self, unpack_item): 230 n = self.unpack_uint() 231 return self.unpack_farray(n, unpack_item) 232