Remove C++ I/O streams

This commit is contained in:
topjohnwu
2025-05-01 11:04:23 -07:00
committed by John Wu
parent 78d1200608
commit dc0acea47c
8 changed files with 20 additions and 362 deletions

View File

@@ -18,7 +18,6 @@ LOCAL_SRC_FILES := \
files.cpp \
misc.cpp \
logging.cpp \
stream.cpp \
base-rs.cpp \
../external/cxx-rs/src/cxx.cc
include $(BUILD_STATIC_LIBRARY)

View File

@@ -1,129 +0,0 @@
#pragma once
#include <sys/uio.h>
#include <cstdio>
#include <memory>
#include "../files.hpp"
#define ENABLE_IOV 0
struct out_stream {
virtual bool write(const void *buf, size_t len) = 0;
#if ENABLE_IOV
virtual ssize_t writev(const iovec *iov, int iovcnt);
#endif
virtual ~out_stream() = default;
};
using out_strm_ptr = std::unique_ptr<out_stream>;
// Delegates all operations to base stream
class filter_out_stream : public out_stream {
public:
filter_out_stream(out_strm_ptr &&base) : base(std::move(base)) {}
bool write(const void *buf, size_t len) override;
protected:
out_strm_ptr base;
};
// Buffered output stream, writing in chunks
class chunk_out_stream : public filter_out_stream {
public:
chunk_out_stream(out_strm_ptr &&base, size_t buf_sz, size_t chunk_sz)
: filter_out_stream(std::move(base)), chunk_sz(chunk_sz), data(buf_sz) {}
chunk_out_stream(out_strm_ptr &&base, size_t buf_sz = 4096)
: chunk_out_stream(std::move(base), buf_sz, buf_sz) {}
bool write(const void *buf, size_t len) final;
protected:
// Classes inheriting this class has to call finalize() in its destructor
void finalize();
virtual bool write_chunk(const void *buf, size_t len, bool final);
size_t chunk_sz;
private:
size_t buf_off = 0;
heap_data data;
};
struct in_stream {
virtual ssize_t read(void *buf, size_t len) = 0;
ssize_t readFully(void *buf, size_t len);
#if ENABLE_IOV
virtual ssize_t readv(const iovec *iov, int iovcnt);
#endif
virtual ~in_stream() = default;
};
// A stream is something that is writable and readable
struct stream : public out_stream, public in_stream {};
using stream_ptr = std::unique_ptr<stream>;
// Byte stream that dynamically allocates memory
class byte_stream : public stream {
public:
byte_stream(heap_data &data) : _data(data) {}
ssize_t read(void *buf, size_t len) override;
bool write(const void *buf, size_t len) override;
private:
heap_data &_data;
size_t _pos = 0;
size_t _cap = 0;
void resize(size_t new_sz, bool zero = false);
};
class rust_vec_stream : public stream {
public:
rust_vec_stream(rust::Vec<uint8_t> &data) : _data(data) {}
ssize_t read(void *buf, size_t len) override;
bool write(const void *buf, size_t len) override;
private:
rust::Vec<uint8_t> &_data;
size_t _pos = 0;
void ensure_size(size_t sz, bool zero = false);
};
class file_stream : public stream {
public:
bool write(const void *buf, size_t len) final;
protected:
virtual ssize_t do_write(const void *buf, size_t len) = 0;
};
// File stream but does not close the file descriptor at any time
class fd_stream : public file_stream {
public:
fd_stream(int fd) : fd(fd) {}
ssize_t read(void *buf, size_t len) override;
#if ENABLE_IOV
ssize_t readv(const iovec *iov, int iovcnt) override;
ssize_t writev(const iovec *iov, int iovcnt) override;
#endif
protected:
ssize_t do_write(const void *buf, size_t len) override;
private:
int fd;
};
/* ****************************************
* Bridge between stream class and C stdio
* ****************************************/
// stream_ptr -> sFILE
sFILE make_stream_fp(stream_ptr &&strm);
template <class T, class... Args>
sFILE make_stream_fp(Args &&... args) {
return make_stream_fp(stream_ptr(new T(std::forward<Args>(args)...)));
}

View File

@@ -58,7 +58,6 @@ pub mod ffi {
fn set_log_level_state_cxx(level: LogLevelCxx, enabled: bool);
fn exit_on_error(b: bool);
fn cmdline_logging();
fn resize_vec(vec: &mut Vec<u8>, size: usize);
}
#[namespace = "rust"]
@@ -80,12 +79,3 @@ fn set_log_level_state_cxx(level: ffi::LogLevelCxx, enabled: bool) {
set_log_level_state(level, enabled)
}
}
fn resize_vec(vec: &mut Vec<u8>, size: usize) {
if size > vec.len() {
vec.reserve(size - vec.len());
}
unsafe {
vec.set_len(size);
}
}

View File

@@ -147,17 +147,12 @@ struct byte_data : public byte_view {
rust::Vec<size_t> patch(byte_view from, byte_view to);
};
class byte_stream;
struct heap_data : public byte_data {
ALLOW_MOVE_ONLY(heap_data)
heap_data() = default;
explicit heap_data(size_t sz) : byte_data(calloc(sz, 1), sz) {}
~heap_data() { free(_buf); }
// byte_stream needs to reallocate the internal buffer
friend byte_stream;
};
struct owned_fd {

View File

@@ -1,201 +0,0 @@
#include <unistd.h>
#include <cstddef>
#include <base.hpp>
#include <stream.hpp>
using namespace std;
static int strm_read(void *v, char *buf, int len) {
auto strm = static_cast<stream *>(v);
return strm->read(buf, len);
}
static int strm_write(void *v, const char *buf, int len) {
auto strm = static_cast<stream *>(v);
if (!strm->write(buf, len))
return -1;
return len;
}
static int strm_close(void *v) {
auto strm = static_cast<stream *>(v);
delete strm;
return 0;
}
sFILE make_stream_fp(stream_ptr &&strm) {
auto fp = make_file(funopen(strm.release(), strm_read, strm_write, nullptr, strm_close));
setbuf(fp.get(), nullptr);
return fp;
}
ssize_t in_stream::readFully(void *buf, size_t len) {
size_t read_sz = 0;
ssize_t ret;
do {
ret = read((byte *) buf + read_sz, len - read_sz);
if (ret < 0) {
if (errno == EINTR)
continue;
return ret;
}
read_sz += ret;
} while (read_sz != len && ret != 0);
return read_sz;
}
bool filter_out_stream::write(const void *buf, size_t len) {
return base->write(buf, len);
}
bool chunk_out_stream::write(const void *_in, size_t len) {
auto in = static_cast<const uint8_t *>(_in);
while (len) {
if (buf_off + len >= chunk_sz) {
// Enough input for a chunk
const uint8_t *src;
if (buf_off) {
src = data.buf();
auto copy = chunk_sz - buf_off;
memcpy(data.buf() + buf_off, in, copy);
in += copy;
len -= copy;
buf_off = 0;
} else {
src = in;
in += chunk_sz;
len -= chunk_sz;
}
if (!write_chunk(src, chunk_sz, false))
return false;
} else {
// Buffer internally
memcpy(data.buf() + buf_off, in, len);
buf_off += len;
break;
}
}
return true;
}
bool chunk_out_stream::write_chunk(const void *buf, size_t len, bool) {
return base->write(buf, len);
}
void chunk_out_stream::finalize() {
if (buf_off) {
if (!write_chunk(data.buf(), buf_off, true)) {
LOGE("Error in finalize, file truncated\n");
}
buf_off = 0;
}
}
ssize_t byte_stream::read(void *buf, size_t len) {
len = std::min((size_t) len, _data._sz- _pos);
memcpy(buf, _data.buf() + _pos, len);
_pos += len;
return len;
}
bool byte_stream::write(const void *buf, size_t len) {
resize(_pos + len);
memcpy(_data.buf() + _pos, buf, len);
_pos += len;
_data._sz= std::max(_data.sz(), _pos);
return true;
}
void byte_stream::resize(size_t new_sz, bool zero) {
bool resize = false;
size_t old_cap = _cap;
while (new_sz > _cap) {
_cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12;
resize = true;
}
if (resize) {
_data._buf = static_cast<uint8_t *>(::realloc(_data._buf, _cap));
if (zero)
memset(_data.buf() + old_cap, 0, _cap - old_cap);
}
}
ssize_t rust_vec_stream::read(void *buf, size_t len) {
len = std::min<size_t>(len, _data.size() - _pos);
memcpy(buf, _data.data() + _pos, len);
_pos += len;
return len;
}
bool rust_vec_stream::write(const void *buf, size_t len) {
ensure_size(_pos + len);
memcpy(_data.data() + _pos, buf, len);
_pos += len;
return true;
}
void rust_vec_stream::ensure_size(size_t sz, bool zero) {
size_t old_sz = _data.size();
if (sz > old_sz) {
resize_vec(_data, sz);
if (zero)
memset(_data.data() + old_sz, 0, sz - old_sz);
}
}
ssize_t fd_stream::read(void *buf, size_t len) {
return ::read(fd, buf, len);
}
ssize_t fd_stream::do_write(const void *buf, size_t len) {
return ::write(fd, buf, len);
}
bool file_stream::write(const void *buf, size_t len) {
size_t write_sz = 0;
ssize_t ret;
do {
ret = do_write((byte *) buf + write_sz, len - write_sz);
if (ret < 0) {
if (errno == EINTR)
continue;
return false;
}
write_sz += ret;
} while (write_sz != len && ret != 0);
return true;
}
#if ENABLE_IOV
ssize_t in_stream::readv(const iovec *iov, int iovcnt) {
size_t read_sz = 0;
for (int i = 0; i < iovcnt; ++i) {
auto ret = readFully(iov[i].iov_base, iov[i].iov_len);
if (ret < 0)
return ret;
read_sz += ret;
}
return read_sz;
}
ssize_t out_stream::writev(const iovec *iov, int iovcnt) {
size_t write_sz = 0;
for (int i = 0; i < iovcnt; ++i) {
if (!write(iov[i].iov_base, iov[i].iov_len))
return write_sz;
write_sz += iov[i].iov_len;
}
return write_sz;
}
ssize_t fd_stream::readv(const iovec *iov, int iovcnt) {
return ::readv(fd, iov, iovcnt);
}
ssize_t fd_stream::writev(const iovec *iov, int iovcnt) {
return ::writev(fd, iov, iovcnt);
}
#endif // ENABLE_IOV