blob: 41c970ae91cdef5862ddaa4da22bd835cb8555a0 [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:
5 import struct
6except ImportError:
7 struct = None
Guido van Rossume3cafbe1992-12-14 23:25:04 +00008
9
Guido van Rossum38625351992-12-15 21:43:59 +000010Long = type(0L)
11
12
Guido van Rossume3cafbe1992-12-14 23:25:04 +000013class Packer:
14
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000015 def __init__(self):
Guido van Rossume3cafbe1992-12-14 23:25:04 +000016 self.reset()
Guido van Rossume3cafbe1992-12-14 23:25:04 +000017
18 def reset(self):
19 self.buf = ''
20
21 def get_buf(self):
22 return self.buf
23
24 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)))
Guido van Rossum7271bab1992-12-17 17:32:24 +000028 if struct and struct.pack('l', 1) == '\0\0\0\1':
Guido van Rossume3cafbe1992-12-14 23:25:04 +000029 def pack_uint(self, x):
Guido van Rossum38625351992-12-15 21:43:59 +000030 if type(x) == Long:
31 x = int((x + 0x80000000L) % 0x100000000L \
32 - 0x80000000L)
33 self.buf = self.buf + struct.pack('l', x)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000034
35 pack_int = pack_uint
36
37 pack_enum = pack_int
38
39 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'
42
43 def pack_uhyper(self, x):
Guido van Rossum38625351992-12-15 21:43:59 +000044 self.pack_uint(int(x>>32 & 0xffffffff))
45 self.pack_uint(int(x & 0xffffffff))
Guido van Rossume3cafbe1992-12-14 23:25:04 +000046
47 pack_hyper = pack_uhyper
48
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000049 def pack_float(self, x):
50 # XXX
51 self.buf = self.buf + struct.pack('f', x)
52
53 def pack_double(self, x):
54 # XXX
55 self.buf = self.buf + struct.pack('d', x)
56
Guido van Rossume3cafbe1992-12-14 23:25:04 +000057 def pack_fstring(self, n, s):
58 if n < 0:
59 raise ValueError, 'fstring size must be nonnegative'
60 n = ((n+3)/4)*4
61 data = s[:n]
62 data = data + (n - len(data)) * '\0'
63 self.buf = self.buf + data
64
65 pack_fopaque = pack_fstring
66
67 def pack_string(self, s):
68 n = len(s)
69 self.pack_uint(n)
70 self.pack_fstring(n, s)
71
Guido van Rossum5e6a3561995-10-11 18:54:15 +000072 pack_opaque = pack_string
Guido van Rossume3cafbe1992-12-14 23:25:04 +000073
74 def pack_list(self, list, pack_item):
75 for item in list:
76 self.pack_uint(1)
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000077 pack_item(item)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000078 self.pack_uint(0)
79
Guido van Rossuma3b986e1992-12-21 14:33:18 +000080 def pack_farray(self, n, list, pack_item):
81 if len(list) <> n:
82 raise ValueError, 'wrong array size'
83 for item in list:
84 pack_item(item)
85
86 def pack_array(self, list, pack_item):
87 n = len(list)
88 self.pack_uint(n)
Guido van Rossumee3de2a1995-10-04 18:39:03 +000089 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
Guido van Rossum9e80d6f1993-12-17 14:32:26 +000094 def __init__(self, data):
Guido van Rossume3cafbe1992-12-14 23:25:04 +000095 self.reset(data)
Guido van Rossume3cafbe1992-12-14 23:25:04 +000096
97 def reset(self, data):
98 self.buf = data
99 self.pos = 0
100
101 def done(self):
102 if self.pos < len(self.buf):
103 raise RuntimeError, 'unextracted data remains'
104
105 def unpack_uint(self):
106 i = self.pos
107 self.pos = j = i+4
108 data = self.buf[i:j]
Guido van Rossumc91d60a1992-12-19 00:06:17 +0000109 if len(data) < 4:
110 raise EOFError
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000111 x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \
112 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
115 if x < 0x80000000L: x = int(x)
116 return x
Guido van Rossum7271bab1992-12-17 17:32:24 +0000117 if struct and struct.unpack('l', '\0\0\0\1') == 1:
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000118 def unpack_uint(self):
119 i = self.pos
120 self.pos = j = i+4
Guido van Rossumc91d60a1992-12-19 00:06:17 +0000121 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
126 def unpack_int(self):
127 x = self.unpack_uint()
128 if x >= 0x80000000L: x = x - 0x100000000L
129 return int(x)
130
131 unpack_enum = unpack_int
132
133 unpack_bool = unpack_int
134
135 def unpack_uhyper(self):
136 hi = self.unpack_uint()
137 lo = self.unpack_uint()
138 return long(hi)<<32 | lo
139
140 def unpack_hyper(self):
141 x = self.unpack_uhyper()
142 if x >= 0x8000000000000000L: x = x - 0x10000000000000000L
143 return x
144
Guido van Rossum9e80d6f1993-12-17 14:32:26 +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]
153
154 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
Fred Drake5b8b8cd1998-01-28 14:59:48 +0000161 return struct.unpack('d', data)[0]
Guido van Rossum9e80d6f1993-12-17 14:32:26 +0000162
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000163 def unpack_fstring(self, n):
164 if n < 0:
165 raise ValueError, 'fstring size must be nonnegative'
166 i = self.pos
167 j = i + (n+3)/4*4
168 if j > len(self.buf):
Guido van Rossumc91d60a1992-12-19 00:06:17 +0000169 raise EOFError
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000170 self.pos = j
171 return self.buf[i:i+n]
172
173 unpack_fopaque = unpack_fstring
174
175 def unpack_string(self):
176 n = self.unpack_uint()
177 return self.unpack_fstring(n)
178
Guido van Rossum5e6a3561995-10-11 18:54:15 +0000179 unpack_opaque = unpack_string
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000180
181 def unpack_list(self, unpack_item):
182 list = []
183 while 1:
184 x = self.unpack_uint()
Guido van Rossum9e80d6f1993-12-17 14:32:26 +0000185 if x == 0: break
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000186 if x <> 1:
187 raise RuntimeError, \
188 '0 or 1 expected, got ' + `x`
Guido van Rossum9e80d6f1993-12-17 14:32:26 +0000189 item = unpack_item()
190 list.append(item)
Guido van Rossume3cafbe1992-12-14 23:25:04 +0000191 return list
Guido van Rossuma3b986e1992-12-21 14:33:18 +0000192
193 def unpack_farray(self, n, unpack_item):
194 list = []
195 for i in range(n):
196 list.append(unpack_item())
197 return list
198
199 def unpack_array(self, unpack_item):
200 n = self.unpack_uint()
201 return self.unpack_farray(n, unpack_item)