Skip to content

Commit cc0717f

Browse files
committed
Add strcspn
1 parent 025fa09 commit cc0717f

3 files changed

Lines changed: 99 additions & 0 deletions

File tree

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ all = [
4242
"strncpy",
4343
"strrchr",
4444
"strspn",
45+
"strcspn",
4546
"strstr",
4647
"strtoimax",
4748
"strtol",
@@ -78,6 +79,7 @@ strncmp = []
7879
strncpy = []
7980
strrchr = []
8081
strspn = []
82+
strcspn = []
8183
strstr = []
8284
strtoimax = []
8385
strtol = []

src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ mod strcat;
2727
mod strchr;
2828
mod strcmp;
2929
mod strcpy;
30+
mod strcspn;
3031
mod strlen;
3132
mod strncasecmp;
3233
mod strncmp;
@@ -73,6 +74,8 @@ pub use self::strchr::strchr;
7374
pub use self::strcmp::strcmp;
7475
#[cfg(feature = "strcpy")]
7576
pub use self::strcpy::strcpy;
77+
#[cfg(feature = "strcspn")]
78+
pub use self::strcspn::strcspn;
7679
#[cfg(feature = "strlen")]
7780
pub use self::strlen::strlen;
7881
#[cfg(feature = "strncasecmp")]

src/strcspn.rs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//! Rust implementation of C library function `strcspn`
2+
//!
3+
//! Copyright (c) Ferrous Systems UK Ltd
4+
//! Licensed under the Blue Oak Model Licence 1.0.0
5+
6+
use crate::{CChar, CInt};
7+
8+
/// Rust implementation of C library function `strcspn`
9+
#[cfg_attr(feature = "strcspn", no_mangle)]
10+
pub unsafe extern "C" fn strcspn(s: *const CChar, charset: *const CChar) -> usize {
11+
if s.is_null() {
12+
return 0;
13+
}
14+
if charset.is_null() {
15+
return 0;
16+
}
17+
18+
let s = unsafe { core::ffi::CStr::from_ptr(s.cast()) };
19+
20+
let charset = unsafe { core::ffi::CStr::from_ptr(charset.cast()) };
21+
22+
let bytes = s.to_bytes();
23+
for (idx, b) in bytes.iter().enumerate() {
24+
if is_c_in_charset(*b, charset) {
25+
return idx;
26+
}
27+
}
28+
29+
bytes.len()
30+
}
31+
32+
fn is_c_in_charset(c: u8, charset: &core::ffi::CStr) -> bool {
33+
for b in charset.to_bytes() {
34+
if c == *b {
35+
return true;
36+
}
37+
}
38+
false
39+
}
40+
41+
#[cfg(test)]
42+
mod test {
43+
#[test]
44+
fn complete() {
45+
let charset = c"0123456789";
46+
let s = c"abcdef";
47+
assert_eq!(
48+
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
49+
6
50+
);
51+
}
52+
53+
#[test]
54+
fn subset() {
55+
let charset = c"0123456789";
56+
let s = c"xyz1";
57+
assert_eq!(
58+
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
59+
3
60+
);
61+
}
62+
63+
#[test]
64+
fn none() {
65+
let charset = c"0123456789";
66+
let s = c"567";
67+
assert_eq!(
68+
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
69+
0
70+
);
71+
}
72+
73+
#[test]
74+
fn empty_charset() {
75+
let charset = c"";
76+
let s = c"AABBCCDD";
77+
assert_eq!(
78+
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
79+
8
80+
);
81+
}
82+
83+
#[test]
84+
fn empty_string() {
85+
let charset = c"0123456789";
86+
let s = c"";
87+
assert_eq!(
88+
unsafe { super::strcspn(s.as_ptr().cast(), charset.as_ptr().cast()) },
89+
0
90+
);
91+
}
92+
}
93+
94+
// End of file

0 commit comments

Comments
 (0)