static SquashStatus squash_bsc_decompress_buffer (SquashCodec* codec, size_t* decompressed_size, uint8_t decompressed[HEDLEY_ARRAY_PARAM(*decompressed_size)], size_t compressed_size, const uint8_t compressed[HEDLEY_ARRAY_PARAM(compressed_size)], SquashOptions* options) { #if INT_MAX < SIZE_MAX if (HEDLEY_UNLIKELY(INT_MAX < compressed_size) || HEDLEY_UNLIKELY(INT_MAX < *decompressed_size)) return squash_error (SQUASH_RANGE); #endif const int features = squash_bsc_options_get_features (codec, options); int p_block_size, p_data_size; int res = bsc_block_info (compressed, (int) compressed_size, &p_block_size, &p_data_size, LIBBSC_DEFAULT_FEATURES); if (HEDLEY_UNLIKELY(p_block_size != (int) compressed_size)) return squash_error (SQUASH_FAILED); if (HEDLEY_UNLIKELY(p_data_size > (int) *decompressed_size)) return squash_error (SQUASH_BUFFER_FULL); res = bsc_decompress (compressed, p_block_size, decompressed, p_data_size, features); if (HEDLEY_UNLIKELY(res < 0)) return squash_error (SQUASH_FAILED); #if SIZE_MAX < INT_MAX if (HEDLEY_UNLIKELY(SIZE_MAX < p_data_size)) return squash_error (SQUASH_RANGE); #endif *decompressed_size = (size_t) p_data_size; return SQUASH_OK; }
HRESULT uncompress_replacement(ISequentialInStream * inStream, ISequentialOutStream *outStream, UInt64 *inSizeProcessed, UInt64 *outSizeProcessed) { UInt32 _inSize; CLibbscProps props; // C=f props.paramSortingContexts = LIBBSC_CONTEXTS_FOLLOWING; // E=2 // LIBBSC_CODER_QLFC_ADAPTIVE props.features |= PARAM_CODER_QLFC_ADAPTIVE; // B=20 props.paramBlockSize = 20 * 1024 * 1024; if (bsc_init(props.paramFeatures()) != LIBBSC_NO_ERROR) { //fprintf(stderr, "\nInternal program error, please contact the author!\n"); return E_FAIL; } #ifdef LIBBSC_OPENMP int numThreads = 1; if (paramEnableParallelProcessing) { numThreads = omp_get_max_threads(); if (numThreads <= nBlocks) paramEnableMultiThreading = 0; if (numThreads >= nBlocks) numThreads = nBlocks; } #pragma omp parallel num_threads(numThreads) if(numThreads > 1) #endif { int bufferSize = -1; unsigned char * buffer = NULL; for (;;) { BSC_FILEOFFSET blockOffset = 0; signed char sortingContexts = 0; signed char recordSize = 0; int blockSize = 0; int dataSize = 0; #ifdef LIBBSC_OPENMP #pragma omp critical(input) #endif { Byte next = 0; if (!prepare_ex_data(inStream, 1)) break; _inSize = 1; next = ex_data[ex_next_offset++]; *inSizeProcessed += 1; if (next == 0) break; BSC_BLOCK_HEADER header = { 0, 0, 0 }; header.blockOffset = read_int(inStream, inSizeProcessed); header.recordSize = (char)read_int(inStream, inSizeProcessed); header.sortingContexts = (char)read_int(inStream, inSizeProcessed); recordSize = header.recordSize; if (recordSize < 1) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); return E_FAIL; } sortingContexts = header.sortingContexts; if ((sortingContexts != LIBBSC_CONTEXTS_FOLLOWING) && (sortingContexts != LIBBSC_CONTEXTS_PRECEDING)) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); return E_FAIL; } blockOffset = (BSC_FILEOFFSET)header.blockOffset; unsigned char *bscBlockHeader; _inSize = LIBBSC_HEADER_SIZE; if (!prepare_ex_data(inStream, _inSize)) break; bscBlockHeader = ex_data + ex_next_offset; ex_next_offset += _inSize; *inSizeProcessed += _inSize; if (bsc_block_info(bscBlockHeader, LIBBSC_HEADER_SIZE, &blockSize, &dataSize, props.paramFeatures()) != LIBBSC_NO_ERROR) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); return E_FAIL; } if ((blockSize > bufferSize) || (dataSize > bufferSize)) { if (blockSize > bufferSize) bufferSize = blockSize; if (dataSize > bufferSize) bufferSize = dataSize; if (buffer != NULL) bsc_free(buffer); buffer = (unsigned char *)bsc_malloc(bufferSize); } if (buffer == NULL) { fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); return E_FAIL; } memcpy(buffer, bscBlockHeader, LIBBSC_HEADER_SIZE); _inSize = blockSize - LIBBSC_HEADER_SIZE; if (!prepare_ex_data(inStream, _inSize)) break; memcpy(buffer + LIBBSC_HEADER_SIZE, ex_data + ex_next_offset, _inSize); ex_next_offset += _inSize; *inSizeProcessed += _inSize; } if (dataSize == 0) break; int result = bsc_decompress(buffer, blockSize, buffer, dataSize, props.paramFeatures()); if (result < LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { switch (result) { case LIBBSC_DATA_CORRUPT: fprintf(stderr, "\nThe compressed data is corrupted!\n"); break; case LIBBSC_NOT_ENOUGH_MEMORY: fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; case LIBBSC_GPU_ERROR: fprintf(stderr, "\nGeneral GPU failure! Please check README file for more information.\n"); break; case LIBBSC_GPU_NOT_SUPPORTED: fprintf(stderr, "\nYour GPU is not supported! Please check README file for more information.\n"); break; case LIBBSC_GPU_NOT_ENOUGH_MEMORY: fprintf(stderr, "\nNot enough GPU memory! Please check README file for more information.\n"); break; default: fprintf(stderr, "\nInternal program error, please contact the author!\n"); } return E_FAIL; } } if (sortingContexts == LIBBSC_CONTEXTS_PRECEDING) { result = bsc_reverse_block(buffer, dataSize, props.paramFeatures()); if (result != LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { fprintf(stderr, "\nInternal program error, please contact the author!\n"); return E_FAIL; } } } if (recordSize > 1) { result = bsc_reorder_reverse(buffer, dataSize, recordSize, props.paramFeatures()); if (result != LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { switch (result) { case LIBBSC_NOT_ENOUGH_MEMORY: fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; default: fprintf(stderr, "\nInternal program error, please contact the author!\n"); } return E_FAIL; } } } #ifdef LIBBSC_OPENMP #pragma omp critical(output) #endif { // if (BSC_FSEEK(fOutput, blockOffset, SEEK_SET)) // { // fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); // return E_FAIL; // } UInt32 processedSize = 0; RINOK(WriteStream(outStream, buffer, dataSize)); *outSizeProcessed += dataSize; } } } return S_OK; }
void Decompression(char * argv[]) { FILE * fInput = fopen(argv[2], "rb"); if (fInput == NULL) { fprintf(stderr, "Can't open input file: %s!\n", argv[2]); exit(1); } FILE * fOutput = fopen(argv[3], "wb"); if (fOutput == NULL) { fprintf(stderr, "Can't create output file: %s!\n", argv[3]); exit(1); } if (BSC_FSEEK(fInput, 0, SEEK_END)) { fprintf(stderr, "IO error on file: %s!\n", argv[2]); exit(1); } BSC_FILEOFFSET fileSize = BSC_FTELL(fInput); if (fileSize < 0) { fprintf(stderr, "IO error on file: %s!\n", argv[2]); exit(1); } if (BSC_FSEEK(fInput, 0, SEEK_SET)) { fprintf(stderr, "IO error on file: %s!\n", argv[2]); exit(1); } unsigned char inputFileSign[sizeof(bscFileSign)]; if (fread(inputFileSign, sizeof(bscFileSign), 1, fInput) != 1) { fprintf(stderr, "This is not bsc archive!\n"); exit(1); } if (memcmp(inputFileSign, bscFileSign, sizeof(bscFileSign)) != 0) { fprintf(stderr, "This is not bsc archive or invalid compression method!\n"); exit(2); } int nBlocks = 0; if (fread(&nBlocks, sizeof(nBlocks), 1, fInput) != 1) { fprintf(stderr, "This is not bsc archive!\n"); exit(1); } double startTime = BSC_CLOCK(); #ifdef LIBBSC_OPENMP int numThreads = 1; if (paramEnableParallelProcessing) { numThreads = omp_get_max_threads(); if (numThreads > nBlocks) { numThreads = nBlocks; } } #pragma omp parallel num_threads(numThreads) if(numThreads > 1) #endif { int bufferSize = -1; unsigned char * buffer = NULL; while (true) { BSC_FILEOFFSET blockOffset = 0; char sortingContexts = 0; char recordSize = 0; int blockSize = 0; int dataSize = 0; #ifdef LIBBSC_OPENMP #pragma omp critical(input) #endif { if ((feof(fInput) == 0) && (BSC_FTELL(fInput) != fileSize)) { #ifdef LIBBSC_OPENMP #pragma omp master #endif { double progress = (100.0 * (double)BSC_FTELL(fInput)) / fileSize; fprintf(stdout, "\rDecompressing %.55s(%02d%%)", argv[2], (int)progress); fflush(stdout); } BSC_BLOCK_HEADER header = {0, 0, 0}; if (fread(&header, sizeof(BSC_BLOCK_HEADER), 1, fInput) != 1) { fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); exit(1); } recordSize = header.recordSize; if (recordSize < 1) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); exit(2); } sortingContexts = header.sortingContexts; if ((sortingContexts != LIBBSC_CONTEXTS_FOLLOWING) && (sortingContexts != LIBBSC_CONTEXTS_PRECEDING)) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); exit(2); } blockOffset = (BSC_FILEOFFSET)header.blockOffset; unsigned char bscBlockHeader[LIBBSC_HEADER_SIZE]; if (fread(bscBlockHeader, LIBBSC_HEADER_SIZE, 1, fInput) != 1) { fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); exit(1); } if (bsc_block_info(bscBlockHeader, LIBBSC_HEADER_SIZE, &blockSize, &dataSize, paramEnableMultiThreading ? LIBBSC_FEATURE_MULTITHREADING : LIBBSC_FEATURE_NONE) != LIBBSC_NO_ERROR) { fprintf(stderr, "\nThis is not bsc archive or invalid compression method!\n"); exit(2); } if ((blockSize > bufferSize) || (dataSize > bufferSize)) { if (blockSize > bufferSize) bufferSize = blockSize; if (dataSize > bufferSize) bufferSize = dataSize; if (buffer != NULL) bsc_free(buffer); buffer = (unsigned char *)bsc_malloc(bufferSize); } if (buffer == NULL) { fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); exit(2); } memcpy(buffer, bscBlockHeader, LIBBSC_HEADER_SIZE); if (fread(buffer + LIBBSC_HEADER_SIZE, blockSize - LIBBSC_HEADER_SIZE, 1, fInput) != 1) { fprintf(stderr, "\nUnexpected end of file: %s!\n", argv[2]); exit(1); } } } if (dataSize == 0) break; int result = bsc_decompress(buffer, blockSize, buffer, dataSize, paramEnableMultiThreading ? LIBBSC_FEATURE_MULTITHREADING : LIBBSC_FEATURE_NONE); if (result < LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { switch (result) { case LIBBSC_DATA_CORRUPT : fprintf(stderr, "\nThe compressed data is corrupted!\n"); break; case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; case LIBBSC_GPU_ERROR : fprintf(stderr, "\nGeneral GPU failure, please contact the author!\n"); break; case LIBBSC_GPU_NOT_SUPPORTED : fprintf(stderr, "\nYour GPU is not supported! Please check README file for more information.\n"); break; case LIBBSC_GPU_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough GPU memory! Please check README file for more information.\n"); break; default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); } exit(2); } } if (sortingContexts == LIBBSC_CONTEXTS_PRECEDING) { result = bsc_reverse_block(buffer, dataSize, paramEnableMultiThreading ? LIBBSC_FEATURE_MULTITHREADING : LIBBSC_FEATURE_NONE); if (result != LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { fprintf(stderr, "\nInternal program error, please contact the author!\n"); exit(2); } } } if (recordSize > 1) { result = bsc_reorder_reverse(buffer, dataSize, recordSize, paramEnableMultiThreading ? LIBBSC_FEATURE_MULTITHREADING : LIBBSC_FEATURE_NONE); if (result != LIBBSC_NO_ERROR) { #ifdef LIBBSC_OPENMP #pragma omp critical(print) #endif { switch (result) { case LIBBSC_NOT_ENOUGH_MEMORY : fprintf(stderr, "\nNot enough memory! Please check README file for more information.\n"); break; default : fprintf(stderr, "\nInternal program error, please contact the author!\n"); } exit(2); } } } #ifdef LIBBSC_OPENMP #pragma omp critical(output) #endif { if (BSC_FSEEK(fOutput, blockOffset, SEEK_SET)) { fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); exit(1); } if ((int)fwrite(buffer, 1, dataSize, fOutput) != dataSize) { fprintf(stderr, "\nIO error on file: %s!\n", argv[3]); exit(1); } } } if (buffer != NULL) bsc_free(buffer); } if (BSC_FSEEK(fOutput, 0, SEEK_END)) { fprintf(stderr, "IO error on file: %s!\n", argv[3]); exit(1); } fprintf(stdout, "\r%.55s decompressed %.0f into %.0f in %.3f seconds.\n", argv[2], (double)fileSize, (double)BSC_FTELL(fOutput), BSC_CLOCK() - startTime); fclose(fInput); fclose(fOutput); }