diff --git a/README.md b/README.md index 279cd02..0b40c1d 100644 --- a/README.md +++ b/README.md @@ -15,6 +15,7 @@ This crate basically came about so that the [nrfxlib](https://github.com/NordicP * strlen * strtol * strstr +* strchr * snprintf * vsnprintf diff --git a/build.rs b/build.rs index acdf444..e2415ba 100644 --- a/build.rs +++ b/build.rs @@ -1,10 +1,10 @@ use cc; fn main() { - // Build our snprintf substitute (which has to be C as Rust doesn't do varargs) - cc::Build::new() - .warnings(true) - .extra_warnings(true) - .file("./src/snprintf.c") - .compile("clocal"); + // Build our snprintf substitute (which has to be C as Rust doesn't do varargs) + cc::Build::new() + .warnings(true) + .extra_warnings(true) + .file("./src/snprintf.c") + .compile("clocal"); } diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..63ad774 --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +hard_tabs = true + + diff --git a/src/atoi.rs b/src/atoi.rs index 61ded8f..0ab4d55 100644 --- a/src/atoi.rs +++ b/src/atoi.rs @@ -16,12 +16,12 @@ use crate::{strtol, CChar, CInt, CLong}; /// ``` #[no_mangle] pub unsafe extern "C" fn atoi(s: *const CChar) -> CInt { - let result = strtol(s); - if result > CInt::max_value() as CLong { - CInt::max_value() - } else if result < CInt::min_value() as CLong { - CInt::min_value() - } else { - result as CInt - } + let result = strtol(s); + if result > CInt::max_value() as CLong { + CInt::max_value() + } else if result < CInt::min_value() as CLong { + CInt::min_value() + } else { + result as CInt + } } diff --git a/src/itoa.rs b/src/itoa.rs index d173899..ed3dc94 100644 --- a/src/itoa.rs +++ b/src/itoa.rs @@ -17,18 +17,18 @@ use crate::CChar; /// Returns the number of bytes written on success (not including the null), /// or -1 if the buffer wasn't large enough. pub unsafe extern "C" fn itoa(i: i64, s: *mut CChar, s_len: usize, radix: u8) -> i32 { - let (is_negative, pos_i) = if i < 0 { - (true, (-i) as u64) - } else { - (false, i as u64) - }; - - if is_negative && (s_len > 0) { - core::ptr::write(s, b'-'); - utoa(pos_i, s.offset(1), s_len - 1, radix) - } else { - utoa(pos_i, s, s_len, radix) - } + let (is_negative, pos_i) = if i < 0 { + (true, (-i) as u64) + } else { + (false, i as u64) + }; + + if is_negative && (s_len > 0) { + core::ptr::write(s, b'-'); + utoa(pos_i, s.offset(1), s_len - 1, radix) + } else { + utoa(pos_i, s, s_len, radix) + } } #[no_mangle] @@ -40,195 +40,195 @@ pub unsafe extern "C" fn itoa(i: i64, s: *mut CChar, s_len: usize, radix: u8) -> /// Returns the number of bytes written on success (not including the null), /// or -1 if the buffer wasn't large enough. pub unsafe extern "C" fn utoa(mut u: u64, s: *mut CChar, s_len: usize, radix: u8) -> i32 { - let buffer_slice = core::slice::from_raw_parts_mut(s, s_len); - - // Build the number up in buffer s in reverse order - let mut index = 0usize; - for slot in buffer_slice.iter_mut() { - let digit = (u % radix as u64) as u8; - if digit <= 9 { - *slot = digit + b'0'; - } else { - *slot = digit - 10 + b'a'; - } - index += 1; - u /= radix as u64; - if u == 0 { - break; - } - } - - if u != 0 { - return -1; - } - - // Null-terminate - if index < buffer_slice.len() { - buffer_slice[index] = b'\0'; - } - - // Reverse buffer into correct order - buffer_slice[0..index].reverse(); - - index as i32 + let buffer_slice = core::slice::from_raw_parts_mut(s, s_len); + + // Build the number up in buffer s in reverse order + let mut index = 0usize; + for slot in buffer_slice.iter_mut() { + let digit = (u % radix as u64) as u8; + if digit <= 9 { + *slot = digit + b'0'; + } else { + *slot = digit - 10 + b'a'; + } + index += 1; + u /= radix as u64; + if u == 0 { + break; + } + } + + if u != 0 { + return -1; + } + + // Null-terminate + if index < buffer_slice.len() { + buffer_slice[index] = b'\0'; + } + + // Reverse buffer into correct order + buffer_slice[0..index].reverse(); + + index as i32 } #[cfg(test)] mod test { - use super::{itoa, utoa}; - use crate::strcmp::strcmp; - - #[test] - fn zero() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { itoa(0, buf.as_mut_ptr(), buf.len(), 10) }, 1); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"0\0" as *const u8) }, - 0 - ); - } - - #[test] - fn one() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { itoa(1, buf.as_mut_ptr(), buf.len(), 10) }, 1); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"1\0" as *const u8) }, - 0 - ); - } - - #[test] - fn hundredish() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { itoa(123, buf.as_mut_ptr(), buf.len(), 10) }, 3); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"123\0" as *const u8) }, - 0 - ); - } - - #[test] - fn too_small() { - let mut buf = [b'\0'; 1]; - assert_eq!(unsafe { itoa(10, buf.as_mut_ptr(), buf.len(), 10) }, -1); - } - - #[test] - fn hex() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { itoa(0xDEADBEEF, buf.as_mut_ptr(), buf.len(), 16) }, - 8 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"deadbeef\0" as *const u8) }, - 0 - ); - } - - #[test] - fn octal() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { itoa(0o774, buf.as_mut_ptr(), buf.len(), 8) }, 3); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"774\0" as *const u8) }, - 0 - ); - } - - #[test] - fn binary() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { itoa(0b11100010, buf.as_mut_ptr(), buf.len(), 2) }, - 8 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"11100010\0" as *const u8) }, - 0 - ); - } - - #[test] - fn negative() { - let mut buf = [b'\0'; 32]; - unsafe { itoa(-123, buf.as_mut_ptr(), buf.len(), 10) }; - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"-123\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_zero() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { utoa(0, buf.as_mut_ptr(), buf.len(), 10) }, 1); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"0\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_one() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { utoa(1, buf.as_mut_ptr(), buf.len(), 10) }, 1); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"1\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_hundredish() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { utoa(123, buf.as_mut_ptr(), buf.len(), 10) }, 3); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"123\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_too_small() { - let mut buf = [b'\0'; 1]; - assert_eq!(unsafe { utoa(10, buf.as_mut_ptr(), buf.len(), 10) }, -1); - } - - #[test] - fn unsigned_hex() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { utoa(0xDEADBEEF, buf.as_mut_ptr(), buf.len(), 16) }, - 8 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"deadbeef\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_octal() { - let mut buf = [b'\0'; 32]; - assert_eq!(unsafe { utoa(0o774, buf.as_mut_ptr(), buf.len(), 8) }, 3); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"774\0" as *const u8) }, - 0 - ); - } - - #[test] - fn unsigned_binary() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { utoa(0b11100010, buf.as_mut_ptr(), buf.len(), 2) }, - 8 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"11100010\0" as *const u8) }, - 0 - ); - } + use super::{itoa, utoa}; + use crate::strcmp::strcmp; + + #[test] + fn zero() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { itoa(0, buf.as_mut_ptr(), buf.len(), 10) }, 1); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"0\0" as *const u8) }, + 0 + ); + } + + #[test] + fn one() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { itoa(1, buf.as_mut_ptr(), buf.len(), 10) }, 1); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"1\0" as *const u8) }, + 0 + ); + } + + #[test] + fn hundredish() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { itoa(123, buf.as_mut_ptr(), buf.len(), 10) }, 3); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"123\0" as *const u8) }, + 0 + ); + } + + #[test] + fn too_small() { + let mut buf = [b'\0'; 1]; + assert_eq!(unsafe { itoa(10, buf.as_mut_ptr(), buf.len(), 10) }, -1); + } + + #[test] + fn hex() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { itoa(0xDEADBEEF, buf.as_mut_ptr(), buf.len(), 16) }, + 8 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"deadbeef\0" as *const u8) }, + 0 + ); + } + + #[test] + fn octal() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { itoa(0o774, buf.as_mut_ptr(), buf.len(), 8) }, 3); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"774\0" as *const u8) }, + 0 + ); + } + + #[test] + fn binary() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { itoa(0b11100010, buf.as_mut_ptr(), buf.len(), 2) }, + 8 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"11100010\0" as *const u8) }, + 0 + ); + } + + #[test] + fn negative() { + let mut buf = [b'\0'; 32]; + unsafe { itoa(-123, buf.as_mut_ptr(), buf.len(), 10) }; + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"-123\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_zero() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { utoa(0, buf.as_mut_ptr(), buf.len(), 10) }, 1); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"0\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_one() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { utoa(1, buf.as_mut_ptr(), buf.len(), 10) }, 1); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"1\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_hundredish() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { utoa(123, buf.as_mut_ptr(), buf.len(), 10) }, 3); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"123\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_too_small() { + let mut buf = [b'\0'; 1]; + assert_eq!(unsafe { utoa(10, buf.as_mut_ptr(), buf.len(), 10) }, -1); + } + + #[test] + fn unsigned_hex() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { utoa(0xDEADBEEF, buf.as_mut_ptr(), buf.len(), 16) }, + 8 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"deadbeef\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_octal() { + let mut buf = [b'\0'; 32]; + assert_eq!(unsafe { utoa(0o774, buf.as_mut_ptr(), buf.len(), 8) }, 3); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"774\0" as *const u8) }, + 0 + ); + } + + #[test] + fn unsigned_binary() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { utoa(0b11100010, buf.as_mut_ptr(), buf.len(), 2) }, + 8 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"11100010\0" as *const u8) }, + 0 + ); + } } diff --git a/src/lib.rs b/src/lib.rs index ed3999b..81cc946 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,6 +28,9 @@ pub use self::strtol::strtol; mod strstr; pub use self::strstr::strstr; +mod strchr; +pub use self::strchr::strchr; + mod atoi; pub use self::atoi::atoi; @@ -81,27 +84,27 @@ pub type CChar = u8; /// This allows you to iterate a null-terminated string in a relatively simple /// way. pub struct CStringIter { - ptr: *const CChar, - idx: isize, + ptr: *const CChar, + idx: isize, } impl CStringIter { - /// Create a new iterator from a pointer to a null-terminated string. The - /// behaviour is undefined if the string is not null-terminated. - pub fn new(s: *const CChar) -> CStringIter { - CStringIter { ptr: s, idx: 0 } - } + /// Create a new iterator from a pointer to a null-terminated string. The + /// behaviour is undefined if the string is not null-terminated. + pub fn new(s: *const CChar) -> CStringIter { + CStringIter { ptr: s, idx: 0 } + } } impl core::iter::Iterator for CStringIter { - type Item = CChar; - fn next(&mut self) -> Option { - let c = unsafe { *self.ptr.offset(self.idx) }; - if c == 0 { - None - } else { - self.idx += 1; - Some(c) - } - } + type Item = CChar; + fn next(&mut self) -> Option { + let c = unsafe { *self.ptr.offset(self.idx) }; + if c == 0 { + None + } else { + self.idx += 1; + Some(c) + } + } } diff --git a/src/snprintf.rs b/src/snprintf.rs index 7a33f29..4ef3e6e 100644 --- a/src/snprintf.rs +++ b/src/snprintf.rs @@ -5,131 +5,131 @@ #[cfg(test)] mod test { - extern "C" { - fn snprintf(buf: *mut CChar, len: usize, fmt: *const CChar, ...) -> i32; - } + extern "C" { + fn snprintf(buf: *mut CChar, len: usize, fmt: *const CChar, ...) -> i32; + } - use crate::{strcmp::strcmp, CChar}; + use crate::{strcmp::strcmp, CChar}; - #[test] - fn plain_string() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { snprintf(buf.as_mut_ptr(), buf.len(), "Hi\0".as_ptr()) }, - 2 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"Hi\0" as *const u8) }, - 0 - ); - } + #[test] + fn plain_string() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { snprintf(buf.as_mut_ptr(), buf.len(), "Hi\0".as_ptr()) }, + 2 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"Hi\0" as *const u8) }, + 0 + ); + } - #[test] - fn strings() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { - snprintf( - buf.as_mut_ptr(), - buf.len(), - "%s, %s!\0".as_ptr(), - "Hello\0".as_ptr(), - "World\0".as_ptr(), - ) - }, - 13 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"Hello, World!\0" as *const u8) }, - 0 - ); - } + #[test] + fn strings() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { + snprintf( + buf.as_mut_ptr(), + buf.len(), + "%s, %s!\0".as_ptr(), + "Hello\0".as_ptr(), + "World\0".as_ptr(), + ) + }, + 13 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"Hello, World!\0" as *const u8) }, + 0 + ); + } - #[test] - fn size() { - let mut buf = [b'\0'; 32]; - assert_eq!( - unsafe { - snprintf( - buf.as_mut_ptr(), - buf.len(), - "%zx\0".as_ptr(), - 0x1000_0000usize, - ) - }, - 8 - ); - assert_eq!( - unsafe { strcmp(buf.as_ptr() as *const u8, b"10000000\0" as *const u8) }, - 0 - ); - } + #[test] + fn size() { + let mut buf = [b'\0'; 32]; + assert_eq!( + unsafe { + snprintf( + buf.as_mut_ptr(), + buf.len(), + "%zx\0".as_ptr(), + 0x1000_0000usize, + ) + }, + 8 + ); + assert_eq!( + unsafe { strcmp(buf.as_ptr() as *const u8, b"10000000\0" as *const u8) }, + 0 + ); + } - #[test] - #[cfg(feature = "lp64")] - fn numbers() { - let mut buf = [b'\0'; 64]; - assert_eq!( - unsafe { - snprintf( - buf.as_mut_ptr(), - buf.len(), - "%u %lu %llu %d %ld %lld %x %lx %llX\0".as_ptr(), - 100u32, - 100u64, - 100u64, - -100i32, - -100i64, - -100i64, - 0xcafe1234u32, - 0xcafe1234u64, - 0xcafe1234u64, - ) - }, - 53 - ); - assert_eq!( - unsafe { - strcmp( - buf.as_ptr() as *const u8, - b"100 100 100 -100 -100 -100 cafe1234 cafe1234 CAFE1234\0" as *const u8, - ) - }, - 0 - ); - } + #[test] + #[cfg(feature = "lp64")] + fn numbers() { + let mut buf = [b'\0'; 64]; + assert_eq!( + unsafe { + snprintf( + buf.as_mut_ptr(), + buf.len(), + "%u %lu %llu %d %ld %lld %x %lx %llX\0".as_ptr(), + 100u32, + 100u64, + 100u64, + -100i32, + -100i64, + -100i64, + 0xcafe1234u32, + 0xcafe1234u64, + 0xcafe1234u64, + ) + }, + 53 + ); + assert_eq!( + unsafe { + strcmp( + buf.as_ptr() as *const u8, + b"100 100 100 -100 -100 -100 cafe1234 cafe1234 CAFE1234\0" as *const u8, + ) + }, + 0 + ); + } - #[test] - #[cfg(not(feature = "lp64"))] - fn numbers() { - let mut buf = [b'\0'; 64]; - assert_eq!( - unsafe { - snprintf( - buf.as_mut_ptr(), - buf.len(), - "%u %lu %llu %d %ld %lld %x %lx %llX\0".as_ptr(), - 100u32, - 100u32, - 100u64, - -100i32, - -100i32, - -100i64, - 0xcafe1234u32, - 0xcafe1234u64, - 0xcafe1234u64, - ) - }, - 53 - ); - assert_eq!( - unsafe { - strcmp( - buf.as_ptr() as *const u8, - b"100 100 100 -100 -100 -100 cafe1234 cafe1234 CAFE1234\0" as *const u8, - ) - }, - 0 - ); - } + #[test] + #[cfg(not(feature = "lp64"))] + fn numbers() { + let mut buf = [b'\0'; 64]; + assert_eq!( + unsafe { + snprintf( + buf.as_mut_ptr(), + buf.len(), + "%u %lu %llu %d %ld %lld %x %lx %llX\0".as_ptr(), + 100u32, + 100u32, + 100u64, + -100i32, + -100i32, + -100i64, + 0xcafe1234u32, + 0xcafe1234u64, + 0xcafe1234u64, + ) + }, + 53 + ); + assert_eq!( + unsafe { + strcmp( + buf.as_ptr() as *const u8, + b"100 100 100 -100 -100 -100 cafe1234 cafe1234 CAFE1234\0" as *const u8, + ) + }, + 0 + ); + } } diff --git a/src/strchr.rs b/src/strchr.rs new file mode 100644 index 0000000..fc9a3a8 --- /dev/null +++ b/src/strchr.rs @@ -0,0 +1,61 @@ +//! 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 `strchr` +#[no_mangle] +pub unsafe extern "C" fn strchr(haystack: *const CChar, needle: CInt) -> *const CChar { + for idx in 0.. { + let ptr = haystack.offset(idx); + if needle == (*ptr) as i32 { + return ptr; + } + if (*ptr) == 0 { + break; + } + } + core::ptr::null() +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn no_match() { + let haystack = b"haystack\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(); + let result = unsafe { strchr(haystack, 0) }; + assert_eq!(result, unsafe { haystack.offset(8) }); + } + + #[test] + fn start() { + let haystack = b"haystack\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(); + 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(); + let result = unsafe { strchr(haystack, b'k' as CInt) }; + assert_eq!(result, unsafe { haystack.offset(7) }); + } +} diff --git a/src/strcmp.rs b/src/strcmp.rs index adff3c5..bd5c50f 100644 --- a/src/strcmp.rs +++ b/src/strcmp.rs @@ -8,14 +8,14 @@ use crate::{CChar, CInt}; /// Rust implementation of C library function `strcmp` #[no_mangle] pub unsafe extern "C" fn strcmp(s1: *const CChar, s2: *const CChar) -> CInt { - for i in 0.. { - let s1_i = s1.offset(i); - let s2_i = s2.offset(i); + for i in 0.. { + let s1_i = s1.offset(i); + let s2_i = s2.offset(i); - let val = *s1_i as CInt - *s2_i as CInt; - if val != 0 || *s1_i == 0 { - return val; - } - } - 0 + let val = *s1_i as CInt - *s2_i as CInt; + if val != 0 || *s1_i == 0 { + return val; + } + } + 0 } diff --git a/src/strlen.rs b/src/strlen.rs index d86bc3e..fc2683d 100644 --- a/src/strlen.rs +++ b/src/strlen.rs @@ -8,31 +8,30 @@ use crate::CChar; /// Rust implementation of C library function `strlen` #[no_mangle] pub unsafe extern "C" fn strlen(mut s: *const CChar) -> usize { - let mut result = 0; - while *s != 0 { - s = s.offset(1); - result += 1; - } - result + let mut result = 0; + while *s != 0 { + s = s.offset(1); + result += 1; + } + result } #[cfg(test)] mod test { - use super::*; + use super::*; - #[test] - fn test1() { - assert_eq!(unsafe { strlen(b"Hello\0" as *const CChar) }, 5); - } + #[test] + fn test1() { + assert_eq!(unsafe { strlen(b"Hello\0" as *const CChar) }, 5); + } - #[test] - fn test2() { - assert_eq!(unsafe { strlen(b"\0" as *const CChar) }, 0); - } - - #[test] - fn test3() { - assert_eq!(unsafe { strlen(b"X\0" as *const CChar) }, 1); - } + #[test] + fn test2() { + assert_eq!(unsafe { strlen(b"\0" as *const CChar) }, 0); + } + #[test] + fn test3() { + assert_eq!(unsafe { strlen(b"X\0" as *const CChar) }, 1); + } } diff --git a/src/strncmp.rs b/src/strncmp.rs index 5f06d3e..498ab03 100644 --- a/src/strncmp.rs +++ b/src/strncmp.rs @@ -9,46 +9,46 @@ use crate::{CChar, CInt}; /// (core::ptr::null()) gives undefined behaviour. #[no_mangle] pub unsafe extern "C" fn strncmp(s1: *const CChar, s2: *const CChar, n: usize) -> crate::CInt { - for i in 0..n as isize { - let s1_i = s1.offset(i); - let s2_i = s2.offset(i); + for i in 0..n as isize { + let s1_i = s1.offset(i); + let s2_i = s2.offset(i); - let val = *s1_i as CInt - *s2_i as CInt; - if val != 0 || *s1_i == 0 { - return val; - } - } - 0 + let val = *s1_i as CInt - *s2_i as CInt; + if val != 0 || *s1_i == 0 { + return val; + } + } + 0 } #[cfg(test)] mod test { - use super::*; + use super::*; - #[test] - fn matches() { - let a = b"123\0"; - let b = b"1234\0"; - let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; - // Match! - assert_eq!(result, 0); - } + #[test] + fn matches() { + let a = b"123\0"; + let b = b"1234\0"; + let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; + // Match! + assert_eq!(result, 0); + } - #[test] - fn no_match() { - let a = b"123\0"; - let b = b"x1234\0"; - let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; - // No match, first string first - assert!(result < 0); - } + #[test] + fn no_match() { + let a = b"123\0"; + let b = b"x1234\0"; + let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; + // No match, first string first + assert!(result < 0); + } - #[test] - fn no_match2() { - let a = b"bbbbb\0"; - let b = b"aaaaa\0"; - let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; - // No match, second string first - assert!(result > 0); - } + #[test] + fn no_match2() { + let a = b"bbbbb\0"; + let b = b"aaaaa\0"; + let result = unsafe { strncmp(a.as_ptr(), b.as_ptr(), 3) }; + // No match, second string first + assert!(result > 0); + } } diff --git a/src/strstr.rs b/src/strstr.rs index cde15f8..64eb58e 100644 --- a/src/strstr.rs +++ b/src/strstr.rs @@ -8,69 +8,69 @@ use crate::{CChar, CStringIter}; /// Rust implementation of C library function `strstr` #[no_mangle] pub unsafe extern "C" fn strstr(haystack: *const CChar, needle: *const CChar) -> *const CChar { - if *needle.offset(0) == 0 { - return haystack; - } - for haystack_trim in (0..).map(|idx| haystack.offset(idx)) { - if *haystack_trim == 0 { - break; - } - let mut len = 0; - for (inner_idx, nec) in CStringIter::new(needle).enumerate() { - let hsc = *haystack_trim.offset(inner_idx as isize); - if hsc != nec { - break; - } - len += 1; - } - if *needle.offset(len) == 0 { - return haystack_trim; - } - } - core::ptr::null() + if *needle.offset(0) == 0 { + return haystack; + } + for haystack_trim in (0..).map(|idx| haystack.offset(idx)) { + if *haystack_trim == 0 { + break; + } + let mut len = 0; + for (inner_idx, nec) in CStringIter::new(needle).enumerate() { + let hsc = *haystack_trim.offset(inner_idx as isize); + if hsc != nec { + break; + } + len += 1; + } + if *needle.offset(len) == 0 { + return haystack_trim; + } + } + core::ptr::null() } #[cfg(test)] mod test { - use super::*; + use super::*; - #[test] - fn no_match() { - let needle = b"needle\0".as_ptr(); - let haystack = b"haystack\0".as_ptr(); - let result = unsafe { strstr(haystack, needle) }; - assert_eq!(result, core::ptr::null()); - } + #[test] + fn no_match() { + let needle = b"needle\0".as_ptr(); + let haystack = b"haystack\0".as_ptr(); + let result = unsafe { strstr(haystack, needle) }; + assert_eq!(result, core::ptr::null()); + } - #[test] - fn start() { - let needle = b"hay\0".as_ptr(); - let haystack = b"haystack\0".as_ptr(); - let result = unsafe { strstr(haystack, needle) }; - assert_eq!(result, haystack); - } + #[test] + fn start() { + let needle = b"hay\0".as_ptr(); + let haystack = b"haystack\0".as_ptr(); + let result = unsafe { strstr(haystack, needle) }; + assert_eq!(result, haystack); + } - #[test] - fn middle() { - let needle = b"yst\0".as_ptr(); - let haystack = b"haystack\0".as_ptr(); - let result = unsafe { strstr(haystack, needle) }; - assert_eq!(result, unsafe { haystack.offset(2) }); - } + #[test] + fn middle() { + let needle = b"yst\0".as_ptr(); + let haystack = b"haystack\0".as_ptr(); + let result = unsafe { strstr(haystack, needle) }; + assert_eq!(result, unsafe { haystack.offset(2) }); + } - #[test] - fn end() { - let needle = b"stack\0".as_ptr(); - let haystack = b"haystack\0".as_ptr(); - let result = unsafe { strstr(haystack, needle) }; - assert_eq!(result, unsafe { haystack.offset(3) }); - } + #[test] + fn end() { + let needle = b"stack\0".as_ptr(); + let haystack = b"haystack\0".as_ptr(); + let result = unsafe { strstr(haystack, needle) }; + assert_eq!(result, unsafe { haystack.offset(3) }); + } - #[test] - fn partial() { - let needle = b"haystacka\0".as_ptr(); - let haystack = b"haystack\0".as_ptr(); - let result = unsafe { strstr(haystack, needle) }; - assert_eq!(result, core::ptr::null()); - } + #[test] + fn partial() { + let needle = b"haystacka\0".as_ptr(); + let haystack = b"haystack\0".as_ptr(); + let result = unsafe { strstr(haystack, needle) }; + assert_eq!(result, core::ptr::null()); + } } diff --git a/src/strtol.rs b/src/strtol.rs index 746a57d..f3dbf01 100644 --- a/src/strtol.rs +++ b/src/strtol.rs @@ -13,55 +13,55 @@ use crate::{CChar, CLong, CStringIter}; /// function returns zero. #[no_mangle] pub unsafe extern "C" fn strtol(s: *const CChar) -> CLong { - let mut result: CLong = 0; - for c in CStringIter::new(s) { - if c >= b'0' && c <= b'9' { - result *= 10; - result += (c - b'0') as CLong; - } else { - break; - } - } - result + let mut result: CLong = 0; + for c in CStringIter::new(s) { + if c >= b'0' && c <= b'9' { + result *= 10; + result += (c - b'0') as CLong; + } else { + break; + } + } + result } #[cfg(test)] mod test { - use super::strtol; + use super::strtol; - #[test] - fn empty() { - let result = unsafe { strtol(b"\0".as_ptr()) }; - assert_eq!(result, 0); - } + #[test] + fn empty() { + let result = unsafe { strtol(b"\0".as_ptr()) }; + assert_eq!(result, 0); + } - #[test] - fn non_digit() { - let result = unsafe { strtol(b"1234x\0".as_ptr()) }; - assert_eq!(result, 1234); - } + #[test] + fn non_digit() { + let result = unsafe { strtol(b"1234x\0".as_ptr()) }; + assert_eq!(result, 1234); + } - #[test] - fn bad_number() { - let result = unsafe { strtol(b"x\0".as_ptr()) }; - assert_eq!(result, 0); - } + #[test] + fn bad_number() { + let result = unsafe { strtol(b"x\0".as_ptr()) }; + assert_eq!(result, 0); + } - #[test] - fn one() { - let result = unsafe { strtol(b"1\0".as_ptr()) }; - assert_eq!(result, 1); - } + #[test] + fn one() { + let result = unsafe { strtol(b"1\0".as_ptr()) }; + assert_eq!(result, 1); + } - #[test] - fn hundredish() { - let result = unsafe { strtol(b"123\0".as_ptr()) }; - assert_eq!(result, 123); - } + #[test] + fn hundredish() { + let result = unsafe { strtol(b"123\0".as_ptr()) }; + assert_eq!(result, 123); + } - #[test] - fn big_long() { - let result = unsafe { strtol(b"2147483647\0".as_ptr()) }; - assert_eq!(result, 2147483647); - } + #[test] + fn big_long() { + let result = unsafe { strtol(b"2147483647\0".as_ptr()) }; + assert_eq!(result, 2147483647); + } }