}
}
#endif
+
+#ifndef ZLIB_COMPAT
+/* =========================================================================
+ * Checks whether buffer size is sufficient and whether this parameter is a duplicate.
+ */
+static int deflateSetParamPre(zng_deflate_param_value **out, size_t min_size, zng_deflate_param_value *param) {
+ int buf_error = param->size < min_size;
+
+ if (*out != NULL) {
+ (*out)->status = Z_BUF_ERROR;
+ buf_error = 1;
+ }
+ *out = param;
+ return buf_error;
+}
+
+/* ========================================================================= */
+int ZEXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) {
+ size_t i;
+ deflate_state *s;
+ zng_deflate_param_value *new_level = NULL;
+ zng_deflate_param_value *new_strategy = NULL;
+ int param_buf_error;
+ int version_error = 0;
+ int buf_error = 0;
+ int stream_error = 0;
+ int ret;
+
+ /* Initialize the statuses. */
+ for (i = 0; i < count; i++)
+ params[i].status = Z_OK;
+
+ /* Check whether the stream state is consistent. */
+ if (deflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ s = strm->state;
+
+ /* Check buffer sizes and detect duplicates. */
+ for (i = 0; i < count; i++) {
+ switch (params[i].param) {
+ case Z_DEFLATE_LEVEL:
+ param_buf_error = deflateSetParamPre(&new_level, sizeof(int), ¶ms[i]);
+ break;
+ case Z_DEFLATE_STRATEGY:
+ param_buf_error = deflateSetParamPre(&new_strategy, sizeof(int), ¶ms[i]);
+ break;
+ default:
+ params[i].status = Z_VERSION_ERROR;
+ version_error = 1;
+ param_buf_error = 0;
+ break;
+ }
+ if (param_buf_error) {
+ params[i].status = Z_BUF_ERROR;
+ buf_error = 1;
+ }
+ }
+ /* Exit early if small buffers or duplicates are detected. */
+ if (buf_error)
+ return Z_BUF_ERROR;
+
+ /* Apply changes, remember if there were errors. */
+ if (new_level != NULL || new_strategy != NULL) {
+ ret = PREFIX(deflateParams)(strm, new_level == NULL ? s->level : *(int *)new_level->buf,
+ new_strategy == NULL ? s->strategy : *(int *)new_strategy->buf);
+ if (ret != Z_OK) {
+ if (new_level != NULL)
+ new_level->status = Z_STREAM_ERROR;
+ if (new_strategy != NULL)
+ new_strategy->status = Z_STREAM_ERROR;
+ stream_error = 1;
+ }
+ }
+
+ /* Report version errors only if there are no real errors. */
+ return stream_error ? Z_STREAM_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK);
+}
+
+/* ========================================================================= */
+int ZEXPORT zng_deflateGetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count) {
+ deflate_state *s;
+ size_t i;
+ int buf_error = 0;
+ int version_error = 0;
+
+ /* Initialize the statuses. */
+ for (i = 0; i < count; i++)
+ params[i].status = Z_OK;
+
+ /* Check whether the stream state is consistent. */
+ if (deflateStateCheck(strm))
+ return Z_STREAM_ERROR;
+ s = strm->state;
+
+ for (i = 0; i < count; i++) {
+ switch (params[i].param) {
+ case Z_DEFLATE_LEVEL:
+ if (params[i].size < sizeof(int))
+ params[i].status = Z_BUF_ERROR;
+ else
+ *(int *)params[i].buf = s->level;
+ break;
+ case Z_DEFLATE_STRATEGY:
+ if (params[i].size < sizeof(int))
+ params[i].status = Z_BUF_ERROR;
+ else
+ *(int *)params[i].buf = s->strategy;
+ break;
+ default:
+ params[i].status = Z_VERSION_ERROR;
+ version_error = 1;
+ break;
+ }
+ if (params[i].status == Z_BUF_ERROR)
+ buf_error = 1;
+ }
+ return buf_error ? Z_BUF_ERROR : (version_error ? Z_VERSION_ERROR : Z_OK);
+}
+#endif
void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen);
void test_deflate (unsigned char *compr, size_t comprLen);
void test_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
-void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
+void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params);
void test_large_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
void test_flush (unsigned char *compr, z_size_t *comprLen);
void test_sync (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
/* ===========================================================================
* Test deflate() with large buffers and dynamic change of compression level
*/
-void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen)
+void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params)
{
PREFIX3(stream) c_stream; /* compression stream */
int err;
+#ifndef ZLIB_COMPAT
+ int level = -1;
+ int strategy = -1;
+ zng_deflate_param_value params[] = {
+ { .param = Z_DEFLATE_LEVEL, .buf = &level, .size = sizeof(level) },
+ { .param = Z_DEFLATE_STRATEGY, .buf = &strategy, .size = sizeof(strategy) },
+ };
+#endif
c_stream.zalloc = zalloc;
c_stream.zfree = zfree;
}
/* Feed in already compressed data and switch to no compression: */
- PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ if (zng_params) {
+#ifndef ZLIB_COMPAT
+ zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
+ if (level != Z_BEST_SPEED) {
+ fprintf(stderr, "Expected compression level Z_BEST_SPEED, got %d\n", level);
+ exit(1);
+ }
+ if (strategy != Z_DEFAULT_STRATEGY) {
+ fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy);
+ exit(1);
+ }
+ level = Z_NO_COMPRESSION;
+ strategy = Z_DEFAULT_STRATEGY;
+ zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
+#else
+ fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n");
+ exit(1);
+#endif
+ } else {
+ PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
+ }
c_stream.next_in = compr;
diff = (unsigned int)(c_stream.next_out - compr);
c_stream.avail_in = diff;
CHECK_ERR(err, "deflate");
/* Switch back to compressing mode: */
- PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ if (zng_params) {
+#ifndef ZLIB_COMPAT
+ level = -1;
+ strategy = -1;
+ zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
+ if (level != Z_NO_COMPRESSION) {
+ fprintf(stderr, "Expected compression level Z_NO_COMPRESSION, got %d\n", level);
+ exit(1);
+ }
+ if (strategy != Z_DEFAULT_STRATEGY) {
+ fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy);
+ exit(1);
+ }
+ level = Z_BEST_COMPRESSION;
+ strategy = Z_FILTERED;
+ zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
+#else
+ fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n");
+ exit(1);
+#endif
+ } else {
+ PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
+ }
c_stream.next_in = uncompr;
c_stream.avail_in = (unsigned int)uncomprLen;
err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
test_deflate(compr, comprLen);
test_inflate(compr, comprLen, uncompr, uncomprLen);
- test_large_deflate(compr, comprLen, uncompr, uncomprLen);
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen, 0);
+ test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+
+#ifndef ZLIB_COMPAT
+ test_large_deflate(compr, comprLen, uncompr, uncomprLen, 1);
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
+#endif
test_flush(compr, &comprLen);
test_sync(compr, comprLen, uncompr, uncomprLen);
zng_deflatePending
zng_deflatePrime
zng_deflateSetHeader
+ zng_deflateSetParams
+ zng_deflateGetParams
zng_inflateSetDictionary
zng_inflateGetDictionary
zng_inflateSync
#endif /* WITH_GZFILEOP */
+typedef enum {
+ Z_DEFLATE_LEVEL = 0, /* compression level, represented as an int */
+ Z_DEFLATE_STRATEGY = 1, /* compression strategy, represented as an int */
+} zng_deflate_param;
+
+typedef struct {
+ zng_deflate_param param; /* parameter ID */
+ void *buf; /* parameter value */
+ size_t size; /* parameter value size */
+ int status; /* result of the last set/get call */
+} zng_deflate_param_value;
+
+ZEXTERN int ZEXPORT zng_deflateSetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count);
+/*
+ Sets the values of the given zlib-ng deflate stream parameters. All the buffers are copied internally, so the
+ caller still owns them after this function returns. Returns Z_OK if success.
+
+ If the size of at least one of the buffers is too small to hold the entire value of the corresponding parameter,
+ or if the same parameter is specified multiple times, Z_BUF_ERROR is returned. The caller may inspect status fields
+ in order to determine which of the parameters caused this error. No other changes are performed.
+
+ If the stream state is inconsistent or if at least one of the values cannot be updated, Z_STREAM_ERROR is
+ returned. The caller may inspect status fields in order to determine which of the parameters caused this error.
+ Parameters, whose status field is equal to Z_OK, have been applied successfully. If all status fields are not equal
+ to Z_STREAM_ERROR, then the error was caused by a stream state inconsistency.
+
+ If there are no other errors, but at least one parameter is not supported by the current zlib-ng version,
+ Z_VERSION_ERROR is returned. The caller may inspect status fields in order to determine which of the parameters
+ caused this error.
+*/
+
+ZEXTERN int ZEXPORT zng_deflateGetParams(zng_stream *strm, zng_deflate_param_value *params, size_t count);
+/*
+ Copies the values of the given zlib-ng deflate stream parameters into the user-provided buffers. Returns Z_OK if
+ success, Z_VERSION_ERROR if at least one parameter is not supported by the current zlib-ng version, Z_STREAM_ERROR
+ if the stream state is inconsistent, and Z_BUF_ERROR if the size of at least one buffer is too small to hold the
+ entire value of the corresponding parameter.
+*/
+
+
/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or
* change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if
* both are true, the application gets the *64 functions, and the regular
zng_deflateCopy;
zng_deflateEnd;
zng_deflateGetDictionary;
+ zng_deflateGetParams;
zng_deflateInit_;
zng_deflateInit2_;
zng_deflateParams;
zng_deflateResetKeep;
zng_deflateSetDictionary;
zng_deflateSetHeader;
+ zng_deflateSetParams;
zng_deflateTune;
zng_get_crc_table;
zng_inflate;