1 | # Implement (a subset of) Sun XDR -- RFC1014.
|
---|
2 |
|
---|
3 |
|
---|
4 | try:
|
---|
5 | import struct
|
---|
6 | except ImportError:
|
---|
7 | struct = None
|
---|
8 |
|
---|
9 |
|
---|
10 | Long = type(0L)
|
---|
11 |
|
---|
12 |
|
---|
13 | class Packer:
|
---|
14 |
|
---|
15 | def __init__(self):
|
---|
16 | self.reset()
|
---|
17 |
|
---|
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)))
|
---|
28 | if struct and struct.pack('l', 1) == '\0\0\0\1':
|
---|
29 | def pack_uint(self, x):
|
---|
30 | if type(x) == Long:
|
---|
31 | x = int((x + 0x80000000L) % 0x100000000L \
|
---|
32 | - 0x80000000L)
|
---|
33 | self.buf = self.buf + struct.pack('l', x)
|
---|
34 |
|
---|
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):
|
---|
44 | self.pack_uint(int(x>>32 & 0xffffffff))
|
---|
45 | self.pack_uint(int(x & 0xffffffff))
|
---|
46 |
|
---|
47 | pack_hyper = pack_uhyper
|
---|
48 |
|
---|
49 | 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 |
|
---|
57 | 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 |
|
---|
72 | pack_opaque = pack_string
|
---|
73 |
|
---|
74 | 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)
|
---|
79 |
|
---|
80 | 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)
|
---|
89 | self.pack_farray(n, list, pack_item)
|
---|
90 |
|
---|
91 |
|
---|
92 | class Unpacker:
|
---|
93 |
|
---|
94 | def __init__(self, data):
|
---|
95 | self.reset(data)
|
---|
96 |
|
---|
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]
|
---|
109 | if len(data) < 4:
|
---|
110 | raise EOFError
|
---|
111 | 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
|
---|
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)
|
---|
125 |
|
---|
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 |
|
---|
145 | 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
|
---|
161 | return struct.unpack('d', data)[0]
|
---|
162 |
|
---|
163 | 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):
|
---|
169 | raise EOFError
|
---|
170 | 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 |
|
---|
179 | unpack_opaque = unpack_string
|
---|
180 |
|
---|
181 | def unpack_list(self, unpack_item):
|
---|
182 | list = []
|
---|
183 | while 1:
|
---|
184 | x = self.unpack_uint()
|
---|
185 | if x == 0: break
|
---|
186 | if x <> 1:
|
---|
187 | raise RuntimeError, '0 or 1 expected, got %r' % (x, )
|
---|
188 | item = unpack_item()
|
---|
189 | list.append(item)
|
---|
190 | return list
|
---|
191 |
|
---|
192 | def unpack_farray(self, n, unpack_item):
|
---|
193 | list = []
|
---|
194 | for i in range(n):
|
---|
195 | list.append(unpack_item())
|
---|
196 | return list
|
---|
197 |
|
---|
198 | def unpack_array(self, unpack_item):
|
---|
199 | n = self.unpack_uint()
|
---|
200 | return self.unpack_farray(n, unpack_item)
|
---|