Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ authors = ["Jonathan 'theJPster' Pallant <github@thejpster.org.uk>"]
edition = "2021"
description = "Tiny, incomplete C library for bare-metal targets, written in Stable (but Unsafe) Rust"
license-file = "LICENCES.md"
rust-version = "1.77"
readme = "README.md"
repository = "https://github.com/rust-embedded-community/tinyrlibc"

Expand Down
4 changes: 2 additions & 2 deletions src/abs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
//!
//! Licensed under the Blue Oak Model Licence 1.0.0

use crate::CInt;
use core::ffi::c_int;

/// Rust implementation of C library function `abs`
#[cfg_attr(feature = "abs", no_mangle)]
pub extern "C" fn abs(i: CInt) -> CInt {
pub extern "C" fn abs(i: c_int) -> c_int {
i.abs()
}

Expand Down
73 changes: 0 additions & 73 deletions src/ctype.rs

This file was deleted.

111 changes: 36 additions & 75 deletions src/itoa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
//! Copyright (c) Jonathan 'theJPster' Pallant 2019
//! Licensed under the Blue Oak Model Licence 1.0.0

use crate::CChar;
use core::ffi::c_char;

/// Formats the given value `i`, with the given radix, into the given buffer (of the given length).
///
Expand All @@ -17,15 +17,15 @@ use crate::CChar;
/// or -1 if the buffer wasn't large enough.
#[cfg_attr(not(feature = "itoa"), export_name = "tinyrlibc_itoa")]
#[cfg_attr(feature = "itoa", no_mangle)]
pub unsafe extern "C" fn itoa(i: i64, s: *mut CChar, s_len: usize, radix: u8) -> i32 {
pub unsafe extern "C" fn itoa(i: i64, s: *mut c_char, 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'-');
core::ptr::write(s, b'-' as c_char);
utoa(pos_i, s.offset(1), s_len - 1, radix)
} else {
utoa(pos_i, s, s_len, radix)
Expand All @@ -41,17 +41,17 @@ pub unsafe extern "C" fn itoa(i: i64, s: *mut CChar, s_len: usize, radix: u8) ->
/// or -1 if the buffer wasn't large enough.
#[cfg_attr(not(feature = "utoa"), export_name = "tinyrlibc_utoa")]
#[cfg_attr(feature = "utoa", no_mangle)]
pub unsafe extern "C" fn utoa(mut u: u64, s: *mut CChar, s_len: usize, radix: u8) -> i32 {
pub unsafe extern "C" fn utoa(mut u: u64, s: *mut c_char, 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;
let digit = (u % radix as u64) as c_char;
if digit <= 9 {
*slot = digit + b'0';
*slot = digit + (b'0' as c_char);
} else {
*slot = digit - 10 + b'a';
*slot = digit - 10 + (b'a' as c_char);
}
index += 1;
u /= radix as u64;
Expand All @@ -66,7 +66,7 @@ pub unsafe extern "C" fn utoa(mut u: u64, s: *mut CChar, s_len: usize, radix: u8

// Null-terminate
if index < buffer_slice.len() {
buffer_slice[index] = b'\0';
buffer_slice[index] = 0;
}

// Reverse buffer into correct order
Expand All @@ -82,155 +82,116 @@ mod test {

#[test]
fn zero() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"0".as_ptr()) }, 0);
}

#[test]
fn one() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"1".as_ptr()) }, 0);
}

#[test]
fn hundredish() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"123".as_ptr()) }, 0);
}

#[test]
fn too_small() {
let mut buf = [b'\0'; 1];
let mut buf = [0; 1];
assert_eq!(unsafe { itoa(10, buf.as_mut_ptr(), buf.len(), 10) }, -1);
}

#[test]
fn hex() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"deadbeef".as_ptr()) }, 0);
}

#[test]
fn octal() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"774".as_ptr()) }, 0);
}

#[test]
fn binary() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"11100010".as_ptr()) }, 0);
}

#[test]
fn negative() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"-123".as_ptr()) }, 0);
}

#[test]
fn unsigned_zero() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"0".as_ptr()) }, 0);
}

#[test]
fn unsigned_one() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"1".as_ptr()) }, 0);
}

#[test]
fn unsigned_hundredish() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"123".as_ptr()) }, 0);
}

#[test]
fn unsigned_too_small() {
let mut buf = [b'\0'; 1];
let mut buf = [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];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"deadbeef".as_ptr()) }, 0);
}

#[test]
fn unsigned_octal() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"774".as_ptr()) }, 0);
}

#[test]
fn unsigned_binary() {
let mut buf = [b'\0'; 32];
let mut buf = [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
);
assert_eq!(unsafe { strcmp(buf.as_ptr(), c"11100010".as_ptr()) }, 0);
}
}
4 changes: 0 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@
#![allow(clippy::missing_safety_doc)]
#![allow(unused_imports)]

// Useful imports
mod ctype;
pub use self::ctype::*;

// Stateless implementations.
// rustfmt will keep these in alphabetical order.
mod abs;
Expand Down
Loading
Loading