blob: b189b450ee0dca40e65f34acc59bbd29fab50ade [file] [log] [blame]
Guido van Rossume3cafbe1992-12-14 23:25:04 +00001# Implement (a subset of) Sun XDR -- RFC1014.
2
3
4import struct
5
6
7class Packer:
8
9 def init(self):
10 self.reset()
11 return self
12
13 def reset(self):
14 self.buf = ''
15
16 def get_buf(self):
17 return self.buf
18
19 def pack_uint(self, x):
20 self.buf = self.buf + \
21 (chr(int(x>>24 & 0xff)) + chr(int(x>>16 & 0xff)) + \
22 chr(int(x>>8 & 0xff)) + chr(int(x & 0xff)))
23 if struct.pack('i', 1) == '\0\0\0\1':
24 def pack_uint(self, x):
25 self.buf = self.buf + struct.pack('i', x)
26
27 pack_int = pack_uint
28
29 pack_enum = pack_int
30
31 def pack_bool(self, x):
32 if x: self.buf = self.buf + '\0\0\0\1'
33 else: self.buf = self.buf + '\0\0\0\0'
34
35 def pack_uhyper(self, x):
36 self.pack_uint(x>>32 & 0xffffffff)
37 self.pack_uint(x & 0xffffffff)
38
39 pack_hyper = pack_uhyper
40
41 def pack_fstring(self, n, s):
42 if n < 0:
43 raise ValueError, 'fstring size must be nonnegative'
44 n = ((n+3)/4)*4
45 data = s[:n]
46 data = data + (n - len(data)) * '\0'
47 self.buf = self.buf + data
48
49 pack_fopaque = pack_fstring
50
51 def pack_string(self, s):
52 n = len(s)
53 self.pack_uint(n)
54 self.pack_fstring(n, s)
55
56 pack_opaque = pack_string
57
58 def pack_list(self, list, pack_item):
59 for item in list:
60 self.pack_uint(1)
61 pack_item(list)
62 self.pack_uint(0)
63
64
65class Unpacker:
66
67 def init(self, data):
68 self.reset(data)
69 return self
70
71 def reset(self, data):
72 self.buf = data
73 self.pos = 0
74
75 def done(self):
76 if self.pos < len(self.buf):
77 raise RuntimeError, 'unextracted data remains'
78
79 def unpack_uint(self):
80 i = self.pos
81 self.pos = j = i+4
82 data = self.buf[i:j]
83 x = long(ord(data[0]))<<24 | ord(data[1])<<16 | \
84 ord(data[2])<<8 | ord(data[3])
85 # Return a Python long only if the value is not representable
86 # as a nonnegative Python int
87 if x < 0x80000000L: x = int(x)
88 return x
89 if struct.unpack('i', '\0\0\0\1') == 1:
90 def unpack_uint(self):
91 i = self.pos
92 self.pos = j = i+4
93 return struct.unpack('i', self.buf[i:j])
94
95 def unpack_int(self):
96 x = self.unpack_uint()
97 if x >= 0x80000000L: x = x - 0x100000000L
98 return int(x)
99
100 unpack_enum = unpack_int
101
102 unpack_bool = unpack_int
103
104 def unpack_uhyper(self):
105 hi = self.unpack_uint()
106 lo = self.unpack_uint()
107 return long(hi)<<32 | lo
108
109 def unpack_hyper(self):
110 x = self.unpack_uhyper()
111 if x >= 0x8000000000000000L: x = x - 0x10000000000000000L
112 return x
113
114 def unpack_fstring(self, n):
115 if n < 0:
116 raise ValueError, 'fstring size must be nonnegative'
117 i = self.pos
118 j = i + (n+3)/4*4
119 if j > len(self.buf):
120 raise RuntimeError, 'buffer overrun'
121 self.pos = j
122 return self.buf[i:i+n]
123
124 unpack_fopaque = unpack_fstring
125
126 def unpack_string(self):
127 n = self.unpack_uint()
128 return self.unpack_fstring(n)
129
130 unpack_opaque = unpack_string
131
132 def unpack_list(self, unpack_item):
133 list = []
134 while 1:
135 x = self.unpack_uint()
136 if not x: break
137 if x <> 1:
138 raise RuntimeError, \
139 '0 or 1 expected, got ' + `x`
140 list.append(unpack_item())
141 return list