blob: ce615dcb8a4e580317f227f1434ac21acfcc134e [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
Antoine Pitrouf2c54842010-01-13 08:07:53 +000022 pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
Thomas Wouters477c8d52006-05-27 19:21:47 +000023
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{
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000035 Py_ssize_t pos;
36
37 if (str_len < 0)
38 return -1;
39 if (sub_len == 0)
40 return str_len + offset;
41
Antoine Pitrouf2c54842010-01-13 08:07:53 +000042 pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000043
44 if (pos >= 0)
45 pos += offset;
46
47 return pos;
Thomas Wouters477c8d52006-05-27 19:21:47 +000048}
49
Antoine Pitrouf2c54842010-01-13 08:07:53 +000050/* helper macro to fixup start/end slice values */
51#define ADJUST_INDICES(start, end, len) \
52 if (end > len) \
53 end = len; \
54 else if (end < 0) { \
55 end += len; \
56 if (end < 0) \
57 end = 0; \
58 } \
59 if (start < 0) { \
60 start += len; \
61 if (start < 0) \
62 start = 0; \
63 }
64
Thomas Wouters477c8d52006-05-27 19:21:47 +000065Py_LOCAL_INLINE(Py_ssize_t)
66stringlib_find_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
67 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
68 Py_ssize_t start, Py_ssize_t end)
69{
Antoine Pitrouf2c54842010-01-13 08:07:53 +000070 ADJUST_INDICES(start, end, str_len);
Antoine Pitrouda2ecaf2010-01-02 21:40:36 +000071 return stringlib_find(str + start, end - start, sub, sub_len, start);
Thomas Wouters477c8d52006-05-27 19:21:47 +000072}
73
74Py_LOCAL_INLINE(Py_ssize_t)
75stringlib_rfind_slice(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
76 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
77 Py_ssize_t start, Py_ssize_t end)
78{
Antoine Pitrouf2c54842010-01-13 08:07:53 +000079 ADJUST_INDICES(start, end, str_len);
Thomas Wouters477c8d52006-05-27 19:21:47 +000080 return stringlib_rfind(str + start, end - start, sub, sub_len, start);
81}
82
Christian Heimes4f3c5612008-08-28 14:55:10 +000083#ifdef STRINGLIB_WANT_CONTAINS_OBJ
Thomas Wouters477c8d52006-05-27 19:21:47 +000084
85Py_LOCAL_INLINE(int)
86stringlib_contains_obj(PyObject* str, PyObject* sub)
87{
88 return stringlib_find(
89 STRINGLIB_STR(str), STRINGLIB_LEN(str),
90 STRINGLIB_STR(sub), STRINGLIB_LEN(sub), 0
91 ) != -1;
92}
93
Antoine Pitrouf2c54842010-01-13 08:07:53 +000094#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
Thomas Wouters477c8d52006-05-27 19:21:47 +000095
Christian Heimes9cd17752007-11-18 19:35:23 +000096/*
97This function is a helper for the "find" family (find, rfind, index,
Jesus Ceaac451502011-04-20 17:09:23 +020098rindex) and for count, startswith and endswith, because they all have
99the same behaviour for the arguments.
Christian Heimes9cd17752007-11-18 19:35:23 +0000100
101It does not touch the variables received until it knows everything
102is ok.
Christian Heimes9cd17752007-11-18 19:35:23 +0000103*/
104
Jesus Ceaac451502011-04-20 17:09:23 +0200105#define FORMAT_BUFFER_SIZE 50
106
Christian Heimes9cd17752007-11-18 19:35:23 +0000107Py_LOCAL_INLINE(int)
Jesus Ceaac451502011-04-20 17:09:23 +0200108stringlib_parse_args_finds(const char * function_name, PyObject *args,
109 PyObject **subobj,
110 Py_ssize_t *start, Py_ssize_t *end)
111{
112 PyObject *tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +0000113 Py_ssize_t tmp_start = 0;
114 Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
115 PyObject *obj_start=Py_None, *obj_end=Py_None;
Jesus Ceaac451502011-04-20 17:09:23 +0200116 char format[FORMAT_BUFFER_SIZE] = "O|OO:";
117 size_t len = strlen(format);
Christian Heimes9cd17752007-11-18 19:35:23 +0000118
Jesus Ceaac451502011-04-20 17:09:23 +0200119 strncpy(format + len, function_name, FORMAT_BUFFER_SIZE - len - 1);
120 format[FORMAT_BUFFER_SIZE - 1] = '\0';
121
122 if (!PyArg_ParseTuple(args, format, &tmp_subobj, &obj_start, &obj_end))
Christian Heimes9cd17752007-11-18 19:35:23 +0000123 return 0;
124
125 /* To support None in "start" and "end" arguments, meaning
126 the same as if they were not passed.
127 */
128 if (obj_start != Py_None)
129 if (!_PyEval_SliceIndex(obj_start, &tmp_start))
130 return 0;
131 if (obj_end != Py_None)
132 if (!_PyEval_SliceIndex(obj_end, &tmp_end))
133 return 0;
134
Christian Heimes9cd17752007-11-18 19:35:23 +0000135 *start = tmp_start;
136 *end = tmp_end;
Jesus Ceaac451502011-04-20 17:09:23 +0200137 *subobj = tmp_subobj;
Christian Heimes9cd17752007-11-18 19:35:23 +0000138 return 1;
139}
140
Jesus Ceaac451502011-04-20 17:09:23 +0200141#undef FORMAT_BUFFER_SIZE
142
Jesus Cea6159ee32011-04-20 17:42:50 +0200143#if STRINGLIB_IS_UNICODE
Jesus Ceaac451502011-04-20 17:09:23 +0200144
145/*
146Wraps stringlib_parse_args_finds() and additionally ensures that the
147first argument is a unicode object.
148
149Note that we receive a pointer to the pointer of the substring object,
150so when we create that object in this function we don't DECREF it,
151because it continues living in the caller functions (those functions,
152after finishing using the substring, must DECREF it).
153*/
154
155Py_LOCAL_INLINE(int)
156stringlib_parse_args_finds_unicode(const char * function_name, PyObject *args,
157 PyUnicodeObject **substring,
158 Py_ssize_t *start, Py_ssize_t *end)
159{
160 PyObject *tmp_substring;
161
162 if(stringlib_parse_args_finds(function_name, args, &tmp_substring,
163 start, end)) {
164 tmp_substring = PyUnicode_FromObject(tmp_substring);
165 if (!tmp_substring)
166 return 0;
167 *substring = (PyUnicodeObject *)tmp_substring;
168 return 1;
169 }
170 return 0;
171}
172
Antoine Pitrouf2c54842010-01-13 08:07:53 +0000173#endif /* STRINGLIB_IS_UNICODE */
Christian Heimes9cd17752007-11-18 19:35:23 +0000174
Thomas Wouters477c8d52006-05-27 19:21:47 +0000175#endif /* STRINGLIB_FIND_H */