1 | use core::iter::Rev; |
2 | |
3 | pub use self::iter::{Memchr, Memchr2, Memchr3}; |
4 | |
5 | // N.B. If you're looking for the cfg knobs for libc, see build.rs. |
6 | #[cfg (memchr_libc)] |
7 | mod c; |
8 | #[allow (dead_code)] |
9 | pub mod fallback; |
10 | mod iter; |
11 | pub mod naive; |
12 | #[cfg (all(not(miri), target_arch = "x86_64" , memchr_runtime_simd))] |
13 | mod x86; |
14 | |
15 | /// An iterator over all occurrences of the needle in a haystack. |
16 | #[inline ] |
17 | pub fn memchr_iter(needle: u8, haystack: &[u8]) -> Memchr<'_> { |
18 | Memchr::new(needle, haystack) |
19 | } |
20 | |
21 | /// An iterator over all occurrences of the needles in a haystack. |
22 | #[inline ] |
23 | pub fn memchr2_iter(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2<'_> { |
24 | Memchr2::new(needle1, needle2, haystack) |
25 | } |
26 | |
27 | /// An iterator over all occurrences of the needles in a haystack. |
28 | #[inline ] |
29 | pub fn memchr3_iter( |
30 | needle1: u8, |
31 | needle2: u8, |
32 | needle3: u8, |
33 | haystack: &[u8], |
34 | ) -> Memchr3<'_> { |
35 | Memchr3::new(needle1, needle2, needle3, haystack) |
36 | } |
37 | |
38 | /// An iterator over all occurrences of the needle in a haystack, in reverse. |
39 | #[inline ] |
40 | pub fn memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>> { |
41 | Memchr::new(needle, haystack).rev() |
42 | } |
43 | |
44 | /// An iterator over all occurrences of the needles in a haystack, in reverse. |
45 | #[inline ] |
46 | pub fn memrchr2_iter( |
47 | needle1: u8, |
48 | needle2: u8, |
49 | haystack: &[u8], |
50 | ) -> Rev<Memchr2<'_>> { |
51 | Memchr2::new(needle1, needle2, haystack).rev() |
52 | } |
53 | |
54 | /// An iterator over all occurrences of the needles in a haystack, in reverse. |
55 | #[inline ] |
56 | pub fn memrchr3_iter( |
57 | needle1: u8, |
58 | needle2: u8, |
59 | needle3: u8, |
60 | haystack: &[u8], |
61 | ) -> Rev<Memchr3<'_>> { |
62 | Memchr3::new(needle1, needle2, needle3, haystack).rev() |
63 | } |
64 | |
65 | /// Search for the first occurrence of a byte in a slice. |
66 | /// |
67 | /// This returns the index corresponding to the first occurrence of `needle` in |
68 | /// `haystack`, or `None` if one is not found. If an index is returned, it is |
69 | /// guaranteed to be less than `usize::MAX`. |
70 | /// |
71 | /// While this is operationally the same as something like |
72 | /// `haystack.iter().position(|&b| b == needle)`, `memchr` will use a highly |
73 | /// optimized routine that can be up to an order of magnitude faster in some |
74 | /// cases. |
75 | /// |
76 | /// # Example |
77 | /// |
78 | /// This shows how to find the first position of a byte in a byte string. |
79 | /// |
80 | /// ``` |
81 | /// use memchr::memchr; |
82 | /// |
83 | /// let haystack = b"the quick brown fox" ; |
84 | /// assert_eq!(memchr(b'k' , haystack), Some(8)); |
85 | /// ``` |
86 | #[inline ] |
87 | pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
88 | #[cfg (miri)] |
89 | #[inline (always)] |
90 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
91 | naive::memchr(n1, haystack) |
92 | } |
93 | |
94 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
95 | #[inline (always)] |
96 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
97 | x86::memchr(n1, haystack) |
98 | } |
99 | |
100 | #[cfg (all( |
101 | memchr_libc, |
102 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
103 | not(miri), |
104 | ))] |
105 | #[inline (always)] |
106 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
107 | c::memchr(n1, haystack) |
108 | } |
109 | |
110 | #[cfg (all( |
111 | not(memchr_libc), |
112 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
113 | not(miri), |
114 | ))] |
115 | #[inline (always)] |
116 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
117 | fallback::memchr(n1, haystack) |
118 | } |
119 | |
120 | if haystack.is_empty() { |
121 | None |
122 | } else { |
123 | imp(needle, haystack) |
124 | } |
125 | } |
126 | |
127 | /// Like `memchr`, but searches for either of two bytes instead of just one. |
128 | /// |
129 | /// This returns the index corresponding to the first occurrence of `needle1` |
130 | /// or the first occurrence of `needle2` in `haystack` (whichever occurs |
131 | /// earlier), or `None` if neither one is found. If an index is returned, it is |
132 | /// guaranteed to be less than `usize::MAX`. |
133 | /// |
134 | /// While this is operationally the same as something like |
135 | /// `haystack.iter().position(|&b| b == needle1 || b == needle2)`, `memchr2` |
136 | /// will use a highly optimized routine that can be up to an order of magnitude |
137 | /// faster in some cases. |
138 | /// |
139 | /// # Example |
140 | /// |
141 | /// This shows how to find the first position of either of two bytes in a byte |
142 | /// string. |
143 | /// |
144 | /// ``` |
145 | /// use memchr::memchr2; |
146 | /// |
147 | /// let haystack = b"the quick brown fox" ; |
148 | /// assert_eq!(memchr2(b'k' , b'q' , haystack), Some(4)); |
149 | /// ``` |
150 | #[inline ] |
151 | pub fn memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { |
152 | #[cfg (miri)] |
153 | #[inline (always)] |
154 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
155 | naive::memchr2(n1, n2, haystack) |
156 | } |
157 | |
158 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
159 | #[inline (always)] |
160 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
161 | x86::memchr2(n1, n2, haystack) |
162 | } |
163 | |
164 | #[cfg (all( |
165 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
166 | not(miri), |
167 | ))] |
168 | #[inline (always)] |
169 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
170 | fallback::memchr2(n1, n2, haystack) |
171 | } |
172 | |
173 | if haystack.is_empty() { |
174 | None |
175 | } else { |
176 | imp(needle1, needle2, haystack) |
177 | } |
178 | } |
179 | |
180 | /// Like `memchr`, but searches for any of three bytes instead of just one. |
181 | /// |
182 | /// This returns the index corresponding to the first occurrence of `needle1`, |
183 | /// the first occurrence of `needle2`, or the first occurrence of `needle3` in |
184 | /// `haystack` (whichever occurs earliest), or `None` if none are found. If an |
185 | /// index is returned, it is guaranteed to be less than `usize::MAX`. |
186 | /// |
187 | /// While this is operationally the same as something like |
188 | /// `haystack.iter().position(|&b| b == needle1 || b == needle2 || |
189 | /// b == needle3)`, `memchr3` will use a highly optimized routine that can be |
190 | /// up to an order of magnitude faster in some cases. |
191 | /// |
192 | /// # Example |
193 | /// |
194 | /// This shows how to find the first position of any of three bytes in a byte |
195 | /// string. |
196 | /// |
197 | /// ``` |
198 | /// use memchr::memchr3; |
199 | /// |
200 | /// let haystack = b"the quick brown fox" ; |
201 | /// assert_eq!(memchr3(b'k' , b'q' , b'e' , haystack), Some(2)); |
202 | /// ``` |
203 | #[inline ] |
204 | pub fn memchr3( |
205 | needle1: u8, |
206 | needle2: u8, |
207 | needle3: u8, |
208 | haystack: &[u8], |
209 | ) -> Option<usize> { |
210 | #[cfg (miri)] |
211 | #[inline (always)] |
212 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
213 | naive::memchr3(n1, n2, n3, haystack) |
214 | } |
215 | |
216 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
217 | #[inline (always)] |
218 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
219 | x86::memchr3(n1, n2, n3, haystack) |
220 | } |
221 | |
222 | #[cfg (all( |
223 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
224 | not(miri), |
225 | ))] |
226 | #[inline (always)] |
227 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
228 | fallback::memchr3(n1, n2, n3, haystack) |
229 | } |
230 | |
231 | if haystack.is_empty() { |
232 | None |
233 | } else { |
234 | imp(needle1, needle2, needle3, haystack) |
235 | } |
236 | } |
237 | |
238 | /// Search for the last occurrence of a byte in a slice. |
239 | /// |
240 | /// This returns the index corresponding to the last occurrence of `needle` in |
241 | /// `haystack`, or `None` if one is not found. If an index is returned, it is |
242 | /// guaranteed to be less than `usize::MAX`. |
243 | /// |
244 | /// While this is operationally the same as something like |
245 | /// `haystack.iter().rposition(|&b| b == needle)`, `memrchr` will use a highly |
246 | /// optimized routine that can be up to an order of magnitude faster in some |
247 | /// cases. |
248 | /// |
249 | /// # Example |
250 | /// |
251 | /// This shows how to find the last position of a byte in a byte string. |
252 | /// |
253 | /// ``` |
254 | /// use memchr::memrchr; |
255 | /// |
256 | /// let haystack = b"the quick brown fox" ; |
257 | /// assert_eq!(memrchr(b'o' , haystack), Some(17)); |
258 | /// ``` |
259 | #[inline ] |
260 | pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> { |
261 | #[cfg (miri)] |
262 | #[inline (always)] |
263 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
264 | naive::memrchr(n1, haystack) |
265 | } |
266 | |
267 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
268 | #[inline (always)] |
269 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
270 | x86::memrchr(n1, haystack) |
271 | } |
272 | |
273 | #[cfg (all( |
274 | memchr_libc, |
275 | target_os = "linux" , |
276 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
277 | not(miri) |
278 | ))] |
279 | #[inline (always)] |
280 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
281 | c::memrchr(n1, haystack) |
282 | } |
283 | |
284 | #[cfg (all( |
285 | not(all(memchr_libc, target_os = "linux" )), |
286 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
287 | not(miri), |
288 | ))] |
289 | #[inline (always)] |
290 | fn imp(n1: u8, haystack: &[u8]) -> Option<usize> { |
291 | fallback::memrchr(n1, haystack) |
292 | } |
293 | |
294 | if haystack.is_empty() { |
295 | None |
296 | } else { |
297 | imp(needle, haystack) |
298 | } |
299 | } |
300 | |
301 | /// Like `memrchr`, but searches for either of two bytes instead of just one. |
302 | /// |
303 | /// This returns the index corresponding to the last occurrence of `needle1` or |
304 | /// the last occurrence of `needle2` in `haystack` (whichever occurs later), or |
305 | /// `None` if neither one is found. If an index is returned, it is guaranteed |
306 | /// to be less than `usize::MAX`. |
307 | /// |
308 | /// While this is operationally the same as something like |
309 | /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2)`, `memrchr2` |
310 | /// will use a highly optimized routine that can be up to an order of magnitude |
311 | /// faster in some cases. |
312 | /// |
313 | /// # Example |
314 | /// |
315 | /// This shows how to find the last position of either of two bytes in a byte |
316 | /// string. |
317 | /// |
318 | /// ``` |
319 | /// use memchr::memrchr2; |
320 | /// |
321 | /// let haystack = b"the quick brown fox" ; |
322 | /// assert_eq!(memrchr2(b'k' , b'q' , haystack), Some(8)); |
323 | /// ``` |
324 | #[inline ] |
325 | pub fn memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize> { |
326 | #[cfg (miri)] |
327 | #[inline (always)] |
328 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
329 | naive::memrchr2(n1, n2, haystack) |
330 | } |
331 | |
332 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
333 | #[inline (always)] |
334 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
335 | x86::memrchr2(n1, n2, haystack) |
336 | } |
337 | |
338 | #[cfg (all( |
339 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
340 | not(miri), |
341 | ))] |
342 | #[inline (always)] |
343 | fn imp(n1: u8, n2: u8, haystack: &[u8]) -> Option<usize> { |
344 | fallback::memrchr2(n1, n2, haystack) |
345 | } |
346 | |
347 | if haystack.is_empty() { |
348 | None |
349 | } else { |
350 | imp(needle1, needle2, haystack) |
351 | } |
352 | } |
353 | |
354 | /// Like `memrchr`, but searches for any of three bytes instead of just one. |
355 | /// |
356 | /// This returns the index corresponding to the last occurrence of `needle1`, |
357 | /// the last occurrence of `needle2`, or the last occurrence of `needle3` in |
358 | /// `haystack` (whichever occurs later), or `None` if none are found. If an |
359 | /// index is returned, it is guaranteed to be less than `usize::MAX`. |
360 | /// |
361 | /// While this is operationally the same as something like |
362 | /// `haystack.iter().rposition(|&b| b == needle1 || b == needle2 || |
363 | /// b == needle3)`, `memrchr3` will use a highly optimized routine that can be |
364 | /// up to an order of magnitude faster in some cases. |
365 | /// |
366 | /// # Example |
367 | /// |
368 | /// This shows how to find the last position of any of three bytes in a byte |
369 | /// string. |
370 | /// |
371 | /// ``` |
372 | /// use memchr::memrchr3; |
373 | /// |
374 | /// let haystack = b"the quick brown fox" ; |
375 | /// assert_eq!(memrchr3(b'k' , b'q' , b'e' , haystack), Some(8)); |
376 | /// ``` |
377 | #[inline ] |
378 | pub fn memrchr3( |
379 | needle1: u8, |
380 | needle2: u8, |
381 | needle3: u8, |
382 | haystack: &[u8], |
383 | ) -> Option<usize> { |
384 | #[cfg (miri)] |
385 | #[inline (always)] |
386 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
387 | naive::memrchr3(n1, n2, n3, haystack) |
388 | } |
389 | |
390 | #[cfg (all(target_arch = "x86_64" , memchr_runtime_simd, not(miri)))] |
391 | #[inline (always)] |
392 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
393 | x86::memrchr3(n1, n2, n3, haystack) |
394 | } |
395 | |
396 | #[cfg (all( |
397 | not(all(target_arch = "x86_64" , memchr_runtime_simd)), |
398 | not(miri), |
399 | ))] |
400 | #[inline (always)] |
401 | fn imp(n1: u8, n2: u8, n3: u8, haystack: &[u8]) -> Option<usize> { |
402 | fallback::memrchr3(n1, n2, n3, haystack) |
403 | } |
404 | |
405 | if haystack.is_empty() { |
406 | None |
407 | } else { |
408 | imp(needle1, needle2, needle3, haystack) |
409 | } |
410 | } |
411 | |