123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516 |
- //! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
- use crate::unix::header::string::slice::memchr;
- use crate::unix::header::{errno::*, signal};
- use crate::unix::platform;
- use cbitset::BitSet256;
- use core::{mem, ptr, slice, usize};
- #[no_mangle]
- pub unsafe extern "C" fn memccpy(
- dest: *mut ::c_void,
- src: *const ::c_void,
- c: ::c_int,
- n: ::size_t,
- ) -> *mut ::c_void {
- let to = memchr(src, c, n);
- if to.is_null() {
- return to;
- }
- let dist = (to as usize) - (src as usize);
- if memcpy(dest, src, dist).is_null() {
- return ptr::null_mut();
- }
- (dest as *mut u8).add(dist + 1) as *mut ::c_void
- }
- #[no_mangle]
- pub unsafe extern "C" fn memchr(
- haystack: *const ::c_void,
- needle: ::c_int,
- len: ::size_t,
- ) -> *mut ::c_void {
- let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
- match memchr::memchr(needle as u8, haystack) {
- Some(index) => haystack[index..].as_ptr() as *mut ::c_void,
- None => ptr::null_mut(),
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn memcmp(s1: *const ::c_void, s2: *const ::c_void, n: ::size_t) -> ::c_int {
- let (div, rem) = (n / mem::size_of::<usize>(), n % mem::size_of::<usize>());
- let mut a = s1 as *const usize;
- let mut b = s2 as *const usize;
- for _ in 0..div {
- if *a != *b {
- for i in 0..mem::size_of::<usize>() {
- let c = *(a as *const u8).add(i);
- let d = *(b as *const u8).add(i);
- if c != d {
- return c as ::c_int - d as ::c_int;
- }
- }
- unreachable!()
- }
- a = a.offset(1);
- b = b.offset(1);
- }
- let mut a = a as *const u8;
- let mut b = b as *const u8;
- for _ in 0..rem {
- if *a != *b {
- return *a as ::c_int - *b as ::c_int;
- }
- a = a.offset(1);
- b = b.offset(1);
- }
- 0
- }
- #[no_mangle]
- pub unsafe extern "C" fn memcpy(
- s1: *mut ::c_void,
- s2: *const ::c_void,
- n: ::size_t,
- ) -> *mut ::c_void {
- let mut i = 0;
- while i + 7 < n {
- *(s1.add(i) as *mut u64) = *(s2.add(i) as *const u64);
- i += 8;
- }
- while i < n {
- *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
- i += 1;
- }
- s1
- }
- #[no_mangle]
- pub unsafe extern "C" fn memmove(
- s1: *mut ::c_void,
- s2: *const ::c_void,
- n: ::size_t,
- ) -> *mut ::c_void {
- if s2 < s1 as *const ::c_void {
- // copy from end
- let mut i = n;
- while i != 0 {
- i -= 1;
- *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
- }
- } else {
- // copy from beginning
- let mut i = 0;
- while i < n {
- *(s1 as *mut u8).add(i) = *(s2 as *const u8).add(i);
- i += 1;
- }
- }
- s1
- }
- #[no_mangle]
- pub unsafe extern "C" fn memrchr(
- haystack: *const ::c_void,
- needle: ::c_int,
- len: ::size_t,
- ) -> *mut ::c_void {
- let haystack = slice::from_raw_parts(haystack as *const u8, len as usize);
- match memchr::memrchr(needle as u8, haystack) {
- Some(index) => haystack[index..].as_ptr() as *mut ::c_void,
- None => ptr::null_mut(),
- }
- }
- #[no_mangle]
- pub unsafe extern "C" fn memset(s: *mut ::c_void, c: ::c_int, n: ::size_t) -> *mut ::c_void {
- for i in 0..n {
- *(s as *mut u8).add(i) = c as u8;
- }
- s
- }
- #[no_mangle]
- pub unsafe extern "C" fn strchr(mut s: *const ::c_char, c: ::c_int) -> *mut ::c_char {
- let c = c as ::c_char;
- while *s != 0 {
- if *s == c {
- return s as *mut ::c_char;
- }
- s = s.offset(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 unsafe extern "C" fn strcoll(s1: *const ::c_char, s2: *const ::c_char) -> ::c_int {
- // relibc has no locale stuff (yet)
- strcmp(s1, s2)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcpy(dst: *mut ::c_char, src: *const ::c_char) -> *mut ::c_char {
- let mut i = 0;
- loop {
- let byte = *src.offset(i);
- *dst.offset(i) = byte;
- if byte == 0 {
- break;
- }
- i += 1;
- }
- dst
- }
- pub unsafe fn inner_strspn(s1: *const ::c_char, s2: *const ::c_char, cmp: bool) -> ::size_t {
- let mut s1 = s1 as *const u8;
- let mut s2 = s2 as *const u8;
- // The below logic is effectively ripped from the musl implementation. It
- // works by placing each byte as it's own bit in an array of numbers. Each
- // number can hold up to 8 * mem::size_of::<usize>() bits. We need 256 bits
- // in total, to fit one byte.
- let mut set = BitSet256::new();
- while *s2 != 0 {
- set.insert(*s2 as usize);
- s2 = s2.offset(1);
- }
- let mut i = 0;
- while *s1 != 0 {
- if set.contains(*s1 as usize) != cmp {
- break;
- }
- i += 1;
- s1 = s1.offset(1);
- }
- i
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcspn(s1: *const ::c_char, s2: *const ::c_char) -> ::size_t {
- inner_strspn(s1, s2, false)
- }
- #[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: ::size_t) -> *mut ::c_char {
- let len = strnlen(s1, size);
- // the "+ 1" is to account for the NUL byte
- let buffer = platform::alloc(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 {
- *buffer.add(i) = *s1.add(i);
- }
- *buffer.add(len) = 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 {
- let _ = w.write_str(STR_ERROR[errnum as usize]);
- } else {
- let _ = w.write_fmt(format_args!("Unknown error {}", errnum));
- }
- strerror_buf.as_mut_ptr() as *mut ::c_char
- }
- #[no_mangle]
- pub unsafe extern "C" fn strerror_r(
- errnum: ::c_int,
- buf: *mut ::c_char,
- buflen: ::size_t,
- ) -> ::c_int {
- let msg = strerror(errnum);
- let len = strlen(msg);
- if len >= buflen {
- if buflen != 0 {
- memcpy(buf as *mut ::c_void, msg as *const ::c_void, buflen - 1);
- *buf.add(buflen - 1) = 0;
- }
- return ERANGE as ::c_int;
- }
- memcpy(buf as *mut ::c_void, msg as *const ::c_void, len + 1);
- 0
- }
- #[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: ::size_t) -> ::size_t {
- let mut i = 0;
- while i < size {
- if *s.add(i) == 0 {
- break;
- }
- i += 1;
- }
- i as ::size_t
- }
- #[no_mangle]
- pub unsafe extern "C" fn strnlen_s(s: *const ::c_char, size: ::size_t) -> ::size_t {
- if s.is_null() {
- 0
- } else {
- strnlen(s, size)
- }
- }
- #[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 strncat(
- s1: *mut ::c_char,
- s2: *const ::c_char,
- n: ::size_t,
- ) -> *mut ::c_char {
- let len = strlen(s1 as *const ::c_char);
- let mut i = 0;
- while i < n {
- let b = *s2.add(i);
- if b == 0 {
- break;
- }
- *s1.add(len + i) = b;
- i += 1;
- }
- *s1.add(len + i) = 0;
- s1
- }
- #[no_mangle]
- pub unsafe extern "C" fn strncmp(s1: *const ::c_char, s2: *const ::c_char, n: ::size_t) -> ::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(
- dst: *mut ::c_char,
- src: *const ::c_char,
- n: ::size_t,
- ) -> *mut ::c_char {
- let mut i = 0;
- while *src.add(i) != 0 && i < n {
- *dst.add(i) = *src.add(i);
- i += 1;
- }
- for i in i..n {
- *dst.add(i) = 0;
- }
- dst
- }
- #[no_mangle]
- pub unsafe extern "C" fn strpbrk(s1: *const ::c_char, s2: *const ::c_char) -> *mut ::c_char {
- let p = s1.add(strcspn(s1, s2));
- if *p != 0 {
- p as *mut ::c_char
- } else {
- ptr::null_mut()
- }
- }
- #[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 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 strsignal(sig: ::c_int) -> *const ::c_char {
- signal::_signal_strings
- .get(sig as usize)
- .unwrap_or(&signal::_signal_strings[0]) // Unknown signal message
- .as_ptr() as *const ::c_char
- }
- #[no_mangle]
- pub unsafe extern "C" fn strspn(s1: *const ::c_char, s2: *const ::c_char) -> ::size_t {
- inner_strspn(s1, s2, true)
- }
- unsafe fn inner_strstr(
- mut haystack: *const ::c_char,
- needle: *const ::c_char,
- mask: ::c_char,
- ) -> *mut ::c_char {
- while *haystack != 0 {
- let mut i = 0;
- loop {
- if *needle.offset(i) == 0 {
- // We reached the end of the needle, everything matches this far
- return haystack as *mut ::c_char;
- }
- if *haystack.offset(i) & mask != *needle.offset(i) & mask {
- break;
- }
- i += 1;
- }
- haystack = haystack.offset(1);
- }
- ptr::null_mut()
- }
- #[no_mangle]
- pub unsafe extern "C" fn strstr(
- haystack: *const ::c_char,
- needle: *const ::c_char,
- ) -> *mut ::c_char {
- inner_strstr(haystack, needle, !0)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strcasestr(
- haystack: *const ::c_char,
- needle: *const ::c_char,
- ) -> *mut ::c_char {
- inner_strstr(haystack, needle, !32)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strtok(s1: *mut ::c_char, delimiter: *const ::c_char) -> *mut ::c_char {
- static mut HAYSTACK: *mut ::c_char = ptr::null_mut();
- strtok_r(s1, delimiter, &mut HAYSTACK)
- }
- #[no_mangle]
- pub unsafe extern "C" fn strtok_r(
- s: *mut ::c_char,
- delimiter: *const ::c_char,
- lasts: *mut *mut ::c_char,
- ) -> *mut ::c_char {
- // Loosely based on GLIBC implementation
- let mut haystack = s;
- if haystack.is_null() {
- if (*lasts).is_null() {
- return ptr::null_mut();
- }
- haystack = *lasts;
- }
- // Skip past any extra delimiter left over from previous call
- haystack = haystack.add(strspn(haystack, delimiter));
- if *haystack == 0 {
- *lasts = ptr::null_mut();
- return ptr::null_mut();
- }
- // Build token by injecting null byte into delimiter
- let token = haystack;
- haystack = strpbrk(token, delimiter);
- if !haystack.is_null() {
- haystack.write(0);
- haystack = haystack.add(1);
- *lasts = haystack;
- } else {
- *lasts = ptr::null_mut();
- }
- token
- }
- #[no_mangle]
- pub unsafe extern "C" fn strxfrm(s1: *mut ::c_char, s2: *const ::c_char, n: ::size_t) -> ::size_t {
- // relibc has no locale stuff (yet)
- let len = strlen(s2);
- if len < n {
- strcpy(s1, s2);
- }
- len
- }
- #[no_mangle]
- pub unsafe extern "C" fn strlcpy(
- dst: *mut ::c_char,
- src: *const ::c_char,
- n: ::size_t,
- ) -> ::size_t {
- let mut i = 0;
- while *src.add(i) != 0 && i < n {
- *dst.add(i) = *src.add(i);
- i += 1;
- }
- *dst.add(i) = 0;
- i as ::size_t
- }
- #[no_mangle]
- pub unsafe extern "C" fn strlcat(
- dst: *mut ::c_char,
- src: *const ::c_char,
- n: ::size_t,
- ) -> ::size_t {
- let len = strlen(dst) as isize;
- let d = dst.offset(len);
- strlcpy(d, src, n)
- }
|