blob: f915296cae61350575c77d01a9c85ad34acba392 [file] [log] [blame]
Fredrik Lundh58b5e842006-05-26 19:24:53 +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
Fredrik Lundhc2d29c52006-05-27 14:58:20 +000010Py_LOCAL_INLINE(Py_ssize_t)
Fredrik Lundh58b5e842006-05-26 19:24:53 +000011stringlib_find(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Fredrik Lundhe6e43c82006-05-26 19:48:07 +000012 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
13 Py_ssize_t offset)
Fredrik Lundh58b5e842006-05-26 19:24:53 +000014{
Fredrik Lundhe6e43c82006-05-26 19:48:07 +000015 Py_ssize_t pos;
Fredrik Lundh58b5e842006-05-26 19:24:53 +000016
Amaury Forgeot d'Arcfc5ea392008-09-26 22:34:08 +000017 if (str_len < 0)
18 return -1;
19 if (sub_len == 0)
Fredrik Lundhe6e43c82006-05-26 19:48:07 +000020 return offset;
21
Antoine Pitrou64672132010-01-13 07:55:48 +000022 pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_SEARCH);
Fredrik Lundhe6e43c82006-05-26 19:48:07 +000023
24 if (pos >= 0)
25 pos += offset;
26
27 return pos;
Fredrik Lundh58b5e842006-05-26 19:24:53 +000028}
29
Fredrik Lundhc2d29c52006-05-27 14:58:20 +000030Py_LOCAL_INLINE(Py_ssize_t)
Fredrik Lundh58b5e842006-05-26 19:24:53 +000031stringlib_rfind(const STRINGLIB_CHAR* str, Py_ssize_t str_len,
Fredrik Lundhe6e43c82006-05-26 19:48:07 +000032 const STRINGLIB_CHAR* sub, Py_ssize_t sub_len,
33 Py_ssize_t offset)
Fredrik Lundh58b5e842006-05-26 19:24:53 +000034{
Antoine Pitrou5b7139a2010-01-02 21:12:58 +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 Pitrou64672132010-01-13 07:55:48 +000042 pos = fastsearch(str, str_len, sub, sub_len, -1, FAST_RSEARCH);
Antoine Pitrou5b7139a2010-01-02 21:12:58 +000043
44 if (pos >= 0)
45 pos += offset;
46
47 return pos;
Fredrik Lundh58b5e842006-05-26 19:24:53 +000048}
49
Antoine Pitrou64672132010-01-13 07:55:48 +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
Fredrik Lundhc2d29c52006-05-27 14:58:20 +000065Py_LOCAL_INLINE(Py_ssize_t)
Fredrik Lundh60d8b182006-05-27 15:20:22 +000066stringlib_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)
Fredrik Lundh2d23d5b2006-05-27 10:05:10 +000069{
Antoine Pitrou64672132010-01-13 07:55:48 +000070 ADJUST_INDICES(start, end, str_len);
Antoine Pitrou5b7139a2010-01-02 21:12:58 +000071 return stringlib_find(str + start, end - start, sub, sub_len, start);
Fredrik Lundh2d23d5b2006-05-27 10:05:10 +000072}
73
Fredrik Lundh60d8b182006-05-27 15:20:22 +000074Py_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 Pitrou64672132010-01-13 07:55:48 +000079 ADJUST_INDICES(start, end, str_len);
Fredrik Lundh60d8b182006-05-27 15:20:22 +000080 return stringlib_rfind(str + start, end - start, sub, sub_len, start);
81}
82
Antoine Pitrou64672132010-01-13 07:55:48 +000083#ifdef STRINGLIB_WANT_CONTAINS_OBJ
Fredrik Lundh60d8b182006-05-27 15:20:22 +000084
Fredrik Lundhc2d29c52006-05-27 14:58:20 +000085Py_LOCAL_INLINE(int)
Fredrik Lundh2d23d5b2006-05-27 10:05:10 +000086stringlib_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 Pitrou64672132010-01-13 07:55:48 +000094#endif /* STRINGLIB_WANT_CONTAINS_OBJ */
Fredrik Lundh2d23d5b2006-05-27 10:05:10 +000095
Antoine Pitrou64672132010-01-13 07:55:48 +000096#if STRINGLIB_IS_UNICODE
Facundo Batista6f7e6fb2007-11-16 19:16:15 +000097
Facundo Batista57d56692007-11-16 18:04:14 +000098/*
99This function is a helper for the "find" family (find, rfind, index,
100rindex) of unicodeobject.c file, because they all have the same
101behaviour for the arguments.
102
103It does not touch the variables received until it knows everything
104is ok.
105
106Note that we receive a pointer to the pointer of the substring object,
107so when we create that object in this function we don't DECREF it,
108because it continues living in the caller functions (those functions,
109after finishing using the substring, must DECREF it).
110*/
111
Facundo Batista292a0692007-11-16 18:41:24 +0000112Py_LOCAL_INLINE(int)
Facundo Batista57d56692007-11-16 18:04:14 +0000113_ParseTupleFinds (PyObject *args, PyObject **substring,
114 Py_ssize_t *start, Py_ssize_t *end) {
115 PyObject *tmp_substring;
116 Py_ssize_t tmp_start = 0;
117 Py_ssize_t tmp_end = PY_SSIZE_T_MAX;
118 PyObject *obj_start=Py_None, *obj_end=Py_None;
119
120 if (!PyArg_ParseTuple(args, "O|OO:find", &tmp_substring,
121 &obj_start, &obj_end))
122 return 0;
123
124 /* To support None in "start" and "end" arguments, meaning
125 the same as if they were not passed.
126 */
127 if (obj_start != Py_None)
128 if (!_PyEval_SliceIndex(obj_start, &tmp_start))
129 return 0;
130 if (obj_end != Py_None)
131 if (!_PyEval_SliceIndex(obj_end, &tmp_end))
132 return 0;
133
134 tmp_substring = PyUnicode_FromObject(tmp_substring);
135 if (!tmp_substring)
136 return 0;
137
138 *start = tmp_start;
139 *end = tmp_end;
140 *substring = tmp_substring;
141 return 1;
142}
143
Antoine Pitrou64672132010-01-13 07:55:48 +0000144#endif /* STRINGLIB_IS_UNICODE */
Facundo Batista57d56692007-11-16 18:04:14 +0000145
Fredrik Lundh60d8b182006-05-27 15:20:22 +0000146#endif /* STRINGLIB_FIND_H */