mirror of
				https://github.com/python/cpython.git
				synced 2025-10-26 00:08:32 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			864 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			864 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #ifndef Py_BUILD_CORE_BUILTIN
 | |
| #  define Py_BUILD_CORE_MODULE 1
 | |
| #endif
 | |
| 
 | |
| #include "parts.h"
 | |
| #include "util.h"
 | |
| #include "clinic/long.c.h"
 | |
| 
 | |
| /*[clinic input]
 | |
| module _testcapi
 | |
| [clinic start generated code]*/
 | |
| /*[clinic end generated code: output=da39a3ee5e6b4b0d input=6361033e795369fc]*/
 | |
| 
 | |
| 
 | |
| static PyObject *
 | |
| raiseTestError(const char* test_name, const char* msg)
 | |
| {
 | |
|     PyErr_Format(PyExc_AssertionError, "%s: %s", test_name, msg);
 | |
|     return NULL;
 | |
| }
 | |
| 
 | |
| /* Tests of PyLong_{As, From}{Unsigned,}Long(), and
 | |
|    PyLong_{As, From}{Unsigned,}LongLong().
 | |
| 
 | |
|    Note that the meat of the test is contained in testcapi_long.h.
 | |
|    This is revolting, but delicate code duplication is worse:  "almost
 | |
|    exactly the same" code is needed to test long long, but the ubiquitous
 | |
|    dependence on type names makes it impossible to use a parameterized
 | |
|    function.  A giant macro would be even worse than this.  A C++ template
 | |
|    would be perfect.
 | |
| 
 | |
|    The "report an error" functions are deliberately not part of the #include
 | |
|    file:  if the test fails, you can set a breakpoint in the appropriate
 | |
|    error function directly, and crawl back from there in the debugger.
 | |
| */
 | |
| 
 | |
| #define UNBIND(X)  Py_DECREF(X); (X) = NULL
 | |
| 
 | |
| static PyObject *
 | |
| raise_test_long_error(const char* msg)
 | |
| {
 | |
|     return raiseTestError("test_long_api", msg);
 | |
| }
 | |
| 
 | |
| // Test PyLong_FromLong()/PyLong_AsLong()
 | |
| // and PyLong_FromUnsignedLong()/PyLong_AsUnsignedLong().
 | |
| 
 | |
| #define TESTNAME        test_long_api_inner
 | |
| #define TYPENAME        long
 | |
| #define F_S_TO_PY       PyLong_FromLong
 | |
| #define F_PY_TO_S       PyLong_AsLong
 | |
| #define F_U_TO_PY       PyLong_FromUnsignedLong
 | |
| #define F_PY_TO_U       PyLong_AsUnsignedLong
 | |
| 
 | |
| #include "testcapi_long.h"
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_api
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_api_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=4405798ca1e9f444 input=e9b8880d7331c688]*/
 | |
| {
 | |
|     return TESTNAME(raise_test_long_error);
 | |
| }
 | |
| 
 | |
| #undef TESTNAME
 | |
| #undef TYPENAME
 | |
| #undef F_S_TO_PY
 | |
| #undef F_PY_TO_S
 | |
| #undef F_U_TO_PY
 | |
| #undef F_PY_TO_U
 | |
| 
 | |
| // Test PyLong_FromLongLong()/PyLong_AsLongLong()
 | |
| // and PyLong_FromUnsignedLongLong()/PyLong_AsUnsignedLongLong().
 | |
| 
 | |
| static PyObject *
 | |
| raise_test_longlong_error(const char* msg)
 | |
| {
 | |
|     return raiseTestError("test_longlong_api", msg);
 | |
| }
 | |
| 
 | |
| #define TESTNAME        test_longlong_api_inner
 | |
| #define TYPENAME        long long
 | |
| #define F_S_TO_PY       PyLong_FromLongLong
 | |
| #define F_PY_TO_S       PyLong_AsLongLong
 | |
| #define F_U_TO_PY       PyLong_FromUnsignedLongLong
 | |
| #define F_PY_TO_U       PyLong_AsUnsignedLongLong
 | |
| 
 | |
| #include "testcapi_long.h"
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_longlong_api
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_longlong_api_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=2b3414ba8c31dfe6 input=ccbb2a48c2b3c4a5]*/
 | |
| {
 | |
|     return TESTNAME(raise_test_longlong_error);
 | |
| }
 | |
| 
 | |
| #undef TESTNAME
 | |
| #undef TYPENAME
 | |
| #undef F_S_TO_PY
 | |
| #undef F_PY_TO_S
 | |
| #undef F_U_TO_PY
 | |
| #undef F_PY_TO_U
 | |
| 
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_and_overflow
 | |
| 
 | |
| Test the PyLong_AsLongAndOverflow API.
 | |
| 
 | |
| General conversion to PY_LONG is tested by test_long_api_inner.
 | |
| This test will concentrate on proper handling of overflow.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_and_overflow_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=f8460ca115e31d8e input=762f6b62da0a3cdc]*/
 | |
| {
 | |
|     PyObject *num, *one, *temp;
 | |
|     long value;
 | |
|     int overflow;
 | |
| 
 | |
|     /* Test that overflow is set properly for a large value. */
 | |
|     /* num is a number larger than LONG_MAX even on 64-bit platforms */
 | |
|     num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != 1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not set to 1");
 | |
| 
 | |
|     /* Same again, with num = LONG_MAX + 1 */
 | |
|     num = PyLong_FromLong(LONG_MAX);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     one = PyLong_FromLong(1L);
 | |
|     if (one == NULL) {
 | |
|         Py_DECREF(num);
 | |
|         return NULL;
 | |
|     }
 | |
|     temp = PyNumber_Add(num, one);
 | |
|     Py_DECREF(one);
 | |
|     Py_SETREF(num, temp);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != 1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not set to 1");
 | |
| 
 | |
|     /* Test that overflow is set properly for a large negative value. */
 | |
|     /* num is a number smaller than LONG_MIN even on 64-bit platforms */
 | |
|     num = PyLong_FromString("-FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not set to -1");
 | |
| 
 | |
|     /* Same again, with num = LONG_MIN - 1 */
 | |
|     num = PyLong_FromLong(LONG_MIN);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     one = PyLong_FromLong(1L);
 | |
|     if (one == NULL) {
 | |
|         Py_DECREF(num);
 | |
|         return NULL;
 | |
|     }
 | |
|     temp = PyNumber_Subtract(num, one);
 | |
|     Py_DECREF(one);
 | |
|     Py_SETREF(num, temp);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != -1)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not set to -1");
 | |
| 
 | |
|     /* Test that overflow is cleared properly for small values. */
 | |
|     num = PyLong_FromString("FF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != 0xFF)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "expected return value 0xFF");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     num = PyLong_FromString("-FF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -0xFF)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "expected return value 0xFF");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was set incorrectly");
 | |
| 
 | |
|     num = PyLong_FromLong(LONG_MAX);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != LONG_MAX)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "expected return value LONG_MAX");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     num = PyLong_FromLong(LONG_MIN);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != LONG_MIN)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "expected return value LONG_MIN");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_long_and_overflow
 | |
| 
 | |
| Test the PyLong_AsLongLongAndOverflow API.
 | |
| 
 | |
| General conversion to long long is tested by test_long_api_inner.
 | |
| This test will concentrate on proper handling of overflow.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_long_and_overflow_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=0b92330786f45483 input=544bb0aefe5e8a9e]*/
 | |
| {
 | |
|     PyObject *num, *one, *temp;
 | |
|     long long value;
 | |
|     int overflow;
 | |
| 
 | |
|     /* Test that overflow is set properly for a large value. */
 | |
|     /* num is a number larger than LLONG_MAX on a typical machine. */
 | |
|     num = PyLong_FromString("FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != 1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not set to 1");
 | |
| 
 | |
|     /* Same again, with num = LLONG_MAX + 1 */
 | |
|     num = PyLong_FromLongLong(LLONG_MAX);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     one = PyLong_FromLong(1L);
 | |
|     if (one == NULL) {
 | |
|         Py_DECREF(num);
 | |
|         return NULL;
 | |
|     }
 | |
|     temp = PyNumber_Add(num, one);
 | |
|     Py_DECREF(one);
 | |
|     Py_SETREF(num, temp);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != 1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not set to 1");
 | |
| 
 | |
|     /* Test that overflow is set properly for a large negative value. */
 | |
|     /* num is a number smaller than LLONG_MIN on a typical platform */
 | |
|     num = PyLong_FromString("-FFFFFFFFFFFFFFFFFFFFFFFF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not set to -1");
 | |
| 
 | |
|     /* Same again, with num = LLONG_MIN - 1 */
 | |
|     num = PyLong_FromLongLong(LLONG_MIN);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     one = PyLong_FromLong(1L);
 | |
|     if (one == NULL) {
 | |
|         Py_DECREF(num);
 | |
|         return NULL;
 | |
|     }
 | |
|     temp = PyNumber_Subtract(num, one);
 | |
|     Py_DECREF(one);
 | |
|     Py_SETREF(num, temp);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "return value was not set to -1");
 | |
|     if (overflow != -1)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not set to -1");
 | |
| 
 | |
|     /* Test that overflow is cleared properly for small values. */
 | |
|     num = PyLong_FromString("FF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != 0xFF)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "expected return value 0xFF");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     num = PyLong_FromString("-FF", NULL, 16);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != -0xFF)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "expected return value 0xFF");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was set incorrectly");
 | |
| 
 | |
|     num = PyLong_FromLongLong(LLONG_MAX);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 1234;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != LLONG_MAX)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "expected return value LLONG_MAX");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     num = PyLong_FromLongLong(LLONG_MIN);
 | |
|     if (num == NULL)
 | |
|         return NULL;
 | |
|     overflow = 0;
 | |
|     value = PyLong_AsLongLongAndOverflow(num, &overflow);
 | |
|     Py_DECREF(num);
 | |
|     if (value == -1 && PyErr_Occurred())
 | |
|         return NULL;
 | |
|     if (value != LLONG_MIN)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "expected return value LLONG_MIN");
 | |
|     if (overflow != 0)
 | |
|         return raiseTestError("test_long_long_and_overflow",
 | |
|             "overflow was not cleared");
 | |
| 
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_as_size_t
 | |
| 
 | |
| Test the PyLong_As{Size,Ssize}_t API.
 | |
| 
 | |
| At present this just tests that non-integer arguments are handled correctly.
 | |
| It should be extended to test overflow handling.
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_as_size_t_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=f6490ea2b41e6173 input=922990c4a3edfb0d]*/
 | |
| {
 | |
|     size_t out_u;
 | |
|     Py_ssize_t out_s;
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
| 
 | |
|     out_u = PyLong_AsSize_t(Py_None);
 | |
|     if (out_u != (size_t)-1 || !PyErr_Occurred())
 | |
|         return raiseTestError("test_long_as_size_t",
 | |
|                               "PyLong_AsSize_t(None) didn't complain");
 | |
|     if (!PyErr_ExceptionMatches(PyExc_TypeError))
 | |
|         return raiseTestError("test_long_as_size_t",
 | |
|                               "PyLong_AsSize_t(None) raised "
 | |
|                               "something other than TypeError");
 | |
|     PyErr_Clear();
 | |
| 
 | |
|     out_s = PyLong_AsSsize_t(Py_None);
 | |
|     if (out_s != (Py_ssize_t)-1 || !PyErr_Occurred())
 | |
|         return raiseTestError("test_long_as_size_t",
 | |
|                               "PyLong_AsSsize_t(None) didn't complain");
 | |
|     if (!PyErr_ExceptionMatches(PyExc_TypeError))
 | |
|         return raiseTestError("test_long_as_size_t",
 | |
|                               "PyLong_AsSsize_t(None) raised "
 | |
|                               "something other than TypeError");
 | |
|     PyErr_Clear();
 | |
| 
 | |
|     /* Py_INCREF(Py_None) omitted - we already have a reference to it. */
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_as_unsigned_long_long_mask
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_as_unsigned_long_long_mask_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=e3e16cd0189440cc input=eb2438493ae7b9af]*/
 | |
| {
 | |
|     unsigned long long res = PyLong_AsUnsignedLongLongMask(NULL);
 | |
| 
 | |
|     if (res != (unsigned long long)-1 || !PyErr_Occurred()) {
 | |
|         return raiseTestError("test_long_as_unsigned_long_long_mask",
 | |
|                               "PyLong_AsUnsignedLongLongMask(NULL) didn't "
 | |
|                               "complain");
 | |
|     }
 | |
|     if (!PyErr_ExceptionMatches(PyExc_SystemError)) {
 | |
|         return raiseTestError("test_long_as_unsigned_long_long_mask",
 | |
|                               "PyLong_AsUnsignedLongLongMask(NULL) raised "
 | |
|                               "something other than SystemError");
 | |
|     }
 | |
|     PyErr_Clear();
 | |
|     Py_RETURN_NONE;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.test_long_as_double
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_test_long_as_double_impl(PyObject *module)
 | |
| /*[clinic end generated code: output=deca0898e15adde5 input=c77bc88ef5a1de76]*/
 | |
| {
 | |
|     double out;
 | |
| 
 | |
|     Py_INCREF(Py_None);
 | |
| 
 | |
|     out = PyLong_AsDouble(Py_None);
 | |
|     if (out != -1.0 || !PyErr_Occurred())
 | |
|         return raiseTestError("test_long_as_double",
 | |
|                               "PyLong_AsDouble(None) didn't complain");
 | |
|     if (!PyErr_ExceptionMatches(PyExc_TypeError))
 | |
|         return raiseTestError("test_long_as_double",
 | |
|                               "PyLong_AsDouble(None) raised "
 | |
|                               "something other than TypeError");
 | |
|     PyErr_Clear();
 | |
| 
 | |
|     /* Py_INCREF(Py_None) omitted - we already have a reference to it. */
 | |
|     return Py_None;
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.call_long_compact_api
 | |
|     arg: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_call_long_compact_api(PyObject *module, PyObject *arg)
 | |
| /*[clinic end generated code: output=7e3894f611b1b2b7 input=87b87396967af14c]*/
 | |
| 
 | |
| {
 | |
|     assert(PyLong_Check(arg));
 | |
|     int is_compact = PyUnstable_Long_IsCompact((PyLongObject*)arg);
 | |
|     Py_ssize_t value = -1;
 | |
|     if (is_compact) {
 | |
|         value = PyUnstable_Long_CompactValue((PyLongObject*)arg);
 | |
|     }
 | |
|     return Py_BuildValue("in", is_compact, value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_check(PyObject *module, PyObject *obj)
 | |
| {
 | |
|     NULLABLE(obj);
 | |
|     return PyLong_FromLong(PyLong_Check(obj));
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_checkexact(PyObject *module, PyObject *obj)
 | |
| {
 | |
|     NULLABLE(obj);
 | |
|     return PyLong_FromLong(PyLong_CheckExact(obj));
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_fromdouble(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     double value;
 | |
|     if (!PyArg_Parse(arg, "d", &value)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromDouble(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_fromstring(PyObject *module, PyObject *args)
 | |
| {
 | |
|     const char *str;
 | |
|     Py_ssize_t len;
 | |
|     int base;
 | |
|     char *end = UNINITIALIZED_PTR;
 | |
|     if (!PyArg_ParseTuple(args, "z#i", &str, &len, &base)) {
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     PyObject *result = PyLong_FromString(str, &end, base);
 | |
|     if (result == NULL) {
 | |
|         // XXX 'end' is not always set.
 | |
|         return NULL;
 | |
|     }
 | |
|     return Py_BuildValue("Nn", result, (Py_ssize_t)(end - str));
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_fromunicodeobject(PyObject *module, PyObject *args)
 | |
| {
 | |
|     PyObject *unicode;
 | |
|     int base;
 | |
|     if (!PyArg_ParseTuple(args, "Oi", &unicode, &base)) {
 | |
|         return NULL;
 | |
|     }
 | |
| 
 | |
|     NULLABLE(unicode);
 | |
|     return PyLong_FromUnicodeObject(unicode, base);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_fromvoidptr(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     return PyLong_FromVoidPtr((void *)arg);
 | |
| }
 | |
| 
 | |
| /*[clinic input]
 | |
| _testcapi.PyLong_AsInt
 | |
|     arg: object
 | |
|     /
 | |
| [clinic start generated code]*/
 | |
| 
 | |
| static PyObject *
 | |
| _testcapi_PyLong_AsInt(PyObject *module, PyObject *arg)
 | |
| /*[clinic end generated code: output=0df9f19de5fa575b input=9561b97105493a67]*/
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     assert(!PyErr_Occurred());
 | |
|     int value = PyLong_AsInt(arg);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_aslong(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     long value = PyLong_AsLong(arg);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_aslongandoverflow(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     int overflow = UNINITIALIZED_INT;
 | |
|     long value = PyLong_AsLongAndOverflow(arg, &overflow);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         assert(overflow == -1);
 | |
|         return NULL;
 | |
|     }
 | |
|     return Py_BuildValue("li", value, overflow);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asunsignedlong(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     unsigned long value = PyLong_AsUnsignedLong(arg);
 | |
|     if (value == (unsigned long)-1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromUnsignedLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asunsignedlongmask(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     unsigned long value = PyLong_AsUnsignedLongMask(arg);
 | |
|     if (value == (unsigned long)-1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromUnsignedLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_aslonglong(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     long long value = PyLong_AsLongLong(arg);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromLongLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_aslonglongandoverflow(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     int overflow = UNINITIALIZED_INT;
 | |
|     long long value = PyLong_AsLongLongAndOverflow(arg, &overflow);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         assert(overflow == -1);
 | |
|         return NULL;
 | |
|     }
 | |
|     return Py_BuildValue("Li", value, overflow);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asunsignedlonglong(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     unsigned long long value = PyLong_AsUnsignedLongLong(arg);
 | |
|     if (value == (unsigned long long)-1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromUnsignedLongLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asunsignedlonglongmask(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     unsigned long long value = PyLong_AsUnsignedLongLongMask(arg);
 | |
|     if (value == (unsigned long long)-1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromUnsignedLongLong(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_as_ssize_t(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     Py_ssize_t value = PyLong_AsSsize_t(arg);
 | |
|     if (value == -1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromSsize_t(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_as_size_t(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     size_t value = PyLong_AsSize_t(arg);
 | |
|     if (value == (size_t)-1 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyLong_FromSize_t(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asdouble(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     double value = PyLong_AsDouble(arg);
 | |
|     if (value == -1.0 && PyErr_Occurred()) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return PyFloat_FromDouble(value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asvoidptr(PyObject *module, PyObject *arg)
 | |
| {
 | |
|     NULLABLE(arg);
 | |
|     void *value = PyLong_AsVoidPtr(arg);
 | |
|     if (value == NULL) {
 | |
|         if (PyErr_Occurred()) {
 | |
|             return NULL;
 | |
|         }
 | |
|         Py_RETURN_NONE;
 | |
|     }
 | |
|     return Py_NewRef((PyObject *)value);
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_asnativebytes(PyObject *module, PyObject *args)
 | |
| {
 | |
|     PyObject *v;
 | |
|     Py_buffer buffer;
 | |
|     Py_ssize_t n, endianness;
 | |
|     if (!PyArg_ParseTuple(args, "Ow*nn", &v, &buffer, &n, &endianness)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     if (buffer.readonly) {
 | |
|         PyErr_SetString(PyExc_TypeError, "buffer must be writable");
 | |
|         PyBuffer_Release(&buffer);
 | |
|         return NULL;
 | |
|     }
 | |
|     if (buffer.len < n) {
 | |
|         PyErr_SetString(PyExc_ValueError, "buffer must be at least 'n' bytes");
 | |
|         PyBuffer_Release(&buffer);
 | |
|         return NULL;
 | |
|     }
 | |
|     Py_ssize_t res = PyLong_AsNativeBytes(v, buffer.buf, n, (int)endianness);
 | |
|     PyBuffer_Release(&buffer);
 | |
|     return res >= 0 ? PyLong_FromSsize_t(res) : NULL;
 | |
| }
 | |
| 
 | |
| static PyObject *
 | |
| pylong_fromnativebytes(PyObject *module, PyObject *args)
 | |
| {
 | |
|     Py_buffer buffer;
 | |
|     Py_ssize_t n, endianness, signed_;
 | |
|     if (!PyArg_ParseTuple(args, "y*nnn", &buffer, &n, &endianness, &signed_)) {
 | |
|         return NULL;
 | |
|     }
 | |
|     if (buffer.len < n) {
 | |
|         PyErr_SetString(PyExc_ValueError, "buffer must be at least 'n' bytes");
 | |
|         PyBuffer_Release(&buffer);
 | |
|         return NULL;
 | |
|     }
 | |
|     PyObject *res = signed_
 | |
|         ? PyLong_FromNativeBytes(buffer.buf, n, (int)endianness)
 | |
|         : PyLong_FromUnsignedNativeBytes(buffer.buf, n, (int)endianness);
 | |
|     PyBuffer_Release(&buffer);
 | |
|     return res;
 | |
| }
 | |
| 
 | |
| 
 | |
| static PyMethodDef test_methods[] = {
 | |
|     _TESTCAPI_TEST_LONG_AND_OVERFLOW_METHODDEF
 | |
|     _TESTCAPI_TEST_LONG_API_METHODDEF
 | |
|     _TESTCAPI_TEST_LONG_AS_DOUBLE_METHODDEF
 | |
|     _TESTCAPI_TEST_LONG_AS_SIZE_T_METHODDEF
 | |
|     _TESTCAPI_TEST_LONG_AS_UNSIGNED_LONG_LONG_MASK_METHODDEF
 | |
|     _TESTCAPI_TEST_LONG_LONG_AND_OVERFLOW_METHODDEF
 | |
|     _TESTCAPI_TEST_LONGLONG_API_METHODDEF
 | |
|     _TESTCAPI_CALL_LONG_COMPACT_API_METHODDEF
 | |
|     {"pylong_check",                pylong_check,               METH_O},
 | |
|     {"pylong_checkexact",           pylong_checkexact,          METH_O},
 | |
|     {"pylong_fromdouble",           pylong_fromdouble,          METH_O},
 | |
|     {"pylong_fromstring",           pylong_fromstring,          METH_VARARGS},
 | |
|     {"pylong_fromunicodeobject",    pylong_fromunicodeobject,   METH_VARARGS},
 | |
|     {"pylong_fromvoidptr",          pylong_fromvoidptr,         METH_O},
 | |
|     _TESTCAPI_PYLONG_ASINT_METHODDEF
 | |
|     {"pylong_aslong",               pylong_aslong,              METH_O},
 | |
|     {"pylong_aslongandoverflow",    pylong_aslongandoverflow,   METH_O},
 | |
|     {"pylong_asunsignedlong",       pylong_asunsignedlong,      METH_O},
 | |
|     {"pylong_asunsignedlongmask",   pylong_asunsignedlongmask,  METH_O},
 | |
|     {"pylong_aslonglong",           pylong_aslonglong,          METH_O},
 | |
|     {"pylong_aslonglongandoverflow", pylong_aslonglongandoverflow, METH_O},
 | |
|     {"pylong_asunsignedlonglong",   pylong_asunsignedlonglong,  METH_O},
 | |
|     {"pylong_asunsignedlonglongmask", pylong_asunsignedlonglongmask, METH_O},
 | |
|     {"pylong_as_ssize_t",           pylong_as_ssize_t,          METH_O},
 | |
|     {"pylong_as_size_t",            pylong_as_size_t,           METH_O},
 | |
|     {"pylong_asdouble",             pylong_asdouble,            METH_O},
 | |
|     {"pylong_asvoidptr",            pylong_asvoidptr,           METH_O},
 | |
|     {"pylong_asnativebytes",        pylong_asnativebytes,       METH_VARARGS},
 | |
|     {"pylong_fromnativebytes",      pylong_fromnativebytes,     METH_VARARGS},
 | |
|     {NULL},
 | |
| };
 | |
| 
 | |
| int
 | |
| _PyTestCapi_Init_Long(PyObject *mod)
 | |
| {
 | |
|     if (PyModule_AddFunctions(mod, test_methods) < 0) {
 | |
|         return -1;
 | |
|     }
 | |
|     return 0;
 | |
| }
 | 
