@@ -179,6 +179,58 @@ static PyObject *cstring_subscript(PyObject *self, PyObject *key) {
179179 return NULL ;
180180}
181181
182+ static const char * _obj_to_utf8 (PyObject * o , Py_ssize_t * len_p ) {
183+ if (PyUnicode_Check (o ))
184+ return PyUnicode_AsUTF8AndSize (o , len_p );
185+ if (Py_TYPE (o ) == & cstring_type ) {
186+ * len_p = cstring_len (o );
187+ return CSTRING_VALUE (o );
188+ }
189+ PyErr_Format (
190+ PyExc_TypeError , "Object cannot be type %s." , Py_TYPE (o )-> tp_name );
191+ return NULL ;
192+ }
193+
194+ static Py_ssize_t _fix_index (Py_ssize_t i , Py_ssize_t len ) {
195+ Py_ssize_t result = i ;
196+ if (result < 0 )
197+ result += len ;
198+ if (result < 0 )
199+ result = 0 ;
200+ if (result > len )
201+ result = len ;
202+ return result ;
203+ }
204+
205+ PyDoc_STRVAR (count__doc__ , "" );
206+ static PyObject * cstring_count (PyObject * self , PyObject * args ) {
207+ PyObject * substr_obj ;
208+ Py_ssize_t start = 0 ;
209+ Py_ssize_t end = PY_SSIZE_T_MAX ;
210+
211+ if (!PyArg_ParseTuple (args , "O|nn" , & substr_obj , & start , & end ))
212+ return NULL ;
213+
214+ Py_ssize_t substr_len ;
215+ const char * substr = _obj_to_utf8 (substr_obj , & substr_len );
216+ if (!substr )
217+ return NULL ;
218+
219+ start = _fix_index (start , cstring_len (self ));
220+ end = _fix_index (end , cstring_len (self ));
221+
222+ char * p = & CSTRING_VALUE (self )[start ];
223+ long result = 0 ;
224+ while ((p = strstr (p , substr )) != NULL ) {
225+ ++ result ;
226+ p += substr_len ;
227+ if (p >= & CSTRING_VALUE (self )[end ])
228+ break ;
229+ }
230+
231+ return PyLong_FromLong (result );
232+ }
233+
182234static PySequenceMethods cstring_as_sequence = {
183235 .sq_length = cstring_len ,
184236 .sq_concat = cstring_concat ,
@@ -193,6 +245,7 @@ static PyMappingMethods cstring_as_mapping = {
193245};
194246
195247static PyMethodDef cstring_methods [] = {
248+ {"count" , cstring_count , METH_VARARGS , count__doc__ },
196249 {0 },
197250};
198251
0 commit comments