blob: a7065fcbc06f6c74e8b7b8e6af59f7fa9358255a [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.
Jesus Ceaac451502011-04-20 17:09:23 +0200126*/
127
128Py_LOCAL_INLINE(int)
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200129STRINGLIB(parse_args_finds_unicode)(const char * function_name, PyObject *args,
Victor Stinner9db1a8b2011-10-23 20:04:37 +0200130 PyObject **substring,
Jesus Ceaac451502011-04-20 17:09:23 +0200131 Py_ssize_t *start, Py_ssize_t *end)
132{
Serhiy Storchaka21a663e2016-04-13 15:37:23 +0300133 if(STRINGLIB(parse_args_finds)(function_name, args, substring,
Jesus Ceaac451502011-04-20 17:09:23 +0200134 start, end)) {
Serhiy Storchaka21a663e2016-04-13 15:37:23 +0300135 if (ensure_unicode(*substring) < 0)
Jesus Ceaac451502011-04-20 17:09:23 +0200136 return 0;
Jesus Ceaac451502011-04-20 17:09:23 +0200137 return 1;
138 }
139 return 0;
140}
141
Antoine Pitrouac65d962011-10-20 23:54:17 +0200142#else /* !STRINGLIB_IS_UNICODE */
143
144/*
145Wraps stringlib_parse_args_finds() and additionally checks whether the
146first argument is an integer in range(0, 256).
147
148If this is the case, writes the integer value to the byte parameter
149and sets subobj to NULL. Otherwise, sets the first argument to subobj
150and doesn't touch byte. The other parameters are similar to those of
151stringlib_parse_args_finds().
152*/
153
154Py_LOCAL_INLINE(int)
155STRINGLIB(parse_args_finds_byte)(const char *function_name, PyObject *args,
156 PyObject **subobj, char *byte,
157 Py_ssize_t *start, Py_ssize_t *end)
158{
159 PyObject *tmp_subobj;
160 Py_ssize_t ival;
Victor Stinnerf8eac002011-12-18 01:17:41 +0100161 PyObject *err;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200162
163 if(!STRINGLIB(parse_args_finds)(function_name, args, &tmp_subobj,
164 start, end))
165 return 0;
166
Victor Stinnerf8eac002011-12-18 01:17:41 +0100167 if (!PyNumber_Check(tmp_subobj)) {
Antoine Pitrouac65d962011-10-20 23:54:17 +0200168 *subobj = tmp_subobj;
Victor Stinnerf8eac002011-12-18 01:17:41 +0100169 return 1;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200170 }
Victor Stinnerf8eac002011-12-18 01:17:41 +0100171
172 ival = PyNumber_AsSsize_t(tmp_subobj, PyExc_OverflowError);
173 if (ival == -1) {
174 err = PyErr_Occurred();
175 if (err && !PyErr_GivenExceptionMatches(err, PyExc_OverflowError)) {
176 PyErr_Clear();
177 *subobj = tmp_subobj;
178 return 1;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200179 }
Antoine Pitrouac65d962011-10-20 23:54:17 +0200180 }
181
Victor Stinnerf8eac002011-12-18 01:17:41 +0100182 if (ival < 0 || ival > 255) {
183 PyErr_SetString(PyExc_ValueError, "byte must be in range(0, 256)");
184 return 0;
185 }
186
187 *subobj = NULL;
188 *byte = (char)ival;
Antoine Pitrouac65d962011-10-20 23:54:17 +0200189 return 1;
190}
191
Antoine Pitrouf2c54842010-01-13 08:07:53 +0000192#endif /* STRINGLIB_IS_UNICODE */