1 | /* 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 |
|
---|
10 | Py_LOCAL_INLINE(Py_ssize_t)
|
---|
11 | stringlib_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 |
|
---|
17 | if (str_len < 0)
|
---|
18 | return -1;
|
---|
19 | if (sub_len == 0)
|
---|
20 | return offset;
|
---|
21 |
|
---|
22 | pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
|
---|
23 |
|
---|
24 | if (pos >= 0)
|
---|
25 | pos += offset;
|
---|
26 |
|
---|
27 | return pos;
|
---|
28 | }
|
---|
29 |
|
---|
30 | Py_LOCAL_INLINE(Py_ssize_t)
|
---|
31 | stringlib_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 | {
|
---|
35 | Py_ssize_t pos;
|
---|
36 |
|
---|
37 | if (str_len < 0)
|
---|
38 | return -1;
|
---|
39 | if (sub_len == 0)
|
---|
40 | return str_len + offset;
|
---|
41 |
|
---|
42 | pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
|
---|
43 |
|
---|
44 | if (pos >= 0)
|
---|
45 | pos += offset;
|
---|
46 |
|
---|
47 | return pos;
|
---|
48 | }
|
---|
49 |
|
---|
50 | /* 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 |
|
---|
65 | Py_LOCAL_INLINE(Py_ssize_t)
|
---|
66 | stringlib_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 | {
|
---|
70 | ADJUST_INDICES(start, end, str_len);
|
---|
71 | return stringlib_find(str + start, end - start, sub, sub_len, start);
|
---|
72 | }
|
---|
73 |
|
---|
74 | Py_LOCAL_INLINE(Py_ssize_t)
|
---|
75 | stringlib_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 | {
|
---|
79 | ADJUST_INDICES(start, end, str_len);
|
---|
80 | return stringlib_rfind(str + start, end - start, sub, sub_len, start);
|
---|
81 | }
|
---|
82 |
|
---|
83 | #ifdef STRINGLIB_WANT_CONTAINS_OBJ
|
---|
84 |
|
---|
85 | Py_LOCAL_INLINE(int)
|
---|
86 | stringlib_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 |
|
---|
94 | #endif /* STRINGLIB_WANT_CONTAINS_OBJ */
|
---|
95 |
|
---|
96 | /*
|
---|
97 | This function is a helper for the "find" family (find, rfind, index,
|
---|
98 | rindex) and for count, startswith and endswith, because they all have
|
---|
99 | the same behaviour for the arguments.
|
---|
100 |
|
---|
101 | It does not touch the variables received until it knows everything
|
---|
102 | is ok.
|
---|
103 | */
|
---|
104 |
|
---|
105 | #define FORMAT_BUFFER_SIZE 50
|
---|
106 |
|
---|
107 | Py_LOCAL_INLINE(int)
|
---|
108 | stringlib_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;
|
---|
113 | 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;
|
---|
116 | char format[FORMAT_BUFFER_SIZE] = "O|OO:";
|
---|
117 | size_t len = strlen(format);
|
---|
118 |
|
---|
119 | 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))
|
---|
123 | 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 |
|
---|
135 | *start = tmp_start;
|
---|
136 | *end = tmp_end;
|
---|
137 | *subobj = tmp_subobj;
|
---|
138 | return 1;
|
---|
139 | }
|
---|
140 |
|
---|
141 | #undef FORMAT_BUFFER_SIZE
|
---|
142 |
|
---|
143 | #if STRINGLIB_IS_UNICODE
|
---|
144 |
|
---|
145 | /*
|
---|
146 | Wraps stringlib_parse_args_finds() and additionally ensures that the
|
---|
147 | first argument is a unicode object.
|
---|
148 |
|
---|
149 | Note that we receive a pointer to the pointer of the substring object,
|
---|
150 | so when we create that object in this function we don't DECREF it,
|
---|
151 | because it continues living in the caller functions (those functions,
|
---|
152 | after finishing using the substring, must DECREF it).
|
---|
153 | */
|
---|
154 |
|
---|
155 | Py_LOCAL_INLINE(int)
|
---|
156 | stringlib_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 |
|
---|
173 | #endif /* STRINGLIB_IS_UNICODE */
|
---|
174 |
|
---|
175 | #endif /* STRINGLIB_FIND_H */
|
---|