Function LZNV_Encode_File_withBuffer
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;
}