PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/module/cpyext/structmember.py

https://bitbucket.org/pypy/pypy/
Python | 128 lines | 117 code | 11 blank | 0 comment | 29 complexity | 840f3cca28f9ea0cdce9a3509dd666d6 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from pypy.interpreter.error import OperationError, oefmt
  2. from pypy.interpreter.typedef import TypeDef, GetSetProperty
  3. from rpython.rtyper.lltypesystem import rffi, lltype
  4. from pypy.module.cpyext.structmemberdefs import *
  5. from pypy.module.cpyext.api import ADDR, PyObjectP, cpython_api, CONST_STRING
  6. from pypy.module.cpyext.intobject import PyInt_AsLong, PyInt_AsUnsignedLong
  7. from pypy.module.cpyext.pyerrors import PyErr_Occurred
  8. from pypy.module.cpyext.pyobject import PyObject, Py_DecRef, from_ref, make_ref
  9. from pypy.module.cpyext.bytesobject import (
  10. PyString_FromString, PyString_FromStringAndSize)
  11. from pypy.module.cpyext.floatobject import PyFloat_AsDouble
  12. from pypy.module.cpyext.longobject import (
  13. PyLong_AsLongLong, PyLong_AsUnsignedLongLong, PyLong_AsSsize_t)
  14. from pypy.module.cpyext.typeobjectdefs import PyMemberDef
  15. from rpython.rlib.unroll import unrolling_iterable
  16. integer_converters = unrolling_iterable([
  17. (T_SHORT, rffi.SHORT, PyInt_AsLong),
  18. (T_INT, rffi.INT, PyInt_AsLong),
  19. (T_LONG, rffi.LONG, PyInt_AsLong),
  20. (T_USHORT, rffi.USHORT, PyInt_AsUnsignedLong),
  21. (T_UINT, rffi.UINT, PyInt_AsUnsignedLong),
  22. (T_ULONG, rffi.ULONG, PyInt_AsUnsignedLong),
  23. (T_BYTE, rffi.SIGNEDCHAR, PyInt_AsLong),
  24. (T_UBYTE, rffi.UCHAR, PyInt_AsUnsignedLong),
  25. (T_BOOL, rffi.UCHAR, PyInt_AsLong),
  26. (T_FLOAT, rffi.FLOAT, PyFloat_AsDouble),
  27. (T_DOUBLE, rffi.DOUBLE, PyFloat_AsDouble),
  28. (T_LONGLONG, rffi.LONGLONG, PyLong_AsLongLong),
  29. (T_ULONGLONG, rffi.ULONGLONG, PyLong_AsUnsignedLongLong),
  30. (T_PYSSIZET, rffi.SSIZE_T, PyLong_AsSsize_t),
  31. ])
  32. _HEADER = 'pypy_structmember_decl.h'
  33. @cpython_api([CONST_STRING, lltype.Ptr(PyMemberDef)], PyObject, header=_HEADER)
  34. def PyMember_GetOne(space, obj, w_member):
  35. addr = rffi.cast(ADDR, obj)
  36. addr += w_member.c_offset
  37. member_type = rffi.cast(lltype.Signed, w_member.c_type)
  38. for converter in integer_converters:
  39. typ, lltyp, _ = converter
  40. if typ == member_type:
  41. result = rffi.cast(rffi.CArrayPtr(lltyp), addr)
  42. if lltyp is rffi.FLOAT:
  43. w_result = space.wrap(lltype.cast_primitive(lltype.Float,
  44. result[0]))
  45. elif typ == T_BOOL:
  46. x = rffi.cast(lltype.Signed, result[0])
  47. w_result = space.wrap(x != 0)
  48. else:
  49. w_result = space.wrap(result[0])
  50. return w_result
  51. if member_type == T_STRING:
  52. result = rffi.cast(rffi.CCHARPP, addr)
  53. if result[0]:
  54. w_result = PyString_FromString(space, result[0])
  55. else:
  56. w_result = space.w_None
  57. elif member_type == T_STRING_INPLACE:
  58. result = rffi.cast(rffi.CCHARP, addr)
  59. w_result = PyString_FromString(space, result)
  60. elif member_type == T_CHAR:
  61. result = rffi.cast(rffi.CCHARP, addr)
  62. w_result = space.wrap(result[0])
  63. elif member_type == T_OBJECT:
  64. obj_ptr = rffi.cast(PyObjectP, addr)
  65. if obj_ptr[0]:
  66. w_result = from_ref(space, obj_ptr[0])
  67. else:
  68. w_result = space.w_None
  69. elif member_type == T_OBJECT_EX:
  70. obj_ptr = rffi.cast(PyObjectP, addr)
  71. if obj_ptr[0]:
  72. w_result = from_ref(space, obj_ptr[0])
  73. else:
  74. w_name = space.wrap(rffi.charp2str(w_member.c_name))
  75. raise OperationError(space.w_AttributeError, w_name)
  76. else:
  77. raise oefmt(space.w_SystemError, "bad memberdescr type")
  78. return w_result
  79. @cpython_api([rffi.CCHARP, lltype.Ptr(PyMemberDef), PyObject], rffi.INT_real,
  80. error=-1, header=_HEADER)
  81. def PyMember_SetOne(space, obj, w_member, w_value):
  82. addr = rffi.cast(ADDR, obj)
  83. addr += w_member.c_offset
  84. member_type = rffi.cast(lltype.Signed, w_member.c_type)
  85. flags = rffi.cast(lltype.Signed, w_member.c_flags)
  86. if (flags & READONLY or
  87. member_type in [T_STRING, T_STRING_INPLACE]):
  88. raise oefmt(space.w_TypeError, "readonly attribute")
  89. elif w_value is None:
  90. if member_type == T_OBJECT_EX:
  91. if not rffi.cast(PyObjectP, addr)[0]:
  92. w_name = space.wrap(rffi.charp2str(w_member.c_name))
  93. raise OperationError(space.w_AttributeError, w_name)
  94. elif member_type != T_OBJECT:
  95. raise oefmt(space.w_TypeError,
  96. "can't delete numeric/char attribute")
  97. for converter in integer_converters:
  98. typ, lltyp, getter = converter
  99. if typ == member_type:
  100. value = getter(space, w_value)
  101. array = rffi.cast(rffi.CArrayPtr(lltyp), addr)
  102. array[0] = rffi.cast(lltyp, value)
  103. return 0
  104. if member_type == T_CHAR:
  105. str_value = space.str_w(w_value)
  106. if len(str_value) != 1:
  107. raise oefmt(space.w_TypeError, "string of length 1 expected")
  108. array = rffi.cast(rffi.CCHARP, addr)
  109. array[0] = str_value[0]
  110. elif member_type in [T_OBJECT, T_OBJECT_EX]:
  111. array = rffi.cast(PyObjectP, addr)
  112. if array[0]:
  113. Py_DecRef(space, array[0])
  114. array[0] = make_ref(space, w_value)
  115. else:
  116. raise oefmt(space.w_SystemError, "bad memberdescr type")
  117. return 0