blob: 509b9297396be86552ae9d8d2f6fb371290fe4e5 [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