/Demo/rpc/xdr.py

http://unladen-swallow.googlecode.com/ · Python · 200 lines · 149 code · 44 blank · 7 comment · 27 complexity · ed8b5f951f3b0f57e46a88632152dfe6 MD5 · raw file

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