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 (!stringlib_parse_args_finds("count", args, &sub_obj, &start, &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; ADJUST_INDICES(start, end, PyString_GET_SIZE(self)); return PyInt_FromSsize_t( stringlib_count(str + start, end - start, sub, sub_len, PY_SSIZE_T_MAX) ); }
replace_delete_substring(PyStringObject *self, const char *from_s, Py_ssize_t from_len, Py_ssize_t maxcount) { char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; Py_ssize_t count, offset; PyStringObject *result; self_len = PyString_GET_SIZE(self); self_s = PyString_AS_STRING(self); count = stringlib_count(self_s, self_len, from_s, from_len, maxcount); if (count == 0) { /* no matches */ return return_self(self); } result_len = self_len - (count * from_len); assert (result_len>=0); if ( (result = (PyStringObject *) PyString_FromStringAndSize(NULL, result_len)) == NULL ) return NULL; result_s = PyString_AS_STRING(result); start = self_s; end = self_s + self_len; while (count-- > 0) { offset = stringlib_find(start, end-start, from_s, from_len, 0); if (offset == -1) break; next = start + offset; Py_MEMCPY(result_s, start, next-start); result_s += (next-start); start = next+from_len; } Py_MEMCPY(result_s, start, end-start); return result; }
replace_substring(PyStringObject *self, const char *from_s, Py_ssize_t from_len, const char *to_s, Py_ssize_t to_len, Py_ssize_t maxcount) { char *self_s, *result_s; char *start, *next, *end; Py_ssize_t self_len, result_len; Py_ssize_t count, offset, product; PyStringObject *result; self_s = PyString_AS_STRING(self); self_len = PyString_GET_SIZE(self); count = stringlib_count(self_s, self_len, from_s, from_len, maxcount); if (count == 0) { /* no matches, return unchanged */ return return_self(self); } /* Check for overflow */ /* result_len = self_len + count * (to_len-from_len) */ product = count * (to_len-from_len); if (product / (to_len-from_len) != count) { PyErr_SetString(PyExc_OverflowError, "replace string is too long"); return NULL; } result_len = self_len + product; if (result_len < 0) { PyErr_SetString(PyExc_OverflowError, "replace string is too long"); return NULL; } if ( (result = (PyStringObject *) PyString_FromStringAndSize(NULL, result_len)) == NULL) return NULL; result_s = PyString_AS_STRING(result); start = self_s; end = self_s + self_len; while (count-- > 0) { offset = stringlib_find(start, end-start, from_s, from_len, 0); if (offset == -1) break; next = start+offset; if (next == start) { /* replace with the 'to' */ Py_MEMCPY(result_s, to_s, to_len); result_s += to_len; start += from_len; } else { /* copy the unchanged old then the 'to' */ Py_MEMCPY(result_s, start, next-start); result_s += (next-start); Py_MEMCPY(result_s, to_s, to_len); result_s += to_len; start = next+from_len; } } /* Copy the remainder of the remaining string */ Py_MEMCPY(result_s, start, end-start); return result; }