You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

marshal.py 6.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. """Marshal module written in Python.
  2. This doesn't marshal code objects, but supports everything else.
  3. Performance or careful error checking is not an issue.
  4. """
  5. import StringIO
  6. import string
  7. from types import *
  8. try:
  9. import new
  10. except ImportError:
  11. new = None
  12. TYPE_NULL = '0'
  13. TYPE_NONE = 'N'
  14. TYPE_ELLIPSIS = '.'
  15. TYPE_INT = 'i'
  16. TYPE_INT64 = 'I'
  17. TYPE_FLOAT = 'f'
  18. TYPE_COMPLEX = 'x'
  19. TYPE_LONG = 'l'
  20. TYPE_STRING = 's'
  21. TYPE_TUPLE = '('
  22. TYPE_LIST = '['
  23. TYPE_DICT = '{'
  24. TYPE_CODE = 'c'
  25. TYPE_UNKNOWN = '?'
  26. class Marshaller:
  27. dispatch = {}
  28. def __init__(self, f):
  29. self.f = f
  30. def dump(self, x):
  31. self.dispatch[type(x)](self, x)
  32. def w_long64(self, x):
  33. self.w_long(x)
  34. self.w_long(x>>32)
  35. def w_long(self, x):
  36. write = self.f.write
  37. write(chr((x) & 0xff))
  38. write(chr((x>> 8) & 0xff))
  39. write(chr((x>>16) & 0xff))
  40. write(chr((x>>24) & 0xff))
  41. def w_short(self, x):
  42. write = self.f.write
  43. write(chr((x) & 0xff))
  44. write(chr((x>> 8) & 0xff))
  45. def dump_none(self, x):
  46. self.f.write(TYPE_NONE)
  47. dispatch[NoneType] = dump_none
  48. def dump_ellipsis(self, x):
  49. self.f.write(TYPE_ELLIPSIS)
  50. try:
  51. dispatch[EllipsisType] = dump_ellipsis
  52. except NameError:
  53. pass
  54. def dump_int(self, x):
  55. y = x>>31
  56. if y and y != -1:
  57. self.f.write(TYPE_INT64)
  58. self.w_long64(x)
  59. else:
  60. self.f.write(TYPE_INT)
  61. self.w_long(x)
  62. dispatch[IntType] = dump_int
  63. def dump_long(self, x):
  64. self.f.write(TYPE_LONG)
  65. sign = 1
  66. if x < 0:
  67. sign = -1
  68. x = -x
  69. digits = []
  70. while x:
  71. digits.append(x & 0x7FFF)
  72. x = x>>15
  73. self.w_long(len(digits) * sign)
  74. for d in digits:
  75. self.w_short(d)
  76. dispatch[LongType] = dump_long
  77. def dump_float(self, x):
  78. write = self.f.write
  79. write(TYPE_FLOAT)
  80. s = `x`
  81. write(chr(len(s)))
  82. write(s)
  83. dispatch[FloatType] = dump_float
  84. def dump_complex(self, x):
  85. write = self.f.write
  86. write(TYPE_COMPLEX)
  87. s = `x.real`
  88. write(chr(len(s)))
  89. write(s)
  90. s = `x.imag`
  91. write(chr(len(s)))
  92. write(s)
  93. try:
  94. dispatch[ComplexType] = dump_complex
  95. except NameError:
  96. pass
  97. def dump_string(self, x):
  98. self.f.write(TYPE_STRING)
  99. self.w_long(len(x))
  100. self.f.write(x)
  101. dispatch[StringType] = dump_string
  102. def dump_tuple(self, x):
  103. self.f.write(TYPE_TUPLE)
  104. self.w_long(len(x))
  105. for item in x:
  106. self.dump(item)
  107. dispatch[TupleType] = dump_tuple
  108. def dump_list(self, x):
  109. self.f.write(TYPE_LIST)
  110. self.w_long(len(x))
  111. for item in x:
  112. self.dump(item)
  113. dispatch[ListType] = dump_list
  114. def dump_dict(self, x):
  115. self.f.write(TYPE_DICT)
  116. for key, value in x.items():
  117. self.dump(key)
  118. self.dump(value)
  119. self.f.write(TYPE_NULL)
  120. dispatch[DictionaryType] = dump_dict
  121. def dump_code(self, x):
  122. self.f.write(TYPE_CODE)
  123. self.w_short(x.co_argcount)
  124. self.w_short(x.co_nlocals)
  125. self.w_short(x.co_stacksize)
  126. self.w_short(x.co_flags)
  127. self.dump(x.co_code)
  128. self.dump(x.co_consts)
  129. self.dump(x.co_names)
  130. self.dump(x.co_varnames)
  131. self.dump(x.co_filename)
  132. self.dump(x.co_name)
  133. self.w_short(x.co_firstlineno)
  134. self.dump(x.co_lnotab)
  135. try:
  136. dispatch[CodeType] = dump_code
  137. except NameError:
  138. pass
  139. class NULL:
  140. pass
  141. class Unmarshaller:
  142. dispatch = {}
  143. def __init__(self, f):
  144. self.f = f
  145. def load(self):
  146. c = self.f.read(1)
  147. if not c:
  148. raise EOFError
  149. return self.dispatch[c](self)
  150. def r_short(self):
  151. read = self.f.read
  152. lo = ord(read(1))
  153. hi = ord(read(1))
  154. x = lo | (hi<<8)
  155. if x & 0x8000:
  156. x = x - 0x10000
  157. return x
  158. def r_long(self):
  159. read = self.f.read
  160. a = ord(read(1))
  161. b = ord(read(1))
  162. c = ord(read(1))
  163. d = ord(read(1))
  164. x = a | (b<<8) | (c<<16) | (d<<24)
  165. if x & 0x80000000 and x > 0:
  166. x = string.atoi(x - 0x100000000L)
  167. return x
  168. def r_long64(self):
  169. a = self.r_long()
  170. b = self.r_long()
  171. return a | (b<<32)
  172. def load_null(self):
  173. return NULL
  174. dispatch[TYPE_NULL] = load_null
  175. def load_none(self):
  176. return None
  177. dispatch[TYPE_NONE] = load_none
  178. def load_ellipsis(self):
  179. return EllipsisType
  180. dispatch[TYPE_ELLIPSIS] = load_ellipsis
  181. def load_int(self):
  182. return self.r_long()
  183. dispatch[TYPE_INT] = load_int
  184. def load_int64(self):
  185. return self.r_long64()
  186. dispatch[TYPE_INT64] = load_int64
  187. def load_long(self):
  188. size = self.r_long()
  189. sign = 1
  190. if size < 0:
  191. sign = -1
  192. size = -size
  193. x = 0L
  194. for i in range(size):
  195. d = self.r_short()
  196. x = x | (d<<(i*15L))
  197. return x * sign
  198. dispatch[TYPE_LONG] = load_long
  199. def load_float(self):
  200. n = ord(self.f.read(1))
  201. s = self.f.read(n)
  202. return string.atof(s)
  203. dispatch[TYPE_FLOAT] = load_float
  204. def load_complex(self):
  205. n = ord(self.f.read(1))
  206. s = self.f.read(n)
  207. real = float(s)
  208. n = ord(self.f.read(1))
  209. s = self.f.read(n)
  210. imag = float(s)
  211. return complex(real, imag)
  212. dispatch[TYPE_COMPLEX] = load_complex
  213. def load_string(self):
  214. n = self.r_long()
  215. return self.f.read(n)
  216. dispatch[TYPE_STRING] = load_string
  217. def load_tuple(self):
  218. return tuple(self.load_list())
  219. dispatch[TYPE_TUPLE] = load_tuple
  220. def load_list(self):
  221. n = self.r_long()
  222. list = []
  223. for i in range(n):
  224. list.append(self.load())
  225. return list
  226. dispatch[TYPE_LIST] = load_list
  227. def load_dict(self):
  228. d = {}
  229. while 1:
  230. key = self.load()
  231. if key is NULL:
  232. break
  233. value = self.load()
  234. d[key] = value
  235. return d
  236. dispatch[TYPE_DICT] = load_dict
  237. def load_code(self):
  238. argcount = self.r_short()
  239. nlocals = self.r_short()
  240. stacksize = self.r_short()
  241. flags = self.r_short()
  242. code = self.load()
  243. consts = self.load()
  244. names = self.load()
  245. varnames = self.load()
  246. filename = self.load()
  247. name = self.load()
  248. firstlineno = self.r_short()
  249. lnotab = self.load()
  250. if not new:
  251. raise RuntimeError, "can't unmarshal code objects; no 'new' module"
  252. return new.code(argcount, nlocals, stacksize, flags, code, consts,
  253. names, varnames, filename, name, firstlineno, lnotab)
  254. dispatch[TYPE_CODE] = load_code
  255. def dump(x, f):
  256. Marshaller(f).dump(x)
  257. def load(f):
  258. return Unmarshaller(f).load()
  259. def dumps(x):
  260. f = StringIO.StringIO()
  261. dump(x, f)
  262. return f.getvalue()
  263. def loads(s):
  264. f = StringIO.StringIO(s)
  265. return load(f)