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

/pypy/module/cpyext/intobject.py

https://bitbucket.org/pypy/pypy/
Python | 161 lines | 150 code | 7 blank | 4 comment | 0 complexity | c6908ab53a07b45f281a8a0739063717 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rtyper.lltypesystem import rffi, lltype
  2. from pypy.interpreter.error import oefmt
  3. from pypy.module.cpyext.api import (
  4. cpython_api, cpython_struct, build_type_checkers, bootstrap_function,
  5. PyObject, PyObjectFields, CONST_STRING, CANNOT_FAIL, Py_ssize_t)
  6. from pypy.module.cpyext.pyobject import (
  7. make_typedescr, track_reference, from_ref)
  8. from rpython.rlib.rarithmetic import r_uint, intmask, LONG_TEST, r_ulonglong
  9. from pypy.objspace.std.intobject import W_IntObject
  10. import sys
  11. PyIntObjectStruct = lltype.ForwardReference()
  12. PyIntObject = lltype.Ptr(PyIntObjectStruct)
  13. PyIntObjectFields = PyObjectFields + \
  14. (("ob_ival", rffi.LONG),)
  15. cpython_struct("PyIntObject", PyIntObjectFields, PyIntObjectStruct)
  16. @bootstrap_function
  17. def init_intobject(space):
  18. "Type description of PyIntObject"
  19. make_typedescr(space.w_int.layout.typedef,
  20. basestruct=PyIntObject.TO,
  21. attach=int_attach,
  22. realize=int_realize)
  23. def int_attach(space, py_obj, w_obj):
  24. """
  25. Fills a newly allocated PyIntObject with the given int object. The
  26. value must not be modified.
  27. """
  28. py_int = rffi.cast(PyIntObject, py_obj)
  29. py_int.c_ob_ival = space.int_w(w_obj)
  30. def int_realize(space, obj):
  31. intval = rffi.cast(lltype.Signed, rffi.cast(PyIntObject, obj).c_ob_ival)
  32. w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
  33. w_obj = space.allocate_instance(W_IntObject, w_type)
  34. w_obj.__init__(intval)
  35. track_reference(space, obj, w_obj)
  36. return w_obj
  37. PyInt_Check, PyInt_CheckExact = build_type_checkers("Int")
  38. @cpython_api([], lltype.Signed, error=CANNOT_FAIL)
  39. def PyInt_GetMax(space):
  40. """Return the system's idea of the largest integer it can handle (LONG_MAX,
  41. as defined in the system header files)."""
  42. return sys.maxint
  43. @cpython_api([lltype.Signed], PyObject)
  44. def PyInt_FromLong(space, ival):
  45. """Create a new integer object with a value of ival.
  46. """
  47. return space.wrap(ival)
  48. @cpython_api([PyObject], lltype.Signed, error=-1)
  49. def PyInt_AsLong(space, w_obj):
  50. """Will first attempt to cast the object to a PyIntObject, if it is not
  51. already one, and then return its value. If there is an error, -1 is
  52. returned, and the caller should check PyErr_Occurred() to find out whether
  53. there was an error, or whether the value just happened to be -1."""
  54. if w_obj is None:
  55. raise oefmt(space.w_TypeError, "an integer is required, got NULL")
  56. return space.int_w(space.int(w_obj))
  57. @cpython_api([PyObject], lltype.Unsigned, error=-1)
  58. def PyInt_AsUnsignedLong(space, w_obj):
  59. """Return a C unsigned long representation of the contents of pylong.
  60. If pylong is greater than ULONG_MAX, an OverflowError is
  61. raised."""
  62. if w_obj is None:
  63. raise oefmt(space.w_TypeError, "an integer is required, got NULL")
  64. return space.uint_w(space.int(w_obj))
  65. @cpython_api([PyObject], rffi.ULONG, error=-1)
  66. def PyInt_AsUnsignedLongMask(space, w_obj):
  67. """Will first attempt to cast the object to a PyIntObject or
  68. PyLongObject, if it is not already one, and then return its value as
  69. unsigned long. This function does not check for overflow.
  70. """
  71. w_int = space.int(w_obj)
  72. if space.isinstance_w(w_int, space.w_int):
  73. num = space.int_w(w_int)
  74. return r_uint(num)
  75. else:
  76. num = space.bigint_w(w_int)
  77. return num.uintmask()
  78. @cpython_api([PyObject], rffi.ULONGLONG, error=-1)
  79. def PyInt_AsUnsignedLongLongMask(space, w_obj):
  80. """Will first attempt to cast the object to a PyIntObject or
  81. PyLongObject, if it is not already one, and then return its value as
  82. unsigned long long, without checking for overflow.
  83. """
  84. w_int = space.int(w_obj)
  85. if space.isinstance_w(w_int, space.w_int):
  86. num = space.int_w(w_int)
  87. return r_ulonglong(num)
  88. else:
  89. num = space.bigint_w(w_int)
  90. return num.ulonglongmask()
  91. @cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
  92. def PyInt_AS_LONG(space, w_int):
  93. """Return the value of the object w_int. No error checking is performed."""
  94. return space.int_w(w_int)
  95. @cpython_api([PyObject], Py_ssize_t, error=-1)
  96. def PyInt_AsSsize_t(space, w_obj):
  97. """Will first attempt to cast the object to a PyIntObject or
  98. PyLongObject, if it is not already one, and then return its value as
  99. Py_ssize_t.
  100. """
  101. if w_obj is None:
  102. raise oefmt(space.w_TypeError, "an integer is required, got NULL")
  103. return space.int_w(w_obj) # XXX this is wrong on win64
  104. LONG_MAX = int(LONG_TEST - 1)
  105. @cpython_api([rffi.SIZE_T], PyObject)
  106. def PyInt_FromSize_t(space, ival):
  107. """Create a new integer object with a value of ival. If the value exceeds
  108. LONG_MAX, a long integer object is returned.
  109. """
  110. if ival <= LONG_MAX:
  111. return space.wrap(intmask(ival))
  112. return space.wrap(ival)
  113. @cpython_api([Py_ssize_t], PyObject)
  114. def PyInt_FromSsize_t(space, ival):
  115. """Create a new integer object with a value of ival. If the value is larger
  116. than LONG_MAX or smaller than LONG_MIN, a long integer object is
  117. returned.
  118. """
  119. return space.wrap(ival)
  120. @cpython_api([CONST_STRING, rffi.CCHARPP, rffi.INT_real], PyObject)
  121. def PyInt_FromString(space, str, pend, base):
  122. """Return a new PyIntObject or PyLongObject based on the string
  123. value in str, which is interpreted according to the radix in base. If
  124. pend is non-NULL, *pend will point to the first character in str which
  125. follows the representation of the number. If base is 0, the radix will be
  126. determined based on the leading characters of str: if str starts with
  127. '0x' or '0X', radix 16 will be used; if str starts with '0', radix
  128. 8 will be used; otherwise radix 10 will be used. If base is not 0, it
  129. must be between 2 and 36, inclusive. Leading spaces are ignored. If
  130. there are no digits, ValueError will be raised. If the string represents
  131. a number too large to be contained within the machine's long int type
  132. and overflow warnings are being suppressed, a PyLongObject will be
  133. returned. If overflow warnings are not being suppressed, NULL will be
  134. returned in this case."""
  135. s = rffi.charp2str(str)
  136. w_str = space.wrap(s)
  137. w_base = space.wrap(rffi.cast(lltype.Signed, base))
  138. if pend:
  139. pend[0] = rffi.ptradd(str, len(s))
  140. return space.call_function(space.w_int, w_str, w_base)