LZNV Tester CPP File Contents


   Function LZNV Encode File with Buffer


LZNV_Encode_File_wBuffer is a sample function that performs file compression with prior buffer manipulation


/// \brief      LZNV_Encode_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_Encode_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_compressInput 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_Encode_File_wBuffer(const uint8_t _encoding_method, const uint32_t _memory_level, const uint8_t _exe_compression, const wchar_t* _wchr_filename_to_compress, 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_compress);


    if ((!_wchr_filename_to_compress) || (!_wchr_output_filename))

    {

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

        return _LZNV_ERROR_INVALID_FILE_PATH_PARAMS;

    }


    ASSERT(_memory_level < _LZNV_MAX_BUFFER_SIZE_INDX);


    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;

    }


    FILE* fin = 0;

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

    if (!fin) {

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

        return _LZNV_ERROR_INVALID_INPUT_FILE;

    }


    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_compress);

        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_compress);

        return _LZNV_ERROR_INVALID_INPUT_FILE_SIZE;

    }


    uint32_t _solid_compression = 0x01; // by default

    int32_t _chunk_to_process = _tbl_size_to_process[_memory_level];


    wprintf(L"\n Compressing %s [ %lld bytes] | CHUNK_SIZE: %d", _wchr_filename_to_compress, _file_len, _chunk_to_process);


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

    if (_chunk_to_process > (64 << 20))                

    {

        return _LZNV_ERROR_BAD_HEADER_INFO; // bad header info on chunk size

    }


    if (NO_ERROR != WriteXZipHeader(fout, _encoding_method, _exe_compression, _solid_compression, _chunk_to_process))

    {

        wprintf(L"\n Unable to write XZip header.\n\n");

        return _LZNV_ERROR_WRITING_HEADER;

    }


    const uint32_t _write_max_bytes = LZNV_MAX_OUTPUT_SIZE_TO_ALLOCATE(_chunk_to_process + 1);


    uint8_t* __restrict _uint8_buffer_to_encode = (uint8_t * __restrict)malloc(_chunk_to_process + 1);

    uint8_t* __restrict _uint8_output_buffer = (uint8_t * __restrict)malloc(_write_max_bytes);


    ASSERT(_uint8_buffer_to_encode);

    ASSERT(_uint8_output_buffer);


    if (!_uint8_buffer_to_encode) {

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

        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_to_process);

        return _LZNV_ERROR_MEMORY_ALLOCATION_ERROR_OR_SIZE;

    }


    {

        int32_t _blockID = 0;

        int32_t _read_bytes = 0;

        uint32_t _file_adler32 = _CRC32_INITIAL;

        uint64_t bufferSizeTotal = 0;


        while ((_read_bytes = (int32_t)fread(_uint8_buffer_to_encode, 1, _chunk_to_process, fin)) > 0)

        {

            const uint64_t passWordLongLong = 0;


            bufferSizeTotal += _read_bytes;


            //

            // Prepare buffer compression command structure

            //

            ASSERT(_read_bytes <= (int32_t)_chunk_to_process);

            {

                LZNV_BUFFER_COMMAND_PARAMS _lznv_buffer_compression_commands = { 0 };


                _lznv_buffer_compression_commands._command_to_execute = _LZNV_COMMAND_ENCODE;

                _lznv_buffer_compression_commands._cpu_priority_level = _LZNV_NORMAL_PRIORITY_CLASS;

                _lznv_buffer_compression_commands._encoding_method = _encoding_method;

                _lznv_buffer_compression_commands._memory_level = _memory_level;


                _lznv_buffer_compression_commands._p_source_buffer = _uint8_buffer_to_encode;

                _lznv_buffer_compression_commands._i_source_buffer_size = _read_bytes;


                _lznv_buffer_compression_commands._p_destination_buffer = _uint8_output_buffer;

                _lznv_buffer_compression_commands._i_destination_buffer_size = _write_max_bytes;

                _lznv_buffer_compression_commands._block_adler32 = _file_adler32; // progressive computation


                uint64_t dwS = GetTickCount64();


                _res = (*_p_LZNV_DLL_Main_Buffer_funct)(_lznv_buffer_compression_commands);


                uint64_t dwE = GetTickCount64();


                int32_t _write_bytes = _lznv_buffer_compression_commands._i_destination_buffer_size;


                wprintf(L"\n\n Encoding 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) {

                    break;

                }


                _putw(_read_bytes, fout);

                _putw(_write_bytes, fout);


                fwrite(_uint8_output_buffer, 1, _write_bytes, fout);


                _file_adler32 = _lznv_buffer_compression_commands._block_adler32; // progressive computation


                _blockID++;

            }

        }


        if (_uint8_buffer_to_encode) {

            free(_uint8_buffer_to_encode);

        }

        if (_uint8_output_buffer) {

            free(_uint8_output_buffer);

        }


        if (fin) {

            fclose(fin);

        }

        if (fout) {

            fclose(fout);

        }

    }


    return _res;

}