Skip to content

Commit 322821a

Browse files
committed
Implement rfind() method
1 parent 1e01714 commit 322821a

File tree

3 files changed

+60
-0
lines changed

3 files changed

+60
-0
lines changed

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ Notes:
4141
* `start` and `end`, if provided, are _byte_ indexes.
4242

4343

44+
### rfind(substring [,start [,end]])
45+
46+
See: https://docs.python.org/3/library/stdtypes.html#str.rfind
47+
48+
Notes:
49+
50+
* `substring` may be a `cstring` or Python `str` object.
51+
* `start` and `end`, if provided, are _byte_ indexes.
52+
53+
4454
## TODO
4555

4656
* Write docs (see `str` type docs)

src/cstring.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,35 @@ PyObject *cstring_index(PyObject *self, PyObject *args) {
292292
return NULL;
293293
}
294294

295+
static const char *_substr_params_rstr(struct _substr_params *params) {
296+
const char *p = params->end - params->substr_len + 1;
297+
298+
for(;;) {
299+
p = memrchr(params->start, *params->substr, p - params->start);
300+
if(!p)
301+
goto done;
302+
if(memcmp(p, params->substr, params->substr_len) == 0)
303+
return p;
304+
}
305+
306+
done:
307+
return NULL;
308+
}
309+
310+
PyDoc_STRVAR(rfind__doc__, "");
311+
PyObject *cstring_rfind(PyObject *self, PyObject *args) {
312+
struct _substr_params params;
313+
314+
if(!_parse_substr_args(self, args, &params))
315+
return NULL;
316+
317+
const char *p = _substr_params_rstr(&params);
318+
if(!p)
319+
return PyLong_FromLong(-1);
320+
321+
return PyLong_FromSsize_t(p - CSTRING_VALUE(self));
322+
}
323+
295324
static PySequenceMethods cstring_as_sequence = {
296325
.sq_length = cstring_len,
297326
.sq_concat = cstring_concat,
@@ -309,6 +338,7 @@ static PyMethodDef cstring_methods[] = {
309338
{"count", cstring_count, METH_VARARGS, count__doc__},
310339
{"find", cstring_find, METH_VARARGS, find__doc__},
311340
{"index", cstring_index, METH_VARARGS, index__doc__},
341+
{"rfind", cstring_rfind, METH_VARARGS, rfind__doc__},
312342
{0},
313343
};
314344

test/test_methods.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,23 @@ def test_index_missing():
5252
with pytest.raises(ValueError):
5353
return target.index('lo', 0, 4)
5454

55+
56+
def test_rfind():
57+
target = cstring('hello')
58+
assert target.rfind('o') == 4
59+
60+
61+
def test_rfind_empty():
62+
target = cstring('hello')
63+
assert target.rfind('') == 5
64+
65+
66+
def test_rfind_with_start():
67+
target = cstring('hello')
68+
assert target.rfind('lo', 3) == 3
69+
70+
71+
def test_rfind_missing():
72+
target = cstring('hello')
73+
assert target.rfind('lo', 0, 4) == -1
74+

0 commit comments

Comments
 (0)