PageRenderTime 39ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/zlib/interp_zlib.py

https://bitbucket.org/pypy/pypy/
Python | 355 lines | 278 code | 24 blank | 53 comment | 14 complexity | af569b6eaafbaa7c22dba2a4ee19c3b3 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. from pypy.interpreter.gateway import interp2app, unwrap_spec
  3. from pypy.interpreter.baseobjspace import W_Root
  4. from pypy.interpreter.typedef import TypeDef, interp_attrproperty
  5. from pypy.interpreter.error import OperationError, oefmt
  6. from rpython.rlib.rarithmetic import intmask, r_uint
  7. from rpython.rlib.objectmodel import keepalive_until_here
  8. from rpython.rlib import rzlib
  9. if intmask(2**31) == -2**31:
  10. # 32-bit platforms
  11. unsigned_to_signed_32bit = intmask
  12. else:
  13. # 64-bit platforms
  14. def unsigned_to_signed_32bit(x):
  15. # assumes that 'x' is in range(0, 2**32) to start with
  16. SIGN_EXTEND2 = 1 << 31
  17. return intmask((x ^ SIGN_EXTEND2) - SIGN_EXTEND2)
  18. @unwrap_spec(string='bufferstr', start='truncatedint_w')
  19. def crc32(space, string, start = rzlib.CRC32_DEFAULT_START):
  20. """
  21. crc32(string[, start]) -- Compute a CRC-32 checksum of string.
  22. An optional starting value can be specified. The returned checksum is
  23. an integer.
  24. """
  25. ustart = r_uint(start)
  26. checksum = rzlib.crc32(string, ustart)
  27. # This is, perhaps, a little stupid. zlib returns the checksum unsigned.
  28. # CPython exposes it as a signed value, though. -exarkun
  29. # Note that in CPython < 2.6 on 64-bit platforms the result is
  30. # actually unsigned, but it was considered to be a bug so we stick to
  31. # the 2.6 behavior and always return a number in range(-2**31, 2**31).
  32. checksum = unsigned_to_signed_32bit(checksum)
  33. return space.wrap(checksum)
  34. @unwrap_spec(string='bufferstr', start='truncatedint_w')
  35. def adler32(space, string, start=rzlib.ADLER32_DEFAULT_START):
  36. """
  37. adler32(string[, start]) -- Compute an Adler-32 checksum of string.
  38. An optional starting value can be specified. The returned checksum is
  39. an integer.
  40. """
  41. ustart = r_uint(start)
  42. checksum = rzlib.adler32(string, ustart)
  43. # See comments in crc32() for the following line
  44. checksum = unsigned_to_signed_32bit(checksum)
  45. return space.wrap(checksum)
  46. class Cache:
  47. def __init__(self, space):
  48. self.w_error = space.new_exception_class("zlib.error")
  49. def zlib_error(space, msg):
  50. w_error = space.fromcache(Cache).w_error
  51. return OperationError(w_error, space.wrap(msg))
  52. @unwrap_spec(string='bufferstr', level=int)
  53. def compress(space, string, level=rzlib.Z_DEFAULT_COMPRESSION):
  54. """
  55. compress(string[, level]) -- Returned compressed string.
  56. Optional arg level is the compression level, in 1-9.
  57. """
  58. try:
  59. try:
  60. stream = rzlib.deflateInit(level)
  61. except ValueError:
  62. raise zlib_error(space, "Bad compression level")
  63. try:
  64. result = rzlib.compress(stream, string, rzlib.Z_FINISH)
  65. finally:
  66. rzlib.deflateEnd(stream)
  67. except rzlib.RZlibError as e:
  68. raise zlib_error(space, e.msg)
  69. return space.wrap(result)
  70. @unwrap_spec(string='bufferstr', wbits="c_int", bufsize=int)
  71. def decompress(space, string, wbits=rzlib.MAX_WBITS, bufsize=0):
  72. """
  73. decompress(string[, wbits[, bufsize]]) -- Return decompressed string.
  74. Optional arg wbits is the window buffer size. Optional arg bufsize is
  75. only for compatibility with CPython and is ignored.
  76. """
  77. try:
  78. try:
  79. stream = rzlib.inflateInit(wbits)
  80. except ValueError:
  81. raise zlib_error(space, "Bad window buffer size")
  82. try:
  83. result, _, _ = rzlib.decompress(stream, string, rzlib.Z_FINISH)
  84. finally:
  85. rzlib.inflateEnd(stream)
  86. except rzlib.RZlibError as e:
  87. raise zlib_error(space, e.msg)
  88. return space.wrap(result)
  89. class ZLibObject(W_Root):
  90. """
  91. Common base class for Compress and Decompress.
  92. """
  93. stream = rzlib.null_stream
  94. def __init__(self, space):
  95. self._lock = space.allocate_lock()
  96. def lock(self):
  97. """To call before using self.stream."""
  98. self._lock.acquire(True)
  99. def unlock(self):
  100. """To call after using self.stream."""
  101. self._lock.release()
  102. keepalive_until_here(self)
  103. # subtle: we have to make sure that 'self' is not garbage-collected
  104. # while we are still using 'self.stream' - hence the keepalive.
  105. class Compress(ZLibObject):
  106. """
  107. Wrapper around zlib's z_stream structure which provides convenient
  108. compression functionality.
  109. """
  110. def __init__(self, space, level=rzlib.Z_DEFAULT_COMPRESSION,
  111. method=rzlib.Z_DEFLATED, # \
  112. wbits=rzlib.MAX_WBITS, # \ undocumented
  113. memLevel=rzlib.DEF_MEM_LEVEL, # / parameters
  114. strategy=rzlib.Z_DEFAULT_STRATEGY): # /
  115. ZLibObject.__init__(self, space)
  116. try:
  117. self.stream = rzlib.deflateInit(level, method, wbits,
  118. memLevel, strategy)
  119. except rzlib.RZlibError as e:
  120. raise zlib_error(space, e.msg)
  121. except ValueError:
  122. raise oefmt(space.w_ValueError, "Invalid initialization option")
  123. self.register_finalizer(space)
  124. def _finalize_(self):
  125. """Automatically free the resources used by the stream."""
  126. if self.stream:
  127. rzlib.deflateEnd(self.stream)
  128. self.stream = rzlib.null_stream
  129. @unwrap_spec(data='bufferstr')
  130. def compress(self, space, data):
  131. """
  132. compress(data) -- Return a string containing data compressed.
  133. After calling this function, some of the input data may still be stored
  134. in internal buffers for later processing.
  135. Call the flush() method to clear these buffers.
  136. """
  137. try:
  138. self.lock()
  139. try:
  140. if not self.stream:
  141. raise zlib_error(space,
  142. "compressor object already flushed")
  143. result = rzlib.compress(self.stream, data)
  144. finally:
  145. self.unlock()
  146. except rzlib.RZlibError as e:
  147. raise zlib_error(space, e.msg)
  148. return space.wrap(result)
  149. @unwrap_spec(mode="c_int")
  150. def flush(self, space, mode=rzlib.Z_FINISH):
  151. """
  152. flush( [mode] ) -- Return a string containing any remaining compressed
  153. data.
  154. mode can be one of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH;
  155. the default value used when mode is not specified is Z_FINISH.
  156. If mode == Z_FINISH, the compressor object can no longer be used after
  157. calling the flush() method. Otherwise, more data can still be
  158. compressed.
  159. """
  160. try:
  161. self.lock()
  162. try:
  163. if not self.stream:
  164. raise zlib_error(space,
  165. "compressor object already flushed")
  166. result = rzlib.compress(self.stream, '', mode)
  167. if mode == rzlib.Z_FINISH: # release the data structures now
  168. rzlib.deflateEnd(self.stream)
  169. self.stream = rzlib.null_stream
  170. finally:
  171. self.unlock()
  172. except rzlib.RZlibError as e:
  173. raise zlib_error(space, e.msg)
  174. return space.wrap(result)
  175. @unwrap_spec(level=int, method=int, wbits=int, memLevel=int, strategy=int)
  176. def Compress___new__(space, w_subtype, level=rzlib.Z_DEFAULT_COMPRESSION,
  177. method=rzlib.Z_DEFLATED, # \
  178. wbits=rzlib.MAX_WBITS, # \ undocumented
  179. memLevel=rzlib.DEF_MEM_LEVEL, # / parameters
  180. strategy=rzlib.Z_DEFAULT_STRATEGY): # /
  181. """
  182. Create a new z_stream and call its initializer.
  183. """
  184. stream = space.allocate_instance(Compress, w_subtype)
  185. stream = space.interp_w(Compress, stream)
  186. Compress.__init__(stream, space, level,
  187. method, wbits, memLevel, strategy)
  188. return space.wrap(stream)
  189. Compress.typedef = TypeDef(
  190. 'Compress',
  191. __new__ = interp2app(Compress___new__),
  192. compress = interp2app(Compress.compress),
  193. flush = interp2app(Compress.flush),
  194. __doc__ = """compressobj([level]) -- Return a compressor object.
  195. Optional arg level is the compression level, in 1-9.
  196. """)
  197. class Decompress(ZLibObject):
  198. """
  199. Wrapper around zlib's z_stream structure which provides convenient
  200. decompression functionality.
  201. """
  202. def __init__(self, space, wbits=rzlib.MAX_WBITS):
  203. """
  204. Initialize a new decompression object.
  205. wbits is an integer between 8 and MAX_WBITS or -8 and -MAX_WBITS
  206. (inclusive) giving the number of "window bits" to use for compression
  207. and decompression. See the documentation for deflateInit2 and
  208. inflateInit2.
  209. """
  210. ZLibObject.__init__(self, space)
  211. self.unused_data = ''
  212. self.unconsumed_tail = ''
  213. try:
  214. self.stream = rzlib.inflateInit(wbits)
  215. except rzlib.RZlibError as e:
  216. raise zlib_error(space, e.msg)
  217. except ValueError:
  218. raise oefmt(space.w_ValueError, "Invalid initialization option")
  219. self.register_finalizer(space)
  220. def _finalize_(self):
  221. """Automatically free the resources used by the stream."""
  222. if self.stream:
  223. rzlib.inflateEnd(self.stream)
  224. self.stream = rzlib.null_stream
  225. def _save_unconsumed_input(self, data, finished, unused_len):
  226. unused_start = len(data) - unused_len
  227. assert unused_start >= 0
  228. tail = data[unused_start:]
  229. if finished:
  230. self.unconsumed_tail = ''
  231. self.unused_data += tail
  232. else:
  233. self.unconsumed_tail = tail
  234. @unwrap_spec(data='bufferstr', max_length="c_int")
  235. def decompress(self, space, data, max_length=0):
  236. """
  237. decompress(data[, max_length]) -- Return a string containing the
  238. decompressed version of the data.
  239. If the max_length parameter is specified then the return value will be
  240. no longer than max_length. Unconsumed input data will be stored in the
  241. unconsumed_tail attribute.
  242. """
  243. if max_length == 0:
  244. max_length = sys.maxint
  245. elif max_length < 0:
  246. raise oefmt(space.w_ValueError,
  247. "max_length must be greater than zero")
  248. try:
  249. self.lock()
  250. try:
  251. result = rzlib.decompress(self.stream, data, max_length=max_length)
  252. finally:
  253. self.unlock()
  254. except rzlib.RZlibError as e:
  255. raise zlib_error(space, e.msg)
  256. string, finished, unused_len = result
  257. self._save_unconsumed_input(data, finished, unused_len)
  258. return space.wrap(string)
  259. def flush(self, space, w_length=None):
  260. """
  261. flush( [length] ) -- This is kept for backward compatibility,
  262. because each call to decompress() immediately returns as much
  263. data as possible.
  264. """
  265. if w_length is not None:
  266. length = space.c_int_w(w_length)
  267. if length <= 0:
  268. raise oefmt(space.w_ValueError,
  269. "length must be greater than zero")
  270. data = self.unconsumed_tail
  271. try:
  272. self.lock()
  273. try:
  274. result = rzlib.decompress(self.stream, data, rzlib.Z_FINISH)
  275. finally:
  276. self.unlock()
  277. except rzlib.RZlibError:
  278. string = ""
  279. else:
  280. string, finished, unused_len = result
  281. self._save_unconsumed_input(data, finished, unused_len)
  282. return space.wrap(string)
  283. @unwrap_spec(wbits=int)
  284. def Decompress___new__(space, w_subtype, wbits=rzlib.MAX_WBITS):
  285. """
  286. Create a new Decompress and call its initializer.
  287. """
  288. stream = space.allocate_instance(Decompress, w_subtype)
  289. stream = space.interp_w(Decompress, stream)
  290. Decompress.__init__(stream, space, wbits)
  291. return space.wrap(stream)
  292. Decompress.typedef = TypeDef(
  293. 'Decompress',
  294. __new__ = interp2app(Decompress___new__),
  295. decompress = interp2app(Decompress.decompress),
  296. flush = interp2app(Decompress.flush),
  297. unused_data = interp_attrproperty('unused_data', Decompress),
  298. unconsumed_tail = interp_attrproperty('unconsumed_tail', Decompress),
  299. __doc__ = """decompressobj([wbits]) -- Return a decompressor object.
  300. Optional arg wbits is the window buffer size.
  301. """)