diff --git a/src/header/stdio/getdelim.rs b/src/header/stdio/getdelim.rs new file mode 100644 index 0000000000..918467ffda --- /dev/null +++ b/src/header/stdio/getdelim.rs @@ -0,0 +1,45 @@ +use alloc::vec::Vec; +use core::ptr; + +use header::stdio::FILE; +use header::stdlib; +use io::BufRead; +use platform::types::*; + +#[no_mangle] +pub extern "C" fn __getline(lineptr: *mut *mut c_char, n: *mut size_t, stream: *mut FILE) -> ssize_t { + __getdelim(lineptr, n, b'\n' as c_int, stream) +} + +#[no_mangle] +pub extern "C" fn __getdelim(lineptr: *mut *mut c_char, n: *mut size_t, delim: c_int, stream: *mut FILE) -> ssize_t { + let lineptr = unsafe { &mut *lineptr }; + let n = unsafe { &mut *n }; + let delim = delim as u8; + + //TODO: More efficient algorithm using lineptr and n instead of this vec + let mut buf = Vec::new(); + let count = { + let mut stream = unsafe { &mut *stream }.lock(); + match stream.read_until(delim, &mut buf) { + Ok(ok) => ok, + Err(err) => return -1, + } + }; + + //TODO: Check errors and improve safety + unsafe { + // Allocate lineptr to size of buf and set n to size of lineptr + *n = count + 1; + *lineptr = stdlib::realloc(*lineptr as *mut c_void, *n) as *mut c_char; + + // Copy buf to lineptr + ptr::copy(buf.as_ptr(), *lineptr as *mut u8, count); + + // NUL terminate lineptr + *lineptr.offset(count as isize) = 0; + + // Return allocated size + *n as ssize_t + } +} diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs index 8af65da051..b115366397 100644 --- a/src/header/stdio/mod.rs +++ b/src/header/stdio/mod.rs @@ -27,6 +27,9 @@ mod constants; pub use self::default::*; mod default; +pub use self::getdelim::*; +mod getdelim; + mod ext; mod helpers; mod printf;