Skip to content

Commit

Permalink
Merge pull request #28 from rafaelbeckel/master
Browse files Browse the repository at this point in the history
implements strcat and strrchr
  • Loading branch information
thejpster authored Aug 26, 2024
2 parents b7b0bb0 + 6551c48 commit d13967b
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 12 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ all = [
"strncmp",
"strncasecmp",
"strcpy",
"strcat",
"strncpy",
"strlen",
"strtol",
Expand All @@ -35,6 +36,7 @@ all = [
"strtoumax",
"strstr",
"strchr",
"strrchr",
"atoi",
"utoa",
"itoa",
Expand All @@ -51,6 +53,7 @@ strcmp = []
strncmp = []
strncasecmp = []
strcpy = []
strcat = []
strncpy = []
strlen = []
strtol = []
Expand All @@ -61,6 +64,7 @@ strtoimax = []
strtoumax = []
strstr = []
strchr = []
strrchr = []
atoi = []
utoa = []
itoa = []
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ This crate basically came about so that the [nrfxlib](https://github.com/NordicP
* strcmp
* strncmp
* strncasecmp
* strcat
* strcpy
* strncpy
* strlen
Expand All @@ -30,6 +31,7 @@ This crate basically came about so that the [nrfxlib](https://github.com/NordicP
* strtoumax
* strstr
* strchr
* strrchr
* snprintf
* vsnprintf
* qsort
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ mod strlen;
#[cfg(feature = "strlen")]
pub use self::strlen::strlen;

mod strcat;
#[cfg(feature = "strcat")]
pub use self::strcat::strcat;

mod strtol;
#[cfg(feature = "atoi")]
pub use self::strtol::atoi;
Expand Down Expand Up @@ -82,6 +86,10 @@ mod strchr;
#[cfg(feature = "strchr")]
pub use self::strchr::strchr;

mod strrchr;
#[cfg(feature = "strrchr")]
pub use self::strrchr::strrchr;

mod qsort;
#[cfg(feature = "qsort")]
pub use self::qsort::qsort;
Expand Down
29 changes: 29 additions & 0 deletions src/strcat.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//! Rust implementation of C library function `strcat`
//!
//! Licensed under the Blue Oak Model Licence 1.0.0
use crate::CChar;

/// Rust implementation of C library function `strcat`. Passing NULL
/// (core::ptr::null()) gives undefined behaviour.
#[cfg_attr(feature = "strcat", no_mangle)]
pub unsafe extern "C" fn strcat(dest: *mut CChar, src: *const CChar) -> *const CChar {
crate::strcpy::strcpy(dest.add(crate::strlen::strlen(dest)), src);
dest
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn simple() {
let mut dest = *b"hello\0\0\0\0\0\0\0\0";
let src = *b" world\0";
let result = unsafe { strcat(dest.as_mut_ptr(), src.as_ptr()) };
assert_eq!(
unsafe { core::slice::from_raw_parts(result, 12) },
b"hello world\0"
);
}
}
24 changes: 12 additions & 12 deletions src/strchr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,37 +25,37 @@ mod test {
use super::*;

#[test]
fn no_match() {
let haystack = b"haystack\0".as_ptr();
fn strchr_no_match() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strchr(haystack, b'X' as CInt) };
assert_eq!(result, core::ptr::null());
}

#[test]
fn null() {
let haystack = b"haystack\0".as_ptr();
fn strchr_null() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strchr(haystack, 0) };
assert_eq!(result, unsafe { haystack.offset(8) });
assert_eq!(result, unsafe { haystack.offset(10) });
}

#[test]
fn start() {
let haystack = b"haystack\0".as_ptr();
fn strchr_start() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strchr(haystack, b'h' as CInt) };
assert_eq!(result, haystack);
}

#[test]
fn middle() {
let haystack = b"haystack\0".as_ptr();
fn strchr_middle() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strchr(haystack, b'y' as CInt) };
assert_eq!(result, unsafe { haystack.offset(2) });
}

#[test]
fn end() {
let haystack = b"haystack\0".as_ptr();
fn strchr_end() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strchr(haystack, b'k' as CInt) };
assert_eq!(result, unsafe { haystack.offset(7) });
assert_eq!(result, unsafe { haystack.offset(9) });
}
}
62 changes: 62 additions & 0 deletions src/strrchr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//! Rust implementation of C library function `strchr`
//!
//! Copyright (c) 42 Technology Ltd
//! Licensed under the Blue Oak Model Licence 1.0.0
use crate::{CChar, CInt};

/// Rust implementation of C library function `strrchr`
#[cfg_attr(feature = "strrchr", no_mangle)]
pub unsafe extern "C" fn strrchr(haystack: *const CChar, needle: CInt) -> *const CChar {
let mut last = core::ptr::null();
for idx in 0.. {
let ptr = haystack.offset(idx);
if needle == (*ptr) as CInt {
last = ptr;
}
if (*ptr) == 0 {
break;
}
}
last
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn strrchr_no_match() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strrchr(haystack, b'X' as CInt) };
assert_eq!(result, core::ptr::null());
}

#[test]
fn strrchr_null() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strrchr(haystack, 0) };
assert_eq!(result, unsafe { haystack.offset(10) });
}

#[test]
fn strrchr_start() {
let haystack = b"hayhay\0".as_ptr();
let result = unsafe { strrchr(haystack, b'h' as CInt) };
assert_eq!(result, unsafe { haystack.offset(3) });
}

#[test]
fn strrchr_middle() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strrchr(haystack, b'y' as CInt) };
assert_eq!(result, unsafe { haystack.offset(4) });
}

#[test]
fn strrchr_end() {
let haystack = b"hayyystack\0".as_ptr();
let result = unsafe { strrchr(haystack, b'k' as CInt) };
assert_eq!(result, unsafe { haystack.offset(9) });
}
}

0 comments on commit d13967b

Please sign in to comment.