1 // Copyright 2023, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 //! This library provides implementation for a few libc functions for building third party C
16 //! libraries.
17
18 #![no_std]
19
20 use core::ptr::null_mut;
21
22 /// void *memchr(const void *ptr, int ch, size_t count);
23 #[no_mangle]
memchr( ptr: *const core::ffi::c_void, ch: core::ffi::c_int, count: core::ffi::c_ulong, ) -> *mut core::ffi::c_void24 pub extern "C" fn memchr(
25 ptr: *const core::ffi::c_void,
26 ch: core::ffi::c_int,
27 count: core::ffi::c_ulong,
28 ) -> *mut core::ffi::c_void {
29 assert!(!ptr.is_null());
30 let start = ptr as *const u8;
31 let target = (ch & 0xff) as u8;
32 for i in 0..count {
33 // SAFETY: Buffer is assumed valid and bounded by count.
34 let curr = unsafe { start.add(i.try_into().unwrap()) };
35 // SAFETY: Buffer is assumed valid and bounded by count.
36 if *unsafe { curr.as_ref().unwrap() } == target {
37 return curr as *mut _;
38 }
39 }
40 null_mut()
41 }
42
43 /// char *strrchr(const char *str, int c);
44 #[no_mangle]
strrchr( ptr: *const core::ffi::c_char, ch: core::ffi::c_int, ) -> *mut core::ffi::c_char45 pub extern "C" fn strrchr(
46 ptr: *const core::ffi::c_char,
47 ch: core::ffi::c_int,
48 ) -> *mut core::ffi::c_char {
49 assert!(!ptr.is_null());
50 // SAFETY: Input is a valid null terminated string.
51 let bytes = unsafe { core::ffi::CStr::from_ptr(ptr).to_bytes_with_nul() };
52 let target = (ch & 0xff) as u8;
53 for c in bytes.iter().rev() {
54 if *c == target {
55 return c as *const _ as *mut _;
56 }
57 }
58 null_mut()
59 }
60
61 /// size_t strnlen(const char *s, size_t maxlen);
62 #[no_mangle]
strnlen(s: *const core::ffi::c_char, maxlen: usize) -> usize63 pub fn strnlen(s: *const core::ffi::c_char, maxlen: usize) -> usize {
64 match memchr(s as *const _, 0, maxlen.try_into().unwrap()) {
65 p if p.is_null() => maxlen,
66 p => (p as usize) - (s as usize),
67 }
68 }
69