blob: 14815f6e62bd7f6033bcd91a9b6f3d9d6a868b6d [file] [log] [blame]
Thomas Wouters477c8d52006-05-27 19:21:47 +00001/* stringlib: find/index implementation */
2
Thomas Wouters477c8d52006-05-27 19:21:47 +00003#ifndef STRINGLIB_FASTSEARCH_H
4#error must include "stringlib/fastsearch.h" before including this module
5#endif
6
7Py_LOCAL_INLINE(Py_ssize_t)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +02008STRINGLIB(find)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Thomas Wouters477c8d52006-05-27 19:21:47 +00009 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
10 Py_ssize_t offset)
11{
12 Py_ssize_t pos;
13
Serhiy Storchakad9d769f2015-03-24 21:55:47 +020014 assert(str_len >= 0);
Amaury Forgeot d'Arcf2e93682008-09-26 22:48:41 +000015 if (sub_len == 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +000016 return offset;
17
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020018 pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_SEARCH);
Thomas Wouters477c8d52006-05-27 19:21:47 +000019
20 if (pos >= 0)
21 pos += offset;
22
23 return pos;
24}
25
26Py_LOCAL_INLINE(Py_ssize_t)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020027STRINGLIB(rfind)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Thomas Wouters477c8d52006-05-27 19:21:47 +000028 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
29 Py_ssize_t offset)
30{
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000031 Py_ssize_t pos;
32
Serhiy Storchakad9d769f2015-03-24 21:55:47 +020033 assert(str_len >= 0);
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000034 if (sub_len == 0)
35 return str_len + offset;
36
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020037 pos = FASTSEARCH(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000038
39 if (pos >= 0)
40 pos += offset;
41
42 return pos;
Thomas Wouters477c8d52006-05-27 19:21:47 +000043}
44
45Py_LOCAL_INLINE(Py_ssize_t)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020046STRINGLIB(find_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Thomas Wouters477c8d52006-05-27 19:21:47 +000047 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
48 Py_ssize_t start, Py_ssize_t end)
49{
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020050 return STRINGLIB(find)(str + start, end - start, sub, sub_len, start);
Thomas Wouters477c8d52006-05-27 19:21:47 +000051}
52
53Py_LOCAL_INLINE(Py_ssize_t)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020054STRINGLIB(rfind_slice)(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Thomas Wouters477c8d52006-05-27 19:21:47 +000055 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
56 Py_ssize_t start, Py_ssize_t end)
57{
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020058 return STRINGLIB(rfind)(str + start, end - start, sub, sub_len, start);
Thomas Wouters477c8d52006-05-27 19:21:47 +000059}
60
Christian Heimes4f3c5612008-08-28 14:55:10 +000061#ifdef STRINGLIB_WANT_CONTAINS_OBJ
Thomas Wouters477c8d52006-05-27 19:21:47 +000062
63Py_LOCAL_INLINE(int)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020064STRINGLIB(contains_obj)(PyObject* str, PyObject* sub)
Thomas Wouters477c8d52006-05-27 19:21:47 +000065{
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020066 return STRINGLIB(find)(
Thomas Wouters477c8d52006-05-27 19:21:47 +000067 STRINGLIB_STR(str), STRINGLIB_LEN(str),
68 STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
69 ) != -1;
70}
71
Antoine Pitrouf2c54842010-01-13 08:07:53 +000072#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
Thomas Wouters477c8d52006-05-27 19:21:47 +000073
Christian Heimes9cd17752007-11-18 19:35:23 +000074/*
75This function is a helper for the "find" family (find, rfind, index,
Jesus Ceaac451502011-04-20 17:09:23 +020076rindex) and for count, startswith and endswith, because they all have
77the same behaviour for the arguments.
Christian Heimes9cd17752007-11-18 19:35:23 +000078
Victor Stinner9db1a8b2011-10-23 20:04:37 +020079It does not touch the variables received until it knows everything
Christian Heimes9cd17752007-11-18 19:35:23 +000080is ok.
Christian Heimes9cd17752007-11-18 19:35:23 +000081*/
82
Jesus Ceaac451502011-04-20 17:09:23 +020083#define FORMAT_BUFFER_SIZE 50
84
Christian Heimes9cd17752007-11-18 19:35:23 +000085Py_LOCAL_INLINE(int)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +020086STRINGLIB(parse_args_finds)(const char * function_name, PyObject *args,
Jesus Ceaac451502011-04-20 17:09:23 +020087 PyObject **subobj,
88 Py_ssize_t *start, Py_ssize_t *end)
89{
90 PyObject *tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +000091 Py_ssize_t tmp_start = 0;
92 Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
93 PyObject *obj_start=Py_None, *obj_end=Py_None;
Jesus Ceaac451502011-04-20 17:09:23 +020094 char format[FORMAT_BUFFER_SIZE] = "O|OO:";
95 size_t len = strlen(format);
Christian Heimes9cd17752007-11-18 19:35:23 +000096
Jesus Ceaac451502011-04-20 17:09:23 +020097 strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
98 format[FORMAT_BUFFER_SIZE - 1] = '\0';
99
100 if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
Christian Heimes9cd17752007-11-18 19:35:23 +0000101 return 0;
102
103 /* To support None in "start" and "end" arguments, meaning
104 the same as if they were not passed.
105 */
106 if (obj_start != Py_None)
107 if (!_PyEval_SliceIndex(obj_start, &tmp_start))
108 return 0;
109 if (obj_end != Py_None)
110 if (!_PyEval_SliceIndex(obj_end, &tmp_end))
111 return 0;
112
Christian Heimes9cd17752007-11-18 19:35:23 +0000113 *start = tmp_start;
114 *end = tmp_end;
Jesus Ceaac451502011-04-20 17:09:23 +0200115 *subobj = tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +0000116 return 1;
117}
118
Jesus Ceaac451502011-04-20 17:09:23 +0200119#undef FORMAT_BUFFER_SIZE
120
Jesus Cea6159ee32011-04-20 17:42:50 +0200121#if STRINGLIB_IS_UNICODE
Jesus Ceaac451502011-04-20 17:09:23 +0200122
123/*
124Wraps stringlib_parse_args_finds() and additionally ensures that the
125first argument is a unicode object.
126
127Note that we receive a pointer to the pointer of the substring object,
128so when we create that object in this function we don't DECREF it,
Victor Stinner9db1a8b2011-10-23 20:04:37 +0200129because it continues living in the caller functions (those functions,
Jesus Ceaac451502011-04-20 17:09:23 +0200130after finishing using the substring, must DECREF it).
131*/
132
133Py_LOCAL_INLINE(int)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200134STRINGLIB(parse_args_finds_unicode)(const char * function_name, PyObject *args,
Victor Stinner9db1a8b2011-10-23 20:04:37 +0200135 PyObject **substring,
Jesus Ceaac451502011-04-20 17:09:23 +0200136 Py_ssize_t *start, Py_ssize_t *end)
137{
138 PyObject *tmp_substring;
139
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200140 if(STRINGLIB(parse_args_finds)(function_name, args, &tmp_substring,
Jesus Ceaac451502011-04-20 17:09:23 +0200141 start, end)) {
142 tmp_substring = PyUnicode_FromObject(tmp_substring);
143 if (!tmp_substring)
144 return 0;
Victor Stinner9db1a8b2011-10-23 20:04:37 +0200145 *substring = tmp_substring;
Jesus Ceaac451502011-04-20 17:09:23 +0200146 return 1;
147 }
148 return 0;
149}
150
Antoine Pitrouac65d962011-10-20 23:54:17 +0200151#else /* !STRINGLIB_IS_UNICODE */
152
153/*
154Wraps stringlib_parse_args_finds() and additionally checks whether the
155first argument is an integer in range(0, 256).
156
157If this is the case, writes the integer value to the byte parameter
158and sets subobj to NULL. Otherwise, sets the first argument to subobj
159and doesn't touch byte. The other parameters are similar to those of
160stringlib_parse_args_finds().
161*/
162
163Py_LOCAL_INLINE(int)
164STRINGLIB(parse_args_finds_byte)(const char *function_name, PyObject *args,
165 PyObject **subobj, char *byte,
166 Py_ssize_t *start, Py_ssize_t *end)
167{
168 PyObject *tmp_subobj;
169 Py_ssize_t ival;
Victor Stinnerf8eac002011-12-18 01:17:41 +0100170 PyObject *err;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200171
172 if(!STRINGLIB(parse_args_finds)(function_name, args, &tmp_subobj,
173 start, end))
174 return 0;
175
Victor Stinnerf8eac002011-12-18 01:17:41 +0100176 if (!PyNumber_Check(tmp_subobj)) {
Antoine Pitrouac65d962011-10-20 23:54:17 +0200177 *subobj = tmp_subobj;
Victor Stinnerf8eac002011-12-18 01:17:41 +0100178 return 1;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200179 }
Victor Stinnerf8eac002011-12-18 01:17:41 +0100180
181 ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
182 if (ival == -1) {
183 err = PyErr_Occurred();
184 if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
185 PyErr_Clear();
186 *subobj = tmp_subobj;
187 return 1;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200188 }
Antoine Pitrouac65d962011-10-20 23:54:17 +0200189 }
190
Victor Stinnerf8eac002011-12-18 01:17:41 +0100191 if (ival < 0 || ival > 255) {
192 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
193 return 0;
194 }
195
196 *subobj = NULL;
197 *byte = (char)ival;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200198 return 1;
199}
200
Antoine Pitrouf2c54842010-01-13 08:07:53 +0000201#endif /* STRINGLIB_IS_UNICODE */