Skip to content

Commit d356185

Browse files
authored
Add strtoul, strcpy (#7)
* add strtoul * add strcpy * update changelog
1 parent d3e68ad commit d356185

File tree

5 files changed

+130
-0
lines changed

5 files changed

+130
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
* [#7] - Add `strtoul` and `strcpy`
6+
7+
[#7]: https://github.com/rust-embedded-community/tinyrlibc/pull/7
8+
39
## v0.2.2 (2022-03-17)
410

511
* [#5] - Swap `i32` to `CInt` in `strchr`.

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ This crate basically came about so that the [nrfxlib](https://github.com/NordicP
1212
* atoi
1313
* strcmp
1414
* strncmp
15+
* strcpy
1516
* strncpy
1617
* strlen
1718
* strtol
19+
* strtoul
1820
* strstr
1921
* strchr
2022
* snprintf

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub use self::strcmp::strcmp;
1919
mod strncmp;
2020
pub use self::strncmp::strncmp;
2121

22+
mod strcpy;
23+
pub use self::strcpy::strcpy;
24+
2225
mod strncpy;
2326
pub use self::strncpy::strncpy;
2427

@@ -28,6 +31,9 @@ pub use self::strlen::strlen;
2831
mod strtol;
2932
pub use self::strtol::strtol;
3033

34+
mod strtoul;
35+
pub use self::strtoul::strtoul;
36+
3137
mod strstr;
3238
pub use self::strstr::strstr;
3339

src/strcpy.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//! Rust implementation of C library function `strcpy`
2+
//!
3+
//! Licensed under the Blue Oak Model Licence 1.0.0
4+
5+
use crate::CChar;
6+
7+
/// Rust implementation of C library function `strcpy`. Passing NULL
8+
/// (core::ptr::null()) gives undefined behaviour.
9+
#[no_mangle]
10+
pub unsafe extern "C" fn strcpy(
11+
dest: *mut CChar,
12+
src: *const CChar,
13+
) -> *const CChar {
14+
let mut i = 0;
15+
loop {
16+
*dest.offset(i) = *src.offset(i);
17+
let c = *dest.offset(i);
18+
if c == 0 {
19+
break;
20+
}
21+
i += 1;
22+
}
23+
dest
24+
}
25+
26+
#[cfg(test)]
27+
mod test {
28+
use super::*;
29+
30+
#[test]
31+
fn short() {
32+
let src = b"hi\0";
33+
let mut dest = *b"abcdef"; // no null terminator
34+
let result = unsafe { strcpy(dest.as_mut_ptr(), src.as_ptr()) };
35+
assert_eq!(
36+
unsafe { core::slice::from_raw_parts(result, 5) },
37+
*b"hi\0de"
38+
);
39+
}
40+
41+
#[test]
42+
fn two() {
43+
let src = b"hi\0";
44+
let mut dest = [0u8; 2]; // no space for null terminator
45+
let result = unsafe { strcpy(dest.as_mut_ptr(), src.as_ptr()) };
46+
assert_eq!(unsafe { core::slice::from_raw_parts(result, 2) }, b"hi");
47+
}
48+
}

src/strtoul.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//! Rust implementation of C library function `strtoul`
2+
//!
3+
//! Copyright (c) Jonathan 'theJPster' Pallant 2019
4+
//! Licensed under the Blue Oak Model Licence 1.0.0
5+
6+
use crate::{CChar, CULong, CStringIter};
7+
8+
/// Rust implementation of C library function `strtoul`.
9+
///
10+
/// Takes a null-terminated string and interprets it as a decimal integer.
11+
/// This integer is returned as a `CULong`. Parsing stops when the first
12+
/// non-digit ASCII byte is seen. If no valid ASCII digit bytes are seen, this
13+
/// function returns zero.
14+
#[no_mangle]
15+
pub unsafe extern "C" fn strtoul(s: *const CChar) -> CULong {
16+
let mut result: CULong = 0;
17+
for c in CStringIter::new(s) {
18+
if c >= b'0' && c <= b'9' {
19+
result *= 10;
20+
result += (c - b'0') as CULong;
21+
} else {
22+
break;
23+
}
24+
}
25+
result
26+
}
27+
28+
#[cfg(test)]
29+
mod test {
30+
use super::strtoul;
31+
32+
#[test]
33+
fn empty() {
34+
let result = unsafe { strtoul(b"\0".as_ptr()) };
35+
assert_eq!(result, 0);
36+
}
37+
38+
#[test]
39+
fn non_digit() {
40+
let result = unsafe { strtoul(b"1234x\0".as_ptr()) };
41+
assert_eq!(result, 1234);
42+
}
43+
44+
#[test]
45+
fn bad_number() {
46+
let result = unsafe { strtoul(b"x\0".as_ptr()) };
47+
assert_eq!(result, 0);
48+
}
49+
50+
#[test]
51+
fn one() {
52+
let result = unsafe { strtoul(b"1\0".as_ptr()) };
53+
assert_eq!(result, 1);
54+
}
55+
56+
#[test]
57+
fn hundredish() {
58+
let result = unsafe { strtoul(b"123\0".as_ptr()) };
59+
assert_eq!(result, 123);
60+
}
61+
62+
#[test]
63+
fn big_long() {
64+
let result = unsafe { strtoul(b"2147483647\0".as_ptr()) };
65+
assert_eq!(result, 2147483647);
66+
}
67+
68+
}

0 commit comments

Comments
 (0)