Issue #7462: Implement the stringlib fast search algorithm for the `rfind`,
[python.git] / Objects / stringlib / find.h
blobb5bace7a966c39f4a8b3f4e87668cd444fd1535f
1 /* stringlib: find/index implementation */
3 #ifndef STRINGLIB_FIND_H
4 #define STRINGLIB_FIND_H
6 #ifndef STRINGLIB_FASTSEARCH_H
7 #error must include "stringlib/fastsearch.h" before including this module
8 #endif
10 Py_LOCAL_INLINE(Py_ssize_t)
11 stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
12 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
13 Py_ssize_t offset)
15 Py_ssize_t pos;
17 if (str_len < 0)
18 return -1;
19 if (sub_len == 0)
20 return offset;
22 pos = fastsearch(str, str_len, sub, sub_len, FAST_SEARCH);
24 if (pos >= 0)
25 pos += offset;
27 return pos;
30 Py_LOCAL_INLINE(Py_ssize_t)
31 stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
32 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
33 Py_ssize_t offset)
35 Py_ssize_t pos;
37 if (str_len < 0)
38 return -1;
39 if (sub_len == 0)
40 return str_len + offset;
42 pos = fastsearch(str, str_len, sub, sub_len, FAST_RSEARCH);
44 if (pos >= 0)
45 pos += offset;
47 return pos;
50 Py_LOCAL_INLINE(Py_ssize_t)
51 stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
52 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
53 Py_ssize_t start, Py_ssize_t end)
55 if (start < 0)
56 start += str_len;
57 if (start < 0)
58 start = 0;
59 if (end > str_len)
60 end = str_len;
61 if (end < 0)
62 end += str_len;
63 if (end < 0)
64 end = 0;
66 return stringlib_find(str + start, end - start, sub, sub_len, start);
69 Py_LOCAL_INLINE(Py_ssize_t)
70 stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
71 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
72 Py_ssize_t start, Py_ssize_t end)
74 if (start < 0)
75 start += str_len;
76 if (start < 0)
77 start = 0;
78 if (end > str_len)
79 end = str_len;
80 if (end < 0)
81 end += str_len;
82 if (end < 0)
83 end = 0;
85 return stringlib_rfind(str + start, end - start, sub, sub_len, start);
88 #if defined(STRINGLIB_STR) && !defined(FROM_BYTEARRAY)
90 Py_LOCAL_INLINE(int)
91 stringlib_contains_obj(PyObject* str, PyObject* sub)
93 return stringlib_find(
94 STRINGLIB_STR(str), STRINGLIB_LEN(str),
95 STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
96 ) != -1;
99 #endif /* STRINGLIB_STR */
101 #ifdef FROM_UNICODE
104 This function is a helper for the "find" family (find, rfind, index,
105 rindex) of unicodeobject.c file, because they all have the same
106 behaviour for the arguments.
108 It does not touch the variables received until it knows everything
109 is ok.
111 Note that we receive a pointer to the pointer of the substring object,
112 so when we create that object in this function we don't DECREF it,
113 because it continues living in the caller functions (those functions,
114 after finishing using the substring, must DECREF it).
117 Py_LOCAL_INLINE(int)
118 _ParseTupleFinds (PyObject *args, PyObject **substring,
119 Py_ssize_t *start, Py_ssize_t *end) {
120 PyObject *tmp_substring;
121 Py_ssize_t tmp_start = 0;
122 Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
123 PyObject *obj_start=Py_None, *obj_end=Py_None;
125 if (!PyArg_ParseTuple(args, "O|OO:find", &tmp_substring,
126 &obj_start, &obj_end))
127 return 0;
129 /* To support None in "start" and "end" arguments, meaning
130 the same as if they were not passed.
132 if (obj_start != Py_None)
133 if (!_PyEval_SliceIndex(obj_start, &tmp_start))
134 return 0;
135 if (obj_end != Py_None)
136 if (!_PyEval_SliceIndex(obj_end, &tmp_end))
137 return 0;
139 tmp_substring = PyUnicode_FromObject(tmp_substring);
140 if (!tmp_substring)
141 return 0;
143 *start = tmp_start;
144 *end = tmp_end;
145 *substring = tmp_substring;
146 return 1;
149 #endif /* FROM_UNICODE */
151 #endif /* STRINGLIB_FIND_H */
154 Local variables:
155 c-basic-offset: 4
156 indent-tabs-mode: nil
157 End: