{"join", (PyCFunction) unicode_join, METH_O, join__doc__}, {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__}, {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__}, {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__}, {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__}, {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__}, {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__}, {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__}, {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__}, {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__}, {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__}, {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__}, {"decode", (PyCFunction) unicode_decode, METH_VARARGS, decode__doc__},/* {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS, maketrans__doc__}, */ {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__}, {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__}, {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__}, {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__}, {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__}, {"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__}, {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__}, {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__}, {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__}, {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__}, {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__}, {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__}, {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__}, {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__}, {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__}, {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__}, {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__}, {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__}, {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__}, {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__}, {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__}, {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__},#if 0 {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__},#endif #if 0 /* This one is just used for debugging the implementation. */ {"freelistsize", (PyCFunction) unicode_freelistsize, METH_NOARGS},#endif {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, {NULL, NULL}}; static PyObject *unicode_mod(PyObject *v, PyObject *w){ if (!PyUnicode_Check(v)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return PyUnicode_Format(v, w);} static PyNumberMethods unicode_as_number = { 0, /*nb_add*/ 0, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_divide*/ unicode_mod, /*nb_remainder*/}; static PySequenceMethods unicode_as_sequence = { (lenfunc) unicode_length, /* sq_length */ PyUnicode_Concat, /* sq_concat */ (ssizeargfunc) unicode_repeat, /* sq_repeat */ (ssizeargfunc) unicode_getitem, /* sq_item */ (ssizessizeargfunc) unicode_slice, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ PyUnicode_Contains, /* sq_contains */}; static PyObject*unicode_subscript(PyUnicodeObject* self, PyObject* item){ if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += PyUnicode_GET_SIZE(self); return unicode_getitem(self, i); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; Py_UNICODE* source_buf; Py_UNICODE* result_buf; PyObject* result; if (PySlice_GetIndicesEx((PySliceObject*)item, PyUnicode_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; } if (slicelength <= 0) { return PyUnicode_FromUnicode(NULL, 0); } else { source_buf = PyUnicode_AS_UNICODE((PyObject*)self); result_buf = (Py_UNICODE *)PyMem_MALLOC(slicelength* sizeof(Py_UNICODE)); if (result_buf == NULL) return PyErr_NoMemory(); for (cur = start, i = 0; i < slicelength; cur += step, i++) { result_buf[i] = source_buf[cur]; } result = PyUnicode_FromUnicode(result_buf, slicelength); PyMem_FREE(result_buf); return result; } } else { PyErr_SetString(PyExc_TypeError, "string indices must be integers"); return NULL; }} static PyMappingMethods unicode_as_mapping = { (lenfunc)unicode_length, /* mp_length */ (binaryfunc)unicode_subscript, /* mp_subscript */ (objobjargproc)0, /* mp_ass_subscript */}; static Py_ssize_tunicode_buffer_getreadbuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr){ if (index != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent unicode segment"); return -1; } *ptr = (void *) self->str; return PyUnicode_GET_DATA_SIZE(self);} static Py_ssize_tunicode_buffer_getwritebuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr){ PyErr_SetString(PyExc_TypeError, "cannot use unicode as modifiable buffer"); return -1;} static intunicode_buffer_getsegcount(PyUnicodeObject *self, Py_ssize_t *lenp){ if (lenp) *lenp = PyUnicode_GET_DATA_SIZE(self); return 1;} static Py_ssize_tunicode_buffer_getcharbuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr){ PyObject *str; if (index != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent unicode segment"); return -1; } str = _PyUnicode_AsDefaultEncodedString((PyObject *)self, NULL); if (str == NULL) return -1; *ptr = (void *) PyString_AS_STRING(str); return PyString_GET_SIZE(str);} /* Helpers for PyUnicode_Format() */ static PyObject *getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx){ Py_ssize_t argidx = *p_argidx; if (argidx < arglen) { (*p_argidx)++; if (arglen < 0) return args; else return PyTuple_GetItem(args, argidx); } PyErr_SetString(PyExc_TypeError, "not enough arguments for format string"); return NULL;} #define F_LJUST (1<<0)#define F_SIGN (1<<1)#define F_BLANK (1<<2)#define F_ALT (1<<3)#define F_ZERO (1<<4) static Py_ssize_tstrtounicode(Py_UNICODE *buffer, const char *charbuffer){ register Py_ssize_t i; Py_ssize_t len = strlen(charbuffer); for (i = len - 1; i >= 0; i--) buffer[i] = (Py_UNICODE) charbuffer[i]; return len;} static intdoubletounicode(Py_UNICODE *buffer, size_t len, const char *format, double x){ Py_ssize_t result; PyOS_ascii_formatd((char *)buffer, len, format, x); result = strtounicode(buffer, (char *)buffer); return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);} static intlongtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x){ Py_ssize_t result; PyOS_snprintf((char *)buffer, len, format, x); result = strtounicode(buffer, (char *)buffer); return Py_SAFE_DOWNCAST(result, Py_ssize_t, int);} /* XXX To save some code duplication, formatfloat/long/int could have been shared with stringobject.c, converting from 8-bit to Unicode after the formatting is done. */ static intformatfloat(Py_UNICODE *buf, size_t buflen, int flags, int prec, int type, PyObject *v){ /* fmt = '%#.' + `prec` + `type` worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/ char fmt[20]; double x; x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) return -1; if (prec < 0) prec = 6; if (type == 'f' && (fabs(x) / 1e25) >= 1e25) type = 'g'; /* Worst case length calc to ensure no buffer overrun: 'g' formats: fmt = %#.<prec>g buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp for any double rep.) len = 1 + prec + 1 + 2 + 5 = 9 + prec 'f' formats: buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50) len = 1 + 50 + 1 + prec = 52 + prec If prec=0 the effective precision is 1 (the leading digit is always given), therefore increase the length by one. */ if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) || (type == 'f' && buflen <= (size_t)53 + (size_t)prec)) { PyErr_SetString(PyExc_OverflowError, "formatted float is too long (precision too large?)"); return -1; } PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type); return doubletounicode(buf, buflen, fmt, x);} static PyObject*formatlong(PyObject *val, int flags, int prec, int type){ char *buf; int i, len; PyObject *str; /* temporary string object. */ PyUnicodeObject *result; str = _PyString_FormatLong(val, flags, prec, type, &buf, &len); if (!str) return NULL; result = _PyUnicode_New(len); if (!result) { Py_DECREF(str); return NULL; } for (i = 0; i < len; i++) result->str[i] = buf[i]; result->str[len] = 0; Py_DECREF(str); return (PyObject*)result;} static intformatint(Py_UNICODE *buf, size_t buflen, int flags, int prec, int type, PyObject *v){ /* fmt = '%#.' + `prec` + 'l' + `type` * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine) * + 1 + 1 * = 24 */ char fmt[64]; /* plenty big enough! */ char *sign; long x; x = PyInt_AsLong(v); if (x == -1 && PyErr_Occurred()) return -1; if (x < 0 && type == 'u') { type = 'd'; } if (x < 0 && (type == 'x' || type == 'X' || type == 'o')) sign = "-"; else sign = ""; if (prec < 0) prec = 1; /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal)) * worst case buf = '-0x' + [0-9]*prec, where prec >= 11 */ if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) { PyErr_SetString(PyExc_OverflowError, "formatted integer is too long (precision too large?)"); return -1; } if ((flags & F_ALT) && (type == 'x' || type == 'X')) { /* When converting under %#x or %#X, there are a number * of issues that cause pain: * - when 0 is being converted, the C standard leaves off * the '0x' or '0X', which is inconsistent with other * %#x/%#X conversions and inconsistent with Python's * hex() function * - there are platforms that violate the standard and * convert 0 with the '0x' or '0X' * (Metrowerks, Compaq Tru64) * - there are platforms that give '0x' when converting * under %#X, but convert 0 in accordance with the * standard (OS/2 EMX) * * We can achieve the desired consistency by inserting our * own '0x' or '0X' prefix, and substituting %x/%X in place * of %#x/%#X. * * Note that this is the same approach as used in * formatint() in stringobject.c */ PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c", sign, type, prec, type); } else { PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c", sign, (flags&F_ALT) ? "#" : "", prec, type); } if (sign[0]) return longtounicode(buf, buflen, fmt, -x); else return longtounicode(buf, buflen, fmt, x);} static intformatchar(Py_UNICODE *buf, size_t buflen, PyObject *v){ /* presume that the buffer is at least 2 characters long */ if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) != 1) goto onError; buf[0] = PyUnicode_AS_UNICODE(v)[0]; } else if (PyString_Check(v)) { if (PyString_GET_SIZE(v) != 1) goto onError; buf[0] = (Py_UNICODE)PyString_AS_STRING(v)[0]; } else { /* Integer input truncated to a character */ long x; x = PyInt_AsLong(v); if (x == -1 && PyErr_Occurred()) goto onError;#ifdef Py_UNICODE_WIDE if (x < 0 || x > 0x10ffff) { PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000) " "(wide Python build)"); return -1; }#else if (x < 0 || x > 0xffff) { PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x10000) " "(narrow Python build)"); return -1; }#endif buf[0] = (Py_UNICODE) x; } buf[1] = '\0'; return 1; onError: PyErr_SetString(PyExc_TypeError, "%c requires int or char"); return -1;} /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) FORMATBUFLEN is the length of the buffer in which the floats, ints, & chars are formatted. XXX This is a magic number. Each formatting routine does bounds checking to ensure no overflow, but a better solution may be to malloc a buffer of appropriate size for each format. For now, the current solution is sufficient.*/#define FORMATBUFLEN (size_t)120 PyObject *PyUnicode_Format(PyObject *format, PyObject *args){ Py_UNICODE *fmt, *res; Py_ssize_t fmtcnt, rescnt, reslen, arglen, argidx; int args_owned = 0; PyUnicodeObject *result = NULL; PyObject *dict = NULL; PyObject *uformat; if (format == NULL || args == NULL) { PyErr_BadInternalCall(); return NULL; } uformat = PyUnicode_FromObject(format); if (uformat == NULL) return NULL; fmt = PyUnicode_AS_UNICODE(uformat); fmtcnt = PyUnicode_GET_SIZE(uformat); reslen = rescnt = fmtcnt + 100; result = _PyUnicode_New(reslen); if (result == NULL) goto onError; res = PyUnicode_AS_UNICODE(result); if (PyTuple_Check(args)) { arglen = PyTuple_Size(args); argidx = 0; } else { arglen = -1; argidx = -2; } if (args->ob_type->tp_as_mapping && !PyTuple_Check(args) && !PyObject_TypeCheck(args, &PyBaseString_Type)) dict = args; while (--fmtcnt >= 0) { if (*fmt != '%') { if (--rescnt < 0) { rescnt = fmtcnt + 100; reslen += rescnt; if (_PyUnicode_Resize(&result, reslen) < 0) goto onError; res = PyUnicode_AS_UNICODE(result) + reslen - rescnt; --rescnt; } *res++ = *fmt++; } else { /* Got a format specifier */ int flags = 0; Py_ssize_t width = -1; int prec = -1;Lines 7001–7500 of 8067. Previous lines Load more
{"join", (PyCFunction) unicode_join, METH_O, join__doc__}, {"capitalize", (PyCFunction) unicode_capitalize, METH_NOARGS, capitalize__doc__}, {"title", (PyCFunction) unicode_title, METH_NOARGS, title__doc__}, {"center", (PyCFunction) unicode_center, METH_VARARGS, center__doc__}, {"count", (PyCFunction) unicode_count, METH_VARARGS, count__doc__}, {"expandtabs", (PyCFunction) unicode_expandtabs, METH_VARARGS, expandtabs__doc__}, {"find", (PyCFunction) unicode_find, METH_VARARGS, find__doc__}, {"partition", (PyCFunction) unicode_partition, METH_O, partition__doc__}, {"index", (PyCFunction) unicode_index, METH_VARARGS, index__doc__}, {"ljust", (PyCFunction) unicode_ljust, METH_VARARGS, ljust__doc__}, {"lower", (PyCFunction) unicode_lower, METH_NOARGS, lower__doc__}, {"lstrip", (PyCFunction) unicode_lstrip, METH_VARARGS, lstrip__doc__}, {"decode", (PyCFunction) unicode_decode, METH_VARARGS, decode__doc__}, /* {"maketrans", (PyCFunction) unicode_maketrans, METH_VARARGS, maketrans__doc__}, */ {"rfind", (PyCFunction) unicode_rfind, METH_VARARGS, rfind__doc__}, {"rindex", (PyCFunction) unicode_rindex, METH_VARARGS, rindex__doc__}, {"rjust", (PyCFunction) unicode_rjust, METH_VARARGS, rjust__doc__}, {"rstrip", (PyCFunction) unicode_rstrip, METH_VARARGS, rstrip__doc__}, {"rpartition", (PyCFunction) unicode_rpartition, METH_O, rpartition__doc__}, {"splitlines", (PyCFunction) unicode_splitlines, METH_VARARGS, splitlines__doc__}, {"strip", (PyCFunction) unicode_strip, METH_VARARGS, strip__doc__}, {"swapcase", (PyCFunction) unicode_swapcase, METH_NOARGS, swapcase__doc__}, {"translate", (PyCFunction) unicode_translate, METH_O, translate__doc__}, {"upper", (PyCFunction) unicode_upper, METH_NOARGS, upper__doc__}, {"startswith", (PyCFunction) unicode_startswith, METH_VARARGS, startswith__doc__}, {"endswith", (PyCFunction) unicode_endswith, METH_VARARGS, endswith__doc__}, {"islower", (PyCFunction) unicode_islower, METH_NOARGS, islower__doc__}, {"isupper", (PyCFunction) unicode_isupper, METH_NOARGS, isupper__doc__}, {"istitle", (PyCFunction) unicode_istitle, METH_NOARGS, istitle__doc__}, {"isspace", (PyCFunction) unicode_isspace, METH_NOARGS, isspace__doc__}, {"isdecimal", (PyCFunction) unicode_isdecimal, METH_NOARGS, isdecimal__doc__}, {"isdigit", (PyCFunction) unicode_isdigit, METH_NOARGS, isdigit__doc__}, {"isnumeric", (PyCFunction) unicode_isnumeric, METH_NOARGS, isnumeric__doc__}, {"isalpha", (PyCFunction) unicode_isalpha, METH_NOARGS, isalpha__doc__}, {"isalnum", (PyCFunction) unicode_isalnum, METH_NOARGS, isalnum__doc__}, {"zfill", (PyCFunction) unicode_zfill, METH_VARARGS, zfill__doc__}, #if 0 {"capwords", (PyCFunction) unicode_capwords, METH_NOARGS, capwords__doc__}, #endif #if 0 /* This one is just used for debugging the implementation. */ {"freelistsize", (PyCFunction) unicode_freelistsize, METH_NOARGS}, #endif {"__getnewargs__", (PyCFunction)unicode_getnewargs, METH_NOARGS}, {NULL, NULL} }; static PyObject * unicode_mod(PyObject *v, PyObject *w) { if (!PyUnicode_Check(v)) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } return PyUnicode_Format(v, w); } static PyNumberMethods unicode_as_number = { 0, /*nb_add*/ 0, /*nb_subtract*/ 0, /*nb_multiply*/ 0, /*nb_divide*/ unicode_mod, /*nb_remainder*/ }; static PySequenceMethods unicode_as_sequence = { (lenfunc) unicode_length, /* sq_length */ PyUnicode_Concat, /* sq_concat */ (ssizeargfunc) unicode_repeat, /* sq_repeat */ (ssizeargfunc) unicode_getitem, /* sq_item */ (ssizessizeargfunc) unicode_slice, /* sq_slice */ 0, /* sq_ass_item */ 0, /* sq_ass_slice */ PyUnicode_Contains, /* sq_contains */ }; static PyObject* unicode_subscript(PyUnicodeObject* self, PyObject* item) { if (PyIndex_Check(item)) { Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += PyUnicode_GET_SIZE(self); return unicode_getitem(self, i); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; Py_UNICODE* source_buf; Py_UNICODE* result_buf; PyObject* result; if (PySlice_GetIndicesEx((PySliceObject*)item, PyUnicode_GET_SIZE(self), &start, &stop, &step, &slicelength) < 0) { return NULL; } if (slicelength <= 0) { return PyUnicode_FromUnicode(NULL, 0); } else { source_buf = PyUnicode_AS_UNICODE((PyObject*)self); result_buf = (Py_UNICODE *)PyMem_MALLOC(slicelength* sizeof(Py_UNICODE)); if (result_buf == NULL) return PyErr_NoMemory(); for (cur = start, i = 0; i < slicelength; cur += step, i++) { result_buf[i] = source_buf[cur]; } result = PyUnicode_FromUnicode(result_buf, slicelength); PyMem_FREE(result_buf); return result; } } else { PyErr_SetString(PyExc_TypeError, "string indices must be integers"); return NULL; } } static PyMappingMethods unicode_as_mapping = { (lenfunc)unicode_length, /* mp_length */ (binaryfunc)unicode_subscript, /* mp_subscript */ (objobjargproc)0, /* mp_ass_subscript */ }; static Py_ssize_t unicode_buffer_getreadbuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr) { if (index != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent unicode segment"); return -1; } *ptr = (void *) self->str; return PyUnicode_GET_DATA_SIZE(self); } static Py_ssize_t unicode_buffer_getwritebuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr) { PyErr_SetString(PyExc_TypeError, "cannot use unicode as modifiable buffer"); return -1; } static int unicode_buffer_getsegcount(PyUnicodeObject *self, Py_ssize_t *lenp) { if (lenp) *lenp = PyUnicode_GET_DATA_SIZE(self); return 1; } static Py_ssize_t unicode_buffer_getcharbuf(PyUnicodeObject *self, Py_ssize_t index, const void **ptr) { PyObject *str; if (index != 0) { PyErr_SetString(PyExc_SystemError, "accessing non-existent unicode segment"); return -1; } str = _PyUnicode_AsDefaultEncodedString((PyObject *)self, NULL); if (str == NULL) return -1; *ptr = (void *) PyString_AS_STRING(str); return PyString_GET_SIZE(str); } /* Helpers for PyUnicode_Format() */ static PyObject * getnextarg(PyObject *args, Py_ssize_t arglen, Py_ssize_t *p_argidx) { Py_ssize_t argidx = *p_argidx; if (argidx < arglen) { (*p_argidx)++; if (arglen < 0) return args; else return PyTuple_GetItem(args, argidx); } PyErr_SetString(PyExc_TypeError, "not enough arguments for format string"); return NULL; } #define F_LJUST (1<<0) #define F_SIGN (1<<1) #define F_BLANK (1<<2) #define F_ALT (1<<3) #define F_ZERO (1<<4) static Py_ssize_t strtounicode(Py_UNICODE *buffer, const char *charbuffer) { register Py_ssize_t i; Py_ssize_t len = strlen(charbuffer); for (i = len - 1; i >= 0; i--) buffer[i] = (Py_UNICODE) charbuffer[i]; return len; } static int doubletounicode(Py_UNICODE *buffer, size_t len, const char *format, double x) { Py_ssize_t result; PyOS_ascii_formatd((char *)buffer, len, format, x); result = strtounicode(buffer, (char *)buffer); return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); } static int longtounicode(Py_UNICODE *buffer, size_t len, const char *format, long x) { Py_ssize_t result; PyOS_snprintf((char *)buffer, len, format, x); result = strtounicode(buffer, (char *)buffer); return Py_SAFE_DOWNCAST(result, Py_ssize_t, int); } /* XXX To save some code duplication, formatfloat/long/int could have been shared with stringobject.c, converting from 8-bit to Unicode after the formatting is done. */ static int formatfloat(Py_UNICODE *buf, size_t buflen, int flags, int prec, int type, PyObject *v) { /* fmt = '%#.' + `prec` + `type` worst case length = 3 + 10 (len of INT_MAX) + 1 = 14 (use 20)*/ char fmt[20]; double x; x = PyFloat_AsDouble(v); if (x == -1.0 && PyErr_Occurred()) return -1; if (prec < 0) prec = 6; if (type == 'f' && (fabs(x) / 1e25) >= 1e25) type = 'g'; /* Worst case length calc to ensure no buffer overrun: 'g' formats: fmt = %#.<prec>g buf = '-' + [0-9]*prec + '.' + 'e+' + (longest exp for any double rep.) len = 1 + prec + 1 + 2 + 5 = 9 + prec 'f' formats: buf = '-' + [0-9]*x + '.' + [0-9]*prec (with x < 50) len = 1 + 50 + 1 + prec = 52 + prec If prec=0 the effective precision is 1 (the leading digit is always given), therefore increase the length by one. */ if ((type == 'g' && buflen <= (size_t)10 + (size_t)prec) || (type == 'f' && buflen <= (size_t)53 + (size_t)prec)) { PyErr_SetString(PyExc_OverflowError, "formatted float is too long (precision too large?)"); return -1; } PyOS_snprintf(fmt, sizeof(fmt), "%%%s.%d%c", (flags&F_ALT) ? "#" : "", prec, type); return doubletounicode(buf, buflen, fmt, x); } static PyObject* formatlong(PyObject *val, int flags, int prec, int type) { char *buf; int i, len; PyObject *str; /* temporary string object. */ PyUnicodeObject *result; str = _PyString_FormatLong(val, flags, prec, type, &buf, &len); if (!str) return NULL; result = _PyUnicode_New(len); if (!result) { Py_DECREF(str); return NULL; } for (i = 0; i < len; i++) result->str[i] = buf[i]; result->str[len] = 0; Py_DECREF(str); return (PyObject*)result; } static int formatint(Py_UNICODE *buf, size_t buflen, int flags, int prec, int type, PyObject *v) { /* fmt = '%#.' + `prec` + 'l' + `type` * worst case length = 3 + 19 (worst len of INT_MAX on 64-bit machine) * + 1 + 1 * = 24 */ char fmt[64]; /* plenty big enough! */ char *sign; long x; x = PyInt_AsLong(v); if (x == -1 && PyErr_Occurred()) return -1; if (x < 0 && type == 'u') { type = 'd'; } if (x < 0 && (type == 'x' || type == 'X' || type == 'o')) sign = "-"; else sign = ""; if (prec < 0) prec = 1; /* buf = '+'/'-'/'' + '0'/'0x'/'' + '[0-9]'*max(prec, len(x in octal)) * worst case buf = '-0x' + [0-9]*prec, where prec >= 11 */ if (buflen <= 14 || buflen <= (size_t)3 + (size_t)prec) { PyErr_SetString(PyExc_OverflowError, "formatted integer is too long (precision too large?)"); return -1; } if ((flags & F_ALT) && (type == 'x' || type == 'X')) { /* When converting under %#x or %#X, there are a number * of issues that cause pain: * - when 0 is being converted, the C standard leaves off * the '0x' or '0X', which is inconsistent with other * %#x/%#X conversions and inconsistent with Python's * hex() function * - there are platforms that violate the standard and * convert 0 with the '0x' or '0X' * (Metrowerks, Compaq Tru64) * - there are platforms that give '0x' when converting * under %#X, but convert 0 in accordance with the * standard (OS/2 EMX) * * We can achieve the desired consistency by inserting our * own '0x' or '0X' prefix, and substituting %x/%X in place * of %#x/%#X. * * Note that this is the same approach as used in * formatint() in stringobject.c */ PyOS_snprintf(fmt, sizeof(fmt), "%s0%c%%.%dl%c", sign, type, prec, type); } else { PyOS_snprintf(fmt, sizeof(fmt), "%s%%%s.%dl%c", sign, (flags&F_ALT) ? "#" : "", prec, type); } if (sign[0]) return longtounicode(buf, buflen, fmt, -x); else return longtounicode(buf, buflen, fmt, x); } static int formatchar(Py_UNICODE *buf, size_t buflen, PyObject *v) { /* presume that the buffer is at least 2 characters long */ if (PyUnicode_Check(v)) { if (PyUnicode_GET_SIZE(v) != 1) goto onError; buf[0] = PyUnicode_AS_UNICODE(v)[0]; } else if (PyString_Check(v)) { if (PyString_GET_SIZE(v) != 1) goto onError; buf[0] = (Py_UNICODE)PyString_AS_STRING(v)[0]; } else { /* Integer input truncated to a character */ long x; x = PyInt_AsLong(v); if (x == -1 && PyErr_Occurred()) goto onError; #ifdef Py_UNICODE_WIDE if (x < 0 || x > 0x10ffff) { PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x110000) " "(wide Python build)"); return -1; } #else if (x < 0 || x > 0xffff) { PyErr_SetString(PyExc_OverflowError, "%c arg not in range(0x10000) " "(narrow Python build)"); return -1; } #endif buf[0] = (Py_UNICODE) x; } buf[1] = '\0'; return 1; onError: PyErr_SetString(PyExc_TypeError, "%c requires int or char"); return -1; } /* fmt%(v1,v2,...) is roughly equivalent to sprintf(fmt, v1, v2, ...) FORMATBUFLEN is the length of the buffer in which the floats, ints, & chars are formatted. XXX This is a magic number. Each formatting routine does bounds checking to ensure no overflow, but a better solution may be to malloc a buffer of appropriate size for each format. For now, the current solution is sufficient. */ #define FORMATBUFLEN (size_t)120 PyObject *PyUnicode_Format(PyObject *format, PyObject *args) { Py_UNICODE *fmt, *res; Py_ssize_t fmtcnt, rescnt, reslen, arglen, argidx; int args_owned = 0; PyUnicodeObject *result = NULL; PyObject *dict = NULL; PyObject *uformat; if (format == NULL || args == NULL) { PyErr_BadInternalCall(); return NULL; } uformat = PyUnicode_FromObject(format); if (uformat == NULL) return NULL; fmt = PyUnicode_AS_UNICODE(uformat); fmtcnt = PyUnicode_GET_SIZE(uformat); reslen = rescnt = fmtcnt + 100; result = _PyUnicode_New(reslen); if (result == NULL) goto onError; res = PyUnicode_AS_UNICODE(result); if (PyTuple_Check(args)) { arglen = PyTuple_Size(args); argidx = 0; } else { arglen = -1; argidx = -2; } if (args->ob_type->tp_as_mapping && !PyTuple_Check(args) && !PyObject_TypeCheck(args, &PyBaseString_Type)) dict = args; while (--fmtcnt >= 0) { if (*fmt != '%') { if (--rescnt < 0) { rescnt = fmtcnt + 100; reslen += rescnt; if (_PyUnicode_Resize(&result, reslen) < 0) goto onError; res = PyUnicode_AS_UNICODE(result) + reslen - rescnt; --rescnt; } *res++ = *fmt++; } else { /* Got a format specifier */ int flags = 0; Py_ssize_t width = -1; int prec = -1;