feat: 9.5.9
This commit is contained in:
parent
cb1753732b
commit
35f43a7909
1084 changed files with 558985 additions and 0 deletions
672
c/compress-io.c
Normal file
672
c/compress-io.c
Normal file
|
|
@ -0,0 +1,672 @@
|
|||
/* compress-io.c
|
||||
* Copyright 1984-2019 Cisco Systems, Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Dispatch to zlib or LZ4 */
|
||||
|
||||
#include "system.h"
|
||||
#include "zlib.h"
|
||||
#include "lz4.h"
|
||||
#include "lz4frame.h"
|
||||
#include "lz4hc.h"
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <io.h>
|
||||
# define WIN32_IZE(id) _ ## id
|
||||
# define GLZ_O_BINARY O_BINARY
|
||||
#else
|
||||
# define WIN32_IZE(id) id
|
||||
# define GLZ_O_BINARY 0
|
||||
#endif
|
||||
|
||||
/* the value of LZ4_OUTPUT_PORT_IN_BUFFER_SIZE was determined
|
||||
through experimentation on an intel linux server and an intel
|
||||
osx laptop. smaller sizes result in significantly worse compression
|
||||
of object files, and larger sizes don't have much beneficial effect.
|
||||
don't increase the output-port in-buffer size unless you're sure
|
||||
it reduces object-file size or reduces compression time
|
||||
significantly. don't decrease it unless you're sure it doesn't
|
||||
increase object-file size significantly. one buffer of size
|
||||
LZ4_OUTPUT_PORT_IN_BUFFER_SIZE is allocated per lz4-compressed
|
||||
output port. another buffer of a closely related size is allocated
|
||||
per thread. */
|
||||
#define LZ4_OUTPUT_PORT_IN_BUFFER_SIZE (1 << 18)
|
||||
|
||||
/* the values we choose for LZ4_INPUT_PORT_IN_BUFFER_SIZE and
|
||||
LZ4_INPUT_PORT_OUT_BUFFER_SIZE don't seem to make much difference
|
||||
in decompression speed, so we keep them fairly small. one buffer
|
||||
of size LZ4_INPUT_PORT_IN_BUFFER_SIZE and one buffer of size
|
||||
LZ4_INPUT_PORT_OUT_BUFFER_SIZE are allocated per lz4-compressed
|
||||
input port. */
|
||||
#define LZ4_INPUT_PORT_IN_BUFFER_SIZE (1 << 12)
|
||||
#define LZ4_INPUT_PORT_OUT_BUFFER_SIZE (1 << 14)
|
||||
|
||||
typedef struct lz4File_out_r {
|
||||
LZ4F_preferences_t preferences;
|
||||
INT fd;
|
||||
INT out_buffer_size;
|
||||
INT in_pos;
|
||||
INT err;
|
||||
size_t stream_pos;
|
||||
char in_buffer[LZ4_OUTPUT_PORT_IN_BUFFER_SIZE];
|
||||
} lz4File_out;
|
||||
|
||||
typedef struct lz4File_in_r {
|
||||
INT fd;
|
||||
LZ4F_dctx *dctx;
|
||||
INT in_pos, in_len, out_pos, out_len;
|
||||
INT frame_ended;
|
||||
INT err;
|
||||
size_t stream_pos;
|
||||
off_t init_pos;
|
||||
char in_buffer[LZ4_INPUT_PORT_IN_BUFFER_SIZE];
|
||||
char out_buffer[LZ4_INPUT_PORT_OUT_BUFFER_SIZE];
|
||||
} lz4File_in;
|
||||
|
||||
typedef struct sized_buffer_r {
|
||||
INT size;
|
||||
char buffer[0];
|
||||
} sized_buffer;
|
||||
|
||||
/* local functions */
|
||||
static glzFile glzdopen_output_gz(INT fd, INT compress_level);
|
||||
static glzFile glzdopen_output_lz4(INT fd, INT compress_level);
|
||||
static glzFile glzdopen_input_gz(INT fd);
|
||||
static glzFile glzdopen_input_lz4(INT fd, off_t init_pos);
|
||||
static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count);
|
||||
static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count);
|
||||
static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count);
|
||||
|
||||
INT S_zlib_compress_level(INT compress_level) {
|
||||
switch (compress_level) {
|
||||
case COMPRESS_MIN:
|
||||
case COMPRESS_LOW:
|
||||
return Z_BEST_SPEED;
|
||||
case COMPRESS_MEDIUM:
|
||||
return (Z_BEST_SPEED + Z_BEST_COMPRESSION) / 2;
|
||||
case COMPRESS_HIGH:
|
||||
return (Z_BEST_SPEED + (3 * Z_BEST_COMPRESSION)) / 4;
|
||||
case COMPRESS_MAX:
|
||||
return Z_BEST_COMPRESSION;
|
||||
default:
|
||||
S_error1("S_zlib_compress_level", "unexpected compress level ~s", Sinteger(compress_level));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_output_gz(INT fd, INT compress_level) {
|
||||
gzFile gz;
|
||||
glzFile glz;
|
||||
INT as_append;
|
||||
INT level;
|
||||
|
||||
#ifdef WIN32
|
||||
as_append = 0;
|
||||
#else
|
||||
as_append = fcntl(fd, F_GETFL) & O_APPEND;
|
||||
#endif
|
||||
|
||||
if ((gz = gzdopen(fd, as_append ? "ab" : "wb")) == Z_NULL) return Z_NULL;
|
||||
|
||||
level = S_zlib_compress_level(compress_level);
|
||||
|
||||
gzsetparams(gz, level, Z_DEFAULT_STRATEGY);
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)gzclose(gz);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 0;
|
||||
glz->format = COMPRESS_GZIP;
|
||||
glz->gz = gz;
|
||||
return glz;
|
||||
}
|
||||
|
||||
INT S_lz4_compress_level(INT compress_level) {
|
||||
switch (compress_level) {
|
||||
case COMPRESS_MIN:
|
||||
case COMPRESS_LOW:
|
||||
return 1;
|
||||
case COMPRESS_MEDIUM:
|
||||
return LZ4HC_CLEVEL_MIN;
|
||||
case COMPRESS_HIGH:
|
||||
return (LZ4HC_CLEVEL_MIN + LZ4HC_CLEVEL_MAX) / 2;
|
||||
case COMPRESS_MAX:
|
||||
return LZ4HC_CLEVEL_MAX;
|
||||
default:
|
||||
S_error1("S_lz4_compress_level", "unexpected compress level ~s", Sinteger(compress_level));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_output_lz4(INT fd, INT compress_level) {
|
||||
glzFile glz;
|
||||
lz4File_out *lz4;
|
||||
INT level;
|
||||
|
||||
level = S_lz4_compress_level(compress_level);
|
||||
|
||||
if ((lz4 = malloc(sizeof(lz4File_out))) == NULL) return Z_NULL;
|
||||
memset(&lz4->preferences, 0, sizeof(LZ4F_preferences_t));
|
||||
lz4->preferences.compressionLevel = level;
|
||||
lz4->fd = fd;
|
||||
lz4->out_buffer_size = (INT)LZ4F_compressFrameBound(LZ4_OUTPUT_PORT_IN_BUFFER_SIZE, &lz4->preferences);
|
||||
lz4->in_pos = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
free(lz4);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 0;
|
||||
glz->format = COMPRESS_LZ4;
|
||||
glz->lz4_out = lz4;
|
||||
return glz;
|
||||
}
|
||||
|
||||
glzFile S_glzdopen_output(INT fd, INT compress_format, INT compress_level) {
|
||||
switch (compress_format) {
|
||||
case COMPRESS_GZIP:
|
||||
return glzdopen_output_gz(fd, compress_level);
|
||||
case COMPRESS_LZ4:
|
||||
return glzdopen_output_lz4(fd, compress_level);
|
||||
default:
|
||||
S_error1("glzdopen_output", "unexpected compress format ~s", Sinteger(compress_format));
|
||||
return Z_NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static glzFile glzdopen_input_gz(INT fd) {
|
||||
gzFile gz;
|
||||
glzFile glz;
|
||||
|
||||
if ((gz = gzdopen(fd, "rb")) == Z_NULL) return Z_NULL;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)gzclose(gz);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 1;
|
||||
glz->format = COMPRESS_GZIP;
|
||||
glz->gz = gz;
|
||||
return glz;
|
||||
}
|
||||
|
||||
static glzFile glzdopen_input_lz4(INT fd, off_t init_pos) {
|
||||
glzFile glz;
|
||||
LZ4F_dctx *dctx;
|
||||
LZ4F_errorCode_t r;
|
||||
lz4File_in *lz4;
|
||||
|
||||
r = LZ4F_createDecompressionContext(&dctx, LZ4F_VERSION);
|
||||
if (LZ4F_isError(r))
|
||||
return Z_NULL;
|
||||
|
||||
if ((lz4 = malloc(sizeof(lz4File_in))) == NULL) {
|
||||
(void)LZ4F_freeDecompressionContext(dctx);
|
||||
return Z_NULL;
|
||||
}
|
||||
lz4->fd = fd;
|
||||
lz4->dctx = dctx;
|
||||
lz4->in_pos = 0;
|
||||
lz4->in_len = 0;
|
||||
lz4->out_len = 0;
|
||||
lz4->out_pos = 0;
|
||||
lz4->frame_ended = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
lz4->init_pos = init_pos;
|
||||
|
||||
if ((glz = malloc(sizeof(struct glzFile_r))) == NULL) {
|
||||
(void)LZ4F_freeDecompressionContext(lz4->dctx);
|
||||
free(lz4);
|
||||
return Z_NULL;
|
||||
}
|
||||
glz->fd = fd;
|
||||
glz->inputp = 1;
|
||||
glz->format = COMPRESS_LZ4;
|
||||
glz->lz4_in = lz4;
|
||||
return glz;
|
||||
}
|
||||
|
||||
glzFile S_glzdopen_input(INT fd) {
|
||||
INT r, pos = 0;
|
||||
unsigned char buffer[4];
|
||||
off_t init_pos;
|
||||
|
||||
/* check for LZ4 magic number, otherwise defer to gzdopen */
|
||||
|
||||
if ((init_pos = WIN32_IZE(lseek)(fd, 0, SEEK_CUR)) == -1) return Z_NULL;
|
||||
|
||||
while (pos < 4) {
|
||||
r = WIN32_IZE(read)(fd, (char*)buffer + pos, 4 - pos);
|
||||
if (r == 0)
|
||||
break;
|
||||
else if (r > 0)
|
||||
pos += r;
|
||||
#ifdef EINTR
|
||||
else if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
else
|
||||
break; /* error reading */
|
||||
}
|
||||
|
||||
if (pos > 0) {
|
||||
if (WIN32_IZE(lseek)(fd, init_pos, SEEK_SET) == -1) return Z_NULL;
|
||||
}
|
||||
|
||||
if ((pos == 4)
|
||||
&& (buffer[0] == 0x04)
|
||||
&& (buffer[1] == 0x22)
|
||||
&& (buffer[2] == 0x4d)
|
||||
&& (buffer[3] == 0x18))
|
||||
return glzdopen_input_lz4(fd, init_pos);
|
||||
|
||||
return glzdopen_input_gz(fd);
|
||||
}
|
||||
|
||||
glzFile S_glzopen_input(const char *path) {
|
||||
INT fd;
|
||||
|
||||
fd = WIN32_IZE(open)(path, O_RDONLY | GLZ_O_BINARY);
|
||||
|
||||
if (fd == -1)
|
||||
return Z_NULL;
|
||||
else
|
||||
return S_glzdopen_input(fd);
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
glzFile S_glzopen_input_w(const wchar_t *path) {
|
||||
INT fd;
|
||||
|
||||
fd = _wopen(path, O_RDONLY | GLZ_O_BINARY);
|
||||
|
||||
if (fd == -1)
|
||||
return Z_NULL;
|
||||
else
|
||||
return S_glzdopen_input(fd);
|
||||
}
|
||||
#endif
|
||||
|
||||
IBOOL S_glzdirect(glzFile glz) {
|
||||
if (glz->format == COMPRESS_GZIP)
|
||||
return gzdirect(glz->gz);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT S_glzclose(glzFile glz) {
|
||||
INT r = Z_OK, saved_errno = 0;
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
r = gzclose(glz->gz);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp) {
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
while (1) {
|
||||
INT r = WIN32_IZE(close)(lz4->fd);
|
||||
#ifdef EINTR
|
||||
if (r < 0 && errno == EINTR) continue;
|
||||
#endif
|
||||
if (r == 0) { saved_errno = errno; }
|
||||
break;
|
||||
}
|
||||
(void)LZ4F_freeDecompressionContext(lz4->dctx);
|
||||
free(lz4);
|
||||
} else {
|
||||
lz4File_out *lz4 = glz->lz4_out;
|
||||
if (lz4->in_pos != 0) {
|
||||
r = glzemit_lz4(lz4, lz4->in_buffer, lz4->in_pos);
|
||||
if (r >= 0) r = Z_OK; else { r = Z_ERRNO; saved_errno = errno; }
|
||||
}
|
||||
while (1) {
|
||||
int r1 = WIN32_IZE(close)(lz4->fd);
|
||||
#ifdef EINTR
|
||||
if (r1 < 0 && errno == EINTR) continue;
|
||||
#endif
|
||||
if (r == Z_OK && r1 < 0) { r = Z_ERRNO; saved_errno = errno; }
|
||||
break;
|
||||
}
|
||||
free(lz4);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzclose", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
}
|
||||
free(glz);
|
||||
if (saved_errno) errno = saved_errno;
|
||||
return r;
|
||||
}
|
||||
|
||||
static INT glzread_lz4(lz4File_in *lz4, void *buffer, UINT count) {
|
||||
while (lz4->out_pos == lz4->out_len) {
|
||||
INT in_avail;
|
||||
|
||||
in_avail = lz4->in_len - lz4->in_pos;
|
||||
if (!in_avail) {
|
||||
while (1) {
|
||||
in_avail = WIN32_IZE(read)(lz4->fd, lz4->in_buffer, LZ4_INPUT_PORT_IN_BUFFER_SIZE);
|
||||
if (in_avail >= 0) {
|
||||
lz4->in_len = in_avail;
|
||||
lz4->in_pos = 0;
|
||||
break;
|
||||
#ifdef EINTR
|
||||
} else if (errno == EINTR) {
|
||||
/* try again */
|
||||
#endif
|
||||
} else {
|
||||
lz4->err = Z_ERRNO;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (in_avail > 0) {
|
||||
size_t amt, out_len = LZ4_INPUT_PORT_OUT_BUFFER_SIZE, in_len = in_avail;
|
||||
|
||||
/* For a large enough result buffer, try to decompress directly
|
||||
to that buffer: */
|
||||
if (count >= (out_len >> 1)) {
|
||||
size_t direct_out_len = count;
|
||||
|
||||
if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0)
|
||||
return 0; /* count 0 after frame as stream terminator */
|
||||
|
||||
amt = LZ4F_decompress(lz4->dctx,
|
||||
buffer, &direct_out_len,
|
||||
lz4->in_buffer + lz4->in_pos, &in_len,
|
||||
NULL);
|
||||
lz4->frame_ended = (amt == 0);
|
||||
|
||||
if (LZ4F_isError(amt)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lz4->in_pos += (INT)in_len;
|
||||
|
||||
if (direct_out_len) {
|
||||
lz4->stream_pos += direct_out_len;
|
||||
return (INT)direct_out_len;
|
||||
}
|
||||
|
||||
in_len = in_avail - in_len;
|
||||
}
|
||||
|
||||
if (in_len > 0) {
|
||||
if (lz4->frame_ended && lz4->in_buffer[lz4->in_pos] == 0)
|
||||
return 0; /* count 0 after frame as stream terminator */
|
||||
|
||||
amt = LZ4F_decompress(lz4->dctx,
|
||||
lz4->out_buffer, &out_len,
|
||||
lz4->in_buffer + lz4->in_pos, &in_len,
|
||||
NULL);
|
||||
lz4->frame_ended = (amt == 0);
|
||||
|
||||
if (LZ4F_isError(amt)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
lz4->in_pos += (INT)in_len;
|
||||
lz4->out_len = (INT)out_len;
|
||||
lz4->out_pos = 0;
|
||||
}
|
||||
} else {
|
||||
/* EOF on read */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lz4->out_pos < lz4->out_len) {
|
||||
UINT amt = lz4->out_len - lz4->out_pos;
|
||||
if (amt > count) amt = count;
|
||||
memcpy(buffer, lz4->out_buffer + lz4->out_pos, amt);
|
||||
lz4->out_pos += amt;
|
||||
lz4->stream_pos += amt;
|
||||
return amt;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
INT S_glzread(glzFile glz, void *buffer, UINT count) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzread(glz->gz, buffer, count);
|
||||
case COMPRESS_LZ4:
|
||||
return glzread_lz4(glz->lz4_in, buffer, count);
|
||||
default:
|
||||
S_error1("S_glzread", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static INT glzemit_lz4(lz4File_out *lz4, void *buffer, UINT count) {
|
||||
ptr tc = get_thread_context();
|
||||
sized_buffer *cached_out_buffer;
|
||||
char *out_buffer;
|
||||
INT out_len, out_pos;
|
||||
INT r = 0;
|
||||
|
||||
/* allocate one out_buffer (per thread) since we don't need one for each file.
|
||||
the buffer is freed by destroy_thread. */
|
||||
if ((cached_out_buffer = LZ4OUTBUFFER(tc)) == NULL || cached_out_buffer->size < lz4->out_buffer_size) {
|
||||
if (cached_out_buffer != NULL) free(cached_out_buffer);
|
||||
if ((LZ4OUTBUFFER(tc) = cached_out_buffer = malloc(sizeof(sized_buffer) + lz4->out_buffer_size)) == NULL) return -1;
|
||||
cached_out_buffer->size = lz4->out_buffer_size;
|
||||
}
|
||||
out_buffer = cached_out_buffer->buffer;
|
||||
|
||||
out_len = (INT)LZ4F_compressFrame(out_buffer, lz4->out_buffer_size,
|
||||
buffer, count,
|
||||
&lz4->preferences);
|
||||
if (LZ4F_isError(out_len)) {
|
||||
lz4->err = Z_STREAM_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
||||
out_pos = 0;
|
||||
while (out_pos < out_len) {
|
||||
r = WIN32_IZE(write)(lz4->fd, out_buffer + out_pos, out_len - out_pos);
|
||||
if (r >= 0)
|
||||
out_pos += r;
|
||||
#ifdef EINTR
|
||||
else if (errno == EINTR)
|
||||
continue;
|
||||
#endif
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static INT glzwrite_lz4(lz4File_out *lz4, void *buffer, UINT count) {
|
||||
UINT amt; INT r;
|
||||
|
||||
if ((amt = LZ4_OUTPUT_PORT_IN_BUFFER_SIZE - lz4->in_pos) > count) amt = count;
|
||||
|
||||
if (amt == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) {
|
||||
/* full buffer coming from input...skip the memcpy */
|
||||
if ((r = glzemit_lz4(lz4, buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0;
|
||||
} else {
|
||||
memcpy(lz4->in_buffer + lz4->in_pos, buffer, amt);
|
||||
if ((lz4->in_pos += amt) == LZ4_OUTPUT_PORT_IN_BUFFER_SIZE) {
|
||||
lz4->in_pos = 0;
|
||||
if ((r = glzemit_lz4(lz4, lz4->in_buffer, LZ4_OUTPUT_PORT_IN_BUFFER_SIZE)) < 0) return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lz4->stream_pos += amt;
|
||||
return amt;
|
||||
}
|
||||
|
||||
INT S_glzwrite(glzFile glz, void *buffer, UINT count) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzwrite(glz->gz, buffer, count);
|
||||
case COMPRESS_LZ4:
|
||||
return glzwrite_lz4(glz->lz4_out, buffer, count);
|
||||
default:
|
||||
S_error1("S_glzwrite", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
long S_glzseek(glzFile glz, long offset, INT whence) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzseek(glz->gz, offset, whence);
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp) {
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
if (whence == SEEK_CUR)
|
||||
offset += (long)lz4->stream_pos;
|
||||
if (offset < 0)
|
||||
offset = 0;
|
||||
if ((size_t)offset < lz4->stream_pos) {
|
||||
/* rewind and read from start */
|
||||
if (WIN32_IZE(lseek)(lz4->fd, lz4->init_pos, SEEK_SET) < 0) {
|
||||
lz4->err = Z_ERRNO;
|
||||
return -1;
|
||||
}
|
||||
LZ4F_resetDecompressionContext(lz4->dctx);
|
||||
lz4->in_pos = 0;
|
||||
lz4->in_len = 0;
|
||||
lz4->out_len = 0;
|
||||
lz4->out_pos = 0;
|
||||
lz4->err = 0;
|
||||
lz4->stream_pos = 0;
|
||||
}
|
||||
while ((size_t)offset > lz4->stream_pos) {
|
||||
static char buffer[1024];
|
||||
size_t amt = (size_t)offset - lz4->stream_pos;
|
||||
if (amt > sizeof(buffer)) amt = sizeof(buffer);
|
||||
if (glzread_lz4(lz4, buffer, (UINT)amt) < 0)
|
||||
return -1;
|
||||
}
|
||||
return (long)lz4->stream_pos;
|
||||
} else {
|
||||
lz4File_out *lz4 = glz->lz4_out;
|
||||
if (whence == SEEK_CUR)
|
||||
offset += (long)lz4->stream_pos;
|
||||
if (offset >= 0) {
|
||||
while ((size_t)offset > lz4->stream_pos) {
|
||||
size_t amt = (size_t)offset - lz4->stream_pos;
|
||||
if (amt > 8) amt = 8;
|
||||
if (glzwrite_lz4(lz4, "\0\0\0\0\0\0\0\0", (UINT)amt) < 0)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return (long)lz4->stream_pos;
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzseek", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzgetc(glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzgetc(glz->gz);
|
||||
case COMPRESS_LZ4:
|
||||
{
|
||||
unsigned char buffer[1];
|
||||
INT r;
|
||||
r = S_glzread(glz, buffer, 1);
|
||||
if (r == 1)
|
||||
return buffer[0];
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzgetc", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzungetc(INT c, glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
return gzungetc(c, glz->gz);
|
||||
case COMPRESS_LZ4:
|
||||
{
|
||||
lz4File_in *lz4 = glz->lz4_in;
|
||||
if (lz4->out_len == 0)
|
||||
lz4->out_len = lz4->out_pos = 1;
|
||||
if (lz4->out_pos) {
|
||||
lz4->out_pos--;
|
||||
lz4->out_buffer[lz4->out_pos] = c;
|
||||
lz4->stream_pos--;
|
||||
return c;
|
||||
} else {
|
||||
/* support ungetc only just after a getc, in which case there
|
||||
should have been room */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
default:
|
||||
S_error1("S_glzungetc", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
INT S_glzrewind(glzFile glz) {
|
||||
return S_glzseek(glz, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
void S_glzerror(glzFile glz, INT *errnum) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
(void)gzerror(glz->gz, errnum);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp)
|
||||
*errnum = glz->lz4_in->err;
|
||||
else
|
||||
*errnum = glz->lz4_out->err;
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
*errnum = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void S_glzclearerr(glzFile glz) {
|
||||
switch (glz->format) {
|
||||
case COMPRESS_GZIP:
|
||||
gzclearerr(glz->gz);
|
||||
break;
|
||||
case COMPRESS_LZ4:
|
||||
if (glz->inputp)
|
||||
glz->lz4_in->err = 0;
|
||||
else
|
||||
glz->lz4_out->err = 0;
|
||||
break;
|
||||
default:
|
||||
S_error1("S_glzerror", "unexpected compress format ~s", Sinteger(glz->format));
|
||||
}
|
||||
}
|
||||
Reference in a new issue