mirror of
https://github.com/topjohnwu/Magisk.git
synced 2025-10-21 15:28:55 +00:00
Pull out buffer-chunk logic into separate class
This commit is contained in:
@@ -35,6 +35,34 @@ protected:
|
||||
stream_ptr base;
|
||||
};
|
||||
|
||||
// Buffered output stream, writing in chunks
|
||||
class chunk_out_stream : public filter_stream {
|
||||
public:
|
||||
chunk_out_stream(stream_ptr &&base, size_t buf_sz, size_t chunk_sz)
|
||||
: filter_stream(std::move(base)), chunk_sz(chunk_sz), buf_sz(buf_sz) {}
|
||||
|
||||
chunk_out_stream(stream_ptr &&base, size_t buf_sz = 4096)
|
||||
: chunk_out_stream(std::move(base), buf_sz, buf_sz) {}
|
||||
|
||||
~chunk_out_stream() { delete[] _buf; }
|
||||
|
||||
// Reading does not make sense
|
||||
ssize_t read(void *buf, size_t len) final { return stream::read(buf, len); }
|
||||
ssize_t write(const void *buf, size_t len) final;
|
||||
|
||||
protected:
|
||||
// Classes inheriting this class has to call close() in the destructor
|
||||
void close();
|
||||
virtual ssize_t write_chunk(const void *buf, size_t len) = 0;
|
||||
|
||||
size_t chunk_sz;
|
||||
|
||||
private:
|
||||
size_t buf_sz;
|
||||
size_t buf_off = 0;
|
||||
uint8_t *_buf = nullptr;
|
||||
};
|
||||
|
||||
// Byte stream that dynamically allocates memory
|
||||
class byte_stream : public stream {
|
||||
public:
|
||||
|
@@ -121,6 +121,51 @@ ssize_t filter_stream::write(const void *buf, size_t len) {
|
||||
return base->write(buf, len);
|
||||
}
|
||||
|
||||
ssize_t chunk_out_stream::write(const void *_in, size_t len) {
|
||||
ssize_t ret = 0;
|
||||
auto in = static_cast<const uint8_t *>(_in);
|
||||
while (len) {
|
||||
if (buf_off + len >= chunk_sz) {
|
||||
const uint8_t *src;
|
||||
if (buf_off) {
|
||||
// Copy the rest of the chunk to internal buffer
|
||||
src = _buf;
|
||||
auto copy = chunk_sz - buf_off;
|
||||
memcpy(_buf + buf_off, in, copy);
|
||||
in += copy;
|
||||
len -= copy;
|
||||
buf_off = 0;
|
||||
} else {
|
||||
src = in;
|
||||
in += chunk_sz;
|
||||
len -= chunk_sz;
|
||||
}
|
||||
auto r = write_chunk(src, chunk_sz);
|
||||
if (r < 0)
|
||||
return ret;
|
||||
ret += r;
|
||||
} else {
|
||||
// Buffer internally
|
||||
if (!_buf) {
|
||||
_buf = new uint8_t[buf_sz];
|
||||
}
|
||||
memcpy(_buf + buf_off, in, len);
|
||||
buf_off += len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void chunk_out_stream::close() {
|
||||
if (buf_off) {
|
||||
write_chunk(_buf, buf_off);
|
||||
delete[] _buf;
|
||||
_buf = nullptr;
|
||||
buf_off = 0;
|
||||
}
|
||||
}
|
||||
|
||||
byte_stream::byte_stream(uint8_t *&buf, size_t &len) : _buf(buf), _len(len) {
|
||||
buf = nullptr;
|
||||
len = 0;
|
||||
|
Reference in New Issue
Block a user