Verified Commit 56e1eceb authored by jD91mZM2's avatar jD91mZM2
Browse files

Replace AllocStringWriter with CVec

parent 39ce623d
use crate::platform::{self, types::*};
use crate::{
io::{self, Write},
platform::{self, WriteByte, types::*},
};
use core::{
cmp,
fmt,
iter::IntoIterator,
mem,
ops::{Deref, DerefMut},
......@@ -67,6 +71,9 @@ impl<T> CVec<T> {
start = start.add(1);
}
}
// Push stuff
pub fn reserve(&mut self, required: usize) -> Result<(), AllocError> {
let reserved_len = self
.len
......@@ -82,8 +89,8 @@ impl<T> CVec<T> {
Ok(())
}
pub fn push(&mut self, elem: T) -> Result<(), AllocError> {
self.reserve(1)?;
unsafe {
self.reserve(1)?;
ptr::write(self.ptr.as_ptr().add(self.len), elem);
}
self.len += 1; // no need to bounds check, as new len <= cap
......@@ -93,21 +100,26 @@ impl<T> CVec<T> {
where
T: Copy,
{
self.reserve(elems.len())?;
unsafe {
self.reserve(elems.len())?;
ptr::copy_nonoverlapping(elems.as_ptr(), self.ptr.as_ptr().add(self.len), elems.len());
}
self.len += elems.len(); // no need to bounds check, as new len <= cap
Ok(())
}
pub fn append(&mut self, other: &mut Self) -> Result<(), AllocError> {
let len = other.len;
other.len = 0; // move
self.reserve(len)?;
unsafe {
self.reserve(other.len())?;
ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), other.len());
ptr::copy_nonoverlapping(other.as_ptr(), self.ptr.as_ptr().add(self.len), len);
}
self.len += other.len(); // no need to bounds check, as new len <= cap
Ok(())
}
// Pop stuff
pub fn truncate(&mut self, len: usize) {
if len < self.len {
unsafe {
......@@ -126,6 +138,18 @@ impl<T> CVec<T> {
}
Ok(())
}
pub fn pop(&mut self) -> Option<T> {
if self.is_empty() {
None
} else {
let elem = unsafe { ptr::read(self.as_ptr().add(self.len - 1)) };
self.len -= 1;
Some(elem)
}
}
// Misc stuff
pub fn capacity(&self) -> usize {
self.cap
}
......@@ -176,3 +200,28 @@ impl<'a, T> IntoIterator for &'a mut CVec<T> {
<&mut [T]>::into_iter(&mut *self)
}
}
impl Write for CVec<u8> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.extend_from_slice(buf).map_err(|err| io::Error::new(
io::ErrorKind::Other,
"AllocStringWriter::write failed to allocate",
))?;
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Write for CVec<u8> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.write(s.as_bytes()).map_err(|_| fmt::Error)?;
Ok(())
}
}
impl WriteByte for CVec<u8> {
fn write_u8(&mut self, byte: u8) -> fmt::Result {
self.write(&[byte]).map_err(|_| fmt::Error)?;
Ok(())
}
}
......@@ -16,6 +16,7 @@ use core::{
use crate::{
c_str::CStr,
c_vec::CVec,
fs::File,
header::{
errno::{self, STR_ERROR},
......@@ -1021,9 +1022,11 @@ pub unsafe extern "C" fn vasprintf(
format: *const c_char,
ap: va_list,
) -> c_int {
let mut alloc_writer = platform::AllocStringWriter(ptr::null_mut(), 0);
let mut alloc_writer = CVec::new();
let ret = printf::printf(&mut alloc_writer, format, ap);
*strp = alloc_writer.0 as *mut c_char;
alloc_writer.push(0).unwrap();
alloc_writer.shrink_to_fit().unwrap();
*strp = alloc_writer.leak() as *mut c_char;
ret
}
......
......@@ -104,45 +104,6 @@ impl Read for FileReader {
}
}
pub struct AllocStringWriter(pub *mut u8, pub usize);
impl Write for AllocStringWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let ptr = unsafe { realloc(self.0 as *mut c_void, self.1 + buf.len() + 1) as *mut u8 };
if ptr.is_null() {
return Err(io::Error::new(
io::ErrorKind::Other,
"AllocStringWriter::write failed to allocate",
));
}
self.0 = ptr;
unsafe {
ptr::copy_nonoverlapping(buf.as_ptr(), self.0.add(self.1), buf.len());
self.1 += buf.len();
*self.0.add(self.1) = 0;
}
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
impl fmt::Write for AllocStringWriter {
fn write_str(&mut self, s: &str) -> fmt::Result {
// can't fail
self.write(s.as_bytes()).unwrap();
Ok(())
}
}
impl WriteByte for AllocStringWriter {
fn write_u8(&mut self, byte: u8) -> fmt::Result {
// can't fail
self.write(&[byte]).unwrap();
Ok(())
}
}
pub struct StringWriter(pub *mut u8, pub usize);
impl Write for StringWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
......@@ -155,11 +116,14 @@ impl Write for StringWriter {
self.0 = self.0.add(copy_size);
*self.0 = 0;
}
Ok(copy_size)
} else {
Ok(0)
}
// Pretend the entire slice was written. This is because many functions
// (like snprintf) expects a return value that reflects how many bytes
// *would have* been written. So keeping track of this information is
// good, and then if we want the *actual* written size we can just go
// `cmp::min(written, maxlen)`.
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment