summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Lib/test/string_tests.py28
-rw-r--r--Objects/stringlib/find.h47
-rw-r--r--Objects/stringobject.c15
-rw-r--r--Objects/unicodeobject.c44
4 files changed, 102 insertions, 32 deletions
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index d0f8c03..cefdcac 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -159,6 +159,13 @@ class CommonTest(unittest.TestCase):
self.checkequal(3, 'abc', 'find', '', 3)
self.checkequal(-1, 'abc', 'find', '', 4)
+ # to check the ability to pass None as defaults
+ self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a')
+ self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4)
+ self.checkequal(-1, 'rrarrrrrrrrra', 'find', 'a', 4, 6)
+ self.checkequal(12, 'rrarrrrrrrrra', 'find', 'a', 4, None)
+ self.checkequal( 2, 'rrarrrrrrrrra', 'find', 'a', None, 6)
+
self.checkraises(TypeError, 'hello', 'find')
self.checkraises(TypeError, 'hello', 'find', 42)
@@ -197,6 +204,13 @@ class CommonTest(unittest.TestCase):
self.checkequal(3, 'abc', 'rfind', '', 3)
self.checkequal(-1, 'abc', 'rfind', '', 4)
+ # to check the ability to pass None as defaults
+ self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a')
+ self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4)
+ self.checkequal(-1, 'rrarrrrrrrrra', 'rfind', 'a', 4, 6)
+ self.checkequal(12, 'rrarrrrrrrrra', 'rfind', 'a', 4, None)
+ self.checkequal( 2, 'rrarrrrrrrrra', 'rfind', 'a', None, 6)
+
self.checkraises(TypeError, 'hello', 'rfind')
self.checkraises(TypeError, 'hello', 'rfind', 42)
@@ -211,6 +225,13 @@ class CommonTest(unittest.TestCase):
self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', 8)
self.checkraises(ValueError, 'abcdefghi', 'index', 'ghi', -1)
+ # to check the ability to pass None as defaults
+ self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a')
+ self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4)
+ self.checkraises(ValueError, 'rrarrrrrrrrra', 'index', 'a', 4, 6)
+ self.checkequal(12, 'rrarrrrrrrrra', 'index', 'a', 4, None)
+ self.checkequal( 2, 'rrarrrrrrrrra', 'index', 'a', None, 6)
+
self.checkraises(TypeError, 'hello', 'index')
self.checkraises(TypeError, 'hello', 'index', 42)
@@ -226,6 +247,13 @@ class CommonTest(unittest.TestCase):
self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, 8)
self.checkraises(ValueError, 'abcdefghi', 'rindex', 'ghi', 0, -1)
+ # to check the ability to pass None as defaults
+ self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a')
+ self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4)
+ self.checkraises(ValueError, 'rrarrrrrrrrra', 'rindex', 'a', 4, 6)
+ self.checkequal(12, 'rrarrrrrrrrra', 'rindex', 'a', 4, None)
+ self.checkequal( 2, 'rrarrrrrrrrra', 'rindex', 'a', None, 6)
+
self.checkraises(TypeError, 'hello', 'rindex')
self.checkraises(TypeError, 'hello', 'rindex', 42)
diff --git a/Objects/stringlib/find.h b/Objects/stringlib/find.h
index 4cdbb09..38f13ab 100644
--- a/Objects/stringlib/find.h
+++ b/Objects/stringlib/find.h
@@ -103,6 +103,53 @@ stringlib_contains_obj(PyObject* str, PyObject* sub)
#endif /* STRINGLIB_STR */
+/*
+This function is a helper for the "find" family (find, rfind, index,
+rindex) of unicodeobject.c file, because they all have the same
+behaviour for the arguments.
+
+It does not touch the variables received until it knows everything
+is ok.
+
+Note that we receive a pointer to the pointer of the substring object,
+so when we create that object in this function we don't DECREF it,
+because it continues living in the caller functions (those functions,
+after finishing using the substring, must DECREF it).
+*/
+
+int
+_ParseTupleFinds (PyObject *args, PyObject **substring,
+ Py_ssize_t *start, Py_ssize_t *end) {
+ PyObject *tmp_substring;
+ Py_ssize_t tmp_start = 0;
+ Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
+ PyObject *obj_start=Py_None, *obj_end=Py_None;
+
+ if (!PyArg_ParseTuple(args, "O|OO:find", &tmp_substring,
+ &obj_start, &obj_end))
+ return 0;
+
+ /* To support None in "start" and "end" arguments, meaning
+ the same as if they were not passed.
+ */
+ if (obj_start != Py_None)
+ if (!_PyEval_SliceIndex(obj_start, &tmp_start))
+ return 0;
+ if (obj_end != Py_None)
+ if (!_PyEval_SliceIndex(obj_end, &tmp_end))
+ return 0;
+
+ tmp_substring = PyUnicode_FromObject(tmp_substring);
+ if (!tmp_substring)
+ return 0;
+
+ *start = tmp_start;
+ *end = tmp_end;
+ *substring = tmp_substring;
+ return 1;
+}
+
+
#endif /* STRINGLIB_FIND_H */
/*
diff --git a/Objects/stringobject.c b/Objects/stringobject.c
index ce24154..a0e2837 100644
--- a/Objects/stringobject.c
+++ b/Objects/stringobject.c
@@ -1880,10 +1880,21 @@ string_find_internal(PyStringObject *self, PyObject *args, int dir)
const char *sub;
Py_ssize_t sub_len;
Py_ssize_t start=0, end=PY_SSIZE_T_MAX;
+ PyObject *obj_start=Py_None, *obj_end=Py_None;
- if (!PyArg_ParseTuple(args, "O|O&O&:find/rfind/index/rindex", &subobj,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
+ if (!PyArg_ParseTuple(args, "O|OO:find/rfind/index/rindex", &subobj,
+ &obj_start, &obj_end))
return -2;
+ /* To support None in "start" and "end" arguments, meaning
+ the same as if they were not passed.
+ */
+ if (obj_start != Py_None)
+ if (!_PyEval_SliceIndex(obj_start, &start))
+ return -2;
+ if (obj_end != Py_None)
+ if (!_PyEval_SliceIndex(obj_end, &end))
+ return -2;
+
if (PyString_Check(subobj)) {
sub = PyString_AS_STRING(subobj);
sub_len = PyString_GET_SIZE(subobj);
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 1f6f738..06c8fc3 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -6040,16 +6040,12 @@ static PyObject *
unicode_find(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
+ Py_ssize_t start;
+ Py_ssize_t end;
Py_ssize_t result;
- if (!PyArg_ParseTuple(args, "O|O&O&:find", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
+ if (!_ParseTupleFinds(args, &substring, &start, &end))
return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
result = stringlib_find_slice(
PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
@@ -6110,15 +6106,11 @@ unicode_index(PyUnicodeObject *self, PyObject *args)
{
Py_ssize_t result;
PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
+ Py_ssize_t start;
+ Py_ssize_t end;
- if (!PyArg_ParseTuple(args, "O|O&O&:index", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
+ if (!_ParseTupleFinds(args, &substring, &start, &end))
return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
result = stringlib_find_slice(
PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
@@ -6781,16 +6773,12 @@ static PyObject *
unicode_rfind(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
+ Py_ssize_t start;
+ Py_ssize_t end;
Py_ssize_t result;
- if (!PyArg_ParseTuple(args, "O|O&O&:rfind", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
+ if (!_ParseTupleFinds(args, &substring, &start, &end))
+ return NULL;
result = stringlib_rfind_slice(
PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),
@@ -6812,16 +6800,12 @@ static PyObject *
unicode_rindex(PyUnicodeObject *self, PyObject *args)
{
PyObject *substring;
- Py_ssize_t start = 0;
- Py_ssize_t end = PY_SSIZE_T_MAX;
+ Py_ssize_t start;
+ Py_ssize_t end;
Py_ssize_t result;
- if (!PyArg_ParseTuple(args, "O|O&O&:rindex", &substring,
- _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &end))
- return NULL;
- substring = PyUnicode_FromObject(substring);
- if (!substring)
- return NULL;
+ if (!_ParseTupleFinds(args, &substring, &start, &end))
+ return NULL;
result = stringlib_rfind_slice(
PyUnicode_AS_UNICODE(self), PyUnicode_GET_SIZE(self),