PageRenderTime 36ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/struct/formatiterator.py

https://bitbucket.org/pypy/pypy/
Python | 161 lines | 131 code | 26 blank | 4 comment | 28 complexity | 4e5eaba6a1f4989cf4ef7bdf440f9085 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.objectmodel import specialize
  3. from rpython.rlib.rstring import StringBuilder
  4. from rpython.rlib.rstruct.error import StructError
  5. from rpython.rlib.rstruct.formatiterator import FormatIterator
  6. from pypy.interpreter.error import OperationError
  7. class PackFormatIterator(FormatIterator):
  8. def __init__(self, space, args_w, size):
  9. self.space = space
  10. self.args_w = args_w
  11. self.args_index = 0
  12. self.result = StringBuilder(size)
  13. # This *should* be always unroll safe, the only way to get here is by
  14. # unroll the interpret function, which means the fmt is const, and thus
  15. # this should be const (in theory ;)
  16. @jit.unroll_safe
  17. @specialize.arg(1)
  18. def operate(self, fmtdesc, repetitions):
  19. if fmtdesc.needcount:
  20. fmtdesc.pack(self, repetitions)
  21. else:
  22. for i in range(repetitions):
  23. fmtdesc.pack(self)
  24. _operate_is_specialized_ = True
  25. @jit.unroll_safe
  26. def align(self, mask):
  27. pad = (-self.result.getlength()) & mask
  28. self.result.append_multiple_char('\x00', pad)
  29. def finished(self):
  30. if self.args_index != len(self.args_w):
  31. raise StructError("too many arguments for struct format")
  32. def accept_obj_arg(self):
  33. try:
  34. w_obj = self.args_w[self.args_index]
  35. except IndexError:
  36. raise StructError("struct format requires more arguments")
  37. self.args_index += 1
  38. return w_obj
  39. def accept_int_arg(self):
  40. return self._accept_integral("int_w")
  41. def accept_uint_arg(self):
  42. return self._accept_integral("uint_w")
  43. def accept_longlong_arg(self):
  44. return self._accept_integral("r_longlong_w")
  45. def accept_ulonglong_arg(self):
  46. return self._accept_integral("r_ulonglong_w")
  47. @specialize.arg(1)
  48. def _accept_integral(self, meth):
  49. space = self.space
  50. w_obj = self.accept_obj_arg()
  51. if (space.isinstance_w(w_obj, space.w_int) or
  52. space.isinstance_w(w_obj, space.w_long)):
  53. w_index = w_obj
  54. else:
  55. w_index = None
  56. if space.lookup(w_obj, '__index__'):
  57. try:
  58. w_index = space.index(w_obj)
  59. except OperationError as e:
  60. if not e.match(space, space.w_TypeError):
  61. raise
  62. pass
  63. if w_index is None and space.lookup(w_obj, '__int__'):
  64. if space.isinstance_w(w_obj, space.w_float):
  65. msg = "integer argument expected, got float"
  66. else:
  67. msg = "integer argument expected, got non-integer" \
  68. " (implicit conversion using __int__ is deprecated)"
  69. space.warn(space.wrap(msg), space.w_DeprecationWarning)
  70. w_index = space.int(w_obj) # wrapped float -> wrapped int or long
  71. if w_index is None:
  72. raise StructError("cannot convert argument to integer")
  73. method = getattr(space, meth)
  74. try:
  75. return method(w_index)
  76. except OperationError as e:
  77. if e.match(self.space, self.space.w_OverflowError):
  78. raise StructError("argument out of range")
  79. raise
  80. def accept_bool_arg(self):
  81. w_obj = self.accept_obj_arg()
  82. return self.space.is_true(w_obj)
  83. def accept_str_arg(self):
  84. w_obj = self.accept_obj_arg()
  85. return self.space.str_w(w_obj)
  86. def accept_unicode_arg(self):
  87. w_obj = self.accept_obj_arg()
  88. return self.space.unicode_w(w_obj)
  89. def accept_float_arg(self):
  90. w_obj = self.accept_obj_arg()
  91. try:
  92. return self.space.float_w(w_obj)
  93. except OperationError as e:
  94. if e.match(self.space, self.space.w_TypeError):
  95. raise StructError("required argument is not a float")
  96. raise
  97. class UnpackFormatIterator(FormatIterator):
  98. def __init__(self, space, buf):
  99. self.space = space
  100. self.buf = buf
  101. self.length = buf.getlength()
  102. self.pos = 0
  103. self.result_w = [] # list of wrapped objects
  104. # See above comment on operate.
  105. @jit.unroll_safe
  106. @specialize.arg(1)
  107. def operate(self, fmtdesc, repetitions):
  108. if fmtdesc.needcount:
  109. fmtdesc.unpack(self, repetitions)
  110. else:
  111. for i in range(repetitions):
  112. fmtdesc.unpack(self)
  113. _operate_is_specialized_ = True
  114. def align(self, mask):
  115. self.pos = (self.pos + mask) & ~mask
  116. def finished(self):
  117. if self.pos != self.length:
  118. raise StructError("unpack str size too long for format")
  119. def read(self, count):
  120. end = self.pos + count
  121. if end > self.length:
  122. raise StructError("unpack str size too short for format")
  123. s = self.buf.getslice(self.pos, end, 1, count)
  124. self.pos = end
  125. return s
  126. @specialize.argtype(1)
  127. def appendobj(self, value):
  128. self.result_w.append(self.space.wrap(value))
  129. def get_pos(self):
  130. return self.pos
  131. def get_buffer_as_string_maybe(self):
  132. string, pos = self.buf.as_str_and_offset_maybe()
  133. return string, pos+self.pos
  134. def skip(self, size):
  135. self.read(size) # XXX, could avoid taking the slice