PageRenderTime 60ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/_cffi_backend/ctypeenum.py

https://bitbucket.org/jerith/pypy
Python | 88 lines | 74 code | 11 blank | 3 comment | 15 complexity | 08bb0e8362a039ff2ccf7048dd9b8b13 MD5 | raw file
  1. """
  2. Enums.
  3. """
  4. from pypy.interpreter.error import OperationError, operationerrfmt
  5. from pypy.rpython.lltypesystem import rffi
  6. from pypy.rlib.rarithmetic import intmask, r_ulonglong
  7. from pypy.rlib.objectmodel import keepalive_until_here
  8. from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned
  9. from pypy.module._cffi_backend import misc
  10. class W_CTypeEnum(W_CTypePrimitiveSigned):
  11. _attrs_ = ['enumerators2values', 'enumvalues2erators']
  12. _immutable_fields_ = ['enumerators2values', 'enumvalues2erators']
  13. def __init__(self, space, name, enumerators, enumvalues):
  14. from pypy.module._cffi_backend.newtype import alignment
  15. name = "enum " + name
  16. size = rffi.sizeof(rffi.INT)
  17. align = alignment(rffi.INT)
  18. W_CTypePrimitiveSigned.__init__(self, space, size,
  19. name, len(name), align)
  20. self.enumerators2values = {} # str -> int
  21. self.enumvalues2erators = {} # int -> str
  22. for i in range(len(enumerators)-1, -1, -1):
  23. self.enumerators2values[enumerators[i]] = enumvalues[i]
  24. self.enumvalues2erators[enumvalues[i]] = enumerators[i]
  25. def _getfields(self):
  26. space = self.space
  27. lst = []
  28. for enumerator in self.enumerators2values:
  29. enumvalue = self.enumerators2values[enumerator]
  30. lst.append(space.newtuple([space.wrap(enumvalue),
  31. space.wrap(enumerator)]))
  32. w_lst = space.newlist(lst)
  33. space.call_method(w_lst, 'sort')
  34. return w_lst
  35. def string(self, cdataobj, maxlen):
  36. w_result = self.convert_to_object(cdataobj._cdata)
  37. keepalive_until_here(cdataobj)
  38. return w_result
  39. def convert_to_object(self, cdata):
  40. value = misc.read_raw_long_data(cdata, self.size)
  41. try:
  42. enumerator = self.enumvalues2erators[value]
  43. except KeyError:
  44. enumerator = '#%d' % (value,)
  45. return self.space.wrap(enumerator)
  46. def convert_from_object(self, cdata, w_ob):
  47. space = self.space
  48. try:
  49. return W_CTypePrimitiveSigned.convert_from_object(self, cdata,
  50. w_ob)
  51. except OperationError, e:
  52. if not e.match(space, space.w_TypeError):
  53. raise
  54. if space.isinstance_w(w_ob, space.w_str):
  55. value = self.convert_enum_string_to_int(space.str_w(w_ob))
  56. value = r_ulonglong(value)
  57. misc.write_raw_integer_data(cdata, value, self.size)
  58. else:
  59. raise self._convert_error("str or int", w_ob)
  60. def cast_str(self, w_ob):
  61. space = self.space
  62. return self.convert_enum_string_to_int(space.str_w(w_ob))
  63. def convert_enum_string_to_int(self, s):
  64. space = self.space
  65. if s.startswith('#'):
  66. try:
  67. return int(s[1:]) # xxx is it RPython?
  68. except ValueError:
  69. raise OperationError(space.w_ValueError,
  70. space.wrap("invalid literal after '#'"))
  71. else:
  72. try:
  73. return self.enumerators2values[s]
  74. except KeyError:
  75. raise operationerrfmt(space.w_ValueError,
  76. "'%s' is not an enumerator for %s",
  77. s, self.name)