From: Yann Collet Date: Wed, 14 Nov 2018 01:36:35 +0000 (-0800) Subject: added constant ZSTD_MAGIC_SKIPPABLE_MASK X-Git-Tag: v1.3.8~33^2~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c8fde538faa229e05c9d7230cf462d8eef17743;p=thirdparty%2Fzstd.git added constant ZSTD_MAGIC_SKIPPABLE_MASK and updated several API comments --- diff --git a/doc/zstd_manual.html b/doc/zstd_manual.html index afacd6cc3..7963bca19 100644 --- a/doc/zstd_manual.html +++ b/doc/zstd_manual.html @@ -20,16 +20,17 @@
  • Streaming decompression - HowTo
  • ADVANCED AND EXPERIMENTAL FUNCTIONS
  • Candidate API for promotion into stable
  • -
  • Frame size functions
  • -
  • Memory management
  • -
  • Advanced compression functions
  • -
  • Advanced decompression functions
  • -
  • Advanced streaming functions
  • -
  • Buffer-less and synchronous inner streaming functions
  • -
  • Buffer-less streaming compression (synchronous mode)
  • -
  • Buffer-less streaming decompression (synchronous mode)
  • -
  • New advanced API (experimental)
  • -
  • Block level API
  • +
  • Purely experimental API
  • +
  • Frame size functions
  • +
  • Memory management
  • +
  • Advanced compression functions
  • +
  • Advanced decompression functions
  • +
  • Advanced streaming functions
  • +
  • Buffer-less and synchronous inner streaming functions
  • +
  • Buffer-less streaming compression (synchronous mode)
  • +
  • Buffer-less streaming decompression (synchronous mode)
  • +
  • New advanced API (experimental)
  • +
  • Block level API

  • Introduction

    @@ -356,23 +357,38 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
     
     
    int ZSTD_minCLevel(void);  /*!< minimum negative compression level allowed */
     

    -
    typedef enum { ZSTD_fast=1, ZSTD_dfast, ZSTD_greedy, ZSTD_lazy, ZSTD_lazy2,
    -               ZSTD_btlazy2, ZSTD_btopt, ZSTD_btultra } ZSTD_strategy;   /* from faster to stronger */
    +

    Purely experimental API

    + The following symbols and constants are not planned
    + to join "stable API" status anytime soon.
    + Some of them might even be removed in the future.
    + 
    +
    + +
    typedef enum { ZSTD_fast=1,
    +               ZSTD_dfast=2,
    +               ZSTD_greedy=3,
    +               ZSTD_lazy=4,
    +               ZSTD_lazy2=5,
    +               ZSTD_btlazy2=6,
    +               ZSTD_btopt=7,
    +               ZSTD_btultra=8
    +               /* note : new strategies might be added in the future */
    +           } ZSTD_strategy;
     

    typedef struct {
    -    unsigned windowLog;      /**< largest match distance : larger == more compression, more memory needed during decompression */
    -    unsigned chainLog;       /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
    -    unsigned hashLog;        /**< dispatch table : larger == faster, more memory */
    -    unsigned searchLog;      /**< nb of searches : larger == more compression, slower */
    -    unsigned searchLength;   /**< match length searched : larger == faster decompression, sometimes less compression */
    -    unsigned targetLength;   /**< acceptable match size for optimal parser (only) : larger == more compression, slower */
    -    ZSTD_strategy strategy;
    +    unsigned windowLog;       /**< largest match distance : larger == more compression, more memory needed during decompression */
    +    unsigned chainLog;        /**< fully searched segment : larger == more compression, slower, more memory (useless for fast) */
    +    unsigned hashLog;         /**< dispatch table : larger == faster, more memory */
    +    unsigned searchLog;       /**< nb of searches : larger == more compression, slower */
    +    unsigned searchLength;    /**< match length searched : larger == faster decompression, sometimes less compression */
    +    unsigned targetLength;    /**< acceptable match size for optimal parser (only) : larger == more compression, slower */
    +    ZSTD_strategy strategy;   /**< see ZSTD_strategy definition above */
     } ZSTD_compressionParameters;
     

    typedef struct {
         unsigned contentSizeFlag; /**< 1: content size will be in frame header (when known) */
    -    unsigned checksumFlag;    /**< 1: generate a 32-bits checksum at end of frame, for error detection */
    -    unsigned noDictIDFlag;    /**< 1: no dictID will be saved into frame header (if dictionary compression) */
    +    unsigned checksumFlag;    /**< 1: generate a 32-bits checksum using XXH64 algorithm at end of frame, for error detection */
    +    unsigned noDictIDFlag;    /**< 1: no dictID will be saved into frame header (dictID is only useful for dictionary compression) */
     } ZSTD_frameParameters;
     

    typedef struct {
    @@ -381,17 +397,17 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB
     } ZSTD_parameters;
     

    typedef enum {
    -    ZSTD_dct_auto = 0,    /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
    -    ZSTD_dct_rawContent,  /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
    -    ZSTD_dct_fullDict     /* refuses to load a dictionary if it does not respect Zstandard's specification */
    +    ZSTD_dct_auto = 0,       /* dictionary is "full" when starting with ZSTD_MAGIC_DICTIONARY, otherwise it is "rawContent" */
    +    ZSTD_dct_rawContent = 1, /* ensures dictionary is always loaded as rawContent, even if it starts with ZSTD_MAGIC_DICTIONARY */
    +    ZSTD_dct_fullDict = 2    /* refuses to load a dictionary if it does not respect Zstandard's specification, starting with ZSTD_MAGIC_DICTIONARY */
     } ZSTD_dictContentType_e;
     

    typedef enum {
    -    ZSTD_dlm_byCopy = 0, /**< Copy dictionary content internally */
    -    ZSTD_dlm_byRef,      /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
    +    ZSTD_dlm_byCopy = 0,  /**< Copy dictionary content internally */
    +    ZSTD_dlm_byRef = 1,   /**< Reference dictionary content -- the dictionary buffer must outlive its users. */
     } ZSTD_dictLoadMethod_e;
     

    -

    Frame size functions

    
    +

    Frame size functions

    
     
     
    size_t ZSTD_findFrameCompressedSize(const void* src, size_t srcSize);
     

    `src` should point to the start of a ZSTD encoded frame or skippable frame @@ -430,7 +446,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB or an error code (if srcSize is too small)


    -

    Memory management

    
    +

    Memory management

    
     
     
    size_t ZSTD_sizeof_CCtx(const ZSTD_CCtx* cctx);
     size_t ZSTD_sizeof_DCtx(const ZSTD_DCtx* dctx);
    @@ -520,7 +536,7 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL };  /**< t
      
     


    -

    Advanced compression functions

    
    +

    Advanced compression functions

    
     
     
    ZSTD_CDict* ZSTD_createCDict_byReference(const void* dictBuffer, size_t dictSize, int compressionLevel);
     

    Create a digested dictionary for compression @@ -562,7 +578,7 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< t

    Same as ZSTD_compress_usingCDict(), with fine-tune control over frame parameters


    -

    Advanced decompression functions

    
    +

    Advanced decompression functions

    
     
     
    unsigned ZSTD_isFrame(const void* buffer, size_t size);
     

    Tells if the content of `buffer` starts with a valid Frame Identifier. @@ -602,7 +618,7 @@ static ZSTD_customMem const ZSTD_defaultCMem = { NULL, NULL, NULL }; /**< t When identifying the exact failure cause, it's possible to use ZSTD_getFrameHeader(), which will provide a more precise error code.


    -

    Advanced streaming functions

    
    +

    Advanced streaming functions

    
     
     

    Advanced Streaming compression functions

    size_t ZSTD_initCStream_srcSize(ZSTD_CStream* zcs, int compressionLevel, unsigned long long pledgedSrcSize);   /**< pledgedSrcSize must be correct. If it is not known at init time, use ZSTD_CONTENTSIZE_UNKNOWN. Note that, for compatibility with older programs, "0" also disables frame content size field. It may be enabled in the future. */
     size_t ZSTD_initCStream_usingDict(ZSTD_CStream* zcs, const void* dict, size_t dictSize, int compressionLevel); /**< creates of an internal CDict (incompatible with static CCtx), except if dict == NULL or dictSize < 8, in which case no dict is used. Note: dict is loaded with ZSTD_dm_auto (treated as a full zstd dictionary if it begins with ZSTD_MAGIC_DICTIONARY, else as raw content) and ZSTD_dlm_byCopy.*/
    @@ -653,14 +669,14 @@ size_t ZSTD_initDStream_usingDict(ZSTD_DStream* zds, const void* dict, size_t di
     size_t ZSTD_initDStream_usingDDict(ZSTD_DStream* zds, const ZSTD_DDict* ddict);  /**< note : ddict is referenced, it must outlive decompression session */
     size_t ZSTD_resetDStream(ZSTD_DStream* zds);  /**< re-use decompression parameters from previous init; saves dictionary loading */
     

    -

    Buffer-less and synchronous inner streaming functions

    +

    Buffer-less and synchronous inner streaming functions

       This is an advanced API, giving full control over buffer management, for users which need direct control over memory.
       But it's also a complex one, with several restrictions, documented below.
       Prefer normal streaming API for an easier experience.
      
     
    -

    Buffer-less streaming compression (synchronous mode)

    +

    Buffer-less streaming compression (synchronous mode)

       A ZSTD_CCtx object is required to track streaming operations.
       Use ZSTD_createCCtx() / ZSTD_freeCCtx() to manage resource.
       ZSTD_CCtx object can be re-used multiple times within successive compression operations.
    @@ -696,7 +712,7 @@ size_t ZSTD_compressBegin_usingCDict(ZSTD_CCtx* cctx, const ZSTD_CDict* cdict);
     size_t ZSTD_compressBegin_usingCDict_advanced(ZSTD_CCtx* const cctx, const ZSTD_CDict* const cdict, ZSTD_frameParameters const fParams, unsigned long long const pledgedSrcSize);   /* compression parameters are already set within cdict. pledgedSrcSize must be correct. If srcSize is not known, use macro ZSTD_CONTENTSIZE_UNKNOWN */
     size_t ZSTD_copyCCtx(ZSTD_CCtx* cctx, const ZSTD_CCtx* preparedCCtx, unsigned long long pledgedSrcSize); /**<  note: if pledgedSrcSize is not known, use ZSTD_CONTENTSIZE_UNKNOWN */
     

    -

    Buffer-less streaming decompression (synchronous mode)

    +

    Buffer-less streaming decompression (synchronous mode)

       A ZSTD_DCtx object is required to track streaming operations.
       Use ZSTD_createDCtx() / ZSTD_freeDCtx() to manage it.
       A ZSTD_DCtx object can be re-used multiple times.
    @@ -787,7 +803,7 @@ size_t ZSTD_decodingBufferSize_min(unsigned long long windowSize, unsigned long
     

    typedef enum { ZSTDnit_frameHeader, ZSTDnit_blockHeader, ZSTDnit_block, ZSTDnit_lastBlock, ZSTDnit_checksum, ZSTDnit_skippableFrame } ZSTD_nextInputType_e;
     

    -

    New advanced API (experimental)

    
    +

    New advanced API (experimental)

    
     
     
    typedef enum {
         /* Opened question : should we have a format ZSTD_f_auto ?
    @@ -1283,7 +1299,7 @@ size_t ZSTD_DCtx_refPrefix_advanced(ZSTD_DCtx* dctx,
      
     


    -

    Block level API

    
    +

    Block level API

    
     
     

    Frame metadata cost is typically ~18 bytes, which can be non-negligible for very small blocks (< 100 bytes). User will have to take in charge required information to regenerate data, such as compressed and content sizes. diff --git a/lib/decompress/zstd_decompress.c b/lib/decompress/zstd_decompress.c index 538479b78..6bd2e3ef3 100644 --- a/lib/decompress/zstd_decompress.c +++ b/lib/decompress/zstd_decompress.c @@ -187,7 +187,7 @@ unsigned ZSTD_isFrame(const void* buffer, size_t size) if (size < ZSTD_FRAMEIDSIZE) return 0; { U32 const magic = MEM_readLE32(buffer); if (magic == ZSTD_MAGICNUMBER) return 1; - if ((magic & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) return 1; + if ((magic & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) return 1; } #if defined(ZSTD_LEGACY_SUPPORT) && (ZSTD_LEGACY_SUPPORT >= 1) if (ZSTD_isLegacy(buffer, size)) return 1; @@ -242,7 +242,7 @@ size_t ZSTD_getFrameHeader_advanced(ZSTD_frameHeader* zfhPtr, const void* src, s if ( (format != ZSTD_f_zstd1_magicless) && (MEM_readLE32(src) != ZSTD_MAGICNUMBER) ) { - if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ZSTD_SKIPPABLEHEADERSIZE; /* magic number + frame length */ @@ -355,7 +355,7 @@ unsigned long long ZSTD_findDecompressedSize(const void* src, size_t srcSize) while (srcSize >= ZSTD_FRAMEHEADERSIZE_PREFIX) { U32 const magicNumber = MEM_readLE32(src); - if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { size_t skippableSize; if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ERROR(srcSize_wrong); @@ -435,7 +435,7 @@ size_t ZSTD_findFrameCompressedSize(const void *src, size_t srcSize) return ZSTD_findFrameCompressedSizeLegacy(src, srcSize); #endif if ( (srcSize >= ZSTD_SKIPPABLEHEADERSIZE) - && (MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START ) { + && (MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START ) { return ZSTD_SKIPPABLEHEADERSIZE + MEM_readLE32((const BYTE*)src + ZSTD_FRAMEIDSIZE); } else { const BYTE* ip = (const BYTE*)src; @@ -659,7 +659,7 @@ static size_t ZSTD_decompressMultiFrame(ZSTD_DCtx* dctx, { U32 const magicNumber = MEM_readLE32(src); DEBUGLOG(4, "reading magic number %08X (expecting %08X)", (U32)magicNumber, (U32)ZSTD_MAGICNUMBER); - if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { size_t skippableSize; if (srcSize < ZSTD_SKIPPABLEHEADERSIZE) return ERROR(srcSize_wrong); @@ -790,7 +790,7 @@ size_t ZSTD_decompressContinue(ZSTD_DCtx* dctx, void* dst, size_t dstCapacity, c assert(src != NULL); if (dctx->format == ZSTD_f_zstd1) { /* allows header */ assert(srcSize >= ZSTD_FRAMEIDSIZE); /* to read skippable magic number */ - if ((MEM_readLE32(src) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ + if ((MEM_readLE32(src) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ memcpy(dctx->headerBuffer, src, srcSize); dctx->expected = ZSTD_SKIPPABLEHEADERSIZE - srcSize; /* remaining to load to get full skippable frame header */ dctx->stage = ZSTDds_decodeSkippableHeader; @@ -1419,7 +1419,7 @@ size_t ZSTD_decompressStream(ZSTD_DStream* zds, ZSTD_outBuffer* output, ZSTD_inB DEBUGLOG(4, "Consume header"); CHECK_F(ZSTD_decompressBegin_usingDDict(zds, zds->ddict)); - if ((MEM_readLE32(zds->headerBuffer) & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ + if ((MEM_readLE32(zds->headerBuffer) & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { /* skippable frame */ zds->expected = MEM_readLE32(zds->headerBuffer + ZSTD_FRAMEIDSIZE); zds->stage = ZSTDds_skipFrame; } else { diff --git a/lib/zstd.h b/lib/zstd.h index e161b02ab..e66738fe5 100644 --- a/lib/zstd.h +++ b/lib/zstd.h @@ -415,9 +415,12 @@ ZSTDLIB_API size_t ZSTD_DStreamOutSize(void); /*!< recommended size for output ZSTDLIB_API int ZSTD_minCLevel(void); /*!< minimum negative compression level allowed */ /* --- Constants ---*/ -#define ZSTD_MAGICNUMBER 0xFD2FB528 /* v0.8+ */ -#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* v0.7+ */ -#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50U + +/* all magic numbers are supposed read/written to/from files/memory using little-endian convention */ +#define ZSTD_MAGICNUMBER 0xFD2FB528 /* valid since v0.8.0 */ +#define ZSTD_MAGIC_DICTIONARY 0xEC30A437 /* valid since v0.7.0 */ +#define ZSTD_MAGIC_SKIPPABLE_START 0x184D2A50 /* all 16 values, from 0x184D2A50 to 0x184D2A5F, are understood as skippable frames */ +#define ZSTD_MAGIC_SKIPPABLE_MASK 0xFFFFFFF0 #define ZSTD_BLOCKSIZELOG_MAX 17 #define ZSTD_BLOCKSIZE_MAX (1<numActualFrames++; } /* Skippable frame */ - else if ((magicNumber & 0xFFFFFFF0U) == ZSTD_MAGIC_SKIPPABLE_START) { + else if ((magicNumber & ZSTD_MAGIC_SKIPPABLE_MASK) == ZSTD_MAGIC_SKIPPABLE_START) { U32 const frameSize = MEM_readLE32(headerBuffer + 4); long const seek = (long)(8 + frameSize - numBytesRead); ERROR_IF(LONG_SEEK(srcFile, seek, SEEK_CUR) != 0,