bool BINARY_OPERATION_ADD_UNICODE_UNICODE_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(*operand1)); assert(PyUnicode_CheckExact(operand2)); #if PYTHON_VERSION >= 300 if (Py_REFCNT(*operand1) == 1 && !PyUnicode_CHECK_INTERNED(*operand1)) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; }
NUITKA_MAY_BE_UNUSED static bool UNICODE_ADD_INCREMENTAL(PyObject **operand1, PyObject *operand2) { Py_ssize_t operand2_size = PyUnicode_GET_SIZE(operand2); if (operand2_size == 0) return true; #if PYTHON_VERSION < 300 Py_ssize_t operand1_size = PyUnicode_GET_SIZE(*operand1); Py_ssize_t new_size = operand1_size + operand2_size; if (unlikely(new_size < 0)) { PyErr_Format(PyExc_OverflowError, "strings are too large to concat"); return false; } if (unlikely(PyUnicode_Resize(operand1, new_size) != 0)) { return false; } memcpy(PyUnicode_AS_UNICODE(*operand1) + operand1_size, PyUnicode_AS_UNICODE(operand2), operand2_size * sizeof(Py_UNICODE)); return true; #else assert(!PyUnicode_CHECK_INTERNED(*operand1)); return UNICODE_APPEND(operand1, operand2); #endif }
bool BINARY_OPERATION_ADD_UNICODE_OBJECT_INPLACE(PyObject **operand1, PyObject *operand2) { assert(operand1); CHECK_OBJECT(*operand1); CHECK_OBJECT(operand2); assert(PyUnicode_CheckExact(*operand1)); if (likely(PyUnicode_CheckExact(operand2))) { #if PYTHON_VERSION >= 300 if (Py_REFCNT(*operand1) == 1 && !PyUnicode_CHECK_INTERNED(*operand1)) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. return UNICODE_ADD_INCREMENTAL(operand1, operand2); } #endif PyObject *result = UNICODE_CONCAT(*operand1, operand2); if (unlikely(result == NULL)) { return false; } Py_DECREF(*operand1); *operand1 = result; return true; } PyObject *result = PyNumber_InPlaceAdd(*operand1, operand2); if (unlikely(result == NULL)) { return false; } // We got an object handed, that we have to release. Py_DECREF(*operand1); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; }
NUITKA_MAY_BE_UNUSED static bool BINARY_OPERATION_ADD_INPLACE( PyObject **operand1, PyObject *operand2 ) { assert( operand1 ); CHECK_OBJECT( *operand1 ); CHECK_OBJECT( operand2 ); #if PYTHON_VERSION < 300 // Something similar for Python3 should exist too. if ( PyInt_CheckExact( *operand1 ) && PyInt_CheckExact( operand2 ) ) { long a, b, i; a = PyInt_AS_LONG( *operand1 ); b = PyInt_AS_LONG( operand2 ); i = a + b; // Detect overflow, in which case, a "long" object would have to be // created, which we won't handle here. TODO: Add an else for that // case. if (likely(!( (i^a) < 0 && (i^b) < 0 ) )) { PyObject *result = PyInt_FromLong( i ); Py_DECREF( *operand1 ); *operand1 = result; return true; } } #endif #if PYTHON_VERSION < 300 if ( Py_REFCNT( *operand1 ) == 1 ) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. if ( PyString_CheckExact( *operand1 ) && !PyString_CHECK_INTERNED( *operand1 ) && PyString_CheckExact( operand2 ) ) { return STRING_ADD_INCREMENTAL( operand1, operand2 ); } else if ( PyFloat_CheckExact( *operand1 ) && PyFloat_CheckExact( operand2 ) ) { return FLOAT_ADD_INCREMENTAL( operand1, operand2 ); } } // Strings are to be treated differently. if ( PyString_CheckExact( *operand1 ) && PyString_CheckExact( operand2 ) ) { PyString_Concat( operand1, operand2 ); return !ERROR_OCCURRED(); } #else if ( Py_REFCNT( *operand1 ) == 1 ) { // We more or less own the operand, so we might re-use its storage and // execute stuff in-place. if ( PyUnicode_CheckExact( *operand1 ) && !PyUnicode_CHECK_INTERNED( *operand1 ) && PyUnicode_CheckExact( operand2 ) ) { return UNICODE_ADD_INCREMENTAL( operand1, operand2 ); } else if ( PyFloat_CheckExact( *operand1 ) && PyFloat_CheckExact( operand2 ) ) { return FLOAT_ADD_INCREMENTAL( operand1, operand2 ); } } // Strings are to be treated differently. if ( PyUnicode_CheckExact( *operand1 ) && PyUnicode_CheckExact( operand2 ) ) { PyObject *result = PyUnicode_Concat( *operand1, operand2 ); if (unlikely( result == NULL )) { return false; } Py_DECREF( *operand1 ); *operand1 = result; return true; } #endif PyObject *result = PyNumber_InPlaceAdd( *operand1, operand2 ); if (unlikely( result == NULL )) { return false; } // We got an object handed, that we have to release. Py_DECREF( *operand1 ); // That's our return value then. As we use a dedicated variable, it's // OK that way. *operand1 = result; return true; }