1
1

comp: split the compress function

It is now made into two separate compress and decompress functions. In
preparation for upcoming further modficications.
Этот коммит содержится в:
Daniel Stenberg 2010-10-20 23:58:41 +02:00
родитель 784db8e987
Коммит 64063d5f0b
2 изменённых файлов: 153 добавлений и 4 удалений

Просмотреть файл

@ -1,4 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2010, Daniel Stenberg <daniel@haxx.se>
* All rights reserved.
*
* Redistribution and use in source and binary forms,
@ -80,6 +81,7 @@ static const LIBSSH2_COMP_METHOD comp_method_none = {
0, /* not really compressing */
NULL,
comp_method_none_comp,
comp_method_none_comp,
NULL
};
@ -149,10 +151,10 @@ comp_method_zlib_init(LIBSSH2_SESSION * session, int compress,
return LIBSSH2_ERROR_NONE;
}
/* libssh2_comp_method_zlib_comp
* zlib, a compression standard for all occasions
/*
* libssh2_comp_method_zlib_comp
*
* Compresses source to destination. Without any allocation.
*/
static int
comp_method_zlib_comp(LIBSSH2_SESSION * session,
@ -290,6 +292,147 @@ comp_method_zlib_comp(LIBSSH2_SESSION * session,
return 0;
}
/*
* libssh2_comp_method_zlib_decomp
*
* Decompresses source to destination. Allocates the output memory.
*/
static int
comp_method_zlib_decomp(LIBSSH2_SESSION * session,
int compress,
unsigned char **dest,
size_t *dest_len,
size_t payload_limit,
int *free_dest,
const unsigned char *src,
size_t src_len, void **abstract)
{
z_stream *strm = *abstract;
/* A short-term alloc of a full data chunk is better than a series of
reallocs */
char *out;
int out_maxlen = compress ? (src_len + 4) : (2 * src_len);
int limiter = 0;
/* If strm is null, then we have not yet been initialized. */
if (strm == NULL) {
*dest = (unsigned char *) src;
*dest_len = src_len;
*free_dest = 0;
return 0;
}
/* In practice they never come smaller than this */
if (out_maxlen < 25) {
out_maxlen = 25;
}
if (out_maxlen > (int) payload_limit) {
out_maxlen = payload_limit;
}
strm->next_in = (unsigned char *) src;
strm->avail_in = src_len;
strm->next_out = (unsigned char *) LIBSSH2_ALLOC(session, out_maxlen);
out = (char *) strm->next_out;
strm->avail_out = out_maxlen;
if (!strm->next_out) {
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to allocate compression/decompression "
"buffer");
}
while (strm->avail_in) {
int status;
if (compress) {
status = deflate(strm, Z_PARTIAL_FLUSH);
} else {
status = inflate(strm, Z_PARTIAL_FLUSH);
}
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
}
if (strm->avail_in) {
size_t out_ofs = out_maxlen - strm->avail_out;
char *newout;
out_maxlen +=
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
if ((out_maxlen > (int) payload_limit) && !compress && limiter++) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression phase");
}
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand compress/"
"decompression buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_ofs;
strm->avail_out +=
compress ? (strm->avail_in + 4) : (2 * strm->avail_in);
} else
while (!strm->avail_out) {
/* Done with input, might be a byte or two in internal buffer
* during compress. Or potentially many bytes if it's a
* decompress
*/
int grow_size = compress ? 8 : 1024;
char *newout;
if (out_maxlen >= (int) payload_limit) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"Excessive growth in decompression "
"phase");
}
if (grow_size > (int) (payload_limit - out_maxlen)) {
grow_size = payload_limit - out_maxlen;
}
out_maxlen += grow_size;
strm->avail_out = grow_size;
newout = LIBSSH2_REALLOC(session, out, out_maxlen);
if (!newout) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ALLOC,
"Unable to expand final compress/"
"decompress buffer");
}
out = newout;
strm->next_out = (unsigned char *) out + out_maxlen -
grow_size;
if (compress) {
status = deflate(strm, Z_PARTIAL_FLUSH);
} else {
status = inflate(strm, Z_PARTIAL_FLUSH);
}
if (status != Z_OK) {
LIBSSH2_FREE(session, out);
return _libssh2_error(session, LIBSSH2_ERROR_ZLIB,
"compress/decompression failure");
}
}
}
*dest = (unsigned char *) out;
*dest_len = out_maxlen - strm->avail_out;
*free_dest = 1;
return 0;
}
/* libssh2_comp_method_zlib_dtor
* All done, no more compression for you
@ -322,6 +465,7 @@ static const LIBSSH2_COMP_METHOD comp_method_zlib = {
1, /* yes, this compresses */
comp_method_zlib_init,
comp_method_zlib_comp,
comp_method_zlib_decomp,
comp_method_zlib_dtor,
};
#endif /* LIBSSH2_HAVE_ZLIB */

Просмотреть файл

@ -1007,6 +1007,11 @@ struct _LIBSSH2_COMP_METHOD
size_t *dest_len, size_t payload_limit,
int *free_dest, const unsigned char *src,
size_t src_len, void **abstract);
int (*decomp) (LIBSSH2_SESSION * session, int compress,
unsigned char **dest,
size_t *dest_len, size_t payload_limit,
int *free_dest, const unsigned char *src,
size_t src_len, void **abstract);
int (*dtor) (LIBSSH2_SESSION * session, int compress, void **abstract);
};