Add docs for string.h, add missing functions
This commit is contained in:
committed by
Jeremy Soller
parent
46c2d36193
commit
2a7d01f02d
+174
-120
@@ -1,4 +1,6 @@
|
||||
//! string implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/string.h.html
|
||||
//! `string.h` implementation.
|
||||
//!
|
||||
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/string.h.html>.
|
||||
|
||||
use core::{iter::once, mem, ptr, slice, usize};
|
||||
|
||||
@@ -10,6 +12,7 @@ use crate::{
|
||||
platform::{self, types::*},
|
||||
};
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memccpy.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memccpy(
|
||||
dest: *mut c_void,
|
||||
@@ -28,6 +31,7 @@ pub unsafe extern "C" fn memccpy(
|
||||
(dest as *mut u8).add(dist + 1) as *mut c_void
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memchr.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memchr(
|
||||
haystack: *const c_void,
|
||||
@@ -42,6 +46,7 @@ pub unsafe extern "C" fn memchr(
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memcmp.html>.
|
||||
#[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>());
|
||||
@@ -74,6 +79,7 @@ pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: size_t)
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memcpy.html>.
|
||||
#[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;
|
||||
@@ -125,6 +131,7 @@ pub unsafe extern "C" fn memmem(
|
||||
.cast_mut()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memmove.html>.
|
||||
#[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 {
|
||||
@@ -145,6 +152,7 @@ pub unsafe extern "C" fn memmove(s1: *mut c_void, s2: *const c_void, n: size_t)
|
||||
s1
|
||||
}
|
||||
|
||||
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/memchr.3.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memrchr(
|
||||
haystack: *const c_void,
|
||||
@@ -159,6 +167,7 @@ pub unsafe extern "C" fn memrchr(
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/memset.html>.
|
||||
#[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 {
|
||||
@@ -167,7 +176,31 @@ pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: size_t) -> *mut c_v
|
||||
s
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/7908799/xsh/strchr.html>.
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcpy.html>.
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn stpcpy(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncpy.html>.
|
||||
// #[no_mangle]
|
||||
pub extern "C" fn stpncpy(s1: *mut c_char, s2: *const c_char, n: size_t) -> *mut c_char {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/strstr.3.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcasestr(haystack: *const c_char, needle: *const c_char) -> *mut c_char {
|
||||
inner_strstr(haystack, needle, !32)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcat.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcat(s1: *mut c_char, s2: *const c_char) -> *mut c_char {
|
||||
strncat(s1, s2, usize::MAX)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strchr.html>.
|
||||
///
|
||||
/// # Safety
|
||||
/// The caller is required to ensure that `s` is a valid pointer to a buffer
|
||||
@@ -189,17 +222,22 @@ pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
|
||||
ptr.cast_mut()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcmp.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcmp(s1: *const c_char, s2: *const c_char) -> c_int {
|
||||
strncmp(s1, s2, usize::MAX)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcoll.html>.
|
||||
#[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)
|
||||
}
|
||||
|
||||
// TODO: strcoll_l
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcpy.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char {
|
||||
let src_iter = unsafe { NulTerminated::new(src) };
|
||||
@@ -238,16 +276,139 @@ pub unsafe fn inner_strspn(s1: *const c_char, s2: *const c_char, cmp: bool) -> s
|
||||
i
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcspn.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strcspn(s1: *const c_char, s2: *const c_char) -> size_t {
|
||||
inner_strspn(s1, s2, false)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strdup.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strdup(s1: *const c_char) -> *mut c_char {
|
||||
strndup(s1, usize::MAX)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strerror.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
// TODO: strerror_l
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strerror.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strlcat.html>.
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strlcat.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strlen.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t {
|
||||
unsafe { NulTerminated::new(s) }.count()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncat.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncmp.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strncpy.html>.
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strdup.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strndup(s1: *const c_char, size: size_t) -> *mut c_char {
|
||||
let len = strnlen(s1, size);
|
||||
@@ -267,50 +428,13 @@ pub unsafe extern "C" fn strndup(s1: *const c_char, size: size_t) -> *mut c_char
|
||||
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 {
|
||||
unsafe { NulTerminated::new(s) }.count()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strlen.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strnlen(s: *const c_char, size: size_t) -> size_t {
|
||||
unsafe { NulTerminated::new(s) }.take(size).count()
|
||||
}
|
||||
|
||||
/// Non-POSIX, see <https://en.cppreference.com/w/c/string/byte/strlen>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strnlen_s(s: *const c_char, size: size_t) -> size_t {
|
||||
if s.is_null() {
|
||||
@@ -320,60 +444,7 @@ pub unsafe extern "C" fn strnlen_s(s: *const c_char, size: size_t) -> size_t {
|
||||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strpbrk.html>.
|
||||
#[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));
|
||||
@@ -384,6 +455,7 @@ pub unsafe extern "C" fn strpbrk(s1: *const c_char, s2: *const c_char) -> *mut c
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strrchr.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char {
|
||||
let len = strlen(s) as isize;
|
||||
@@ -398,6 +470,7 @@ pub unsafe extern "C" fn strrchr(s: *const c_char, c: c_int) -> *mut c_char {
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strsignal.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strsignal(sig: c_int) -> *mut c_char {
|
||||
signal::SIGNAL_STRINGS
|
||||
@@ -406,6 +479,7 @@ pub unsafe extern "C" fn strsignal(sig: c_int) -> *mut c_char {
|
||||
.as_ptr() as *mut c_char
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strspn.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strspn(s1: *const c_char, s2: *const c_char) -> size_t {
|
||||
inner_strspn(s1, s2, true)
|
||||
@@ -435,21 +509,20 @@ unsafe fn inner_strstr(
|
||||
ptr::null_mut()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strstr.html>.
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtok.html>.
|
||||
#[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)
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtok.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strtok_r(
|
||||
s: *mut c_char,
|
||||
@@ -486,6 +559,7 @@ pub unsafe extern "C" fn strtok_r(
|
||||
token
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strxfrm.html>.
|
||||
#[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)
|
||||
@@ -496,24 +570,4 @@ pub unsafe extern "C" fn strxfrm(s1: *mut c_char, s2: *const c_char, n: size_t)
|
||||
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)
|
||||
}
|
||||
// TODO: strxfrm_l
|
||||
|
||||
Reference in New Issue
Block a user