Skip to content

Commit

Permalink
Add strcspn
Browse files Browse the repository at this point in the history
  • Loading branch information
thejpster committed Nov 25, 2024
1 parent 025fa09 commit 2532566
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 0 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ all = [
"strncpy",
"strrchr",
"strspn",
"strcspn",
"strstr",
"strtoimax",
"strtol",
Expand Down Expand Up @@ -78,6 +79,7 @@ strncmp = []
strncpy = []
strrchr = []
strspn = []
strcspn = []
strstr = []
strtoimax = []
strtol = []
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ mod strcat;
mod strchr;
mod strcmp;
mod strcpy;
mod strcspn;
mod strlen;
mod strncasecmp;
mod strncmp;
Expand Down Expand Up @@ -73,6 +74,8 @@ pub use self::strchr::strchr;
pub use self::strcmp::strcmp;
#[cfg(feature = "strcpy")]
pub use self::strcpy::strcpy;
#[cfg(feature = "strcspn")]
pub use self::strcspn::strcspn;
#[cfg(feature = "strlen")]
pub use self::strlen::strlen;
#[cfg(feature = "strncasecmp")]
Expand Down
94 changes: 94 additions & 0 deletions src/strcspn.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//! Rust implementation of C library function `strcspn`
//!
//! Copyright (c) Ferrous Systems UK Ltd
//! Licensed under the Blue Oak Model Licence 1.0.0
use crate::{CChar, CInt};

/// Rust implementation of C library function `strcspn`
#[cfg_attr(feature = "strcspn", no_mangle)]
pub unsafe extern "C" fn strcspn(s: *const CChar, charset: *const CChar) -> usize {
if s.is_null() {
return 0;
}
if charset.is_null() {
return 0;
}

let s = unsafe { core::ffi::CStr::from_ptr(s.cast()) };

let charset = unsafe { core::ffi::CStr::from_ptr(charset.cast()) };

let bytes = s.to_bytes();
for (idx, b) in bytes.iter().enumerate() {
if is_c_in_charset(*b, charset) {
return idx;
}
}

bytes.len()
}

fn is_c_in_charset(c: u8, charset: &core::ffi::CStr) -> bool {
for b in charset.to_bytes() {
if c == *b {
return true;
}
}
false
}

#[cfg(test)]
mod test {
#[test]
fn complete() {
let charset = c"0123456789";
let s = c"abcdef1";
assert_eq!(
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
6
);
}

#[test]
fn subset() {
let charset = c"0123456789";
let s = c"xyz";
assert_eq!(
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
3
);
}

#[test]
fn none() {
let charset = c"0123456789";
let s = c"567";
assert_eq!(
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
0
);
}

#[test]
fn empty_charset() {
let charset = c"";
let s = c"AABBCCDD";
assert_eq!(
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
8
);
}

#[test]
fn empty_string() {
let charset = c"0123456789";
let s = c"";
assert_eq!(
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
0
);
}
}

// End of file

0 comments on commit 2532566

Please sign in to comment.