xref: /third_party/rust/crates/memchr/src/memchr/c.rs (revision fb6c1f39)
1// This module defines safe wrappers around memchr (POSIX) and memrchr (GNU
2// extension).
3
4#![allow(dead_code)]
5
6use libc::{c_int, c_void, size_t};
7
8pub fn memchr(needle: u8, haystack: &[u8]) -> Option<usize> {
9    // SAFETY: This is safe to call since all pointers are valid.
10    let p = unsafe {
11        libc::memchr(
12            haystack.as_ptr() as *const c_void,
13            needle as c_int,
14            haystack.len() as size_t,
15        )
16    };
17    if p.is_null() {
18        None
19    } else {
20        Some(p as usize - (haystack.as_ptr() as usize))
21    }
22}
23
24// memrchr is a GNU extension. We know it's available on Linux at least.
25#[cfg(target_os = "linux")]
26pub fn memrchr(needle: u8, haystack: &[u8]) -> Option<usize> {
27    // GNU's memrchr() will - unlike memchr() - error if haystack is empty.
28    if haystack.is_empty() {
29        return None;
30    }
31    // SAFETY: This is safe to call since all pointers are valid.
32    let p = unsafe {
33        libc::memrchr(
34            haystack.as_ptr() as *const c_void,
35            needle as c_int,
36            haystack.len() as size_t,
37        )
38    };
39    if p.is_null() {
40        None
41    } else {
42        Some(p as usize - (haystack.as_ptr() as usize))
43    }
44}
45