diff -ru Python-2.4.2.orig/Include/abstract.h Python-2.4.2/Include/abstract.h --- Python-2.4.2.orig/Include/abstract.h 2004-03-12 16:38:17.000000000 +0000 +++ Python-2.4.2/Include/abstract.h 2005-10-25 20:53:50.000000000 +0100 @@ -455,6 +455,15 @@ This is the equivalent of the Python statement: del o[key]. */ + PyAPI_FUNC(int) PyObject_CheckCharBuffer(PyObject *obj); + + /* + Checks whether an arbitrary object supports the (character, + single segment) buffer interface. Returns 1 on success, 0 + on failure. + + */ + PyAPI_FUNC(int) PyObject_AsCharBuffer(PyObject *obj, const char **buffer, int *buffer_len); diff -ru Python-2.4.2.orig/Objects/abstract.c Python-2.4.2/Objects/abstract.c --- Python-2.4.2.orig/Objects/abstract.c 2005-08-21 12:09:58.000000000 +0100 +++ Python-2.4.2/Objects/abstract.c 2005-10-25 20:53:50.000000000 +0100 @@ -191,6 +191,19 @@ return ret; } +int +PyObject_CheckCharBuffer(PyObject *obj) +{ + PyBufferProcs *pb = obj->ob_type->tp_as_buffer; + + if (pb == NULL || + pb->bf_getcharbuffer == NULL || + pb->bf_getsegcount == NULL || + (*pb->bf_getsegcount)(obj, NULL) != 1) + return 0; + return 1; +} + int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, int *buffer_len) diff -ru Python-2.4.2.orig/Objects/stringobject.c Python-2.4.2/Objects/stringobject.c --- Python-2.4.2.orig/Objects/stringobject.c 2004-10-26 02:52:37.000000000 +0100 +++ Python-2.4.2/Objects/stringobject.c 2005-10-25 22:18:49.000000000 +0100 @@ -1004,19 +1004,20 @@ const char *lhs, *rhs, *end; int size; - if (!PyString_CheckExact(el)) { + if (PyString_Check(el)) { + size = PyString_GET_SIZE(el); + rhs = PyString_AS_STRING(el); + } #ifdef Py_USING_UNICODE - if (PyUnicode_Check(el)) - return PyUnicode_Contains(a, el); + else if (PyUnicode_Check(el)) + return PyUnicode_Contains(a, el); #endif - if (!PyString_Check(el)) { - PyErr_SetString(PyExc_TypeError, - "'in ' requires string as left operand"); - return -1; - } + else if (PyObject_AsCharBuffer(el, &rhs, &size)) + { + PyErr_SetString(PyExc_TypeError, + "'in ' requires string as left operand"); + return -1; } - size = PyString_GET_SIZE(el); - rhs = PyString_AS_STRING(el); lhs = PyString_AS_STRING(a); /* optimize for a single character */ @@ -1597,6 +1598,7 @@ const int seplen = PyString_GET_SIZE(self); PyObject *res = NULL; char *p; + const char *itemstr; int seqlen = 0; size_t sz = 0; int i; @@ -1633,21 +1635,28 @@ */ for (i = 0; i < seqlen; i++) { const size_t old_sz = sz; + int n; item = PySequence_Fast_GET_ITEM(seq, i); - if (!PyString_Check(item)){ + if (PyString_Check(item)){ + sz += PyString_GET_SIZE(item); + } #ifdef Py_USING_UNICODE - if (PyUnicode_Check(item)) { - /* Defer to Unicode join. - * CAUTION: There's no gurantee that the - * original sequence can be iterated over - * again, so we must pass seq here. - */ - PyObject *result; - result = PyUnicode_Join((PyObject *)self, seq); - Py_DECREF(seq); - return result; - } + else if (PyUnicode_Check(item)) { + /* Defer to Unicode join. + * CAUTION: There's no guarantee that the + * original sequence can be iterated over + * again, so we must pass seq here. + */ + PyObject *result; + result = PyUnicode_Join((PyObject *)self, seq); + Py_DECREF(seq); + return result; + } #endif + else if (!PyObject_AsCharBuffer(item, &itemstr, &n)) { + sz += n; + } + else { PyErr_Format(PyExc_TypeError, "sequence item %i: expected string," " %.80s found", @@ -1655,7 +1664,6 @@ Py_DECREF(seq); return NULL; } - sz += PyString_GET_SIZE(item); if (i != 0) sz += seplen; if (sz < old_sz || sz > INT_MAX) { @@ -1676,10 +1684,16 @@ /* Catenate everything. */ p = PyString_AS_STRING(res); for (i = 0; i < seqlen; ++i) { - size_t n; + int n; item = PySequence_Fast_GET_ITEM(seq, i); - n = PyString_GET_SIZE(item); - memcpy(p, PyString_AS_STRING(item), n); + if (PyString_Check(item)){ + itemstr = PyString_AS_STRING(item); + n = PyString_GET_SIZE(item); + } + else + PyObject_AsCharBuffer(item, &itemstr, &n); + + memcpy(p, itemstr, n); p += n; if (i < seqlen - 1) { memcpy(p, sep, seplen); @@ -1839,12 +1853,10 @@ static PyObject * -do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj) +do_xstrip(PyStringObject *self, int striptype, const char *sep, int seplen) { char *s = PyString_AS_STRING(self); int len = PyString_GET_SIZE(self); - char *sep = PyString_AS_STRING(sepobj); - int seplen = PyString_GET_SIZE(sepobj); int i, j; i = 0; @@ -1904,27 +1916,32 @@ static PyObject * do_argstrip(PyStringObject *self, int striptype, PyObject *args) { - PyObject *sep = NULL; + PyObject *sepobj = NULL; - if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep)) + if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sepobj)) return NULL; - if (sep != NULL && sep != Py_None) { - if (PyString_Check(sep)) - return do_xstrip(self, striptype, sep); + if (sepobj != NULL && sepobj != Py_None) { + const char *sep; + int seplen; + + if (PyString_Check(sepobj)) { + sep = PyString_AS_STRING(sepobj); + seplen = PyString_GET_SIZE(sepobj); + } #ifdef Py_USING_UNICODE - else if (PyUnicode_Check(sep)) { + else if (PyUnicode_Check(sepobj)) { PyObject *uniself = PyUnicode_FromObject((PyObject *)self); PyObject *res; if (uniself==NULL) return NULL; res = _PyUnicode_XStrip((PyUnicodeObject *)uniself, - striptype, sep); + striptype, sepobj); Py_DECREF(uniself); return res; } #endif - else { + else if (PyObject_AsCharBuffer(sepobj, &sep, &seplen)) { PyErr_Format(PyExc_TypeError, #ifdef Py_USING_UNICODE "%s arg must be None, str or unicode", @@ -1934,7 +1951,7 @@ STRIPNAME(striptype)); return NULL; } - return do_xstrip(self, striptype, sep); + return do_xstrip(self, striptype, sep, seplen); } return do_strip(self, striptype); @@ -2820,6 +2837,42 @@ return u; } +static int +parse_just_args(PyObject *args, char *fmt, int *width, char *fillchar) +{ + PyObject *fillobj = NULL; + + if (!PyArg_ParseTuple(args, fmt, width, &fillobj)) + return 0; + + if (fillobj) { + int n, rc; + const char *s; + + if (PyString_Check(fillobj)) { + s = PyString_AS_STRING(fillobj); + n = PyString_GET_SIZE(fillobj); + rc = 0; + } + else { + /* Unicode will be picked up here. */ + rc = PyObject_AsCharBuffer(fillobj, &s, &n); + } + + if (rc || n != 1) { + PyErr_Format(PyExc_TypeError, "fillchar arg must be a str of length 1"); + return 0; + } + + *fillchar = *s; + } + else { + *fillchar = ' '; + } + + return 1; +} + PyDoc_STRVAR(ljust__doc__, "S.ljust(width[, fillchar]) -> string\n" "\n" @@ -2830,9 +2883,9 @@ string_ljust(PyStringObject *self, PyObject *args) { int width; - char fillchar = ' '; + char fillchar; - if (!PyArg_ParseTuple(args, "i|c:ljust", &width, &fillchar)) + if (!parse_just_args(args, "i|O:ljust", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -2854,9 +2907,9 @@ string_rjust(PyStringObject *self, PyObject *args) { int width; - char fillchar = ' '; + char fillchar; - if (!PyArg_ParseTuple(args, "i|c:rjust", &width, &fillchar)) + if (!parse_just_args(args, "i|O:rjust", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -2879,9 +2932,9 @@ { int marg, left; int width; - char fillchar = ' '; + char fillchar; - if (!PyArg_ParseTuple(args, "i|c:center", &width, &fillchar)) + if (!parse_just_args(args, "i|O:center", &width, &fillchar)) return NULL; if (PyString_GET_SIZE(self) >= width && PyString_CheckExact(self)) { @@ -3832,6 +3885,18 @@ if (!PyArg_Parse(v, "c;%c requires int or char", &buf[0])) return -1; } + else if (PyObject_CheckCharBuffer(v)) { + const char *s; + int n; + + if (PyObject_AsCharBuffer(v, &s, &n) || n != 1) { + PyErr_SetString(PyExc_TypeError, + "%c requires int or char"); + return -1; + } + + buf[0] = s[0]; + } else { if (!PyArg_Parse(v, "b;%c requires int or char", &buf[0])) return -1; diff -ru Python-2.4.2.orig/Objects/unicodeobject.c Python-2.4.2/Objects/unicodeobject.c --- Python-2.4.2.orig/Objects/unicodeobject.c 2005-08-30 11:46:06.000000000 +0100 +++ Python-2.4.2/Objects/unicodeobject.c 2005-10-25 20:53:50.000000000 +0100 @@ -4169,7 +4169,7 @@ item = PySequence_Fast_GET_ITEM(fseq, i); /* Convert item to Unicode. */ - if (! PyUnicode_Check(item) && ! PyString_Check(item)) { + if (! PyUnicode_Check(item) && ! PyString_Check(item) && ! PyObject_CheckCharBuffer(item)) { PyErr_Format(PyExc_TypeError, "sequence item %i: expected string or Unicode," " %.80s found", @@ -5738,7 +5738,7 @@ if (sep != NULL && sep != Py_None) { if (PyUnicode_Check(sep)) return _PyUnicode_XStrip(self, striptype, sep); - else if (PyString_Check(sep)) { + else if (PyString_Check(sep) || PyObject_CheckCharBuffer(sep)) { PyObject *res; sep = PyUnicode_FromObject(sep); if (sep==NULL) @@ -6721,6 +6721,15 @@ buf[0] = (Py_UNICODE)PyString_AS_STRING(v)[0]; } + else if (PyObject_CheckCharBuffer(v)) { + const char *s; + int n; + + if (PyObject_AsCharBuffer(v, &s, &n) || n != 1) + goto onError; + buf[0] = (Py_UNICODE)s[0]; + } + else { /* Integer input truncated to a character */ long x;