mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-25 14:27:39 +00:00
Stream should always write all bytes
This commit is contained in:
parent
d8b9265484
commit
5787aa1078
@ -29,19 +29,15 @@ constexpr size_t ZOPFLI_CHUNK = ZOPFLI_MASTER_BLOCK_SIZE;
|
|||||||
constexpr size_t ZOPFLI_CHUNK = CHUNK;
|
constexpr size_t ZOPFLI_CHUNK = CHUNK;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class cpr_stream : public filter_stream {
|
class out_stream : public filter_stream {
|
||||||
public:
|
|
||||||
using filter_stream::filter_stream;
|
using filter_stream::filter_stream;
|
||||||
using stream::read;
|
using stream::read;
|
||||||
ssize_t writeFully(void *buf, size_t len) override {
|
|
||||||
return write(buf, len);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class gz_strm : public cpr_stream {
|
class gz_strm : public out_stream {
|
||||||
public:
|
public:
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
bool write(const void *buf, size_t len) override {
|
||||||
return len ? write(buf, len, Z_NO_FLUSH) : 0;
|
return len == 0 || write(buf, len, Z_NO_FLUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
~gz_strm() override {
|
~gz_strm() override {
|
||||||
@ -63,7 +59,7 @@ protected:
|
|||||||
} mode;
|
} mode;
|
||||||
|
|
||||||
gz_strm(mode_t mode, stream_ptr &&base) :
|
gz_strm(mode_t mode, stream_ptr &&base) :
|
||||||
cpr_stream(std::move(base)), mode(mode), strm{}, outbuf{0} {
|
out_stream(std::move(base)), mode(mode), strm{}, outbuf{0} {
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case DECODE:
|
case DECODE:
|
||||||
inflateInit2(&strm, 15 | 16);
|
inflateInit2(&strm, 15 | 16);
|
||||||
@ -78,8 +74,7 @@ private:
|
|||||||
z_stream strm;
|
z_stream strm;
|
||||||
uint8_t outbuf[CHUNK];
|
uint8_t outbuf[CHUNK];
|
||||||
|
|
||||||
ssize_t write(const void *buf, size_t len, int flush) {
|
bool write(const void *buf, size_t len, int flush) {
|
||||||
size_t ret = 0;
|
|
||||||
strm.next_in = (Bytef *) buf;
|
strm.next_in = (Bytef *) buf;
|
||||||
strm.avail_in = len;
|
strm.avail_in = len;
|
||||||
do {
|
do {
|
||||||
@ -96,11 +91,12 @@ private:
|
|||||||
}
|
}
|
||||||
if (code == Z_STREAM_ERROR) {
|
if (code == Z_STREAM_ERROR) {
|
||||||
LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code);
|
LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
|
if (!bwrite(outbuf, sizeof(outbuf) - strm.avail_out))
|
||||||
|
return false;
|
||||||
} while (strm.avail_out == 0);
|
} while (strm.avail_out == 0);
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -114,14 +110,40 @@ public:
|
|||||||
explicit gz_encoder(stream_ptr &&base) : gz_strm(ENCODE, std::move(base)) {};
|
explicit gz_encoder(stream_ptr &&base) : gz_strm(ENCODE, std::move(base)) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class zopfli_encoder : public cpr_stream {
|
class zopfli_encoder : public out_stream {
|
||||||
public:
|
public:
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
bool write(const void *buf, size_t len) override {
|
||||||
return len ? write(static_cast<const unsigned char *>(buf), len) : 0;
|
if (len == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto in = static_cast<const unsigned char *>(buf);
|
||||||
|
in_size += len;
|
||||||
|
crcvalue = crc32_z(crcvalue, in, len);
|
||||||
|
|
||||||
|
for (size_t offset = 0; offset < len; offset += ZOPFLI_CHUNK) {
|
||||||
|
size_t end_offset = std::min(len, offset + ZOPFLI_CHUNK);
|
||||||
|
ZopfliDeflatePart(&zo, 2, 0, in, offset, end_offset, &bp, &out, &outsize);
|
||||||
|
|
||||||
|
if (bp) {
|
||||||
|
// The last byte is not complete
|
||||||
|
if (!bwrite(out, outsize - 1))
|
||||||
|
return false;
|
||||||
|
uint8_t b = out[outsize - 1];
|
||||||
|
free_out();
|
||||||
|
ZOPFLI_APPEND_DATA(b, &out, &outsize);
|
||||||
|
} else {
|
||||||
|
if (!bwrite(out, outsize))
|
||||||
|
return false;
|
||||||
|
free_out();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit zopfli_encoder(stream_ptr &&base) : cpr_stream(std::move(base)),
|
return true;
|
||||||
zo({}), out(nullptr), outsize(0), bp(0), crcvalue(crc32_z(0L, Z_NULL, 0)), in_size(0) {
|
}
|
||||||
|
|
||||||
|
explicit zopfli_encoder(stream_ptr &&base) :
|
||||||
|
out_stream(std::move(base)), zo({}), out(nullptr), outsize(0), bp(0),
|
||||||
|
crcvalue(crc32_z(0L, Z_NULL, 0)), in_size(0) {
|
||||||
ZopfliInitOptions(&zo);
|
ZopfliInitOptions(&zo);
|
||||||
|
|
||||||
// Speed things up a bit, this still leads to better compression than zlib
|
// Speed things up a bit, this still leads to better compression than zlib
|
||||||
@ -174,36 +196,12 @@ private:
|
|||||||
out = nullptr;
|
out = nullptr;
|
||||||
outsize = 0;
|
outsize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t write(const unsigned char *buf, size_t len) {
|
|
||||||
ssize_t ret = 0;
|
|
||||||
in_size += len;
|
|
||||||
crcvalue = crc32_z(crcvalue, buf, len);
|
|
||||||
|
|
||||||
for (size_t offset = 0; offset < len; offset += ZOPFLI_CHUNK) {
|
|
||||||
size_t end_offset = std::min(len, offset + ZOPFLI_CHUNK);
|
|
||||||
ZopfliDeflatePart(&zo, 2, 0, buf, offset, end_offset, &bp, &out, &outsize);
|
|
||||||
|
|
||||||
if (bp) {
|
|
||||||
// The last byte is not complete
|
|
||||||
ret += bwrite(out, outsize - 1);
|
|
||||||
uint8_t b = out[outsize - 1];
|
|
||||||
free_out();
|
|
||||||
ZOPFLI_APPEND_DATA(b, &out, &outsize);
|
|
||||||
} else {
|
|
||||||
ret += bwrite(out, outsize);
|
|
||||||
free_out();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class bz_strm : public cpr_stream {
|
class bz_strm : public out_stream {
|
||||||
public:
|
public:
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
bool write(const void *buf, size_t len) override {
|
||||||
return len ? write(buf, len, BZ_RUN) : 0;
|
return len == 0 || write(buf, len, BZ_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
~bz_strm() override {
|
~bz_strm() override {
|
||||||
@ -225,7 +223,7 @@ protected:
|
|||||||
} mode;
|
} mode;
|
||||||
|
|
||||||
bz_strm(mode_t mode, stream_ptr &&base) :
|
bz_strm(mode_t mode, stream_ptr &&base) :
|
||||||
cpr_stream(std::move(base)), mode(mode), strm{}, outbuf{0} {
|
out_stream(std::move(base)), mode(mode), strm{}, outbuf{0} {
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case DECODE:
|
case DECODE:
|
||||||
BZ2_bzDecompressInit(&strm, 0, 0);
|
BZ2_bzDecompressInit(&strm, 0, 0);
|
||||||
@ -240,8 +238,7 @@ private:
|
|||||||
bz_stream strm;
|
bz_stream strm;
|
||||||
char outbuf[CHUNK];
|
char outbuf[CHUNK];
|
||||||
|
|
||||||
ssize_t write(const void *buf, size_t len, int flush) {
|
bool write(const void *buf, size_t len, int flush) {
|
||||||
size_t ret = 0;
|
|
||||||
strm.next_in = (char *) buf;
|
strm.next_in = (char *) buf;
|
||||||
strm.avail_in = len;
|
strm.avail_in = len;
|
||||||
do {
|
do {
|
||||||
@ -258,11 +255,12 @@ private:
|
|||||||
}
|
}
|
||||||
if (code < 0) {
|
if (code < 0) {
|
||||||
LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code);
|
LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
|
if (!bwrite(outbuf, sizeof(outbuf) - strm.avail_out))
|
||||||
|
return false;
|
||||||
} while (strm.avail_out == 0);
|
} while (strm.avail_out == 0);
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -276,10 +274,10 @@ public:
|
|||||||
explicit bz_encoder(stream_ptr &&base) : bz_strm(ENCODE, std::move(base)) {};
|
explicit bz_encoder(stream_ptr &&base) : bz_strm(ENCODE, std::move(base)) {};
|
||||||
};
|
};
|
||||||
|
|
||||||
class lzma_strm : public cpr_stream {
|
class lzma_strm : public out_stream {
|
||||||
public:
|
public:
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
bool write(const void *buf, size_t len) override {
|
||||||
return len ? write(buf, len, LZMA_RUN) : 0;
|
return len == 0 || write(buf, len, LZMA_RUN);
|
||||||
}
|
}
|
||||||
|
|
||||||
~lzma_strm() override {
|
~lzma_strm() override {
|
||||||
@ -295,7 +293,7 @@ protected:
|
|||||||
} mode;
|
} mode;
|
||||||
|
|
||||||
lzma_strm(mode_t mode, stream_ptr &&base) :
|
lzma_strm(mode_t mode, stream_ptr &&base) :
|
||||||
cpr_stream(std::move(base)), mode(mode), strm(LZMA_STREAM_INIT), outbuf{0} {
|
out_stream(std::move(base)), mode(mode), strm(LZMA_STREAM_INIT), outbuf{0} {
|
||||||
lzma_options_lzma opt;
|
lzma_options_lzma opt;
|
||||||
|
|
||||||
// Initialize preset
|
// Initialize preset
|
||||||
@ -326,8 +324,7 @@ private:
|
|||||||
lzma_stream strm;
|
lzma_stream strm;
|
||||||
uint8_t outbuf[CHUNK];
|
uint8_t outbuf[CHUNK];
|
||||||
|
|
||||||
ssize_t write(const void *buf, size_t len, lzma_action flush) {
|
bool write(const void *buf, size_t len, lzma_action flush) {
|
||||||
size_t ret = 0;
|
|
||||||
strm.next_in = (uint8_t *) buf;
|
strm.next_in = (uint8_t *) buf;
|
||||||
strm.avail_in = len;
|
strm.avail_in = len;
|
||||||
do {
|
do {
|
||||||
@ -336,11 +333,12 @@ private:
|
|||||||
int code = lzma_code(&strm, flush);
|
int code = lzma_code(&strm, flush);
|
||||||
if (code != LZMA_OK && code != LZMA_STREAM_END) {
|
if (code != LZMA_OK && code != LZMA_STREAM_END) {
|
||||||
LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code);
|
LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out);
|
if (!bwrite(outbuf, sizeof(outbuf) - strm.avail_out))
|
||||||
|
return false;
|
||||||
} while (strm.avail_out == 0);
|
} while (strm.avail_out == 0);
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -359,10 +357,10 @@ public:
|
|||||||
explicit lzma_encoder(stream_ptr &&base) : lzma_strm(ENCODE_LZMA, std::move(base)) {}
|
explicit lzma_encoder(stream_ptr &&base) : lzma_strm(ENCODE_LZMA, std::move(base)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class LZ4F_decoder : public cpr_stream {
|
class LZ4F_decoder : public out_stream {
|
||||||
public:
|
public:
|
||||||
explicit LZ4F_decoder(stream_ptr &&base) :
|
explicit LZ4F_decoder(stream_ptr &&base) :
|
||||||
cpr_stream(std::move(base)), ctx(nullptr), outbuf(nullptr), outCapacity(0) {
|
out_stream(std::move(base)), ctx(nullptr), outbuf(nullptr), outCapacity(0) {
|
||||||
LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
|
LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -371,35 +369,10 @@ public:
|
|||||||
delete[] outbuf;
|
delete[] outbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
bool write(const void *buf, size_t len) override {
|
||||||
size_t ret = 0;
|
auto in = reinterpret_cast<const uint8_t *>(buf);
|
||||||
auto inbuf = reinterpret_cast<const uint8_t *>(buf);
|
if (!outbuf) {
|
||||||
if (!outbuf)
|
size_t read = len;
|
||||||
read_header(inbuf, len);
|
|
||||||
size_t read, write;
|
|
||||||
LZ4F_errorCode_t code;
|
|
||||||
do {
|
|
||||||
read = len;
|
|
||||||
write = outCapacity;
|
|
||||||
code = LZ4F_decompress(ctx, outbuf, &write, inbuf, &read, nullptr);
|
|
||||||
if (LZ4F_isError(code)) {
|
|
||||||
LOGW("LZ4F decode error: %s\n", LZ4F_getErrorName(code));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
len -= read;
|
|
||||||
inbuf += read;
|
|
||||||
ret += bwrite(outbuf, write);
|
|
||||||
} while (len != 0 || write != 0);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
LZ4F_decompressionContext_t ctx;
|
|
||||||
uint8_t *outbuf;
|
|
||||||
size_t outCapacity;
|
|
||||||
|
|
||||||
void read_header(const uint8_t *&in, size_t &size) {
|
|
||||||
size_t read = size;
|
|
||||||
LZ4F_frameInfo_t info;
|
LZ4F_frameInfo_t info;
|
||||||
LZ4F_getFrameInfo(ctx, &info, in, &read);
|
LZ4F_getFrameInfo(ctx, &info, in, &read);
|
||||||
switch (info.blockSizeID) {
|
switch (info.blockSizeID) {
|
||||||
@ -411,54 +384,41 @@ private:
|
|||||||
}
|
}
|
||||||
outbuf = new uint8_t[outCapacity];
|
outbuf = new uint8_t[outCapacity];
|
||||||
in += read;
|
in += read;
|
||||||
size -= read;
|
len -= read;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
class LZ4F_encoder : public cpr_stream {
|
|
||||||
public:
|
|
||||||
explicit LZ4F_encoder(stream_ptr &&base) :
|
|
||||||
cpr_stream(std::move(base)), ctx(nullptr), outbuf(nullptr), outCapacity(0) {
|
|
||||||
LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t write(const void *buf, size_t len) override {
|
|
||||||
size_t ret = 0;
|
|
||||||
if (!outbuf)
|
|
||||||
ret += write_header();
|
|
||||||
if (len == 0)
|
|
||||||
return 0;
|
|
||||||
auto inbuf = reinterpret_cast<const uint8_t *>(buf);
|
|
||||||
size_t read, write;
|
size_t read, write;
|
||||||
|
LZ4F_errorCode_t code;
|
||||||
do {
|
do {
|
||||||
read = len > BLOCK_SZ ? BLOCK_SZ : len;
|
read = len;
|
||||||
write = LZ4F_compressUpdate(ctx, outbuf, outCapacity, inbuf, read, nullptr);
|
write = outCapacity;
|
||||||
if (LZ4F_isError(write)) {
|
code = LZ4F_decompress(ctx, outbuf, &write, in, &read, nullptr);
|
||||||
LOGW("LZ4F encode error: %s\n", LZ4F_getErrorName(write));
|
if (LZ4F_isError(code)) {
|
||||||
return -1;
|
LOGW("LZ4F decode error: %s\n", LZ4F_getErrorName(code));
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
len -= read;
|
len -= read;
|
||||||
inbuf += read;
|
in += read;
|
||||||
ret += bwrite(outbuf, write);
|
if (!bwrite(outbuf, write))
|
||||||
} while (len != 0);
|
return false;
|
||||||
return ret;
|
} while (len != 0 || write != 0);
|
||||||
}
|
return true;
|
||||||
|
|
||||||
~LZ4F_encoder() override {
|
|
||||||
size_t len = LZ4F_compressEnd(ctx, outbuf, outCapacity, nullptr);
|
|
||||||
bwrite(outbuf, len);
|
|
||||||
LZ4F_freeCompressionContext(ctx);
|
|
||||||
delete[] outbuf;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
LZ4F_compressionContext_t ctx;
|
LZ4F_decompressionContext_t ctx;
|
||||||
uint8_t *outbuf;
|
uint8_t *outbuf;
|
||||||
size_t outCapacity;
|
size_t outCapacity;
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr size_t BLOCK_SZ = 1 << 22;
|
class LZ4F_encoder : public out_stream {
|
||||||
|
public:
|
||||||
|
explicit LZ4F_encoder(stream_ptr &&base) :
|
||||||
|
out_stream(std::move(base)), ctx(nullptr), out_buf(nullptr), outCapacity(0) {
|
||||||
|
LZ4F_createCompressionContext(&ctx, LZ4F_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
int write_header() {
|
bool write(const void *buf, size_t len) override {
|
||||||
|
if (!out_buf) {
|
||||||
LZ4F_preferences_t prefs {
|
LZ4F_preferences_t prefs {
|
||||||
.frameInfo = {
|
.frameInfo = {
|
||||||
.blockSizeID = LZ4F_max4MB,
|
.blockSizeID = LZ4F_max4MB,
|
||||||
@ -470,24 +430,50 @@ private:
|
|||||||
.autoFlush = 1,
|
.autoFlush = 1,
|
||||||
};
|
};
|
||||||
outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs);
|
outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs);
|
||||||
outbuf = new uint8_t[outCapacity];
|
out_buf = new uint8_t[outCapacity];
|
||||||
size_t write = LZ4F_compressBegin(ctx, outbuf, outCapacity, &prefs);
|
size_t write = LZ4F_compressBegin(ctx, out_buf, outCapacity, &prefs);
|
||||||
return bwrite(outbuf, write);
|
if (!bwrite(out_buf, write))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
if (len == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto in = reinterpret_cast<const uint8_t *>(buf);
|
||||||
|
size_t read, write;
|
||||||
|
do {
|
||||||
|
read = len > BLOCK_SZ ? BLOCK_SZ : len;
|
||||||
|
write = LZ4F_compressUpdate(ctx, out_buf, outCapacity, in, read, nullptr);
|
||||||
|
if (LZ4F_isError(write)) {
|
||||||
|
LOGW("LZ4F encode error: %s\n", LZ4F_getErrorName(write));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
len -= read;
|
||||||
|
in += read;
|
||||||
|
if (!bwrite(out_buf, write))
|
||||||
|
return false;
|
||||||
|
} while (len != 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~LZ4F_encoder() override {
|
||||||
|
size_t len = LZ4F_compressEnd(ctx, out_buf, outCapacity, nullptr);
|
||||||
|
bwrite(out_buf, len);
|
||||||
|
LZ4F_freeCompressionContext(ctx);
|
||||||
|
delete[] out_buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
LZ4F_compressionContext_t ctx;
|
||||||
|
uint8_t *out_buf;
|
||||||
|
size_t outCapacity;
|
||||||
|
|
||||||
|
static constexpr size_t BLOCK_SZ = 1 << 22;
|
||||||
};
|
};
|
||||||
|
|
||||||
class buf_cpr_stream : public chunk_out_stream {
|
class LZ4_decoder : public chunk_out_stream {
|
||||||
public:
|
|
||||||
using chunk_out_stream::chunk_out_stream;
|
|
||||||
ssize_t writeFully(void *buf, size_t len) override {
|
|
||||||
return write(buf, len);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class LZ4_decoder : public buf_cpr_stream {
|
|
||||||
public:
|
public:
|
||||||
explicit LZ4_decoder(stream_ptr &&base) :
|
explicit LZ4_decoder(stream_ptr &&base) :
|
||||||
buf_cpr_stream(std::move(base), LZ4_COMPRESSED, sizeof(block_sz) + 4),
|
chunk_out_stream(std::move(base), LZ4_COMPRESSED, sizeof(block_sz) + 4),
|
||||||
out_buf(new char[LZ4_UNCOMPRESSED]), block_sz(0) {}
|
out_buf(new char[LZ4_UNCOMPRESSED]), block_sz(0) {}
|
||||||
|
|
||||||
~LZ4_decoder() override {
|
~LZ4_decoder() override {
|
||||||
@ -496,10 +482,10 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ssize_t write_chunk(const void *buf, size_t len) override {
|
bool write_chunk(const void *buf, size_t len) override {
|
||||||
// This is an error
|
// This is an error
|
||||||
if (len != chunk_sz)
|
if (len != chunk_sz)
|
||||||
return -1;
|
return false;
|
||||||
|
|
||||||
auto in = reinterpret_cast<const char *>(buf);
|
auto in = reinterpret_cast<const char *>(buf);
|
||||||
|
|
||||||
@ -511,14 +497,14 @@ protected:
|
|||||||
memcpy(&block_sz, in, sizeof(block_sz));
|
memcpy(&block_sz, in, sizeof(block_sz));
|
||||||
}
|
}
|
||||||
chunk_sz = block_sz;
|
chunk_sz = block_sz;
|
||||||
return 0;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
int r = LZ4_decompress_safe(in, out_buf, block_sz, LZ4_UNCOMPRESSED);
|
int r = LZ4_decompress_safe(in, out_buf, block_sz, LZ4_UNCOMPRESSED);
|
||||||
chunk_sz = sizeof(block_sz);
|
chunk_sz = sizeof(block_sz);
|
||||||
block_sz = 0;
|
block_sz = 0;
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
LOGW("LZ4HC decompression failure (%d)\n", r);
|
LOGW("LZ4HC decompression failure (%d)\n", r);
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
return bwrite(out_buf, r);
|
return bwrite(out_buf, r);
|
||||||
}
|
}
|
||||||
@ -529,10 +515,10 @@ private:
|
|||||||
uint32_t block_sz;
|
uint32_t block_sz;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LZ4_encoder : public buf_cpr_stream {
|
class LZ4_encoder : public chunk_out_stream {
|
||||||
public:
|
public:
|
||||||
explicit LZ4_encoder(stream_ptr &&base, bool lg) :
|
explicit LZ4_encoder(stream_ptr &&base, bool lg) :
|
||||||
buf_cpr_stream(std::move(base), LZ4_UNCOMPRESSED),
|
chunk_out_stream(std::move(base), LZ4_UNCOMPRESSED),
|
||||||
out_buf(new char[LZ4_COMPRESSED]), lg(lg), in_total(0) {
|
out_buf(new char[LZ4_COMPRESSED]), lg(lg), in_total(0) {
|
||||||
bwrite("\x02\x21\x4c\x18", 4);
|
bwrite("\x02\x21\x4c\x18", 4);
|
||||||
}
|
}
|
||||||
@ -545,15 +531,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ssize_t write_chunk(const void *buf, size_t len) override {
|
bool write_chunk(const void *buf, size_t len) override {
|
||||||
int r = LZ4_compress_HC((const char *) buf, out_buf, len, LZ4_COMPRESSED, LZ4HC_CLEVEL_MAX);
|
int r = LZ4_compress_HC((const char *) buf, out_buf, len, LZ4_COMPRESSED, LZ4HC_CLEVEL_MAX);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
LOGW("LZ4HC compression failure\n");
|
LOGW("LZ4HC compression failure\n");
|
||||||
return -1;
|
return false;
|
||||||
}
|
}
|
||||||
bwrite(&r, sizeof(r));
|
return bwrite(&r, sizeof(r)) && bwrite(out_buf, r);
|
||||||
bwrite(out_buf, r);
|
|
||||||
return r + sizeof(r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -644,7 +628,7 @@ void decompress(char *infile, const char *outfile) {
|
|||||||
strm = get_decoder(type, make_unique<fp_stream>(out_fp));
|
strm = get_decoder(type, make_unique<fp_stream>(out_fp));
|
||||||
if (ext) *ext = '.';
|
if (ext) *ext = '.';
|
||||||
}
|
}
|
||||||
if (strm->write(buf, len) < 0)
|
if (!strm->write(buf, len))
|
||||||
LOGE("Decompression error!\n");
|
LOGE("Decompression error!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -687,9 +671,9 @@ void compress(const char *method, const char *infile, const char *outfile) {
|
|||||||
char buf[4096];
|
char buf[4096];
|
||||||
size_t len;
|
size_t len;
|
||||||
while ((len = fread(buf, 1, sizeof(buf), in_fp))) {
|
while ((len = fread(buf, 1, sizeof(buf), in_fp))) {
|
||||||
if (strm->write(buf, len) < 0)
|
if (!strm->write(buf, len))
|
||||||
LOGE("Compression error!\n");
|
LOGE("Compression error!\n");
|
||||||
};
|
}
|
||||||
|
|
||||||
strm.reset(nullptr);
|
strm.reset(nullptr);
|
||||||
fclose(in_fp);
|
fclose(in_fp);
|
||||||
|
@ -11,8 +11,7 @@ public:
|
|||||||
virtual ssize_t read(void *buf, size_t len);
|
virtual ssize_t read(void *buf, size_t len);
|
||||||
virtual ssize_t readFully(void *buf, size_t len);
|
virtual ssize_t readFully(void *buf, size_t len);
|
||||||
virtual ssize_t readv(const iovec *iov, int iovcnt);
|
virtual ssize_t readv(const iovec *iov, int iovcnt);
|
||||||
virtual ssize_t write(const void *buf, size_t len);
|
virtual bool write(const void *buf, size_t len);
|
||||||
virtual ssize_t writeFully(void *buf, size_t len);
|
|
||||||
virtual ssize_t writev(const iovec *iov, int iovcnt);
|
virtual ssize_t writev(const iovec *iov, int iovcnt);
|
||||||
virtual off_t seek(off_t off, int whence);
|
virtual off_t seek(off_t off, int whence);
|
||||||
virtual ~stream() = default;
|
virtual ~stream() = default;
|
||||||
@ -26,7 +25,7 @@ public:
|
|||||||
filter_stream(stream_ptr &&base) : base(std::move(base)) {}
|
filter_stream(stream_ptr &&base) : base(std::move(base)) {}
|
||||||
|
|
||||||
ssize_t read(void *buf, size_t len) override;
|
ssize_t read(void *buf, size_t len) override;
|
||||||
ssize_t write(const void *buf, size_t len) override;
|
bool write(const void *buf, size_t len) override;
|
||||||
|
|
||||||
// Seeking while filtering does not make sense
|
// Seeking while filtering does not make sense
|
||||||
off_t seek(off_t off, int whence) final { return stream::seek(off, whence); }
|
off_t seek(off_t off, int whence) final { return stream::seek(off, whence); }
|
||||||
@ -44,16 +43,16 @@ public:
|
|||||||
chunk_out_stream(stream_ptr &&base, size_t buf_sz = 4096)
|
chunk_out_stream(stream_ptr &&base, size_t buf_sz = 4096)
|
||||||
: chunk_out_stream(std::move(base), buf_sz, buf_sz) {}
|
: chunk_out_stream(std::move(base), buf_sz, buf_sz) {}
|
||||||
|
|
||||||
~chunk_out_stream() { delete[] _buf; }
|
~chunk_out_stream() override { delete[] _buf; }
|
||||||
|
|
||||||
// Reading does not make sense
|
// Reading does not make sense
|
||||||
ssize_t read(void *buf, size_t len) final { return stream::read(buf, len); }
|
ssize_t read(void *buf, size_t len) final { return stream::read(buf, len); }
|
||||||
ssize_t write(const void *buf, size_t len) final;
|
bool write(const void *buf, size_t len) final;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Classes inheriting this class has to call close() in the destructor
|
// Classes inheriting this class has to call close() in its destructor
|
||||||
void close();
|
void close();
|
||||||
virtual ssize_t write_chunk(const void *buf, size_t len) = 0;
|
virtual bool write_chunk(const void *buf, size_t len) = 0;
|
||||||
|
|
||||||
size_t chunk_sz;
|
size_t chunk_sz;
|
||||||
|
|
||||||
@ -71,7 +70,7 @@ public:
|
|||||||
byte_stream(Byte *&buf, size_t &len) : byte_stream(reinterpret_cast<uint8_t *&>(buf), len) {}
|
byte_stream(Byte *&buf, size_t &len) : byte_stream(reinterpret_cast<uint8_t *&>(buf), len) {}
|
||||||
|
|
||||||
ssize_t read(void *buf, size_t len) override;
|
ssize_t read(void *buf, size_t len) override;
|
||||||
ssize_t write(const void *buf, size_t len) override;
|
bool write(const void *buf, size_t len) override;
|
||||||
off_t seek(off_t off, int whence) override;
|
off_t seek(off_t off, int whence) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -83,16 +82,23 @@ private:
|
|||||||
void resize(size_t new_pos, bool zero = false);
|
void resize(size_t new_pos, 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
|
// File stream but does not close the file descriptor at any time
|
||||||
class fd_stream : public stream {
|
class fd_stream : public file_stream {
|
||||||
public:
|
public:
|
||||||
fd_stream(int fd) : fd(fd) {}
|
fd_stream(int fd) : fd(fd) {}
|
||||||
ssize_t read(void *buf, size_t len) override;
|
ssize_t read(void *buf, size_t len) override;
|
||||||
ssize_t readv(const iovec *iov, int iovcnt) override;
|
ssize_t readv(const iovec *iov, int iovcnt) override;
|
||||||
ssize_t write(const void *buf, size_t len) override;
|
|
||||||
ssize_t writev(const iovec *iov, int iovcnt) override;
|
ssize_t writev(const iovec *iov, int iovcnt) override;
|
||||||
off_t seek(off_t off, int whence) override;
|
off_t seek(off_t off, int whence) override;
|
||||||
|
protected:
|
||||||
|
ssize_t do_write(const void *buf, size_t len) override;
|
||||||
private:
|
private:
|
||||||
int fd;
|
int fd;
|
||||||
};
|
};
|
||||||
@ -102,15 +108,14 @@ private:
|
|||||||
* ****************************************/
|
* ****************************************/
|
||||||
|
|
||||||
// sFILE -> stream_ptr
|
// sFILE -> stream_ptr
|
||||||
class fp_stream final : public stream {
|
class fp_stream final : public file_stream {
|
||||||
public:
|
public:
|
||||||
fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {}
|
fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {}
|
||||||
fp_stream(sFILE &&fp) : fp(std::move(fp)) {}
|
fp_stream(sFILE &&fp) : fp(std::move(fp)) {}
|
||||||
|
|
||||||
ssize_t read(void *buf, size_t len) override;
|
ssize_t read(void *buf, size_t len) override;
|
||||||
ssize_t write(const void *buf, size_t len) override;
|
|
||||||
off_t seek(off_t off, int whence) override;
|
off_t seek(off_t off, int whence) override;
|
||||||
|
protected:
|
||||||
|
ssize_t do_write(const void *buf, size_t len) override;
|
||||||
private:
|
private:
|
||||||
sFILE fp;
|
sFILE fp;
|
||||||
};
|
};
|
||||||
|
@ -13,7 +13,9 @@ static int strm_read(void *v, char *buf, int len) {
|
|||||||
|
|
||||||
static int strm_write(void *v, const char *buf, int len) {
|
static int strm_write(void *v, const char *buf, int len) {
|
||||||
auto strm = static_cast<stream *>(v);
|
auto strm = static_cast<stream *>(v);
|
||||||
return strm->write(buf, len);
|
if (!strm->write(buf, len))
|
||||||
|
return -1;
|
||||||
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
static fpos_t strm_seek(void *v, fpos_t off, int whence) {
|
static fpos_t strm_seek(void *v, fpos_t off, int whence) {
|
||||||
@ -64,33 +66,17 @@ ssize_t stream::readv(const iovec *iov, int iovcnt) {
|
|||||||
return read_sz;
|
return read_sz;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t stream::write(const void *buf, size_t len) {
|
bool stream::write(const void *buf, size_t len) {
|
||||||
LOGE("This stream does not implement write\n");
|
LOGE("This stream does not implement write\n");
|
||||||
return -1;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t stream::writeFully(void *buf, size_t len) {
|
|
||||||
size_t write_sz = 0;
|
|
||||||
ssize_t ret;
|
|
||||||
do {
|
|
||||||
ret = write((byte *) buf + write_sz, len - write_sz);
|
|
||||||
if (ret < 0) {
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
write_sz += ret;
|
|
||||||
} while (write_sz != len && ret != 0);
|
|
||||||
return write_sz;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t stream::writev(const iovec *iov, int iovcnt) {
|
ssize_t stream::writev(const iovec *iov, int iovcnt) {
|
||||||
size_t write_sz = 0;
|
size_t write_sz = 0;
|
||||||
for (int i = 0; i < iovcnt; ++i) {
|
for (int i = 0; i < iovcnt; ++i) {
|
||||||
auto ret = writeFully(iov[i].iov_base, iov[i].iov_len);
|
if (!write(iov[i].iov_base, iov[i].iov_len))
|
||||||
if (ret < 0)
|
return write_sz;
|
||||||
return ret;
|
write_sz += iov[i].iov_len;
|
||||||
write_sz += ret;
|
|
||||||
}
|
}
|
||||||
return write_sz;
|
return write_sz;
|
||||||
}
|
}
|
||||||
@ -105,7 +91,7 @@ ssize_t fp_stream::read(void *buf, size_t len) {
|
|||||||
return ret ? ret : (ferror(fp.get()) ? -1 : 0);
|
return ret ? ret : (ferror(fp.get()) ? -1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fp_stream::write(const void *buf, size_t len) {
|
ssize_t fp_stream::do_write(const void *buf, size_t len) {
|
||||||
return fwrite(buf, 1, len, fp.get());
|
return fwrite(buf, 1, len, fp.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,12 +103,11 @@ ssize_t filter_stream::read(void *buf, size_t len) {
|
|||||||
return base->read(buf, len);
|
return base->read(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t filter_stream::write(const void *buf, size_t len) {
|
bool filter_stream::write(const void *buf, size_t len) {
|
||||||
return base->write(buf, len);
|
return base->write(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t chunk_out_stream::write(const void *_in, size_t len) {
|
bool chunk_out_stream::write(const void *_in, size_t len) {
|
||||||
ssize_t ret = 0;
|
|
||||||
auto in = static_cast<const uint8_t *>(_in);
|
auto in = static_cast<const uint8_t *>(_in);
|
||||||
while (len) {
|
while (len) {
|
||||||
if (buf_off + len >= chunk_sz) {
|
if (buf_off + len >= chunk_sz) {
|
||||||
@ -140,10 +125,8 @@ ssize_t chunk_out_stream::write(const void *_in, size_t len) {
|
|||||||
in += chunk_sz;
|
in += chunk_sz;
|
||||||
len -= chunk_sz;
|
len -= chunk_sz;
|
||||||
}
|
}
|
||||||
auto r = write_chunk(src, chunk_sz);
|
if (!write_chunk(src, chunk_sz))
|
||||||
if (r < 0)
|
return false;
|
||||||
return ret;
|
|
||||||
ret += r;
|
|
||||||
} else {
|
} else {
|
||||||
// Buffer internally
|
// Buffer internally
|
||||||
if (!_buf) {
|
if (!_buf) {
|
||||||
@ -154,7 +137,7 @@ ssize_t chunk_out_stream::write(const void *_in, size_t len) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void chunk_out_stream::close() {
|
void chunk_out_stream::close() {
|
||||||
@ -177,12 +160,12 @@ ssize_t byte_stream::read(void *buf, size_t len) {
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t byte_stream::write(const void *buf, size_t len) {
|
bool byte_stream::write(const void *buf, size_t len) {
|
||||||
resize(_pos + len);
|
resize(_pos + len);
|
||||||
memcpy(_buf + _pos, buf, len);
|
memcpy(_buf + _pos, buf, len);
|
||||||
_pos += len;
|
_pos += len;
|
||||||
_len = std::max(_len, _pos);
|
_len = std::max(_len, _pos);
|
||||||
return len;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t byte_stream::seek(off_t off, int whence) {
|
off_t byte_stream::seek(off_t off, int whence) {
|
||||||
@ -227,7 +210,7 @@ ssize_t fd_stream::readv(const iovec *iov, int iovcnt) {
|
|||||||
return ::readv(fd, iov, iovcnt);
|
return ::readv(fd, iov, iovcnt);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t fd_stream::write(const void *buf, size_t len) {
|
ssize_t fd_stream::do_write(const void *buf, size_t len) {
|
||||||
return ::write(fd, buf, len);
|
return ::write(fd, buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,3 +221,18 @@ ssize_t fd_stream::writev(const iovec *iov, int iovcnt) {
|
|||||||
off_t fd_stream::seek(off_t off, int whence) {
|
off_t fd_stream::seek(off_t off, int whence) {
|
||||||
return lseek(fd, off, whence);
|
return lseek(fd, off, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user