Refactor strcasecmp, strncasecmp with iterators

This commit is contained in:
Peter Limkilde Svendsen
2024-10-15 18:10:52 +00:00
committed by Jeremy Soller
parent ff853a7b82
commit b60fb9bace
+27 -18
View File
@@ -1,9 +1,14 @@
//! strings implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/strings.h.html
use core::{arch, ptr};
use core::{
arch,
iter::{once, zip},
ptr,
};
use crate::{
header::{ctype, string},
iter::NulTerminated,
platform::types::*,
};
@@ -49,25 +54,29 @@ pub unsafe extern "C" fn rindex(s: *const c_char, c: c_int) -> *mut c_char {
}
#[no_mangle]
pub unsafe extern "C" fn strcasecmp(first: *const c_char, second: *const c_char) -> c_int {
strncasecmp(first, second, size_t::max_value())
pub unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int {
// SAFETY: the caller must ensure that s1 and s2 point to nul-terminated buffers.
let s1_iter = unsafe { NulTerminated::new(s1) }.chain(once(&0));
let s2_iter = unsafe { NulTerminated::new(s2) }.chain(once(&0));
let zipped = zip(s1_iter, s2_iter);
inner_casecmp(zipped)
}
#[no_mangle]
pub unsafe extern "C" fn strncasecmp(
mut first: *const c_char,
mut second: *const c_char,
mut n: size_t,
) -> c_int {
while n > 0 && (*first != 0 || *second != 0) {
let cmp = ctype::tolower(*first as c_int) - ctype::tolower(*second as c_int);
if cmp != 0 {
return cmp;
}
pub unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int {
// SAFETY: the caller must ensure that s1 and s2 point to nul-terminated buffers.
let s1_iter = unsafe { NulTerminated::new(s1) }.chain(once(&0));
let s2_iter = unsafe { NulTerminated::new(s2) }.chain(once(&0));
first = first.offset(1);
second = second.offset(1);
n -= 1;
}
0
let zipped = zip(s1_iter, s2_iter).take(n);
inner_casecmp(zipped)
}
/// Given two zipped `&c_char` iterators, either find the first comparison != 0, or return 0.
fn inner_casecmp<'a>(iterator: impl Iterator<Item = (&'a c_char, &'a c_char)>) -> c_int {
let mut cmp_iter =
iterator.map(|(&c1, &c2)| ctype::tolower(c1.into()) - ctype::tolower(c2.into()));
let mut skip_iter = cmp_iter.skip_while(|&cmp| cmp == 0);
skip_iter.next().or(Some(0)).unwrap()
}