Skip to content
Snippets Groups Projects
Commit b60fb9ba authored by Peter Limkilde Svendsen's avatar Peter Limkilde Svendsen Committed by Jeremy Soller
Browse files

Refactor strcasecmp, strncasecmp with iterators

parent ff853a7b
No related branches found
No related tags found
1 merge request!524Refactor strcasecmp, strncasecmp with iterators
//! strings implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/strings.h.html //! 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::{ use crate::{
header::{ctype, string}, header::{ctype, string},
iter::NulTerminated,
platform::types::*, platform::types::*,
}; };
...@@ -49,25 +54,29 @@ pub unsafe extern "C" fn rindex(s: *const c_char, c: c_int) -> *mut c_char { ...@@ -49,25 +54,29 @@ pub unsafe extern "C" fn rindex(s: *const c_char, c: c_int) -> *mut c_char {
} }
#[no_mangle] #[no_mangle]
pub unsafe extern "C" fn strcasecmp(first: *const c_char, second: *const c_char) -> c_int { pub unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int {
strncasecmp(first, second, size_t::max_value()) // 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] #[no_mangle]
pub unsafe extern "C" fn strncasecmp( pub unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: size_t) -> c_int {
mut first: *const c_char, // SAFETY: the caller must ensure that s1 and s2 point to nul-terminated buffers.
mut second: *const c_char, let s1_iter = unsafe { NulTerminated::new(s1) }.chain(once(&0));
mut n: size_t, let s2_iter = unsafe { NulTerminated::new(s2) }.chain(once(&0));
) -> 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;
}
first = first.offset(1); let zipped = zip(s1_iter, s2_iter).take(n);
second = second.offset(1); inner_casecmp(zipped)
n -= 1; }
}
0 /// 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()
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment