Merge branch 'imp_str' into 'master'
Add missing functions to `string.h` See merge request redox-os/relibc!592
This commit is contained in:
+76
-23
@@ -52,7 +52,8 @@ 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 {
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn memcmp(s1: *const c_void, s2: *const c_void, n: usize) -> 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;
|
||||
@@ -285,15 +286,44 @@ pub unsafe extern "C" fn memset(s: *mut c_void, c: c_int, n: size_t) -> *mut c_v
|
||||
}
|
||||
|
||||
/// 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!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn stpcpy(mut s1: *mut c_char, mut s2: *const c_char) -> *mut c_char {
|
||||
loop {
|
||||
*s1 = *s2;
|
||||
|
||||
if *s1 == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
s1 = s1.add(1);
|
||||
s2 = s2.add(1);
|
||||
}
|
||||
|
||||
s1
|
||||
}
|
||||
|
||||
/// 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!();
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn stpncpy(
|
||||
mut s1: *mut c_char,
|
||||
mut s2: *const c_char,
|
||||
mut n: size_t,
|
||||
) -> *mut c_char {
|
||||
while n > 0 {
|
||||
*s1 = *s2;
|
||||
|
||||
if *s1 == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
n -= 1;
|
||||
s1 = s1.add(1);
|
||||
s2 = s2.add(1);
|
||||
}
|
||||
|
||||
memset(s1.cast(), 0, n);
|
||||
|
||||
s1
|
||||
}
|
||||
|
||||
/// Non-POSIX, see <https://www.man7.org/linux/man-pages/man3/strstr.3.html>.
|
||||
@@ -330,6 +360,22 @@ pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char {
|
||||
ptr.cast_mut()
|
||||
}
|
||||
|
||||
/// Non-POSIX, see <https://man7.org/linux/man-pages/man3/strchr.3.html>.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
|
||||
let mut s = s.cast_mut();
|
||||
loop {
|
||||
if *s == c as _ {
|
||||
break;
|
||||
}
|
||||
if *s == 0 {
|
||||
break;
|
||||
}
|
||||
s = s.add(1);
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
@@ -443,6 +489,23 @@ pub unsafe extern "C" fn strlcat(dst: *mut c_char, src: *const c_char, n: size_t
|
||||
strlcpy(d, src, n)
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn strsep(str_: *mut *mut c_char, sep: *const c_char) -> *mut c_char {
|
||||
let s = *str_;
|
||||
if s.is_null() {
|
||||
return ptr::null_mut();
|
||||
}
|
||||
let mut end = s.add(strcspn(s, sep));
|
||||
if *end != 0 {
|
||||
*end = 0;
|
||||
end = end.add(1);
|
||||
} else {
|
||||
end = ptr::null_mut();
|
||||
}
|
||||
*str_ = end;
|
||||
s
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
@@ -467,7 +530,7 @@ pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t {
|
||||
/// 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 len = strlen(s1.cast());
|
||||
let mut i = 0;
|
||||
while i < n {
|
||||
let b = *s2.add(i);
|
||||
@@ -486,8 +549,8 @@ pub unsafe extern "C" fn strncat(s1: *mut c_char, s2: *const c_char, n: size_t)
|
||||
/// 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);
|
||||
let s1 = slice::from_raw_parts(s1 as *const c_uchar, n);
|
||||
let s2 = 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);
|
||||
@@ -501,19 +564,9 @@ pub unsafe extern "C" fn strncmp(s1: *const c_char, s2: *const c_char, n: size_t
|
||||
|
||||
/// 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
|
||||
pub unsafe extern "C" fn strncpy(s1: *mut c_char, s2: *const c_char, n: size_t) -> *mut c_char {
|
||||
stpncpy(s1, s2, n);
|
||||
s1
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strdup.html>.
|
||||
|
||||
@@ -80,6 +80,7 @@ EXPECT_NAMES=\
|
||||
string/memmem \
|
||||
string/strcat \
|
||||
string/strchr \
|
||||
string/strchrnul \
|
||||
string/strcpy \
|
||||
string/strcspn \
|
||||
string/strlen \
|
||||
@@ -90,7 +91,10 @@ EXPECT_NAMES=\
|
||||
string/strstr \
|
||||
string/strtok \
|
||||
string/strtok_r \
|
||||
string/strsep \
|
||||
string/strsignal \
|
||||
string/stpcpy \
|
||||
string/stpncpy \
|
||||
strings \
|
||||
sys_mman \
|
||||
time/asctime \
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
void test_stpcpy(const char *src, char *dest) {
|
||||
char *end = stpcpy(dest, src);
|
||||
assert(strcmp(dest, src) == 0);
|
||||
assert(*end == '\0');
|
||||
assert(end == dest + strlen(dest));
|
||||
}
|
||||
|
||||
int main() {
|
||||
char dest[20];
|
||||
|
||||
test_stpcpy("Hello, World!", dest);
|
||||
|
||||
// Test case 2: Empty string
|
||||
test_stpcpy("", dest);
|
||||
|
||||
// Test case 3: String with special characters
|
||||
test_stpcpy("Special chars: !@#$%^&*()", dest);
|
||||
|
||||
// Test case 4: String with spaces
|
||||
test_stpcpy("A string with spaces", dest);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
// Define some test strings
|
||||
const char *src = "Hello, World!";
|
||||
char dest[50];
|
||||
|
||||
// Test 1: Copy exactly 5 characters from src to dest
|
||||
char *result = stpncpy(dest, src, 5);
|
||||
dest[5] = '\0'; // Ensure the destination string is null-terminated
|
||||
assert(strcmp(dest, "Hello") == 0); // Verify the string in dest
|
||||
assert(result == &dest[5]); // Ensure the return pointer points to the null terminator
|
||||
|
||||
// Test 2: Copy 15 characters from src to dest (more than the length of src)
|
||||
result = stpncpy(dest, src, 15);
|
||||
dest[13] = '\0'; // Ensure the destination string is null-terminated
|
||||
assert(strcmp(dest, "Hello, World!") == 0); // Verify the string in dest
|
||||
assert(result == &dest[13]); // Ensure the return pointer points to the null terminator
|
||||
|
||||
// Test 3: Copy 3 characters from src to dest
|
||||
result = stpncpy(dest, src, 3);
|
||||
dest[3] = '\0'; // Ensure the destination string is null-terminated
|
||||
assert(strcmp(dest, "Hel") == 0); // Verify the string in dest
|
||||
assert(result == &dest[3]); // Ensure the return pointer points to the null terminator
|
||||
|
||||
// Test 4: Copy 0 characters from src to dest
|
||||
result = stpncpy(dest, src, 0);
|
||||
dest[0] = '\0'; // Ensure the destination is explicitly null-terminated
|
||||
assert(dest[0] == '\0'); // Ensure the destination is an empty string
|
||||
assert(result == dest); // Ensure the return pointer points to the start of dest
|
||||
|
||||
// Test 5: Copy exactly the length of the source string
|
||||
result = stpncpy(dest, src, strlen(src));
|
||||
dest[strlen(src)] = '\0'; // Ensure the destination string is null-terminated
|
||||
assert(strcmp(dest, "Hello, World!") == 0); // Verify the string in dest
|
||||
assert(result == &dest[strlen(src)]); // Ensure the return pointer points to the null terminator
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
int main() {
|
||||
// Test 1: Character is present in the string
|
||||
const char *str1 = "Hello, World!";
|
||||
const char *result1 = strchrnul(str1, 'o');
|
||||
assert(result1 == &str1[4]); // 'o' is at position 4 in "Hello, World!"
|
||||
|
||||
// Test 2: Character is not in the string (should return the null terminator)
|
||||
const char *str2 = "Hello, World!";
|
||||
const char *result2 = strchrnul(str2, 'z');
|
||||
assert(result2 == &str2[13]); // 'z' is not present, so it returns the null terminator
|
||||
|
||||
// Test 3: Character is the first character in the string
|
||||
const char *str3 = "abcdef";
|
||||
const char *result3 = strchrnul(str3, 'a');
|
||||
assert(result3 == &str3[0]); // 'a' is at position 0
|
||||
|
||||
// Test 4: Character is the last character in the string
|
||||
const char *str4 = "abcdef";
|
||||
const char *result4 = strchrnul(str4, 'f');
|
||||
assert(result4 == &str4[5]); // 'f' is at position 5, the last character
|
||||
|
||||
// Test 5: Searching for the null terminator itself
|
||||
const char *str5 = "abcdef";
|
||||
const char *result5 = strchrnul(str5, '\0');
|
||||
assert(result5 == &str5[6]); // The null terminator is at position 6 (end of the string)
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
int main() {
|
||||
// Test case 1: Basic case with multiple tokens
|
||||
char str1[] = "apple,orange,banana";
|
||||
char *delim = ",";
|
||||
char *token = str1;
|
||||
char *result = NULL;
|
||||
|
||||
// First token should be "apple"
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "apple") == 0);
|
||||
|
||||
// Second token should be "orange"
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "orange") == 0);
|
||||
|
||||
// Third token should be "banana"
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "banana") == 0);
|
||||
|
||||
// No more tokens
|
||||
result = strsep(&token, delim);
|
||||
assert(result == NULL);
|
||||
|
||||
// Test case 2: Empty string
|
||||
char str2[] = "";
|
||||
token = str2;
|
||||
result = strsep(&token, delim);
|
||||
|
||||
// Test case 3: String with no delimiter
|
||||
char str3[] = "apple";
|
||||
token = str3;
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "apple") == 0);
|
||||
assert(token == NULL); // No more tokens
|
||||
|
||||
// Test case 4: String starts with delimiter
|
||||
char str4[] = ",apple,orange";
|
||||
token = str4;
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strlen(result) == 0); // First token should be an empty string ("")
|
||||
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "apple") == 0);
|
||||
|
||||
// Test case 5: Multiple delimiters in a row
|
||||
char str5[] = "apple,,orange";
|
||||
token = str5;
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "apple") == 0);
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strlen(result) == 0); // Empty token due to consecutive delimiters
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "orange") == 0);
|
||||
|
||||
// Test case 6: Delimiters at the end of the string
|
||||
char str6[] = "apple,orange,";
|
||||
token = str6;
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "apple") == 0);
|
||||
result = strsep(&token, delim);
|
||||
assert(result != NULL && strcmp(result, "orange") == 0);
|
||||
result = strsep(&token, delim);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user