xref: /drstd/dlibc/src/unix/header/stdio/getdelim.rs (revision 9670759b785600bf6315e4173e46a602f16add7a)
1 use alloc::vec::Vec;
2 use core::ptr;
3 
4 use crate::unix::{
5     header::{stdio::FILE, stdlib},
6     io::BufRead,
7 };
8 
9 #[no_mangle]
10 pub unsafe extern "C" fn __getline(
11     lineptr: *mut *mut ::c_char,
12     n: *mut ::size_t,
13     stream: *mut FILE,
14 ) -> ::ssize_t {
15     __getdelim(lineptr, n, b'\n' as ::c_int, stream)
16 }
17 
18 #[no_mangle]
19 pub unsafe extern "C" fn __getdelim(
20     lineptr: *mut *mut ::c_char,
21     n: *mut ::size_t,
22     delim: ::c_int,
23     stream: *mut FILE,
24 ) -> ::ssize_t {
25     let lineptr = &mut *lineptr;
26     let n = &mut *n;
27     let delim = delim as u8;
28 
29     //TODO: More efficient algorithm using lineptr and n instead of this vec
30     let mut buf = Vec::new();
31     let count = {
32         let mut stream = (*stream).lock();
33         match stream.read_until(delim, &mut buf) {
34             Ok(ok) => ok,
35             Err(err) => return -1,
36         }
37     };
38 
39     //TODO: Check errors and improve safety
40     {
41         // Allocate lineptr to size of buf and set n to size of lineptr
42         *n = count + 1;
43         *lineptr = stdlib::realloc(*lineptr as *mut ::c_void, *n) as *mut ::c_char;
44 
45         // Copy buf to lineptr
46         ptr::copy(buf.as_ptr(), *lineptr as *mut u8, count);
47 
48         // NUL terminate lineptr
49         *lineptr.offset(count as isize) = 0;
50 
51         // Return allocated size
52         *n as ::ssize_t
53     }
54 }
55