static PyObject * complex_subtype_from_string(PyTypeObject *type, PyObject *v) { const char *s; PyObject *s_buffer = NULL, *result = NULL; Py_ssize_t len; if (PyUnicode_Check(v)) { s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v); if (s_buffer == NULL) { return NULL; } assert(PyUnicode_IS_ASCII(s_buffer)); /* Simply get a pointer to existing ASCII characters. */ s = PyUnicode_AsUTF8AndSize(s_buffer, &len); assert(s != NULL); } else { PyErr_Format(PyExc_TypeError, "complex() argument must be a string or a number, not '%.200s'", Py_TYPE(v)->tp_name); return NULL; } result = _Py_string_to_number_with_underscores(s, len, "complex", v, type, complex_from_string_inner); Py_DECREF(s_buffer); return result; }
static PyObject * complex_subtype_from_string(PyTypeObject *type, PyObject *v) { const char *s, *start; char *end; double x=0.0, y=0.0, z; int got_bracket=0; PyObject *s_buffer = NULL; Py_ssize_t len; Py_buffer view = {NULL, NULL}; if (PyUnicode_Check(v)) { s_buffer = _PyUnicode_TransformDecimalAndSpaceToASCII(v); if (s_buffer == NULL) return NULL; s = PyUnicode_AsUTF8AndSize(s_buffer, &len); if (s == NULL) goto error; } else if (PyObject_GetBuffer(v, &view, PyBUF_SIMPLE) == 0) { s = (const char *)view.buf; len = view.len; } else { PyErr_Format(PyExc_TypeError, "complex() argument must be a string or a number, not '%.200s'", Py_TYPE(v)->tp_name); return NULL; } /* position on first nonblank */ start = s; while (Py_ISSPACE(*s)) s++; if (*s == '(') { /* Skip over possible bracket from repr(). */ got_bracket = 1; s++; while (Py_ISSPACE(*s)) s++; } /* a valid complex string usually takes one of the three forms: <float> - real part only <float>j - imaginary part only <float><signed-float>j - real and imaginary parts where <float> represents any numeric string that's accepted by the float constructor (including 'nan', 'inf', 'infinity', etc.), and <signed-float> is any string of the form <float> whose first character is '+' or '-'. For backwards compatibility, the extra forms <float><sign>j <sign>j j are also accepted, though support for these forms may be removed from a future version of Python. */ /* first look for forms starting with <float> */ z = PyOS_string_to_double(s, &end, NULL); if (z == -1.0 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else goto error; } if (end != s) { /* all 4 forms starting with <float> land here */ s = end; if (*s == '+' || *s == '-') { /* <float><signed-float>j | <float><sign>j */ x = z; y = PyOS_string_to_double(s, &end, NULL); if (y == -1.0 && PyErr_Occurred()) { if (PyErr_ExceptionMatches(PyExc_ValueError)) PyErr_Clear(); else goto error; } if (end != s) /* <float><signed-float>j */ s = end; else { /* <float><sign>j */ y = *s == '+' ? 1.0 : -1.0; s++; } if (!(*s == 'j' || *s == 'J')) goto parse_error; s++; } else if (*s == 'j' || *s == 'J') { /* <float>j */ s++; y = z; } else /* <float> */ x = z; } else { /* not starting with <float>; must be <sign>j or j */ if (*s == '+' || *s == '-') { /* <sign>j */ y = *s == '+' ? 1.0 : -1.0; s++; } else /* j */ y = 1.0; if (!(*s == 'j' || *s == 'J')) goto parse_error; s++; } /* trailing whitespace and closing bracket */ while (Py_ISSPACE(*s)) s++; if (got_bracket) { /* if there was an opening parenthesis, then the corresponding closing parenthesis should be right here */ if (*s != ')') goto parse_error; s++; while (Py_ISSPACE(*s)) s++; } /* we should now be at the end of the string */ if (s-start != len) goto parse_error; PyBuffer_Release(&view); Py_XDECREF(s_buffer); return complex_subtype_from_doubles(type, x, y); parse_error: PyErr_SetString(PyExc_ValueError, "complex() arg is a malformed string"); error: PyBuffer_Release(&view); Py_XDECREF(s_buffer); return NULL; }