do_strip(PyStringObject *self, int striptype){ char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self), i, j; i = 0; if (striptype != RIGHTSTRIP) { while (i < len && isspace(Py_CHARMASK(s[i]))) { i++; } } j = len; if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && isspace(Py_CHARMASK(s[j]))); 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 *)do_argstrip(PyStringObject *self, int striptype, PyObject *args){ PyObject *sep = NULL; if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep)) return NULL; if (sep != NULL && sep != Py_None) { if (PyString_Check(sep)) return do_xstrip(self, striptype, sep);#ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep)) { PyObject *uniself = PyUnicode_FromObject((PyObject *)self); PyObject *res; if (uniself==NULL) return NULL; res = _PyUnicode_XStrip((PyUnicodeObject *)uniself, striptype, sep); Py_DECREF(uniself); return res; }#endif PyErr_Format(PyExc_TypeError,#ifdef Py_USING_UNICODE "%s arg must be None, str or unicode",#else "%s arg must be None or str",#endif STRIPNAME(striptype)); return NULL; } return do_strip(self, striptype);} PyDoc_STRVAR(strip__doc__,"S.strip([chars]) -> string or unicode\n\\n\Return a copy of the string S with leading and trailing\n\whitespace removed.\n\If chars is given and not None, remove characters in chars instead.\n\If chars is unicode, S will be converted to unicode before stripping"); static PyObject *string_strip(PyStringObject *self, PyObject *args){ if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, BOTHSTRIP); /* Common case */ else return do_argstrip(self, BOTHSTRIP, args);} PyDoc_STRVAR(lstrip__doc__,"S.lstrip([chars]) -> string or unicode\n\\n\Return a copy of the string S with leading whitespace removed.\n\If chars is given and not None, remove characters in chars instead.\n\If chars is unicode, S will be converted to unicode before stripping"); static PyObject *string_lstrip(PyStringObject *self, PyObject *args){ if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, LEFTSTRIP); /* Common case */ else return do_argstrip(self, LEFTSTRIP, args);} PyDoc_STRVAR(rstrip__doc__,"S.rstrip([chars]) -> string or unicode\n\\n\Return a copy of the string S with trailing whitespace removed.\n\If chars is given and not None, remove characters in chars instead.\n\If chars is unicode, S will be converted to unicode before stripping"); static PyObject *string_rstrip(PyStringObject *self, PyObject *args){ if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, RIGHTSTRIP); /* Common case */ else return do_argstrip(self, RIGHTSTRIP, args);} PyDoc_STRVAR(lower__doc__,"S.lower() -> string\n\\n\Return a copy of the string S converted to lowercase."); /* _tolower and _toupper are defined by SUSv2, but they're not ISO C */#ifndef _tolower#define _tolower tolower#endif static PyObject *string_lower(PyStringObject *self){ char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; s = PyString_AS_STRING(newobj); Py_MEMCPY(s, PyString_AS_STRING(self), n); for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (isupper(c)) s[i] = _tolower(c); } return newobj;} PyDoc_STRVAR(upper__doc__,"S.upper() -> string\n\\n\Return a copy of the string S converted to uppercase."); #ifndef _toupper#define _toupper toupper#endif static PyObject *string_upper(PyStringObject *self){ char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; s = PyString_AS_STRING(newobj); Py_MEMCPY(s, PyString_AS_STRING(self), n); for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (islower(c)) s[i] = _toupper(c); } return newobj;} PyDoc_STRVAR(title__doc__,"S.title() -> string\n\\n\Return a titlecased version of S, i.e. words start with uppercase\n\characters, all remaining cased characters have lowercase."); static PyObject*string_title(PyStringObject *self){ char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); int previous_is_cased = 0; PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); if (islower(c)) { if (!previous_is_cased) c = toupper(c); previous_is_cased = 1; } else if (isupper(c)) { if (previous_is_cased) c = tolower(c); previous_is_cased = 1; } else previous_is_cased = 0; *s_new++ = c; } return newobj;} PyDoc_STRVAR(capitalize__doc__,"S.capitalize() -> string\n\\n\Return a copy of the string S with only its first character\n\capitalized."); static PyObject *string_capitalize(PyStringObject *self){ char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); if (0 < n) { int c = Py_CHARMASK(*s++); if (islower(c)) *s_new = toupper(c); else *s_new = c; s_new++; } for (i = 1; i < n; i++) { int c = Py_CHARMASK(*s++); if (isupper(c)) *s_new = tolower(c); else *s_new = c; s_new++; } return newobj;} PyDoc_STRVAR(count__doc__,"S.count(sub[, start[, end]]) -> int\n\\n\Return the number of non-overlapping occurrences of substring sub in\n\string S[start:end]. Optional arguments start and end are interpreted\n\as in slice notation."); static PyObject *string_count(PyStringObject *self, PyObject *args){ PyObject *sub_obj; const char *str = PyString_AS_STRING(self), *sub; Py_ssize_t sub_len; Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) return NULL; if (PyString_Check(sub_obj)) { sub = PyString_AS_STRING(sub_obj); sub_len = PyString_GET_SIZE(sub_obj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(sub_obj)) { Py_ssize_t count; count = PyUnicode_Count((PyObject *)self, sub_obj, start, end); if (count == -1) return NULL; else return PyInt_FromSsize_t(count); }#endif else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len)) return NULL; string_adjust_indices(&start, &end, PyString_GET_SIZE(self)); return PyInt_FromSsize_t( stringlib_count(str + start, end - start, sub, sub_len) );} PyDoc_STRVAR(swapcase__doc__,"S.swapcase() -> string\n\\n\Return a copy of the string S with uppercase characters\n\converted to lowercase and vice versa."); static PyObject *string_swapcase(PyStringObject *self){ char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); if (islower(c)) { *s_new = toupper(c); } else if (isupper(c)) { *s_new = tolower(c); } else *s_new = c; s_new++; } return newobj;} PyDoc_STRVAR(translate__doc__,"S.translate(table [,deletechars]) -> string\n\\n\Return a copy of the string S, where all characters occurring\n\in the optional argument deletechars are removed, and the\n\remaining characters have been mapped through the given\n\translation table, which must be a string of length 256."); static PyObject *string_translate(PyStringObject *self, PyObject *args){ register char *input, *output; register const char *table; register Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; const char *table1, *output_start, *del_table=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; PyObject *tableobj, *delobj = NULL; if (!PyArg_UnpackTuple(args, "translate", 1, 2, &tableobj, &delobj)) return NULL; if (PyString_Check(tableobj)) { table1 = PyString_AS_STRING(tableobj); tablen = PyString_GET_SIZE(tableobj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(tableobj)) { /* Unicode .translate() does not support the deletechars parameter; instead a mapping to None will cause characters to be deleted. */ if (delobj != NULL) { PyErr_SetString(PyExc_TypeError, "deletions are implemented differently for unicode"); return NULL; } return PyUnicode_Translate((PyObject *)self, tableobj, NULL); }#endif else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen)) return NULL; if (tablen != 256) { PyErr_SetString(PyExc_ValueError, "translation table must be 256 characters long"); return NULL; } if (delobj != NULL) { if (PyString_Check(delobj)) { del_table = PyString_AS_STRING(delobj); dellen = PyString_GET_SIZE(delobj); }#ifdef Py_USING_UNICODE else if (PyUnicode_Check(delobj)) { PyErr_SetString(PyExc_TypeError, "deletions are implemented differently for unicode"); return NULL; }#endif else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen)) return NULL; } else { del_table = NULL; dellen = 0; } table = table1; inlen = PyString_GET_SIZE(input_obj); result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) return NULL; output_start = output = PyString_AsString(result); input = PyString_AS_STRING(input_obj); if (dellen == 0) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (Py_CHARMASK((*output++ = table[c])) != c) changed = 1; } if (changed || !PyString_CheckExact(input_obj)) return result; Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(table[i]); for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (trans_table[c] != -1) if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) continue; changed = 1; } if (!changed && PyString_CheckExact(input_obj)) { Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } /* Fix the size of the resulting string */ if (inlen > 0) _PyString_Resize(&result, output - output_start); return result;} #define FORWARD 1#define REVERSE -1 /* find and count characters and substrings */ #define findchar(target, target_len, c) \ ((char *)memchr((const void *)(target), c, target_len)) /* String ops must return a string. *//* If the object is subclass of string, create a copy */Py_LOCAL(PyStringObject *)return_self(PyStringObject *self){ if (PyString_CheckExact(self)) { Py_INCREF(self); return self; } return (PyStringObject *)PyString_FromStringAndSize( PyString_AS_STRING(self), PyString_GET_SIZE(self));} Py_LOCAL_INLINE(Py_ssize_t)countchar(const char *target, int target_len, char c, Py_ssize_t maxcount){ Py_ssize_t count=0; const char *start=target; const char *end=target+target_len; while ( (start=findchar(start, end-start, c)) != NULL ) { count++; if (count >= maxcount) break; start += 1; } return count;} Py_LOCAL(Py_ssize_t)findstring(const char *target, Py_ssize_t target_len, const char *pattern, Py_ssize_t pattern_len, Py_ssize_t start, Py_ssize_t end, int direction){ if (start < 0) { start += target_len; if (start < 0) start = 0;Lines 2001–2500 of 5009. Previous lines Load more
do_strip(PyStringObject *self, int striptype) { char *s = PyString_AS_STRING(self); Py_ssize_t len = PyString_GET_SIZE(self), i, j; i = 0; if (striptype != RIGHTSTRIP) { while (i < len && isspace(Py_CHARMASK(s[i]))) { i++; } } j = len; if (striptype != LEFTSTRIP) { do { j--; } while (j >= i && isspace(Py_CHARMASK(s[j]))); 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 *) do_argstrip(PyStringObject *self, int striptype, PyObject *args) { PyObject *sep = NULL; if (!PyArg_ParseTuple(args, (char *)stripformat[striptype], &sep)) return NULL; if (sep != NULL && sep != Py_None) { if (PyString_Check(sep)) return do_xstrip(self, striptype, sep); #ifdef Py_USING_UNICODE else if (PyUnicode_Check(sep)) { PyObject *uniself = PyUnicode_FromObject((PyObject *)self); PyObject *res; if (uniself==NULL) return NULL; res = _PyUnicode_XStrip((PyUnicodeObject *)uniself, striptype, sep); Py_DECREF(uniself); return res; } #endif PyErr_Format(PyExc_TypeError, #ifdef Py_USING_UNICODE "%s arg must be None, str or unicode", #else "%s arg must be None or str", #endif STRIPNAME(striptype)); return NULL; } return do_strip(self, striptype); } PyDoc_STRVAR(strip__doc__, "S.strip([chars]) -> string or unicode\n\ \n\ Return a copy of the string S with leading and trailing\n\ whitespace removed.\n\ If chars is given and not None, remove characters in chars instead.\n\ If chars is unicode, S will be converted to unicode before stripping"); static PyObject * string_strip(PyStringObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, BOTHSTRIP); /* Common case */ else return do_argstrip(self, BOTHSTRIP, args); } PyDoc_STRVAR(lstrip__doc__, "S.lstrip([chars]) -> string or unicode\n\ \n\ Return a copy of the string S with leading whitespace removed.\n\ If chars is given and not None, remove characters in chars instead.\n\ If chars is unicode, S will be converted to unicode before stripping"); static PyObject * string_lstrip(PyStringObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, LEFTSTRIP); /* Common case */ else return do_argstrip(self, LEFTSTRIP, args); } PyDoc_STRVAR(rstrip__doc__, "S.rstrip([chars]) -> string or unicode\n\ \n\ Return a copy of the string S with trailing whitespace removed.\n\ If chars is given and not None, remove characters in chars instead.\n\ If chars is unicode, S will be converted to unicode before stripping"); static PyObject * string_rstrip(PyStringObject *self, PyObject *args) { if (PyTuple_GET_SIZE(args) == 0) return do_strip(self, RIGHTSTRIP); /* Common case */ else return do_argstrip(self, RIGHTSTRIP, args); } PyDoc_STRVAR(lower__doc__, "S.lower() -> string\n\ \n\ Return a copy of the string S converted to lowercase."); /* _tolower and _toupper are defined by SUSv2, but they're not ISO C */ #ifndef _tolower #define _tolower tolower #endif static PyObject * string_lower(PyStringObject *self) { char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; s = PyString_AS_STRING(newobj); Py_MEMCPY(s, PyString_AS_STRING(self), n); for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (isupper(c)) s[i] = _tolower(c); } return newobj; } PyDoc_STRVAR(upper__doc__, "S.upper() -> string\n\ \n\ Return a copy of the string S converted to uppercase."); #ifndef _toupper #define _toupper toupper #endif static PyObject * string_upper(PyStringObject *self) { char *s; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (!newobj) return NULL; s = PyString_AS_STRING(newobj); Py_MEMCPY(s, PyString_AS_STRING(self), n); for (i = 0; i < n; i++) { int c = Py_CHARMASK(s[i]); if (islower(c)) s[i] = _toupper(c); } return newobj; } PyDoc_STRVAR(title__doc__, "S.title() -> string\n\ \n\ Return a titlecased version of S, i.e. words start with uppercase\n\ characters, all remaining cased characters have lowercase."); static PyObject* string_title(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); int previous_is_cased = 0; PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); if (islower(c)) { if (!previous_is_cased) c = toupper(c); previous_is_cased = 1; } else if (isupper(c)) { if (previous_is_cased) c = tolower(c); previous_is_cased = 1; } else previous_is_cased = 0; *s_new++ = c; } return newobj; } PyDoc_STRVAR(capitalize__doc__, "S.capitalize() -> string\n\ \n\ Return a copy of the string S with only its first character\n\ capitalized."); static PyObject * string_capitalize(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); if (0 < n) { int c = Py_CHARMASK(*s++); if (islower(c)) *s_new = toupper(c); else *s_new = c; s_new++; } for (i = 1; i < n; i++) { int c = Py_CHARMASK(*s++); if (isupper(c)) *s_new = tolower(c); else *s_new = c; s_new++; } return newobj; } PyDoc_STRVAR(count__doc__, "S.count(sub[, start[, end]]) -> int\n\ \n\ Return the number of non-overlapping occurrences of substring sub in\n\ string S[start:end]. Optional arguments start and end are interpreted\n\ as in slice notation."); static PyObject * string_count(PyStringObject *self, PyObject *args) { PyObject *sub_obj; const char *str = PyString_AS_STRING(self), *sub; Py_ssize_t sub_len; Py_ssize_t start = 0, end = PY_SSIZE_T_MAX; if (!PyArg_ParseTuple(args, "O|O&O&:count", &sub_obj, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end)) return NULL; if (PyString_Check(sub_obj)) { sub = PyString_AS_STRING(sub_obj); sub_len = PyString_GET_SIZE(sub_obj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(sub_obj)) { Py_ssize_t count; count = PyUnicode_Count((PyObject *)self, sub_obj, start, end); if (count == -1) return NULL; else return PyInt_FromSsize_t(count); } #endif else if (PyObject_AsCharBuffer(sub_obj, &sub, &sub_len)) return NULL; string_adjust_indices(&start, &end, PyString_GET_SIZE(self)); return PyInt_FromSsize_t( stringlib_count(str + start, end - start, sub, sub_len) ); } PyDoc_STRVAR(swapcase__doc__, "S.swapcase() -> string\n\ \n\ Return a copy of the string S with uppercase characters\n\ converted to lowercase and vice versa."); static PyObject * string_swapcase(PyStringObject *self) { char *s = PyString_AS_STRING(self), *s_new; Py_ssize_t i, n = PyString_GET_SIZE(self); PyObject *newobj; newobj = PyString_FromStringAndSize(NULL, n); if (newobj == NULL) return NULL; s_new = PyString_AsString(newobj); for (i = 0; i < n; i++) { int c = Py_CHARMASK(*s++); if (islower(c)) { *s_new = toupper(c); } else if (isupper(c)) { *s_new = tolower(c); } else *s_new = c; s_new++; } return newobj; } PyDoc_STRVAR(translate__doc__, "S.translate(table [,deletechars]) -> string\n\ \n\ Return a copy of the string S, where all characters occurring\n\ in the optional argument deletechars are removed, and the\n\ remaining characters have been mapped through the given\n\ translation table, which must be a string of length 256."); static PyObject * string_translate(PyStringObject *self, PyObject *args) { register char *input, *output; register const char *table; register Py_ssize_t i, c, changed = 0; PyObject *input_obj = (PyObject*)self; const char *table1, *output_start, *del_table=NULL; Py_ssize_t inlen, tablen, dellen = 0; PyObject *result; int trans_table[256]; PyObject *tableobj, *delobj = NULL; if (!PyArg_UnpackTuple(args, "translate", 1, 2, &tableobj, &delobj)) return NULL; if (PyString_Check(tableobj)) { table1 = PyString_AS_STRING(tableobj); tablen = PyString_GET_SIZE(tableobj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(tableobj)) { /* Unicode .translate() does not support the deletechars parameter; instead a mapping to None will cause characters to be deleted. */ if (delobj != NULL) { PyErr_SetString(PyExc_TypeError, "deletions are implemented differently for unicode"); return NULL; } return PyUnicode_Translate((PyObject *)self, tableobj, NULL); } #endif else if (PyObject_AsCharBuffer(tableobj, &table1, &tablen)) return NULL; if (tablen != 256) { PyErr_SetString(PyExc_ValueError, "translation table must be 256 characters long"); return NULL; } if (delobj != NULL) { if (PyString_Check(delobj)) { del_table = PyString_AS_STRING(delobj); dellen = PyString_GET_SIZE(delobj); } #ifdef Py_USING_UNICODE else if (PyUnicode_Check(delobj)) { PyErr_SetString(PyExc_TypeError, "deletions are implemented differently for unicode"); return NULL; } #endif else if (PyObject_AsCharBuffer(delobj, &del_table, &dellen)) return NULL; } else { del_table = NULL; dellen = 0; } table = table1; inlen = PyString_GET_SIZE(input_obj); result = PyString_FromStringAndSize((char *)NULL, inlen); if (result == NULL) return NULL; output_start = output = PyString_AsString(result); input = PyString_AS_STRING(input_obj); if (dellen == 0) { /* If no deletions are required, use faster code */ for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (Py_CHARMASK((*output++ = table[c])) != c) changed = 1; } if (changed || !PyString_CheckExact(input_obj)) return result; Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } for (i = 0; i < 256; i++) trans_table[i] = Py_CHARMASK(table[i]); for (i = 0; i < dellen; i++) trans_table[(int) Py_CHARMASK(del_table[i])] = -1; for (i = inlen; --i >= 0; ) { c = Py_CHARMASK(*input++); if (trans_table[c] != -1) if (Py_CHARMASK(*output++ = (char)trans_table[c]) == c) continue; changed = 1; } if (!changed && PyString_CheckExact(input_obj)) { Py_DECREF(result); Py_INCREF(input_obj); return input_obj; } /* Fix the size of the resulting string */ if (inlen > 0) _PyString_Resize(&result, output - output_start); return result; } #define FORWARD 1 #define REVERSE -1 /* find and count characters and substrings */ #define findchar(target, target_len, c) \ ((char *)memchr((const void *)(target), c, target_len)) /* String ops must return a string. */ /* If the object is subclass of string, create a copy */ Py_LOCAL(PyStringObject *) return_self(PyStringObject *self) { if (PyString_CheckExact(self)) { Py_INCREF(self); return self; } return (PyStringObject *)PyString_FromStringAndSize( PyString_AS_STRING(self), PyString_GET_SIZE(self)); } Py_LOCAL_INLINE(Py_ssize_t) countchar(const char *target, int target_len, char c, Py_ssize_t maxcount) { Py_ssize_t count=0; const char *start=target; const char *end=target+target_len; while ( (start=findchar(start, end-start, c)) != NULL ) { count++; if (count >= maxcount) break; start += 1; } return count; } Py_LOCAL(Py_ssize_t) findstring(const char *target, Py_ssize_t target_len, const char *pattern, Py_ssize_t pattern_len, Py_ssize_t start, Py_ssize_t end, int direction) { if (start < 0) { start += target_len; if (start < 0) start = 0;