]> git.ipfire.org Git - thirdparty/zstd.git/commitdiff
added ZSTD_setDStreamParameter()
authorYann Collet <yann.collet.73@gmail.com>
Tue, 23 Aug 2016 14:58:10 +0000 (16:58 +0200)
committerYann Collet <yann.collet.73@gmail.com>
Tue, 23 Aug 2016 14:58:10 +0000 (16:58 +0200)
lib/common/error_private.h
lib/common/error_public.h
lib/decompress/zstd_decompress.c
lib/zstd.h
tests/zstreamtest.c

index 88906149629adc108c8f6ddc757bd4df63248fe0..34c0c4c048e01b685abbb00e01656f30ece6909e 100644 (file)
@@ -93,6 +93,7 @@ ERR_STATIC const char* ERR_getErrorString(ERR_enum code)
     case PREFIX(no_error): return "No error detected";
     case PREFIX(GENERIC):  return "Error (generic)";
     case PREFIX(prefix_unknown): return "Unknown frame descriptor";
+    case PREFIX(parameter_unknown): return "Unknown parameter type";
     case PREFIX(frameParameter_unsupported): return "Unsupported frame parameter";
     case PREFIX(frameParameter_unsupportedBy32bits): return "Frame parameter unsupported in 32-bits mode";
     case PREFIX(compressionParameter_unsupported): return "Compression parameter is out of bound";
index 29050b3b3e4f393e7a655dfd030cce5cec8e8a93..10f020cfea8df70299e4a3285e4f2560e69c014e 100644 (file)
@@ -37,6 +37,9 @@
 extern "C" {
 #endif
 
+/*===== dependency =====*/
+#include <stddef.h>   /* size_t */
+
 
 /* ****************************************
 *  error codes list
@@ -45,6 +48,7 @@ typedef enum {
   ZSTD_error_no_error,
   ZSTD_error_GENERIC,
   ZSTD_error_prefix_unknown,
+  ZSTD_error_parameter_unknown,
   ZSTD_error_frameParameter_unsupported,
   ZSTD_error_frameParameter_unsupportedBy32bits,
   ZSTD_error_compressionParameter_unsupported,
index 524c2f56efa9843b70aa05abbe5bc33895630dc9..bbeca0d804e408d9a8cc9541a35fb7e631ce4b9c 100644 (file)
 
 
 /*!
-*  STREAM_WINDOW_MAX :
-*  maximum window size accepted by DStream.
-*  frames requiring more memory will be rejected.
+*  MAXWINDOWSIZE_DEFAULT :
+*  maximum window size accepted by DStream, by default.
+*  Frames requiring more memory will be rejected.
 */
-#ifndef ZSTD_STREAM_WINDOW_MAX
-#  define ZSTD_STREAM_WINDOW_MAX (257 << 20)   /* 257 MB */
+#ifndef ZSTD_MAXWINDOWSIZE_DEFAULT
+#  define ZSTD_MAXWINDOWSIZE_DEFAULT (257 << 20)   /* 257 MB */
 #endif
 
 
@@ -1329,6 +1329,7 @@ struct ZSTD_DStream_s {
     char*  inBuff;
     size_t inBuffSize;
     size_t inPos;
+    size_t maxWindowSize;
     char*  outBuff;
     size_t outBuffSize;
     size_t outStart;
@@ -1362,6 +1363,7 @@ ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem)
     zds->zd = ZSTD_createDCtx_advanced(customMem);
     if (zds->zd == NULL) { ZSTD_freeDStream(zds); return NULL; }
     zds->stage = zdss_init;
+    zds->maxWindowSize = ZSTD_MAXWINDOWSIZE_DEFAULT;
     return zds;
 }
 
@@ -1393,6 +1395,18 @@ size_t ZSTD_initDStream(ZSTD_DStream* zds)
     return ZSTD_initDStream_usingDict(zds, NULL, 0);
 }
 
+size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds,
+                                ZSTD_DStreamParameter_e paramType, unsigned paramValue)
+{
+    switch(paramType)
+    {
+        default : return ERROR(parameter_unknown);
+        case ZSTDdsp_maxWindowSize : zds->maxWindowSize = paramValue; break;
+    }
+    return 0;
+}
+
+
 size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds)
 {
     return sizeof(*zds) + ZSTD_sizeof_DCtx(zds->zd) + zds->inBuffSize + zds->outBuffSize;
@@ -1451,11 +1465,11 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
             }   }
 
             zds->fParams.windowSize = MAX(zds->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
+            if (zds->fParams.windowSize > zds->maxWindowSize) return ERROR(frameParameter_unsupported);
 
             /* Frame header instruct buffer sizes */
             {   size_t const blockSize = MIN(zds->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
                 size_t const neededOutSize = zds->fParams.windowSize + blockSize;
-                if (zds->fParams.windowSize > ZSTD_STREAM_WINDOW_MAX) return ERROR(frameParameter_unsupported);
                 zds->blockSize = blockSize;
                 if (zds->inBuffSize < blockSize) {
                     zds->customMem.customFree(zds->customMem.opaque, zds->inBuff);
index cb667484bc221fd0e39d36cdf507d856d4bf37fb..fd6170c8a2d9db6c1eaa28d4dd395aa8ad3b48d6 100644 (file)
@@ -87,7 +87,7 @@ ZSTDLIB_API size_t ZSTD_compress( void* dst, size_t dstCapacity,
 *             When `return==0`, data to decompress can have any size.
 *             In which case, it's necessary to use streaming mode to decompress data.
 *             Optionally, application may rely on its own implied limits.
-*             (For example, application own data could be necessarily cut into blocks <= 16 KB).
+*             (For example, application data could be necessarily cut into blocks <= 16 KB).
 *    note 3 : decompressed size could be wrong or intentionally modified !
 *             Always ensure result fits within application's authorized limits !
 *             Each application can set its own limits.
@@ -264,7 +264,7 @@ ZSTDLIB_API size_t ZSTD_endStream(ZSTD_CStream* zcs, ZSTD_outBuffer* output);
 *
 *  A ZSTD_DStream object is required to track streaming operations.
 *  Use ZSTD_createDStream() and ZSTD_freeDStream() to create/release resources.
-*  ZSTD_DStream objects can be re-init multiple times.
+*  ZSTD_DStream objects can be re-used multiple times.
 *
 *  Use ZSTD_initDStream() to start a new decompression operation,
 *   or ZSTD_initDStream_usingDict() if decompression requires a dictionary.
@@ -422,7 +422,7 @@ ZSTDLIB_API size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
 
 
 /* ******************************************************************
-*  Advanced Streaming
+*  Advanced Streaming functions
 ********************************************************************/
 
 /*======   compression   ======*/
@@ -436,9 +436,11 @@ ZSTDLIB_API size_t ZSTD_sizeof_CStream(const ZSTD_CStream* zcs);
 
 /*======   decompression   ======*/
 
-/* advanced */
+typedef enum { ZSTDdsp_maxWindowSize } ZSTD_DStreamParameter_e;
+
 ZSTDLIB_API ZSTD_DStream* ZSTD_createDStream_advanced(ZSTD_customMem customMem);
 ZSTDLIB_API size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t dictSize);
+ZSTDLIB_API size_t ZSTD_setDStreamParameter(ZSTD_DStream* zds, ZSTD_DStreamParameter_e paramType, unsigned paramValue);
 ZSTDLIB_API size_t ZSTD_sizeof_DStream(const ZSTD_DStream* zds);
 
 
index 4c81e8df61a242bc173bbc0f01f045474a248760..edfb07eb70ee3fdac7f5ea3b717e810cb62f9dc3 100644 (file)
@@ -212,6 +212,8 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
     /* Basic decompression test */
     DISPLAYLEVEL(4, "test%3i : decompress %u bytes : ", testNb++, COMPRESSIBLE_NOISE_LENGTH);
     ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+    { size_t const r = ZSTD_setDStreamParameter(zd, ZSTDdsp_maxWindowSize, 1000000000);  /* large limit */
+      if (ZSTD_isError(r)) goto _output_error; }
     { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
       if (r != 0) goto _output_error; }  /* should reach end of frame == 0; otherwise, some data left, or an error */
     if (outBuff.pos != CNBufferSize) goto _output_error;   /* should regenerate the same amount */
@@ -267,6 +269,27 @@ static int basicUnitTests(U32 seed, double compressibility, ZSTD_customMem custo
     }   }
     DISPLAYLEVEL(4, "OK \n");
 
+    DISPLAYLEVEL(4, "test%3i : wrong parameter for ZSTD_setDStreamParameter(): ", testNb++);
+    { size_t const r = ZSTD_setDStreamParameter(zd, (ZSTD_DStreamParameter_e)999, 1);  /* large limit */
+      if (!ZSTD_isError(r)) goto _output_error; }
+    DISPLAYLEVEL(4, "OK \n");
+
+    /* Memory restriction */
+    DISPLAYLEVEL(4, "test%3i : maxWindowSize < frame requirement : ", testNb++);
+    ZSTD_initDStream_usingDict(zd, CNBuffer, 128 KB);
+    { size_t const r = ZSTD_setDStreamParameter(zd, ZSTDdsp_maxWindowSize, 1000);  /* too small limit */
+      if (ZSTD_isError(r)) goto _output_error; }
+    inBuff.src = compressedBuffer;
+    inBuff.size = cSize;
+    inBuff.pos = 0;
+    outBuff.dst = decodedBuffer;
+    outBuff.size = CNBufferSize;
+    outBuff.pos = 0;
+    { size_t const r = ZSTD_decompressStream(zd, &outBuff, &inBuff);
+      if (!ZSTD_isError(r)) goto _output_error;  /* must fail : frame requires > 100 bytes */
+      DISPLAYLEVEL(4, "OK (%s)\n", ZSTD_getErrorName(r)); }
+
+
 _end:
     ZSTD_freeCStream(zc);
     ZSTD_freeDStream(zd);