LZNV Tester CPP File Contents


   Function LZNV Decode File with Buffer


LZNV_Decode_File_wBuffer is a sample function that performs file decompression with prior buffer manipulation


/// \brief      LZNV_Decode_File_wBuffer performs a straight forward file compression with prior buffer manipulation.

/// \note       The function performs internal buffering. If you do not want to perform your own buffering, please use LZNV_Decode_File.

/// \param[in]  _encoding_method: One of the methods _LZNV_ULTRAFAST_COMPRESSION to _LZNV_BETTER_COMPRESSION or _LZNV_HUFFMAN_COMPRESSION to _LZNV_RLE64_COMPRESSION.

/// \param[in]  _memory_level: The working size of the LZ algorithm. _LZNV_BUFFER_SIZE_256KB_INDX to _LZNV_BUFFER_SIZE_16MB_INDX.

/// \param[in]  _wchr_filename_to_compress: Input file path to compress. Unicode WCHAR.

/// \param[in]  _wchr_output_filename: Output file path to compress. Unicode WCHAR.

/// \return     returns NO_ERROR (0) in case of no errors or one of the error codes defined in LZNV_Defines.h header file

///             possible values:

///             - _LZNV_ERROR_INVALID_COMPRESSION_METHOD      

///             - _LZNV_ERROR_INVALID_BUFFER_SIZE            

///             - _LZNV_ERROR_EXPORTED_MAIN_FUNC_NOT_FOUND    

///             - _LZNV_ERROR_INVALID_PROCESS_SIZE            

///              


int32_t LZNV_Decode_File_wBuffer(const wchar_t* _wchr_filename_to_decompress, const wchar_t* _wchr_output_filename)

{

    int32_t _res = 0;  


    ASSERT(_p_LZNV_DLL_Main_Buffer_funct);

    if (!_p_LZNV_DLL_Main_Buffer_funct) {

        wprintf(L"\n LZNV DLL Not Loaded? Aborting...\n\n");

        return 1;

    }


    ASSERT(_wchr_output_filename);

    ASSERT(_wchr_filename_to_decompress);


    if ((!_wchr_filename_to_decompress) || (!_wchr_output_filename))

    {

        wprintf(L"\n LZNV DLL passed NULL parameters..\n\n");

        return _LZNV_ERROR_INVALID_FILE_PATH_PARAMS;

    }


 FILE* fin = 0;

    _wfopen_s(&fin, _wchr_filename_to_decompress, L"rb");

    if (!fin) {

        wprintf(L"\n Unable to open input file! Please check %s.\n\n", _wchr_filename_to_decompress);

        return _LZNV_ERROR_INVALID_INPUT_FILE;

    }


    _wunlink(_wchr_output_filename);


    FILE* fout = 0;

    _wfopen_s(&fout, _wchr_output_filename, L"wb+");

    if (!fout)

    {

        wprintf(L"\n Unable to open output file! Please check %s.\n\n", _wchr_filename_to_decompress);

        if (fin)

            fclose(fin);

        return _LZNV_ERROR_INVALID_OUTPUT_FILE;

    }


    int64_t _file_len = (int64_t)_filelengthi64(_fileno(fin));

    if (_file_len <= 0) {

        wprintf(L"\n Invalid input file size! Please check %s.\n\n", _wchr_filename_to_decompress);

        return _LZNV_ERROR_INVALID_INPUT_FILE_SIZE;

    }


    wprintf(L"\n Decompressing %s [ %lld bytes]", _wchr_filename_to_decompress, _file_len);


    uint8_t _encoding_method = 0;

    uint8_t _exe_compression = 0;

    uint8_t _solid_compression = 0;

    int32_t _chunk_size = 0;


    if (NO_ERROR != ReadXZipHeader(fin, _encoding_method, _exe_compression, _solid_compression, _chunk_size))

    {

        wprintf(L"\n Read Header function failed! Please check %s.\n\n", _wchr_filename_to_decompress);

        return _LZNV_ERROR_WRITING_HEADER;

    }


    ASSERT(((_encoding_method >= _LZNV_ULTRAFAST_COMPRESSION) && (_encoding_method < _LZNV_MAX_LZ_ALGORITHMS)) ||

        ((_encoding_method >= _LZNV_HUFFMAN_COMPRESSION) && (_encoding_method < _LZNV_MAX_ENTROPY_ALGORITHMS)));


    if (!(((_encoding_method >= _LZNV_ULTRAFAST_COMPRESSION) && (_encoding_method < _LZNV_MAX_LZ_ALGORITHMS)) ||

        ((_encoding_method >= _LZNV_HUFFMAN_COMPRESSION) && (_encoding_method < _LZNV_MAX_ENTROPY_ALGORITHMS))))

    {

        return _LZNV_ERROR_INVALID_COMPRESSION_METHOD;

    }


    ASSERT(_chunk_size < ((64 << 20) + 1)); // 64MB Table Size MAX

    if (_chunk_size > (64 << 20)) // 64MB Table Size MAX

    {

        return _LZNV_ERROR_BAD_HEADER_INFO_RECORDED; // bad header info on chunk size

    }


    uint8_t* _uint8_buffer_to_decode = (uint8_t*)malloc(_chunk_size + 4096 );  // _chunk_to_process + NO_BLOCKS * Buffer_Headers

    uint8_t* _uint8_output_buffer = (uint8_t*)malloc(_chunk_size + 256);        // _chunk_to_process + _santinel


    ASSERT(_uint8_buffer_to_decode);

    ASSERT(_uint8_output_buffer);


    if (!_uint8_buffer_to_decode) {

        wprintf(L"\n Not enough memory for chunk size %d... Exiting!\n\n", _chunk_size);

        return _LZNV_ERROR_MEMORY_ALLOCATION_ERROR_OR_SIZE;

    }

    if (!_uint8_output_buffer) {

        wprintf(L"\n Not enough memory for chunk size %d... Exiting!\n\n", _chunk_size);

        return _LZNV_ERROR_MEMORY_ALLOCATION_ERROR_OR_SIZE;

    }



    int32_t _blockID = 0;

    int64_t bufferSizeTotal = 0;


    while (1)

    {

        int32_t toWrite = _getw(fin);

        int32_t toRead = _getw(fin);


        if (toWrite < 0 || toRead < 0) {

            wprintf(L"\n\n Performing Exit.");

            break;

        }


        #ifdef _DEBUG

            wprintf(L"\n #%4d: To Read: %05d -> To Write: %05d", _blockID, toRead, toWrite);

        #endif


        ASSERT((toWrite > 0) && (toWrite <= _chunk_size));

        if (!((toWrite > 0) && (toWrite <= _chunk_size)))

            return 1201; // not enough output space


        int32_t _write_bytes = toWrite;

        int32_t _read_bytes = (int32_t)fread(_uint8_buffer_to_decode, 1, toRead, fin);


        ASSERT(_read_bytes == toRead);

        if(_read_bytes != toRead) {

            return _LZNV_ERROR_INVALID_READ; // read error

        }


        bufferSizeTotal += _read_bytes;


        //

        // Prepare buffer decompression command structure

        //

        {

            LZNV_BUFFER_COMMAND_PARAMS _lznv_buffer_decompression_commands = { 0 };


            _lznv_buffer_decompression_commands._command_to_execute = _LZNV_COMMAND_DECODE;         // Required

            _lznv_buffer_decompression_commands._cpu_priority_level = _LZNV_NORMAL_PRIORITY_CLASS;  // Optional


            _lznv_buffer_decompression_commands._encoding_method = _encoding_method;                      // Required

                         

            _lznv_buffer_decompression_commands._p_source_buffer = _uint8_buffer_to_decode;         // Required, Preallocate

            _lznv_buffer_decompression_commands._i_source_buffer_size = _read_bytes;                // Required, Non-zero value

                         

            _lznv_buffer_decompression_commands._p_destination_buffer = _uint8_output_buffer;       // Required, Preallocate

            _lznv_buffer_decompression_commands._i_destination_buffer_size = _write_bytes;          // Required, Non-zero value


            uint64_t dwS = GetTickCount64();


            _res = (*_p_LZNV_DLL_Main_Buffer_funct)(_lznv_buffer_decompression_commands);


            uint64_t dwE = GetTickCount64();


            _write_bytes = _lznv_buffer_decompression_commands._i_destination_buffer_size;


            wprintf(L"\n\n Decoding Block #%02d: %d --> %d [%lldms] [res = %d, %s]", _blockID, _read_bytes, _write_bytes, dwE - dwS, _res, _res == 0 ? L"Ok!" : L"NOk!");


            if (NO_ERROR == _res)

            {

                fwrite(_uint8_output_buffer, 1, _write_bytes, fout);

            }

            else

            {

                break;

            }

        }


        _blockID++;

    }


    if (_uint8_buffer_to_decode) {

        free(_uint8_buffer_to_decode);

    }

    if (_uint8_output_buffer) {

        free(_uint8_output_buffer);

    }


    if (fin) {

        fclose(fin);

    }

    if (fout) {

        fclose(fout);

    }


    return _res;

}