123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330 |
- //! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
- #![feature(compiler_builtins_lib)]
- #![no_std]
- extern crate compiler_builtins;
- extern crate errno;
- extern crate platform;
- extern crate stdlib;
- use platform::types::*;
- use errno::*;
- use core::cmp;
- use core::usize;
- use core::ptr;
- #[no_mangle]
- pub unsafe extern "C" fn memccpy(
- dest: *mut c_void,
- src: *const c_void,
- c: c_int,
- n: usize,
- ) -> *mut c_void {
- use compiler_builtins::mem::memcpy;
- let dest = dest as *mut u8;
- let to = memchr(src, c, n);
- if to.is_null() {
- return to;
- }
- let src = src as *mut u8;
- let dist = (to as usize) - (src as usize);
- if memcpy(dest, src, dist).is_null() {
- return ptr::null_mut();
- }
- dest.offset(dist as isize + 1) as *mut c_void
- }
- #[no_mangle]
- pub unsafe extern "C" fn memchr(s: *const c_void, c: c_int, n: usize) -> *mut c_void {
- let s = s as *mut u8;
- let c = c as u8;
- for i in 0..n {
- if *s.offset(i as isize) == c {
- return s.offset(i as isize) as *mut c_void;
- }
- }
- ptr::null_mut()
- }
- // #[no_mangle]
- // pub extern "C" fn memcmp(
- // s1: *const c_void,
- // s2: *const c_void,
- // n: usize,
- // ) -> c_int {
- // unimplemented!();
- // }
- // #[no_mangle]
- // pub extern "C" fn memcpy(
- // s1: *mut c_void,
- // s2: *const c_void,
- // n: usize,
- // ) -> *mut c_void {
- // unimplemented!();
- // }
- // #[no_mangle]
- // pub extern "C" fn memmove(
- // s1: *mut c_void,
- // s2: *const c_void,
- // n: usize,
- // ) -> *mut c_void {
- // unimplemented!();
- // }
- // #[no_mangle]
- // pub extern "C" fn memset(
- // s: *mut c_void,
- // c: c_int,
- // n: usize,
- // ) -> *mut c_void {
- // unimplemented!();
- // }
- #[no_mangle]
- pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
- strncat(s1, s2, usize::MAX)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strchr(s: *const c_char, c: c_int) -> *mut c_char {
- let c = c as i8;
- let mut i = 0;
- while *s.offset(i) != 0 {
- if *s.offset(i) == c {
- return s.offset(i) as *mut c_char;
- }
- i += 1;
- }
- ptr::null_mut()
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcmp(s1: *const c_char, s2: *const c_char) -> c_int {
- strncmp(s1, s2, usize::MAX)
- }
- #[no_mangle]
- pub extern "C" fn strcoll(s1: *const c_char, s2: *const c_char) -> c_int {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcpy(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
- strncpy(s1, s2, usize::MAX)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
- use core::mem;
- let s1 = s1 as *const u8;
- let s2 = s2 as *const u8;
- // The below logic is effectively ripped from the musl implementation
- let mut byteset = [0u8; 32 / mem::size_of::<usize>()];
- let mut i = 0;
- while *s2.offset(i) != 0 {
- byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())] |=
- 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>()));
- i += 1;
- }
- i = 0; // reset
- while *s2.offset(i) != 0 {
- if byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())]
- & 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>())) > 0
- {
- break;
- }
- i += 1;
- }
- i as u64
- }
- #[no_mangle]
- pub unsafe extern "C" fn strdup(s1: *const c_char) -> *mut c_char {
- strndup(s1, usize::MAX)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strndup(s1: *const c_char, size: usize) -> *mut c_char {
- let len = strnlen(s1, size);
- // the "+ 1" is to account for the NUL byte
- let buffer = stdlib::malloc(len + 1) as *mut c_char;
- if buffer.is_null() {
- platform::errno = ENOMEM as c_int;
- } else {
- //memcpy(buffer, s1, len)
- for i in 0..len as isize {
- *buffer.offset(i) = *s1.offset(i);
- }
- *buffer.offset(len as isize) = 0;
- }
- buffer
- }
- #[no_mangle]
- pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
- use core::fmt::Write;
- static mut strerror_buf: [u8; 256] = [0; 256];
- let mut w = platform::StringWriter(strerror_buf.as_mut_ptr(), strerror_buf.len());
- if errnum >= 0 && errnum < STR_ERROR.len() as c_int {
- w.write_str(STR_ERROR[errnum as usize]);
- } else {
- w.write_fmt(format_args!("Unknown error {}", errnum));
- }
- strerror_buf.as_mut_ptr() as *mut c_char
- }
- #[no_mangle]
- pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t {
- strnlen(s, usize::MAX)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strnlen(s: *const c_char, size: usize) -> size_t {
- platform::c_str_n(s, size).len() as size_t
- }
- #[no_mangle]
- pub unsafe extern "C" fn strncat(s1: *mut c_char, s2: *const c_char, n: usize) -> *mut c_char {
- let mut idx = strlen(s1 as *const _) as isize;
- for i in 0..n as isize {
- if *s2.offset(i) == 0 {
- break;
- }
- *s1.offset(idx) = *s2.offset(i);
- idx += 1;
- }
- *s1.offset(idx) = 0;
- s1
- }
- #[no_mangle]
- pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
- let s1 = core::slice::from_raw_parts(s1 as *const c_uchar, n);
- let s2 = core::slice::from_raw_parts(s2 as *const c_uchar, n);
- for (&a, &b) in s1.iter().zip(s2.iter()) {
- let val = (a as c_int) - (b as c_int);
- if a != b || a == 0 {
- return val;
- }
- }
- 0
- }
- #[no_mangle]
- pub unsafe extern "C" fn strncpy(s1: *mut c_char, s2: *const c_char, n: usize) -> *mut c_char {
- let s2_slice = platform::c_str_n(s2, n);
- let s2_len = s2_slice.len();
- //memcpy(s1 as *mut _, s2 as *const _, cmp::min(n, s2_len));
- let mut idx = 0;
- for _ in 0..cmp::min(n, s2_len) {
- *s1.offset(idx as isize) = s2_slice[idx] as c_char;
- idx += 1;
- }
- // if length of s2 < n, pad s1 with zeroes
- for _ in cmp::min(n, s2_len)..n {
- *s1.offset(idx as isize) = 0;
- idx += 1;
- }
- s1
- }
- #[no_mangle]
- pub extern "C" fn strpbrk(s1: *const c_char, s2: *const c_char) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char {
- let len = strlen(s) as isize;
- let c = c as i8;
- let mut i = len - 1;
- while *s.offset(i) != 0 && i >= 0 {
- if *s.offset(i) == c {
- return s.offset(i) as *mut c_char;
- }
- i -= 1;
- }
- ptr::null_mut()
- }
- #[no_mangle]
- pub unsafe extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> c_ulong {
- use core::mem;
- let s1 = s1 as *const u8;
- let s2 = s2 as *const u8;
- // The below logic is effectively ripped from the musl implementation
- let mut byteset = [0u8; 32 / mem::size_of::<usize>()];
- let mut i = 0;
- while *s2.offset(i) != 0 {
- byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())] |=
- 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>()));
- i += 1;
- }
- i = 0; // reset
- while *s2.offset(i) != 0 {
- if byteset[(*s2.offset(i) as usize) / (8 * mem::size_of::<usize>())]
- & 1 << (*s2.offset(i) as usize % (8 * mem::size_of::<usize>())) < 1
- {
- break;
- }
- i += 1;
- }
- i as u64
- }
- #[no_mangle]
- pub extern "C" fn strstr(s1: *const c_char, s2: *const c_char) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn strtok(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn strtok_r(
- s: *mut c_char,
- sep: *const c_char,
- lasts: *mut *mut c_char,
- ) -> *mut c_char {
- unimplemented!();
- }
- #[no_mangle]
- pub extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: usize) -> c_ulong {
- unimplemented!();
- }
- /*
- #[no_mangle]
- pub extern "C" fn func(args) -> c_int {
- unimplemented!();
- }
- */
|