Jeremy Soller 6 роки тому
батько
коміт
5c4c49a9d1
2 змінених файлів з 48 додано та 0 видалено
  1. 45 0
      src/header/stdio/getdelim.rs
  2. 3 0
      src/header/stdio/mod.rs

+ 45 - 0
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
+    }
+}

+ 3 - 0
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;