1 | """Implements (a subset of) Sun XDR -- eXternal Data Representation.
|
---|
2 |
|
---|
3 | See: RFC 1014
|
---|
4 |
|
---|
5 | """
|
---|
6 |
|
---|
7 | import struct
|
---|
8 | try:
|
---|
9 | from cStringIO import StringIO as _StringIO
|
---|
10 | except ImportError:
|
---|
11 | from StringIO import StringIO as _StringIO
|
---|
12 |
|
---|
13 | __all__ = ["Error", "Packer", "Unpacker", "ConversionError"]
|
---|
14 |
|
---|
15 | # exceptions
|
---|
16 | class 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 |
|
---|
34 | class ConversionError(Error):
|
---|
35 | pass
|
---|
36 |
|
---|
37 |
|
---|
38 |
|
---|
39 | class 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 |
|
---|
118 | class 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)
|
---|