blob: 4407d717d2e89dfea640f0372ea66941f7891c4d [file] [log] [blame]
Thomas Wouters477c8d52006-05-27 19:21:47 +00001/* stringlib: find/index implementation */
2
3#ifndef STRINGLIB_FIND_H
4#define STRINGLIB_FIND_H
5
6#ifndef STRINGLIB_FASTSEARCH_H
7#error must include "stringlib/fastsearch.h" before including this module
8#endif
9
10Py_LOCAL_INLINE(Py_ssize_t)
11stringlib_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)
14{
15 Py_ssize_t pos;
16
Amaury Forgeot d'Arcf2e93682008-09-26 22:48:41 +000017 if (str_len < 0)
18 return -1;
19 if (sub_len == 0)
Thomas Wouters477c8d52006-05-27 19:21:47 +000020 return offset;
21
22 pos = fastsearch(str, str_len, sub, sub_len, FAST_SEARCH);
23
24 if (pos >= 0)
25 pos += offset;
26
27 return pos;
28}
29
30Py_LOCAL_INLINE(Py_ssize_t)
31stringlib_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)
34{
Thomas Wouters477c8d52006-05-27 19:21:47 +000035 /* XXX - create reversefastsearch helper! */
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000036 if (sub_len == 0) {
37 if (str_len < 0)
38 return -1;
39 return str_len + offset;
40 } else {
41 Py_ssize_t j, pos = -1;
Thomas Wouters477c8d52006-05-27 19:21:47 +000042 for (j = str_len - sub_len; j >= 0; --j)
43 if (STRINGLIB_CMP(str+j, sub, sub_len) == 0) {
44 pos = j + offset;
45 break;
46 }
Thomas Wouters4d70c3d2006-06-08 14:42:34 +000047 return pos;
Thomas Wouters477c8d52006-05-27 19:21:47 +000048 }
Thomas Wouters477c8d52006-05-27 19:21:47 +000049}
50
51Py_LOCAL_INLINE(Py_ssize_t)
52stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
53 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
54 Py_ssize_t start, Py_ssize_t end)
55{
56 if (start < 0)
57 start += str_len;
58 if (start < 0)
59 start = 0;
60 if (end > str_len)
61 end = str_len;
62 if (end < 0)
63 end += str_len;
64 if (end < 0)
65 end = 0;
66
67 return stringlib_find(
68 str + start, end - start,
69 sub, sub_len, start
70 );
71}
72
73Py_LOCAL_INLINE(Py_ssize_t)
74stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
75 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
76 Py_ssize_t start, Py_ssize_t end)
77{
78 if (start < 0)
79 start += str_len;
80 if (start < 0)
81 start = 0;
82 if (end > str_len)
83 end = str_len;
84 if (end < 0)
85 end += str_len;
86 if (end < 0)
87 end = 0;
88
89 return stringlib_rfind(str + start, end - start, sub, sub_len, start);
90}
91
Christian Heimes4f3c5612008-08-28 14:55:10 +000092#ifdef STRINGLIB_WANT_CONTAINS_OBJ
Thomas Wouters477c8d52006-05-27 19:21:47 +000093
94Py_LOCAL_INLINE(int)
95stringlib_contains_obj(PyObject* str, PyObject* sub)
96{
97 return stringlib_find(
98 STRINGLIB_STR(str), STRINGLIB_LEN(str),
99 STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
100 ) != -1;
101}
102
103#endif /* STRINGLIB_STR */
104
Christian Heimes9cd17752007-11-18 19:35:23 +0000105/*
106This function is a helper for the "find" family (find, rfind, index,
Jesus Ceaac451502011-04-20 17:09:23 +0200107rindex) and for count, startswith and endswith, because they all have
108the same behaviour for the arguments.
Christian Heimes9cd17752007-11-18 19:35:23 +0000109
110It does not touch the variables received until it knows everything
111is ok.
Christian Heimes9cd17752007-11-18 19:35:23 +0000112*/
113
Jesus Ceaac451502011-04-20 17:09:23 +0200114#define FORMAT_BUFFER_SIZE 50
115
Christian Heimes9cd17752007-11-18 19:35:23 +0000116Py_LOCAL_INLINE(int)
Jesus Ceaac451502011-04-20 17:09:23 +0200117stringlib_parse_args_finds(const char * function_name, PyObject *args,
118 PyObject **subobj,
119 Py_ssize_t *start, Py_ssize_t *end)
120{
121 PyObject *tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +0000122 Py_ssize_t tmp_start = 0;
123 Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
124 PyObject *obj_start=Py_None, *obj_end=Py_None;
Jesus Ceaac451502011-04-20 17:09:23 +0200125 char format[FORMAT_BUFFER_SIZE] = "O|OO:";
126 size_t len = strlen(format);
Christian Heimes9cd17752007-11-18 19:35:23 +0000127
Jesus Ceaac451502011-04-20 17:09:23 +0200128 strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
129 format[FORMAT_BUFFER_SIZE - 1] = '\0';
130
131 if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
Christian Heimes9cd17752007-11-18 19:35:23 +0000132 return 0;
133
134 /* To support None in "start" and "end" arguments, meaning
135 the same as if they were not passed.
136 */
137 if (obj_start != Py_None)
138 if (!_PyEval_SliceIndex(obj_start, &tmp_start))
139 return 0;
140 if (obj_end != Py_None)
141 if (!_PyEval_SliceIndex(obj_end, &tmp_end))
142 return 0;
143
Christian Heimes9cd17752007-11-18 19:35:23 +0000144 *start = tmp_start;
145 *end = tmp_end;
Jesus Ceaac451502011-04-20 17:09:23 +0200146 *subobj = tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +0000147 return 1;
148}
149
Jesus Ceaac451502011-04-20 17:09:23 +0200150#undef FORMAT_BUFFER_SIZE
151
152#ifdef FROM_UNICODE
153
154/*
155Wraps stringlib_parse_args_finds() and additionally ensures that the
156first argument is a unicode object.
157
158Note that we receive a pointer to the pointer of the substring object,
159so when we create that object in this function we don't DECREF it,
160because it continues living in the caller functions (those functions,
161after finishing using the substring, must DECREF it).
162*/
163
164Py_LOCAL_INLINE(int)
165stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
166 PyUnicodeObject **substring,
167 Py_ssize_t *start, Py_ssize_t *end)
168{
169 PyObject *tmp_substring;
170
171 if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
172 start, end)) {
173 tmp_substring = PyUnicode_FromObject(tmp_substring);
174 if (!tmp_substring)
175 return 0;
176 *substring = (PyUnicodeObject *)tmp_substring;
177 return 1;
178 }
179 return 0;
180}
181
Christian Heimes9cd17752007-11-18 19:35:23 +0000182#endif /* FROM_UNICODE */
183
Thomas Wouters477c8d52006-05-27 19:21:47 +0000184#endif /* STRINGLIB_FIND_H */
185
186/*
187Local variables:
188c-basic-offset: 4
189indent-tabs-mode: nil
190End:
191*/