getdelim.rs 1.3 KB

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