blob: fd9efee7f57c4e9b782273f19806179fa6f721c2 [file] [log] [blame]
Guido van Rossume3cafbe1992-12-14 23:25:04 +00001# Implement (a subset of) Sun XDR -- RFC1014.
2
3
Guido van Rossum7271bab1992-12-17 17:32:24 +00004try:
Tim Peterse6ddc8b2004-07-18 05:56:09 +00005 import struct
Guido van Rossum7271bab1992-12-17 17:32:24 +00006except ImportError:
Tim Peterse6ddc8b2004-07-18 05:56:09 +00007 struct = None
Guido van Rossume3cafbe1992-12-14 23:25:04 +00008
9
Collin Winter6f2df4d2007-07-17 20:59:35 +000010Long = type(0)
Guido van Rossum38625351992-12-15 21:43:59 +000011
12
Guido van Rossume3cafbe1992-12-14 23:25:04 +000013class Packer:
14
Tim Peterse6ddc8b2004-07-18 05:56:09 +000015 def __init__(self):
16 self.reset()
Guido van Rossume3cafbe1992-12-14 23:25:04 +000017
Tim Peterse6ddc8b2004-07-18 05:56:09 +000018 def reset(self):
19 self.buf = ''
Guido van Rossume3cafbe1992-12-14 23:25:04 +000020
Tim Peterse6ddc8b2004-07-18 05:56:09 +000021 def get_buf(self):
22 return self.buf
Guido van Rossume3cafbe1992-12-14 23:25:04 +000023
Tim Peterse6ddc8b2004-07-18 05:56:09 +000024 def pack_uint(self, x):
25 self.buf = self.buf + \
26 (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
27 chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
28 if struct and struct.pack('l', 1) == '\0\0\0\1':
29 def pack_uint(self, x):
30 if type(x) == Long:
Collin Winter6f2df4d2007-07-17 20:59:35 +000031 x = int((x + 0x80000000) % 0x100000000 \
32 - 0x80000000)
Tim Peterse6ddc8b2004-07-18 05:56:09 +000033 self.buf = self.buf + struct.pack('l', x)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000034
Tim Peterse6ddc8b2004-07-18 05:56:09 +000035 pack_int = pack_uint
Guido van Rossume3cafbe1992-12-14 23:25:04 +000036
Tim Peterse6ddc8b2004-07-18 05:56:09 +000037 pack_enum = pack_int
Guido van Rossume3cafbe1992-12-14 23:25:04 +000038
Tim Peterse6ddc8b2004-07-18 05:56:09 +000039 def pack_bool(self, x):
40 if x: self.buf = self.buf + '\0\0\0\1'
41 else: self.buf = self.buf + '\0\0\0\0'
Guido van Rossume3cafbe1992-12-14 23:25:04 +000042
Tim Peterse6ddc8b2004-07-18 05:56:09 +000043 def pack_uhyper(self, x):
44 self.pack_uint(int(x>>32 & 0xffffffff))
45 self.pack_uint(int(x & 0xffffffff))
Guido van Rossume3cafbe1992-12-14 23:25:04 +000046
Tim Peterse6ddc8b2004-07-18 05:56:09 +000047 pack_hyper = pack_uhyper
Guido van Rossume3cafbe1992-12-14 23:25:04 +000048
Tim Peterse6ddc8b2004-07-18 05:56:09 +000049 def pack_float(self, x):
50 # XXX
51 self.buf = self.buf + struct.pack('f', x)
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000052
Tim Peterse6ddc8b2004-07-18 05:56:09 +000053 def pack_double(self, x):
54 # XXX
55 self.buf = self.buf + struct.pack('d', x)
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000056
Tim Peterse6ddc8b2004-07-18 05:56:09 +000057 def pack_fstring(self, n, s):
58 if n < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +000059 raise ValueError('fstring size must be nonnegative')
Tim Peterse6ddc8b2004-07-18 05:56:09 +000060 n = ((n+3)/4)*4
61 data = s[:n]
62 data = data + (n - len(data)) * '\0'
63 self.buf = self.buf + data
Guido van Rossume3cafbe1992-12-14 23:25:04 +000064
Tim Peterse6ddc8b2004-07-18 05:56:09 +000065 pack_fopaque = pack_fstring
Guido van Rossume3cafbe1992-12-14 23:25:04 +000066
Tim Peterse6ddc8b2004-07-18 05:56:09 +000067 def pack_string(self, s):
68 n = len(s)
69 self.pack_uint(n)
70 self.pack_fstring(n, s)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000071
Tim Peterse6ddc8b2004-07-18 05:56:09 +000072 pack_opaque = pack_string
Guido van Rossume3cafbe1992-12-14 23:25:04 +000073
Tim Peterse6ddc8b2004-07-18 05:56:09 +000074 def pack_list(self, list, pack_item):
75 for item in list:
76 self.pack_uint(1)
77 pack_item(item)
78 self.pack_uint(0)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000079
Tim Peterse6ddc8b2004-07-18 05:56:09 +000080 def pack_farray(self, n, list, pack_item):
Neal Norwitz3bd844e2006-08-29 04:39:12 +000081 if len(list) != n:
Collin Winter6f2df4d2007-07-17 20:59:35 +000082 raise ValueError('wrong array size')
Tim Peterse6ddc8b2004-07-18 05:56:09 +000083 for item in list:
84 pack_item(item)
Guido van Rossuma3b986e1992-12-21 14:33:18 +000085
Tim Peterse6ddc8b2004-07-18 05:56:09 +000086 def pack_array(self, list, pack_item):
87 n = len(list)
88 self.pack_uint(n)
89 self.pack_farray(n, list, pack_item)
Guido van Rossuma3b986e1992-12-21 14:33:18 +000090
Guido van Rossume3cafbe1992-12-14 23:25:04 +000091
92class Unpacker:
93
Tim Peterse6ddc8b2004-07-18 05:56:09 +000094 def __init__(self, data):
95 self.reset(data)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000096
Tim Peterse6ddc8b2004-07-18 05:56:09 +000097 def reset(self, data):
98 self.buf = data
99 self.pos = 0
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000100
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000101 def done(self):
102 if self.pos < len(self.buf):
Collin Winter6f2df4d2007-07-17 20:59:35 +0000103 raise RuntimeError('unextracted data remains')
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000104
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000105 def unpack_uint(self):
106 i = self.pos
107 self.pos = j = i+4
108 data = self.buf[i:j]
109 if len(data) < 4:
110 raise EOFError
Collin Winter6f2df4d2007-07-17 20:59:35 +0000111 x = int(ord(data[0]))<<24 | ord(data[1])<<16 | \
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000112 ord(data[2])<<8 | ord(data[3])
113 # Return a Python long only if the value is not representable
114 # as a nonnegative Python int
Collin Winter6f2df4d2007-07-17 20:59:35 +0000115 if x < 0x80000000: x = int(x)
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000116 return x
117 if struct and struct.unpack('l', '\0\0\0\1') == 1:
118 def unpack_uint(self):
119 i = self.pos
120 self.pos = j = i+4
121 data = self.buf[i:j]
122 if len(data) < 4:
123 raise EOFError
124 return struct.unpack('l', data)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000125
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000126 def unpack_int(self):
127 x = self.unpack_uint()
Collin Winter6f2df4d2007-07-17 20:59:35 +0000128 if x >= 0x80000000: x = x - 0x100000000
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000129 return int(x)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000130
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000131 unpack_enum = unpack_int
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000132
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000133 unpack_bool = unpack_int
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000134
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000135 def unpack_uhyper(self):
136 hi = self.unpack_uint()
137 lo = self.unpack_uint()
Collin Winter6f2df4d2007-07-17 20:59:35 +0000138 return int(hi)<<32 | lo
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000139
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000140 def unpack_hyper(self):
141 x = self.unpack_uhyper()
Collin Winter6f2df4d2007-07-17 20:59:35 +0000142 if x >= 0x8000000000000000: x = x - 0x10000000000000000
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000143 return x
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000144
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000145 def unpack_float(self):
146 # XXX
147 i = self.pos
148 self.pos = j = i+4
149 data = self.buf[i:j]
150 if len(data) < 4:
151 raise EOFError
152 return struct.unpack('f', data)[0]
Guido van Rossum9e80d6f1993-12-17 14:32:26 +0000153
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000154 def unpack_double(self):
155 # XXX
156 i = self.pos
157 self.pos = j = i+8
158 data = self.buf[i:j]
159 if len(data) < 8:
160 raise EOFError
161 return struct.unpack('d', data)[0]
Guido van Rossum9e80d6f1993-12-17 14:32:26 +0000162
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000163 def unpack_fstring(self, n):
164 if n < 0:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000165 raise ValueError('fstring size must be nonnegative')
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000166 i = self.pos
167 j = i + (n+3)/4*4
168 if j > len(self.buf):
169 raise EOFError
170 self.pos = j
171 return self.buf[i:i+n]
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000172
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000173 unpack_fopaque = unpack_fstring
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000174
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000175 def unpack_string(self):
176 n = self.unpack_uint()
177 return self.unpack_fstring(n)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000178
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000179 unpack_opaque = unpack_string
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000180
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000181 def unpack_list(self, unpack_item):
182 list = []
183 while 1:
184 x = self.unpack_uint()
185 if x == 0: break
Neal Norwitz3bd844e2006-08-29 04:39:12 +0000186 if x != 1:
Collin Winter6f2df4d2007-07-17 20:59:35 +0000187 raise RuntimeError('0 or 1 expected, got %r' % (x, ))
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000188 item = unpack_item()
189 list.append(item)
190 return list
Guido van Rossuma3b986e1992-12-21 14:33:18 +0000191
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000192 def unpack_farray(self, n, unpack_item):
193 list = []
194 for i in range(n):
195 list.append(unpack_item())
196 return list
Guido van Rossuma3b986e1992-12-21 14:33:18 +0000197
Tim Peterse6ddc8b2004-07-18 05:56:09 +0000198 def unpack_array(self, unpack_item):
199 n = self.unpack_uint()
200 return self.unpack_farray(n, unpack_item)