• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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]
memchr_iter(needle: u8, haystack: &[u8]) -> Memchr<'_>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]
memchr2_iter(needle1: u8, needle2: u8, haystack: &[u8]) -> Memchr2<'_>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]
memchr3_iter( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Memchr3<'_>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]
memrchr_iter(needle: u8, haystack: &[u8]) -> Rev<Memchr<'_>>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]
memrchr2_iter( needle1: u8, needle2: u8, haystack: &[u8], ) -> Rev<Memchr2<'_>>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]
memrchr3_iter( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Rev<Memchr3<'_>>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]
memchr(needle: u8, haystack: &[u8]) -> Option<usize>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]
memchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize>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]
memchr3( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Option<usize>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]
memrchr(needle: u8, haystack: &[u8]) -> Option<usize>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]
memrchr2(needle1: u8, needle2: u8, haystack: &[u8]) -> Option<usize>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]
memrchr3( needle1: u8, needle2: u8, needle3: u8, haystack: &[u8], ) -> Option<usize>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