1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
//! Subset of C standard library. //! //! This module implements some functions from libc. Thus it eases linking Drone //! applications with C libraries. //! //! Dynamic memory functions (e.g. `malloc`, `free`) are implemented in terms of //! [Drone Heap](crate::heap). use crate::ffi::{c_char, c_int}; use ::alloc::alloc; use core::{alloc::Layout, ffi::c_void, ptr}; /// A type able to represent the size of any object in bytes. #[allow(non_camel_case_types)] pub type size_t = usize; /// Calculates the length of the string `s`, excluding the terminating null byte /// (`'\0'`). /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn strlen(s: *const c_char) -> size_t { let mut cursor = s; while *cursor != 0 { cursor = cursor.add(1); } (cursor as size_t) - (s as size_t) } /// Returns a pointer to the first occurrence of the character `c` in the string /// `s`. /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn strchr(mut s: *const c_char, c: c_int) -> *mut c_char { loop { match *s { x if x == c as c_char => return s as *mut _, 0 => return ptr::null_mut(), _ => s = s.add(1), } } } /// Compares the two strings `s1` and `s2`. It returns an integer less than, /// equal to, or greater than zero if `s1` is found, respectively, to be less /// than, to match, or be greater than `s2`. /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn strcmp(mut s1: *const c_char, mut s2: *const c_char) -> c_int { while *s1 != 0 && *s1 == *s2 { s1 = s1.add(1); s2 = s2.add(1); } c_int::from(*s1) - c_int::from(*s2) } /// Allocates size bytes and returns a pointer to the allocated memory. *The /// memory is not initialized*. If `size` is `0`, then it returns either `NULL`, /// or a unique pointer value that can later be successfully passed to /// [`free`](free). /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn malloc(size: size_t) -> *mut c_void { alloc::alloc(Layout::from_size_align_unchecked(size, 1)) as *mut c_void } /// Allocates memory for an array of `nmemb` elements of `size` bytes each and /// returns a pointer to the allocated memory. The memory is set to zero. If /// `nmemb` or `size` is 0, then it returns either `NULL`, or a unique pointer /// value that can later be successfully passed to [`free`](free). /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn calloc(nmemb: size_t, size: size_t) -> *mut c_void { alloc::alloc_zeroed(Layout::from_size_align_unchecked(nmemb * size, 1)) as *mut c_void } /// Changes the size of the memory block pointed to by `ptr` to `size` bytes. /// The contents will be unchanged in the range from the start of the region up /// to the minimum of the old and new sizes. If the new size is larger than the /// old size, the added memory will not be initialized. If `ptr` is `NULL`, then /// the call is equivalent to `malloc(size)`, for all values of `size`; if /// `size` is equal to zero, and `ptr` is not `NULL`, then the call is /// equivalent to `free(ptr)`. Unless `ptr` is `NULL`, it must have been /// returned by an earlier call to [`malloc`](malloc), [`calloc`](calloc), or /// [`realloc`](realloc). If the area pointed to was moved, a `free(ptr)` is /// done. /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn realloc(ptr: *mut c_void, size: size_t) -> *mut c_void { alloc::realloc( ptr as *mut u8, Layout::from_size_align_unchecked(1, 1), size, ) as *mut c_void } /// Frees the memory space pointed to by `ptr`, which must have been returned by /// a previous call to [`malloc`](malloc), [`calloc`](calloc), or /// [`realloc`](realloc). Otherwise, or if `free(ptr)` has already been called /// before, undefined behavior occurs. If `ptr` is `NULL`, no operation is /// performed. /// /// # Safety /// /// This function works with raw pointers. #[cfg_attr(not(feature = "std"), no_mangle)] pub unsafe extern "C" fn free(ptr: *mut c_void) { alloc::dealloc(ptr as *mut u8, Layout::from_size_align_unchecked(1, 1)) }