PageRenderTime 43ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/struct/interp_struct.py

https://bitbucket.org/pypy/pypy/
Python | 147 lines | 113 code | 32 blank | 2 comment | 18 complexity | 2fbffaf13cefddb5926691d6abdfa7e9 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rlib import jit
  2. from rpython.rlib.buffer import SubBuffer
  3. from rpython.rlib.rstruct.error import StructError, StructOverflowError
  4. from rpython.rlib.rstruct.formatiterator import CalcSizeFormatIterator
  5. from pypy.interpreter.baseobjspace import W_Root
  6. from pypy.interpreter.gateway import interp2app, unwrap_spec
  7. from pypy.interpreter.error import OperationError, oefmt
  8. from pypy.interpreter.typedef import TypeDef, interp_attrproperty
  9. from pypy.module.struct.formatiterator import (
  10. PackFormatIterator, UnpackFormatIterator
  11. )
  12. class Cache:
  13. def __init__(self, space):
  14. self.error = space.new_exception_class("struct.error", space.w_Exception)
  15. def get_error(space):
  16. return space.fromcache(Cache).error
  17. def _calcsize(space, format):
  18. fmtiter = CalcSizeFormatIterator()
  19. try:
  20. fmtiter.interpret(format)
  21. except StructOverflowError as e:
  22. raise OperationError(space.w_OverflowError, space.wrap(e.msg))
  23. except StructError as e:
  24. raise OperationError(get_error(space), space.wrap(e.msg))
  25. return fmtiter.totalsize
  26. @unwrap_spec(format=str)
  27. def calcsize(space, format):
  28. return space.wrap(_calcsize(space, format))
  29. def _pack(space, format, args_w):
  30. if jit.isconstant(format):
  31. size = _calcsize(space, format)
  32. else:
  33. size = 8
  34. fmtiter = PackFormatIterator(space, args_w, size)
  35. try:
  36. fmtiter.interpret(format)
  37. except StructOverflowError as e:
  38. raise OperationError(space.w_OverflowError, space.wrap(e.msg))
  39. except StructError as e:
  40. raise OperationError(get_error(space), space.wrap(e.msg))
  41. return fmtiter.result.build()
  42. @unwrap_spec(format=str)
  43. def pack(space, format, args_w):
  44. return space.wrap(_pack(space, format, args_w))
  45. # XXX inefficient
  46. @unwrap_spec(format=str, offset=int)
  47. def pack_into(space, format, w_buffer, offset, args_w):
  48. res = _pack(space, format, args_w)
  49. buf = space.getarg_w('w*', w_buffer)
  50. if offset < 0:
  51. offset += buf.getlength()
  52. size = len(res)
  53. if offset < 0 or (buf.getlength() - offset) < size:
  54. raise oefmt(get_error(space),
  55. "pack_into requires a buffer of at least %d bytes",
  56. size)
  57. buf.setslice(offset, res)
  58. def _unpack(space, format, buf):
  59. fmtiter = UnpackFormatIterator(space, buf)
  60. try:
  61. fmtiter.interpret(format)
  62. except StructOverflowError as e:
  63. raise OperationError(space.w_OverflowError, space.wrap(e.msg))
  64. except StructError as e:
  65. raise OperationError(get_error(space), space.wrap(e.msg))
  66. return space.newtuple(fmtiter.result_w[:])
  67. @unwrap_spec(format=str)
  68. def unpack(space, format, w_str):
  69. buf = space.getarg_w('s*', w_str)
  70. return _unpack(space, format, buf)
  71. @unwrap_spec(format=str, offset=int)
  72. def unpack_from(space, format, w_buffer, offset=0):
  73. size = _calcsize(space, format)
  74. buf = space.getarg_w('z*', w_buffer)
  75. if buf is None:
  76. raise oefmt(get_error(space), "unpack_from requires a buffer argument")
  77. if offset < 0:
  78. offset += buf.getlength()
  79. if offset < 0 or (buf.getlength() - offset) < size:
  80. raise oefmt(get_error(space),
  81. "unpack_from requires a buffer of at least %d bytes",
  82. size)
  83. buf = SubBuffer(buf, offset, size)
  84. return _unpack(space, format, buf)
  85. class W_Struct(W_Root):
  86. _immutable_fields_ = ["format", "size"]
  87. def __init__(self, space, format):
  88. self.format = format
  89. self.size = _calcsize(space, format)
  90. @unwrap_spec(format=str)
  91. def descr__new__(space, w_subtype, format):
  92. self = space.allocate_instance(W_Struct, w_subtype)
  93. W_Struct.__init__(self, space, format)
  94. return self
  95. def descr_pack(self, space, args_w):
  96. return pack(space, jit.promote_string(self.format), args_w)
  97. @unwrap_spec(offset=int)
  98. def descr_pack_into(self, space, w_buffer, offset, args_w):
  99. return pack_into(space, jit.promote_string(self.format), w_buffer, offset, args_w)
  100. def descr_unpack(self, space, w_str):
  101. return unpack(space, jit.promote_string(self.format), w_str)
  102. @unwrap_spec(offset=int)
  103. def descr_unpack_from(self, space, w_buffer, offset=0):
  104. return unpack_from(space, jit.promote_string(self.format), w_buffer, offset)
  105. W_Struct.typedef = TypeDef("Struct",
  106. __new__=interp2app(W_Struct.descr__new__.im_func),
  107. format=interp_attrproperty("format", cls=W_Struct),
  108. size=interp_attrproperty("size", cls=W_Struct),
  109. pack=interp2app(W_Struct.descr_pack),
  110. unpack=interp2app(W_Struct.descr_unpack),
  111. pack_into=interp2app(W_Struct.descr_pack_into),
  112. unpack_from=interp2app(W_Struct.descr_unpack_from),
  113. )
  114. def clearcache(space):
  115. """No-op on PyPy"""