123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- /*
- * LZ4 file library
- * Copyright (C) 2022, Xiaomi Inc.
- *
- * BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * - Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * You can contact the author at :
- * - LZ4 homepage : http://www.lz4.org
- * - LZ4 source repository : https://github.com/lz4/lz4
- */
- #include <stdlib.h>
- #include <string.h>
- #include "lz4.h"
- #include "lz4file.h"
- struct LZ4_readFile_s {
- LZ4F_dctx* dctxPtr;
- FILE* fp;
- LZ4_byte* srcBuf;
- size_t srcBufNext;
- size_t srcBufSize;
- size_t srcBufMaxSize;
- };
- struct LZ4_writeFile_s {
- LZ4F_cctx* cctxPtr;
- FILE* fp;
- LZ4_byte* dstBuf;
- size_t maxWriteSize;
- size_t dstBufMaxSize;
- LZ4F_errorCode_t errCode;
- };
- LZ4F_errorCode_t LZ4F_readOpen(LZ4_readFile_t** lz4fRead, FILE* fp)
- {
- char buf[LZ4F_HEADER_SIZE_MAX];
- size_t consumedSize;
- LZ4F_errorCode_t ret;
- LZ4F_frameInfo_t info;
- if (fp == NULL || lz4fRead == NULL) {
- return -LZ4F_ERROR_GENERIC;
- }
- *lz4fRead = (LZ4_readFile_t*)calloc(1, sizeof(LZ4_readFile_t));
- if (*lz4fRead == NULL) {
- return -LZ4F_ERROR_allocation_failed;
- }
- ret = LZ4F_createDecompressionContext(&(*lz4fRead)->dctxPtr, LZ4F_getVersion());
- if (LZ4F_isError(ret)) {
- free(*lz4fRead);
- return ret;
- }
- (*lz4fRead)->fp = fp;
- consumedSize = fread(buf, 1, sizeof(buf), (*lz4fRead)->fp);
- if (consumedSize != sizeof(buf)) {
- free(*lz4fRead);
- return -LZ4F_ERROR_GENERIC;
- }
- ret = LZ4F_getFrameInfo((*lz4fRead)->dctxPtr, &info, buf, &consumedSize);
- if (LZ4F_isError(ret)) {
- LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
- free(*lz4fRead);
- return ret;
- }
- switch (info.blockSizeID) {
- case LZ4F_default :
- case LZ4F_max64KB :
- (*lz4fRead)->srcBufMaxSize = 64 * 1024;
- break;
- case LZ4F_max256KB:
- (*lz4fRead)->srcBufMaxSize = 256 * 1024;
- break;
- case LZ4F_max1MB:
- (*lz4fRead)->srcBufMaxSize = 1 * 1024 * 1024;
- break;
- case LZ4F_max4MB:
- (*lz4fRead)->srcBufMaxSize = 4 * 1024 * 1024;
- break;
- default:
- LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
- free(*lz4fRead);
- return -LZ4F_ERROR_maxBlockSize_invalid;
- }
- (*lz4fRead)->srcBuf = (LZ4_byte*)malloc((*lz4fRead)->srcBufMaxSize);
- if ((*lz4fRead)->srcBuf == NULL) {
- LZ4F_freeDecompressionContext((*lz4fRead)->dctxPtr);
- free(lz4fRead);
- return -LZ4F_ERROR_allocation_failed;
- }
- (*lz4fRead)->srcBufSize = sizeof(buf) - consumedSize;
- memcpy((*lz4fRead)->srcBuf, buf + consumedSize, (*lz4fRead)->srcBufSize);
- return ret;
- }
- size_t LZ4F_read(LZ4_readFile_t* lz4fRead, void* buf, size_t size)
- {
- LZ4_byte* p = (LZ4_byte*)buf;
- size_t next = 0;
- if (lz4fRead == NULL || buf == NULL)
- return -LZ4F_ERROR_GENERIC;
- while (next < size) {
- size_t srcsize = lz4fRead->srcBufSize - lz4fRead->srcBufNext;
- size_t dstsize = size - next;
- size_t ret;
- if (srcsize == 0) {
- ret = fread(lz4fRead->srcBuf, 1, lz4fRead->srcBufMaxSize, lz4fRead->fp);
- if (ret > 0) {
- lz4fRead->srcBufSize = ret;
- srcsize = lz4fRead->srcBufSize;
- lz4fRead->srcBufNext = 0;
- }
- else if (ret == 0) {
- break;
- }
- else {
- return -LZ4F_ERROR_GENERIC;
- }
- }
- ret = LZ4F_decompress(lz4fRead->dctxPtr,
- p, &dstsize,
- lz4fRead->srcBuf + lz4fRead->srcBufNext,
- &srcsize,
- NULL);
- if (LZ4F_isError(ret)) {
- return ret;
- }
- lz4fRead->srcBufNext += srcsize;
- next += dstsize;
- p += dstsize;
- }
- return next;
- }
- LZ4F_errorCode_t LZ4F_readClose(LZ4_readFile_t* lz4fRead)
- {
- if (lz4fRead == NULL)
- return -LZ4F_ERROR_GENERIC;
- LZ4F_freeDecompressionContext(lz4fRead->dctxPtr);
- free(lz4fRead->srcBuf);
- free(lz4fRead);
- return LZ4F_OK_NoError;
- }
- LZ4F_errorCode_t LZ4F_writeOpen(LZ4_writeFile_t** lz4fWrite, FILE* fp, const LZ4F_preferences_t* prefsPtr)
- {
- LZ4_byte buf[LZ4F_HEADER_SIZE_MAX];
- size_t ret;
- if (fp == NULL || lz4fWrite == NULL)
- return -LZ4F_ERROR_GENERIC;
- *lz4fWrite = (LZ4_writeFile_t*)malloc(sizeof(LZ4_writeFile_t));
- if (*lz4fWrite == NULL) {
- return -LZ4F_ERROR_allocation_failed;
- }
- if (prefsPtr != NULL) {
- switch (prefsPtr->frameInfo.blockSizeID) {
- case LZ4F_default :
- case LZ4F_max64KB :
- (*lz4fWrite)->maxWriteSize = 64 * 1024;
- break;
- case LZ4F_max256KB:
- (*lz4fWrite)->maxWriteSize = 256 * 1024;
- break;
- case LZ4F_max1MB:
- (*lz4fWrite)->maxWriteSize = 1 * 1024 * 1024;
- break;
- case LZ4F_max4MB:
- (*lz4fWrite)->maxWriteSize = 4 * 1024 * 1024;
- break;
- default:
- free(lz4fWrite);
- return -LZ4F_ERROR_maxBlockSize_invalid;
- }
- } else {
- (*lz4fWrite)->maxWriteSize = 64 * 1024;
- }
- (*lz4fWrite)->dstBufMaxSize = LZ4F_compressBound((*lz4fWrite)->maxWriteSize, prefsPtr);
- (*lz4fWrite)->dstBuf = (LZ4_byte*)malloc((*lz4fWrite)->dstBufMaxSize);
- if ((*lz4fWrite)->dstBuf == NULL) {
- free(*lz4fWrite);
- return -LZ4F_ERROR_allocation_failed;
- }
- ret = LZ4F_createCompressionContext(&(*lz4fWrite)->cctxPtr, LZ4F_getVersion());
- if (LZ4F_isError(ret)) {
- free((*lz4fWrite)->dstBuf);
- free(*lz4fWrite);
- return ret;
- }
- ret = LZ4F_compressBegin((*lz4fWrite)->cctxPtr, buf, LZ4F_HEADER_SIZE_MAX, prefsPtr);
- if (LZ4F_isError(ret)) {
- LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
- free((*lz4fWrite)->dstBuf);
- free(*lz4fWrite);
- return ret;
- }
- if (ret != fwrite(buf, 1, ret, fp)) {
- LZ4F_freeCompressionContext((*lz4fWrite)->cctxPtr);
- free((*lz4fWrite)->dstBuf);
- free(*lz4fWrite);
- return -LZ4F_ERROR_GENERIC;
- }
- (*lz4fWrite)->fp = fp;
- (*lz4fWrite)->errCode = LZ4F_OK_NoError;
- return LZ4F_OK_NoError;
- }
- size_t LZ4F_write(LZ4_writeFile_t* lz4fWrite, void* buf, size_t size)
- {
- LZ4_byte* p = (LZ4_byte*)buf;
- size_t remain = size;
- size_t chunk;
- size_t ret;
- if (lz4fWrite == NULL || buf == NULL)
- return -LZ4F_ERROR_GENERIC;
- while (remain) {
- if (remain > lz4fWrite->maxWriteSize)
- chunk = lz4fWrite->maxWriteSize;
- else
- chunk = remain;
- ret = LZ4F_compressUpdate(lz4fWrite->cctxPtr,
- lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
- p, chunk,
- NULL);
- if (LZ4F_isError(ret)) {
- lz4fWrite->errCode = ret;
- return ret;
- }
- if(ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
- lz4fWrite->errCode = -LZ4F_ERROR_GENERIC;
- return -LZ4F_ERROR_GENERIC;
- }
- p += chunk;
- remain -= chunk;
- }
- return size;
- }
- LZ4F_errorCode_t LZ4F_writeClose(LZ4_writeFile_t* lz4fWrite)
- {
- LZ4F_errorCode_t ret = LZ4F_OK_NoError;
- if (lz4fWrite == NULL)
- return -LZ4F_ERROR_GENERIC;
- if (lz4fWrite->errCode == LZ4F_OK_NoError) {
- ret = LZ4F_compressEnd(lz4fWrite->cctxPtr,
- lz4fWrite->dstBuf, lz4fWrite->dstBufMaxSize,
- NULL);
- if (LZ4F_isError(ret)) {
- goto out;
- }
- if (ret != fwrite(lz4fWrite->dstBuf, 1, ret, lz4fWrite->fp)) {
- ret = -LZ4F_ERROR_GENERIC;
- }
- }
- out:
- LZ4F_freeCompressionContext(lz4fWrite->cctxPtr);
- free(lz4fWrite->dstBuf);
- free(lz4fWrite);
- return ret;
- }
|