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