Refactor strcasecmp, strncasecmp with iterators
This commit is contained in:
committed by
Jeremy Soller
parent
ff853a7b82
commit
b60fb9bace
+27
-18
@@ -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()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user