LCOV - code coverage report
Current view: top level - pression/compressor/zstd/lib/decompress - zbuff_decompress.c (source / functions) Hit Total Coverage
Test: Pression Lines: 0 131 0.0 %
Date: 2016-12-06 05:44:58 Functions: 0 9 0.0 %

          Line data    Source code
       1             : /**
       2             :  * Copyright (c) 2016-present, Yann Collet, Facebook, Inc.
       3             :  * All rights reserved.
       4             :  *
       5             :  * This source code is licensed under the BSD-style license found in the
       6             :  * LICENSE file in the root directory of this source tree. An additional grant
       7             :  * of patent rights can be found in the PATENTS file in the same directory.
       8             :  */
       9             : 
      10             : 
      11             : 
      12             : /* *************************************
      13             : *  Dependencies
      14             : ***************************************/
      15             : #include <stdlib.h>
      16             : #include "error_private.h"
      17             : #include "zstd_internal.h"  /* MIN, ZSTD_blockHeaderSize, ZSTD_BLOCKSIZE_MAX */
      18             : #define ZBUFF_STATIC_LINKING_ONLY
      19             : #include "zbuff.h"
      20             : 
      21             : 
      22             : typedef enum { ZBUFFds_init, ZBUFFds_loadHeader,
      23             :                ZBUFFds_read, ZBUFFds_load, ZBUFFds_flush } ZBUFF_dStage;
      24             : 
      25             : /* *** Resource management *** */
      26             : struct ZBUFF_DCtx_s {
      27             :     ZSTD_DCtx* zd;
      28             :     ZSTD_frameParams fParams;
      29             :     ZBUFF_dStage stage;
      30             :     char*  inBuff;
      31             :     size_t inBuffSize;
      32             :     size_t inPos;
      33             :     char*  outBuff;
      34             :     size_t outBuffSize;
      35             :     size_t outStart;
      36             :     size_t outEnd;
      37             :     size_t blockSize;
      38             :     BYTE headerBuffer[ZSTD_FRAMEHEADERSIZE_MAX];
      39             :     size_t lhSize;
      40             :     ZSTD_customMem customMem;
      41             : };   /* typedef'd to ZBUFF_DCtx within "zbuff.h" */
      42             : 
      43             : 
      44           0 : ZBUFF_DCtx* ZBUFF_createDCtx(void)
      45             : {
      46           0 :     return ZBUFF_createDCtx_advanced(defaultCustomMem);
      47             : }
      48             : 
      49           0 : ZBUFF_DCtx* ZBUFF_createDCtx_advanced(ZSTD_customMem customMem)
      50             : {
      51             :     ZBUFF_DCtx* zbd;
      52             : 
      53           0 :     if (!customMem.customAlloc && !customMem.customFree)
      54           0 :         customMem = defaultCustomMem;
      55             : 
      56           0 :     if (!customMem.customAlloc || !customMem.customFree)
      57           0 :         return NULL;
      58             : 
      59           0 :     zbd = (ZBUFF_DCtx*)customMem.customAlloc(customMem.opaque, sizeof(ZBUFF_DCtx));
      60           0 :     if (zbd==NULL) return NULL;
      61           0 :     memset(zbd, 0, sizeof(ZBUFF_DCtx));
      62           0 :     memcpy(&zbd->customMem, &customMem, sizeof(ZSTD_customMem));
      63           0 :     zbd->zd = ZSTD_createDCtx_advanced(customMem);
      64           0 :     if (zbd->zd == NULL) { ZBUFF_freeDCtx(zbd); return NULL; }
      65           0 :     zbd->stage = ZBUFFds_init;
      66           0 :     return zbd;
      67             : }
      68             : 
      69           0 : size_t ZBUFF_freeDCtx(ZBUFF_DCtx* zbd)
      70             : {
      71           0 :     if (zbd==NULL) return 0;   /* support free on null */
      72           0 :     ZSTD_freeDCtx(zbd->zd);
      73           0 :     if (zbd->inBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
      74           0 :     if (zbd->outBuff) zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
      75           0 :     zbd->customMem.customFree(zbd->customMem.opaque, zbd);
      76           0 :     return 0;
      77             : }
      78             : 
      79             : 
      80             : /* *** Initialization *** */
      81             : 
      82           0 : size_t ZBUFF_decompressInitDictionary(ZBUFF_DCtx* zbd, const void* dict, size_t dictSize)
      83             : {
      84           0 :     zbd->stage = ZBUFFds_loadHeader;
      85           0 :     zbd->lhSize = zbd->inPos = zbd->outStart = zbd->outEnd = 0;
      86           0 :     return ZSTD_decompressBegin_usingDict(zbd->zd, dict, dictSize);
      87             : }
      88             : 
      89           0 : size_t ZBUFF_decompressInit(ZBUFF_DCtx* zbd)
      90             : {
      91           0 :     return ZBUFF_decompressInitDictionary(zbd, NULL, 0);
      92             : }
      93             : 
      94             : 
      95             : /* internal util function */
      96           0 : MEM_STATIC size_t ZBUFF_limitCopy(void* dst, size_t dstCapacity, const void* src, size_t srcSize)
      97             : {
      98           0 :     size_t const length = MIN(dstCapacity, srcSize);
      99           0 :     memcpy(dst, src, length);
     100           0 :     return length;
     101             : }
     102             : 
     103             : 
     104             : /* *** Decompression *** */
     105             : 
     106           0 : size_t ZBUFF_decompressContinue(ZBUFF_DCtx* zbd,
     107             :                                 void* dst, size_t* dstCapacityPtr,
     108             :                           const void* src, size_t* srcSizePtr)
     109             : {
     110           0 :     const char* const istart = (const char*)src;
     111           0 :     const char* const iend = istart + *srcSizePtr;
     112           0 :     const char* ip = istart;
     113           0 :     char* const ostart = (char*)dst;
     114           0 :     char* const oend = ostart + *dstCapacityPtr;
     115           0 :     char* op = ostart;
     116           0 :     U32 someMoreWork = 1;
     117             : 
     118           0 :     while (someMoreWork) {
     119           0 :         switch(zbd->stage)
     120             :         {
     121             :         case ZBUFFds_init :
     122           0 :             return ERROR(init_missing);
     123             : 
     124             :         case ZBUFFds_loadHeader :
     125           0 :             {   size_t const hSize = ZSTD_getFrameParams(&(zbd->fParams), zbd->headerBuffer, zbd->lhSize);
     126           0 :                 if (ZSTD_isError(hSize)) return hSize;
     127           0 :                 if (hSize != 0) {   /* need more input */
     128           0 :                     size_t const toLoad = hSize - zbd->lhSize;   /* if hSize!=0, hSize > zbd->lhSize */
     129           0 :                     if (toLoad > (size_t)(iend-ip)) {   /* not enough input to load full header */
     130           0 :                         memcpy(zbd->headerBuffer + zbd->lhSize, ip, iend-ip);
     131           0 :                         zbd->lhSize += iend-ip;
     132           0 :                         *dstCapacityPtr = 0;
     133           0 :                         return (hSize - zbd->lhSize) + ZSTD_blockHeaderSize;   /* remaining header bytes + next block header */
     134             :                     }
     135           0 :                     memcpy(zbd->headerBuffer + zbd->lhSize, ip, toLoad); zbd->lhSize = hSize; ip += toLoad;
     136           0 :                     break;
     137             :             }   }
     138             : 
     139             :             /* Consume header */
     140           0 :             {   size_t const h1Size = ZSTD_nextSrcSizeToDecompress(zbd->zd);  /* == ZSTD_frameHeaderSize_min */
     141           0 :                 size_t const h1Result = ZSTD_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer, h1Size);
     142           0 :                 if (ZSTD_isError(h1Result)) return h1Result;   /* should not happen : already checked */
     143           0 :                 if (h1Size < zbd->lhSize) {   /* long header */
     144           0 :                     size_t const h2Size = ZSTD_nextSrcSizeToDecompress(zbd->zd);
     145           0 :                     size_t const h2Result = ZSTD_decompressContinue(zbd->zd, NULL, 0, zbd->headerBuffer+h1Size, h2Size);
     146           0 :                     if (ZSTD_isError(h2Result)) return h2Result;
     147             :             }   }
     148             : 
     149           0 :             zbd->fParams.windowSize = MAX(zbd->fParams.windowSize, 1U << ZSTD_WINDOWLOG_ABSOLUTEMIN);
     150             : 
     151             :             /* Frame header instruct buffer sizes */
     152           0 :             {   size_t const blockSize = MIN(zbd->fParams.windowSize, ZSTD_BLOCKSIZE_ABSOLUTEMAX);
     153           0 :                 size_t const neededOutSize = zbd->fParams.windowSize + blockSize;
     154           0 :                 zbd->blockSize = blockSize;
     155           0 :                 if (zbd->inBuffSize < blockSize) {
     156           0 :                     zbd->customMem.customFree(zbd->customMem.opaque, zbd->inBuff);
     157           0 :                     zbd->inBuffSize = blockSize;
     158           0 :                     zbd->inBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, blockSize);
     159           0 :                     if (zbd->inBuff == NULL) return ERROR(memory_allocation);
     160             :                 }
     161           0 :                 if (zbd->outBuffSize < neededOutSize) {
     162           0 :                     zbd->customMem.customFree(zbd->customMem.opaque, zbd->outBuff);
     163           0 :                     zbd->outBuffSize = neededOutSize;
     164           0 :                     zbd->outBuff = (char*)zbd->customMem.customAlloc(zbd->customMem.opaque, neededOutSize);
     165           0 :                     if (zbd->outBuff == NULL) return ERROR(memory_allocation);
     166             :             }   }
     167           0 :             zbd->stage = ZBUFFds_read;
     168             :             /* pass-through */
     169             : 
     170             :         case ZBUFFds_read:
     171           0 :             {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbd->zd);
     172           0 :                 if (neededInSize==0) {  /* end of frame */
     173           0 :                     zbd->stage = ZBUFFds_init;
     174           0 :                     someMoreWork = 0;
     175           0 :                     break;
     176             :                 }
     177           0 :                 if ((size_t)(iend-ip) >= neededInSize) {  /* decode directly from src */
     178           0 :                     const int isSkipFrame = ZSTD_isSkipFrame(zbd->zd);
     179           0 :                     size_t const decodedSize = ZSTD_decompressContinue(zbd->zd,
     180           0 :                         zbd->outBuff + zbd->outStart, (isSkipFrame ? 0 : zbd->outBuffSize - zbd->outStart),
     181             :                         ip, neededInSize);
     182           0 :                     if (ZSTD_isError(decodedSize)) return decodedSize;
     183           0 :                     ip += neededInSize;
     184           0 :                     if (!decodedSize && !isSkipFrame) break;   /* this was just a header */
     185           0 :                     zbd->outEnd = zbd->outStart +  decodedSize;
     186           0 :                     zbd->stage = ZBUFFds_flush;
     187           0 :                     break;
     188             :                 }
     189           0 :                 if (ip==iend) { someMoreWork = 0; break; }   /* no more input */
     190           0 :                 zbd->stage = ZBUFFds_load;
     191             :                 /* pass-through */
     192             :             }
     193             : 
     194             :         case ZBUFFds_load:
     195           0 :             {   size_t const neededInSize = ZSTD_nextSrcSizeToDecompress(zbd->zd);
     196           0 :                 size_t const toLoad = neededInSize - zbd->inPos;   /* should always be <= remaining space within inBuff */
     197             :                 size_t loadedSize;
     198           0 :                 if (toLoad > zbd->inBuffSize - zbd->inPos) return ERROR(corruption_detected);   /* should never happen */
     199           0 :                 loadedSize = ZBUFF_limitCopy(zbd->inBuff + zbd->inPos, toLoad, ip, iend-ip);
     200           0 :                 ip += loadedSize;
     201           0 :                 zbd->inPos += loadedSize;
     202           0 :                 if (loadedSize < toLoad) { someMoreWork = 0; break; }   /* not enough input, wait for more */
     203             : 
     204             :                 /* decode loaded input */
     205           0 :                 {  const int isSkipFrame = ZSTD_isSkipFrame(zbd->zd);
     206           0 :                    size_t const decodedSize = ZSTD_decompressContinue(zbd->zd,
     207           0 :                         zbd->outBuff + zbd->outStart, zbd->outBuffSize - zbd->outStart,
     208           0 :                         zbd->inBuff, neededInSize);
     209           0 :                     if (ZSTD_isError(decodedSize)) return decodedSize;
     210           0 :                     zbd->inPos = 0;   /* input is consumed */
     211           0 :                     if (!decodedSize && !isSkipFrame) { zbd->stage = ZBUFFds_read; break; }   /* this was just a header */
     212           0 :                     zbd->outEnd = zbd->outStart +  decodedSize;
     213           0 :                     zbd->stage = ZBUFFds_flush;
     214             :                     /* pass-through */
     215             :             }   }
     216             : 
     217             :         case ZBUFFds_flush:
     218           0 :             {   size_t const toFlushSize = zbd->outEnd - zbd->outStart;
     219           0 :                 size_t const flushedSize = ZBUFF_limitCopy(op, oend-op, zbd->outBuff + zbd->outStart, toFlushSize);
     220           0 :                 op += flushedSize;
     221           0 :                 zbd->outStart += flushedSize;
     222           0 :                 if (flushedSize == toFlushSize) {  /* flush completed */
     223           0 :                     zbd->stage = ZBUFFds_read;
     224           0 :                     if (zbd->outStart + zbd->blockSize > zbd->outBuffSize)
     225           0 :                         zbd->outStart = zbd->outEnd = 0;
     226           0 :                     break;
     227             :                 }
     228             :                 /* cannot flush everything */
     229           0 :                 someMoreWork = 0;
     230           0 :                 break;
     231             :             }
     232           0 :         default: return ERROR(GENERIC);   /* impossible */
     233             :     }   }
     234             : 
     235             :     /* result */
     236           0 :     *srcSizePtr = ip-istart;
     237           0 :     *dstCapacityPtr = op-ostart;
     238           0 :     {   size_t nextSrcSizeHint = ZSTD_nextSrcSizeToDecompress(zbd->zd);
     239           0 :         if (!nextSrcSizeHint) return (zbd->outEnd != zbd->outStart);   /* return 0 only if fully flushed too */
     240           0 :         nextSrcSizeHint += ZSTD_blockHeaderSize * (ZSTD_nextInputType(zbd->zd) == ZSTDnit_block);
     241           0 :         if (zbd->inPos > nextSrcSizeHint) return ERROR(GENERIC);   /* should never happen */
     242           0 :         nextSrcSizeHint -= zbd->inPos;   /* already loaded*/
     243           0 :         return nextSrcSizeHint;
     244             :     }
     245             : }
     246             : 
     247             : 
     248             : /* *************************************
     249             : *  Tool functions
     250             : ***************************************/
     251           0 : size_t ZBUFF_recommendedDInSize(void)  { return ZSTD_BLOCKSIZE_ABSOLUTEMAX + ZSTD_blockHeaderSize /* block header size*/ ; }
     252           0 : size_t ZBUFF_recommendedDOutSize(void) { return ZSTD_BLOCKSIZE_ABSOLUTEMAX; }

Generated by: LCOV version 1.11