j = i+pos; SPLIT_ADD(s, i, j); i = j + n; }#else i = j = 0; while ((j+n <= len) && (maxsplit-- > 0)) { for (; j+n <= len; j++) { if (Py_STRING_MATCH(s, j, sub, n)) { SPLIT_ADD(s, i, j); i = j = j + n; break; } } }#endif SPLIT_ADD(s, i, len); FIX_PREALLOC_SIZE(list); return list; onError: Py_DECREF(list); return NULL;} PyDoc_STRVAR(partition__doc__,"S.partition(sep) -> (head, sep, tail)\n\\n\Searches for the separator sep in S, and returns the part before it,\n\the separator itself, and the part after it. If the separator is not\n\found, returns S and two empty strings."); static PyObject *string_partition(PyStringObject *self, PyObject *sep_obj){ const char *sep; Py_ssize_t sep_len; if (PyString_Check(sep_obj)) { sep = PyString_AS_STRING(sep_obj); sep_len = PyString_GET_SIZE(sep_obj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep_obj)) return PyUnicode_Partition((PyObject *) self, sep_obj);#endif else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) return NULL; return stringlib_partition( (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self), sep_obj, sep, sep_len );} PyDoc_STRVAR(rpartition__doc__,"S.rpartition(sep) -> (tail, sep, head)\n\\n\Searches for the separator sep in S, starting at the end of S, and returns\n\the part before it, the separator itself, and the part after it. If the\n\separator is not found, returns two empty strings and S."); static PyObject *string_rpartition(PyStringObject *self, PyObject *sep_obj){ const char *sep; Py_ssize_t sep_len; if (PyString_Check(sep_obj)) { sep = PyString_AS_STRING(sep_obj); sep_len = PyString_GET_SIZE(sep_obj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep_obj)) return PyUnicode_Partition((PyObject *) self, sep_obj);#endif else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) return NULL; return stringlib_rpartition( (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self), sep_obj, sep, sep_len );} Py_LOCAL_INLINE(PyObject *)rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit){ Py_ssize_t i, j, count=0; PyObject *str; PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) return NULL; i = j = len-1; while (maxsplit-- > 0) { RSKIP_SPACE(s, i); if (i<0) break; j = i; i--; RSKIP_NONSPACE(s, i); SPLIT_ADD(s, i + 1, j + 1); } if (i >= 0) { /* Only occurs when maxsplit was reached */ /* Skip any remaining whitespace and copy to beginning of string */ RSKIP_SPACE(s, i); if (i >= 0) SPLIT_ADD(s, 0, i + 1); } FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL;} Py_LOCAL_INLINE(PyObject *)rsplit_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount){ register Py_ssize_t i, j, count=0; PyObject *str; PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); if (list == NULL) return NULL; i = j = len - 1; while ((i >= 0) && (maxcount-- > 0)) { for (; i >= 0; i--) { if (s[i] == ch) { SPLIT_ADD(s, i + 1, j + 1); j = i = i - 1; break; } } } if (j >= -1) { SPLIT_ADD(s, 0, j + 1); } FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL;} PyDoc_STRVAR(rsplit__doc__,"S.rsplit([sep [,maxsplit]]) -> list of strings\n\\n\Return a list of the words in the string S, using sep as the\n\delimiter string, starting at the end of the string and working\n\to the front. If maxsplit is given, at most maxsplit splits are\n\done. If sep is not specified or is None, any whitespace string\n\is a separator."); static PyObject *string_rsplit(PyStringObject *self, PyObject *args){ Py_ssize_t len = PyString_GET_SIZE(self), n, i, j; Py_ssize_t maxsplit = -1, count=0; const char *s = PyString_AS_STRING(self), *sub; PyObject *list, *str, *subobj = Py_None; if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit)) return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) return rsplit_whitespace(s, len, maxsplit); if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); n = PyString_GET_SIZE(subobj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(subobj)) return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit);#endif else if (PyObject_AsCharBuffer(subobj, &sub, &n)) return NULL; if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); return NULL; } else if (n == 1) return rsplit_char(s, len, sub[0], maxsplit); list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) return NULL; j = len; i = j - n; while ( (i >= 0) && (maxsplit-- > 0) ) { for (; i>=0; i--) { if (Py_STRING_MATCH(s, i, sub, n)) { SPLIT_ADD(s, i + n, j); j = i; i -= n; break; } } } SPLIT_ADD(s, 0, j); FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL;} PyDoc_STRVAR(join__doc__,"S.join(sequence) -> string\n\\n\Return a string which is the concatenation of the strings in the\n\sequence. The separator between elements is S."); static PyObject *string_join(PyStringObject *self, PyObject *orig){ char *sep = PyString_AS_STRING(self); const Py_ssize_t seplen = PyString_GET_SIZE(self); PyObject *res = NULL; char *p; Py_ssize_t seqlen = 0; size_t sz = 0; Py_ssize_t i; PyObject *seq, *item; seq = PySequence_Fast(orig, ""); if (seq == NULL) { return NULL; } seqlen = PySequence_Size(seq); if (seqlen == 0) { Py_DECREF(seq); return PyString_FromString(""); } if (seqlen == 1) { item = PySequence_Fast_GET_ITEM(seq, 0); if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) { Py_INCREF(item); Py_DECREF(seq); return item; } } /* There are at least two things to join, or else we have a subclass * of the builtin types in the sequence. * Do a pre-pass to figure out the total amount of space we'll * need (sz), see whether any argument is absurd, and defer to * the Unicode join if appropriate. */ for (i = 0; i < seqlen; i++) { const size_t old_sz = sz; item = PySequence_Fast_GET_ITEM(seq, i); if (!PyString_Check(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; }#endif PyErr_Format(PyExc_TypeError, "sequence item %zd: expected string," " %.80s found", i, item->ob_type->tp_name); Py_DECREF(seq); return NULL; } sz += PyString_GET_SIZE(item); if (i != 0) sz += seplen; if (sz < old_sz || sz > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); Py_DECREF(seq); return NULL; } } /* Allocate result space. */ res = PyString_FromStringAndSize((char*)NULL, sz); if (res == NULL) { Py_DECREF(seq); return NULL; } /* Catenate everything. */ p = PyString_AS_STRING(res); for (i = 0; i < seqlen; ++i) { size_t n; item = PySequence_Fast_GET_ITEM(seq, i); n = PyString_GET_SIZE(item); Py_MEMCPY(p, PyString_AS_STRING(item), n); p += n; if (i < seqlen - 1) { Py_MEMCPY(p, sep, seplen); p += seplen; } } Py_DECREF(seq); return res;} PyObject *_PyString_Join(PyObject *sep, PyObject *x){ assert(sep != NULL && PyString_Check(sep)); assert(x != NULL); return string_join((PyStringObject *)sep, x);} Py_LOCAL_INLINE(void)string_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len){ if (*end > len) *end = len; else if (*end < 0) *end += len; if (*end < 0) *end = 0; if (*start < 0) *start += len; if (*start < 0) *start = 0;} Py_LOCAL_INLINE(Py_ssize_t)string_find_internal(PyStringObject *self, PyObject *args, int dir){ PyObject *subobj; const char *sub; Py_ssize_t sub_len; Py_ssize_t start=0, end=PY_SSIZE_T_MAX; if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) return -2; if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); sub_len = PyString_GET_SIZE(subobj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(subobj)) return PyUnicode_Find( (PyObject *)self, subobj, start, end, dir);#endif else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len)) /* XXX - the "expected a character buffer object" is pretty confusing for a non-expert. remap to something else ? */ return -2; if (dir > 0) return stringlib_find_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end); else return stringlib_rfind_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end);} PyDoc_STRVAR(find__doc__,"S.find(sub [,start [,end]]) -> int\n\\n\Return the lowest index in S where substring sub is found,\n\such that sub is contained within s[start,end]. Optional\n\arguments start and end are interpreted as in slice notation.\n\\n\Return -1 on failure."); static PyObject *string_find(PyStringObject *self, PyObject *args){ Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; return PyInt_FromSsize_t(result);} PyDoc_STRVAR(index__doc__,"S.index(sub [,start [,end]]) -> int\n\\n\Like S.find() but raise ValueError when the substring is not found."); static PyObject *string_index(PyStringObject *self, PyObject *args){ Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result);} PyDoc_STRVAR(rfind__doc__,"S.rfind(sub [,start [,end]]) -> int\n\\n\Return the highest index in S where substring sub is found,\n\such that sub is contained within s[start,end]. Optional\n\arguments start and end are interpreted as in slice notation.\n\\n\Return -1 on failure."); static PyObject *string_rfind(PyStringObject *self, PyObject *args){ Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; return PyInt_FromSsize_t(result);} PyDoc_STRVAR(rindex__doc__,"S.rindex(sub [,start [,end]]) -> int\n\\n\Like S.rfind() but raise ValueError when the substring is not found."); static PyObject *string_rindex(PyStringObject *self, PyObject *args){ Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result);} Py_LOCAL_INLINE(PyObject *)do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj){ char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self); char *sep = PyString_AS_STRING(sepobj); Py_ssize_t seplen = PyString_GET_SIZE(sepobj); Py_ssize_t i, j; i = 0; if (striptype != RIGHTSTRIP) { while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) { i++; } } j = len; if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen)); j++; } if (i == 0 && j == len && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*)self; } else return PyString_FromStringAndSize(s+i, j-i);} Py_LOCAL_INLINE(PyObject *)Lines 1501–2000 of 5009. Previous lines Load more
j = i+pos; SPLIT_ADD(s, i, j); i = j + n; } #else i = j = 0; while ((j+n <= len) && (maxsplit-- > 0)) { for (; j+n <= len; j++) { if (Py_STRING_MATCH(s, j, sub, n)) { SPLIT_ADD(s, i, j); i = j = j + n; break; } } } #endif SPLIT_ADD(s, i, len); FIX_PREALLOC_SIZE(list); return list; onError: Py_DECREF(list); return NULL; } PyDoc_STRVAR(partition__doc__, "S.partition(sep) -> (head, sep, tail)\n\ \n\ Searches for the separator sep in S, and returns the part before it,\n\ the separator itself, and the part after it. If the separator is not\n\ found, returns S and two empty strings."); static PyObject * string_partition(PyStringObject *self, PyObject *sep_obj) { const char *sep; Py_ssize_t sep_len; if (PyString_Check(sep_obj)) { sep = PyString_AS_STRING(sep_obj); sep_len = PyString_GET_SIZE(sep_obj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep_obj)) return PyUnicode_Partition((PyObject *) self, sep_obj); #endif else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) return NULL; return stringlib_partition( (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self), sep_obj, sep, sep_len ); } PyDoc_STRVAR(rpartition__doc__, "S.rpartition(sep) -> (tail, sep, head)\n\ \n\ Searches for the separator sep in S, starting at the end of S, and returns\n\ the part before it, the separator itself, and the part after it. If the\n\ separator is not found, returns two empty strings and S."); static PyObject * string_rpartition(PyStringObject *self, PyObject *sep_obj) { const char *sep; Py_ssize_t sep_len; if (PyString_Check(sep_obj)) { sep = PyString_AS_STRING(sep_obj); sep_len = PyString_GET_SIZE(sep_obj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep_obj)) return PyUnicode_Partition((PyObject *) self, sep_obj); #endif else if (PyObject_AsCharBuffer(sep_obj, &sep, &sep_len)) return NULL; return stringlib_rpartition( (PyObject*) self, PyString_AS_STRING(self), PyString_GET_SIZE(self), sep_obj, sep, sep_len ); } Py_LOCAL_INLINE(PyObject *) rsplit_whitespace(const char *s, Py_ssize_t len, Py_ssize_t maxsplit) { Py_ssize_t i, j, count=0; PyObject *str; PyObject *list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) return NULL; i = j = len-1; while (maxsplit-- > 0) { RSKIP_SPACE(s, i); if (i<0) break; j = i; i--; RSKIP_NONSPACE(s, i); SPLIT_ADD(s, i + 1, j + 1); } if (i >= 0) { /* Only occurs when maxsplit was reached */ /* Skip any remaining whitespace and copy to beginning of string */ RSKIP_SPACE(s, i); if (i >= 0) SPLIT_ADD(s, 0, i + 1); } FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL; } Py_LOCAL_INLINE(PyObject *) rsplit_char(const char *s, Py_ssize_t len, char ch, Py_ssize_t maxcount) { register Py_ssize_t i, j, count=0; PyObject *str; PyObject *list = PyList_New(PREALLOC_SIZE(maxcount)); if (list == NULL) return NULL; i = j = len - 1; while ((i >= 0) && (maxcount-- > 0)) { for (; i >= 0; i--) { if (s[i] == ch) { SPLIT_ADD(s, i + 1, j + 1); j = i = i - 1; break; } } } if (j >= -1) { SPLIT_ADD(s, 0, j + 1); } FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL; } PyDoc_STRVAR(rsplit__doc__, "S.rsplit([sep [,maxsplit]]) -> list of strings\n\ \n\ Return a list of the words in the string S, using sep as the\n\ delimiter string, starting at the end of the string and working\n\ to the front. If maxsplit is given, at most maxsplit splits are\n\ done. If sep is not specified or is None, any whitespace string\n\ is a separator."); static PyObject * string_rsplit(PyStringObject *self, PyObject *args) { Py_ssize_t len = PyString_GET_SIZE(self), n, i, j; Py_ssize_t maxsplit = -1, count=0; const char *s = PyString_AS_STRING(self), *sub; PyObject *list, *str, *subobj = Py_None; if (!PyArg_ParseTuple(args, "|On:rsplit", &subobj, &maxsplit)) return NULL; if (maxsplit < 0) maxsplit = PY_SSIZE_T_MAX; if (subobj == Py_None) return rsplit_whitespace(s, len, maxsplit); if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); n = PyString_GET_SIZE(subobj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(subobj)) return PyUnicode_RSplit((PyObject *)self, subobj, maxsplit); #endif else if (PyObject_AsCharBuffer(subobj, &sub, &n)) return NULL; if (n == 0) { PyErr_SetString(PyExc_ValueError, "empty separator"); return NULL; } else if (n == 1) return rsplit_char(s, len, sub[0], maxsplit); list = PyList_New(PREALLOC_SIZE(maxsplit)); if (list == NULL) return NULL; j = len; i = j - n; while ( (i >= 0) && (maxsplit-- > 0) ) { for (; i>=0; i--) { if (Py_STRING_MATCH(s, i, sub, n)) { SPLIT_ADD(s, i + n, j); j = i; i -= n; break; } } } SPLIT_ADD(s, 0, j); FIX_PREALLOC_SIZE(list); if (PyList_Reverse(list) < 0) goto onError; return list; onError: Py_DECREF(list); return NULL; } PyDoc_STRVAR(join__doc__, "S.join(sequence) -> string\n\ \n\ Return a string which is the concatenation of the strings in the\n\ sequence. The separator between elements is S."); static PyObject * string_join(PyStringObject *self, PyObject *orig) { char *sep = PyString_AS_STRING(self); const Py_ssize_t seplen = PyString_GET_SIZE(self); PyObject *res = NULL; char *p; Py_ssize_t seqlen = 0; size_t sz = 0; Py_ssize_t i; PyObject *seq, *item; seq = PySequence_Fast(orig, ""); if (seq == NULL) { return NULL; } seqlen = PySequence_Size(seq); if (seqlen == 0) { Py_DECREF(seq); return PyString_FromString(""); } if (seqlen == 1) { item = PySequence_Fast_GET_ITEM(seq, 0); if (PyString_CheckExact(item) || PyUnicode_CheckExact(item)) { Py_INCREF(item); Py_DECREF(seq); return item; } } /* There are at least two things to join, or else we have a subclass * of the builtin types in the sequence. * Do a pre-pass to figure out the total amount of space we'll * need (sz), see whether any argument is absurd, and defer to * the Unicode join if appropriate. */ for (i = 0; i < seqlen; i++) { const size_t old_sz = sz; item = PySequence_Fast_GET_ITEM(seq, i); if (!PyString_Check(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; } #endif PyErr_Format(PyExc_TypeError, "sequence item %zd: expected string," " %.80s found", i, item->ob_type->tp_name); Py_DECREF(seq); return NULL; } sz += PyString_GET_SIZE(item); if (i != 0) sz += seplen; if (sz < old_sz || sz > PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "join() result is too long for a Python string"); Py_DECREF(seq); return NULL; } } /* Allocate result space. */ res = PyString_FromStringAndSize((char*)NULL, sz); if (res == NULL) { Py_DECREF(seq); return NULL; } /* Catenate everything. */ p = PyString_AS_STRING(res); for (i = 0; i < seqlen; ++i) { size_t n; item = PySequence_Fast_GET_ITEM(seq, i); n = PyString_GET_SIZE(item); Py_MEMCPY(p, PyString_AS_STRING(item), n); p += n; if (i < seqlen - 1) { Py_MEMCPY(p, sep, seplen); p += seplen; } } Py_DECREF(seq); return res; } PyObject * _PyString_Join(PyObject *sep, PyObject *x) { assert(sep != NULL && PyString_Check(sep)); assert(x != NULL); return string_join((PyStringObject *)sep, x); } Py_LOCAL_INLINE(void) string_adjust_indices(Py_ssize_t *start, Py_ssize_t *end, Py_ssize_t len) { if (*end > len) *end = len; else if (*end < 0) *end += len; if (*end < 0) *end = 0; if (*start < 0) *start += len; if (*start < 0) *start = 0; } Py_LOCAL_INLINE(Py_ssize_t) string_find_internal(PyStringObject *self, PyObject *args, int dir) { PyObject *subobj; const char *sub; Py_ssize_t sub_len; Py_ssize_t start=0, end=PY_SSIZE_T_MAX; if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) return -2; if (PyString_Check(subobj)) { sub = PyString_AS_STRING(subobj); sub_len = PyString_GET_SIZE(subobj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(subobj)) return PyUnicode_Find( (PyObject *)self, subobj, start, end, dir); #endif else if (PyObject_AsCharBuffer(subobj, &sub, &sub_len)) /* XXX - the "expected a character buffer object" is pretty confusing for a non-expert. remap to something else ? */ return -2; if (dir > 0) return stringlib_find_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end); else return stringlib_rfind_slice( PyString_AS_STRING(self), PyString_GET_SIZE(self), sub, sub_len, start, end); } PyDoc_STRVAR(find__doc__, "S.find(sub [,start [,end]]) -> int\n\ \n\ Return the lowest index in S where substring sub is found,\n\ such that sub is contained within s[start,end]. Optional\n\ arguments start and end are interpreted as in slice notation.\n\ \n\ Return -1 on failure."); static PyObject * string_find(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; return PyInt_FromSsize_t(result); } PyDoc_STRVAR(index__doc__, "S.index(sub [,start [,end]]) -> int\n\ \n\ Like S.find() but raise ValueError when the substring is not found."); static PyObject * string_index(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, +1); if (result == -2) return NULL; if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result); } PyDoc_STRVAR(rfind__doc__, "S.rfind(sub [,start [,end]]) -> int\n\ \n\ Return the highest index in S where substring sub is found,\n\ such that sub is contained within s[start,end]. Optional\n\ arguments start and end are interpreted as in slice notation.\n\ \n\ Return -1 on failure."); static PyObject * string_rfind(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; return PyInt_FromSsize_t(result); } PyDoc_STRVAR(rindex__doc__, "S.rindex(sub [,start [,end]]) -> int\n\ \n\ Like S.rfind() but raise ValueError when the substring is not found."); static PyObject * string_rindex(PyStringObject *self, PyObject *args) { Py_ssize_t result = string_find_internal(self, args, -1); if (result == -2) return NULL; if (result == -1) { PyErr_SetString(PyExc_ValueError, "substring not found"); return NULL; } return PyInt_FromSsize_t(result); } Py_LOCAL_INLINE(PyObject *) do_xstrip(PyStringObject *self, int striptype, PyObject *sepobj) { char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self); char *sep = PyString_AS_STRING(sepobj); Py_ssize_t seplen = PyString_GET_SIZE(sepobj); Py_ssize_t i, j; i = 0; if (striptype != RIGHTSTRIP) { while (i < len && memchr(sep, Py_CHARMASK(s[i]), seplen)) { i++; } } j = len; if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && memchr(sep, Py_CHARMASK(s[j]), seplen)); j++; } if (i == 0 && j == len && PyString_CheckExact(self)) { Py_INCREF(self); return (PyObject*)self; } else return PyString_FromStringAndSize(s+i, j-i); } Py_LOCAL_INLINE(PyObject *)