static lzham_compress_status_t create_init_params(lzcompressor::init_params ¶ms, const lzham_compress_params *pParams) { if ((pParams->m_dict_size_log2 < CLZBase::cMinDictSizeLog2) || (pParams->m_dict_size_log2 > CLZBase::cMaxDictSizeLog2)) return LZHAM_COMP_STATUS_INVALID_PARAMETER; if (pParams->m_cpucache_total_lines) { if (!math::is_power_of_2(pParams->m_cpucache_line_size)) { return LZHAM_COMP_STATUS_INVALID_PARAMETER; } } params.m_dict_size_log2 = pParams->m_dict_size_log2; params.m_max_helper_threads = LZHAM_MIN(LZHAM_MAX_HELPER_THREADS, pParams->m_max_helper_threads); params.m_num_cachelines = pParams->m_cpucache_total_lines; params.m_cacheline_size = pParams->m_cpucache_line_size; params.m_lzham_compress_flags = pParams->m_compress_flags; switch (pParams->m_level) { case LZHAM_COMP_LEVEL_FASTEST: params.m_compression_level = cCompressionLevelFastest; break; case LZHAM_COMP_LEVEL_FASTER: params.m_compression_level = cCompressionLevelFaster; break; case LZHAM_COMP_LEVEL_DEFAULT: params.m_compression_level = cCompressionLevelDefault; break; case LZHAM_COMP_LEVEL_BETTER: params.m_compression_level = cCompressionLevelBetter; break; case LZHAM_COMP_LEVEL_UBER: params.m_compression_level = cCompressionLevelUber; break; default: return LZHAM_COMP_STATUS_INVALID_PARAMETER; }; return LZHAM_COMP_STATUS_SUCCESS; }
bool generate_huffman_codes(void* pContext, uint num_syms, const uint16* pFreq, uint8* pCodesizes, uint& max_code_size, uint& total_freq_ret, code_size_histogram &code_size_hist) { if ((!num_syms) || (num_syms > cHuffmanMaxSupportedSyms)) return false; huffman_work_tables& state = *static_cast<huffman_work_tables*>(pContext);; uint max_freq = 0; uint total_freq = 0; uint num_used_syms = 0; for (uint i = 0; i < num_syms; i++) { uint freq = pFreq[i]; if (!freq) pCodesizes[i] = 0; else { total_freq += freq; max_freq = math::maximum(max_freq, freq); sym_freq& sf = state.syms0[num_used_syms]; sf.m_left = (uint16)i; sf.m_right = cUINT16_MAX; sf.m_freq = freq; num_used_syms++; } } total_freq_ret = total_freq; if (num_used_syms == 1) { pCodesizes[state.syms0[0].m_left] = 1; return true; } sym_freq* syms = radix_sort_syms(num_used_syms, state.syms0, state.syms1); int x[cHuffmanMaxSupportedSyms]; for (uint i = 0; i < num_used_syms; i++) x[i] = syms[i].m_freq; calculate_minimum_redundancy(x, num_used_syms); uint max_len = 0; for (uint i = 0; i < num_used_syms; i++) { uint len = x[i]; max_len = math::maximum(len, max_len); code_size_hist.m_num_codes[LZHAM_MIN(len, (uint)code_size_histogram::cMaxUnlimitedHuffCodeSize)]++; pCodesizes[syms[i].m_left] = static_cast<uint8>(len); } max_code_size = max_len; return true; }
int vsprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, va_list args) { if (!sizeOfBuffer) return 0; int c = vsnprintf(buffer, sizeOfBuffer, format, args); buffer[sizeOfBuffer - 1] = '\0'; if (c < 0) return sizeOfBuffer - 1; return LZHAM_MIN(c, (int)sizeOfBuffer - 1); }
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...) { if (!sizeOfBuffer) return 0; va_list args; va_start(args, format); int c = vsnprintf(buffer, sizeOfBuffer, format, args); va_end(args); buffer[sizeOfBuffer - 1] = '\0'; if (c < 0) return sizeOfBuffer - 1; return LZHAM_MIN(c, (int)sizeOfBuffer - 1); }
lzham_compress_status_t lzham_lib_compress( lzham_compress_state_ptr p, const lzham_uint8 *pIn_buf, size_t *pIn_buf_size, lzham_uint8 *pOut_buf, size_t *pOut_buf_size, lzham_bool no_more_input_bytes_flag) { lzham_compress_state *pState = static_cast<lzham_compress_state*>(p); if ((!pState) || (!pState->m_params.m_dict_size_log2) || (pState->m_status >= LZHAM_COMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE) || (!pIn_buf_size) || (!pOut_buf_size)) { return LZHAM_COMP_STATUS_INVALID_PARAMETER; } if ((*pIn_buf_size) && (!pIn_buf)) { return LZHAM_COMP_STATUS_INVALID_PARAMETER; } if ((!*pOut_buf_size) || (!pOut_buf)) { return LZHAM_COMP_STATUS_INVALID_PARAMETER; } byte_vec &comp_data = pState->m_compressor.get_compressed_data(); if (pState->m_comp_data_ofs < comp_data.size()) { *pIn_buf_size = 0; *pOut_buf_size = LZHAM_MIN(comp_data.size() - pState->m_comp_data_ofs, *pOut_buf_size); memcpy(pOut_buf, comp_data.get_ptr() + pState->m_comp_data_ofs, *pOut_buf_size); pState->m_comp_data_ofs += *pOut_buf_size; pState->m_status = LZHAM_COMP_STATUS_NOT_FINISHED; return pState->m_status; } comp_data.try_resize(0); pState->m_comp_data_ofs = 0; if (pState->m_flushed_compressor) { if ((*pIn_buf_size) || (!no_more_input_bytes_flag)) { pState->m_status = LZHAM_COMP_STATUS_INVALID_PARAMETER; return pState->m_status; } *pIn_buf_size = 0; *pOut_buf_size = 0; pState->m_status = LZHAM_COMP_STATUS_SUCCESS; return pState->m_status; } const size_t cMaxBytesToPutPerIteration = 4*1024*1024; size_t bytes_to_put = LZHAM_MIN(cMaxBytesToPutPerIteration, *pIn_buf_size); const bool consumed_entire_input_buf = (bytes_to_put == *pIn_buf_size); if (bytes_to_put) { if (!pState->m_compressor.put_bytes(pIn_buf, (uint)bytes_to_put)) { *pIn_buf_size = 0; *pOut_buf_size = 0; pState->m_status = LZHAM_COMP_STATUS_FAILED; return pState->m_status; } } if ((consumed_entire_input_buf) && (no_more_input_bytes_flag) && (!pState->m_flushed_compressor)) { if (!pState->m_compressor.put_bytes(NULL, 0)) { *pIn_buf_size = 0; *pOut_buf_size = 0; pState->m_status = LZHAM_COMP_STATUS_FAILED; return pState->m_status; } pState->m_flushed_compressor = true; } *pIn_buf_size = bytes_to_put; *pOut_buf_size = LZHAM_MIN(comp_data.size() - pState->m_comp_data_ofs, *pOut_buf_size); if (*pOut_buf_size) { memcpy(pOut_buf, comp_data.get_ptr() + pState->m_comp_data_ofs, *pOut_buf_size); pState->m_comp_data_ofs += *pOut_buf_size; } if ((no_more_input_bytes_flag) && (pState->m_flushed_compressor) && (pState->m_comp_data_ofs >= comp_data.size())) pState->m_status = LZHAM_COMP_STATUS_SUCCESS; else if ((consumed_entire_input_buf) && (!no_more_input_bytes_flag) && (pState->m_comp_data_ofs >= comp_data.size())) pState->m_status = LZHAM_COMP_STATUS_NEEDS_MORE_INPUT; else pState->m_status = LZHAM_COMP_STATUS_NOT_FINISHED; return pState->m_status; }
lzham_compress_status_t LZHAM_CDECL lzham_lib_compress2( lzham_compress_state_ptr p, const lzham_uint8 *pIn_buf, size_t *pIn_buf_size, lzham_uint8 *pOut_buf, size_t *pOut_buf_size, lzham_flush_t flush_type) { lzham_compress_state *pState = static_cast<lzham_compress_state*>(p); if ((!pState) || (!pState->m_params.m_dict_size_log2) || (pState->m_status >= LZHAM_COMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE) || (!pIn_buf_size) || (!pOut_buf_size)) return LZHAM_COMP_STATUS_INVALID_PARAMETER; if ((*pIn_buf_size) && (!pIn_buf)) return LZHAM_COMP_STATUS_INVALID_PARAMETER; if ((!*pOut_buf_size) || (!pOut_buf)) return LZHAM_COMP_STATUS_INVALID_PARAMETER; byte_vec &comp_data = pState->m_compressor.get_compressed_data(); size_t num_bytes_written_to_out_buf = 0; if (pState->m_comp_data_ofs < comp_data.size()) { size_t n = LZHAM_MIN(comp_data.size() - pState->m_comp_data_ofs, *pOut_buf_size); memcpy(pOut_buf, comp_data.get_ptr() + pState->m_comp_data_ofs, n); pState->m_comp_data_ofs += n; const bool has_no_more_output = (pState->m_comp_data_ofs >= comp_data.size()); if (has_no_more_output) { pOut_buf += n; *pOut_buf_size -= n; num_bytes_written_to_out_buf += n; } else { *pIn_buf_size = 0; *pOut_buf_size = n; pState->m_status = LZHAM_COMP_STATUS_HAS_MORE_OUTPUT; return pState->m_status; } } comp_data.try_resize(0); pState->m_comp_data_ofs = 0; if (pState->m_finished_compression) { if ((*pIn_buf_size) || (flush_type != LZHAM_FINISH)) { pState->m_status = LZHAM_COMP_STATUS_INVALID_PARAMETER; return pState->m_status; } *pIn_buf_size = 0; *pOut_buf_size = num_bytes_written_to_out_buf; pState->m_status = LZHAM_COMP_STATUS_SUCCESS; return pState->m_status; } const size_t cMaxBytesToPutPerIteration = 4*1024*1024; size_t bytes_to_put = LZHAM_MIN(cMaxBytesToPutPerIteration, *pIn_buf_size); const bool consumed_entire_input_buf = (bytes_to_put == *pIn_buf_size); if (bytes_to_put) { if (!pState->m_compressor.put_bytes(pIn_buf, (uint)bytes_to_put)) { *pIn_buf_size = 0; *pOut_buf_size = num_bytes_written_to_out_buf; pState->m_status = LZHAM_COMP_STATUS_FAILED; return pState->m_status; } } if ((consumed_entire_input_buf) && (flush_type != LZHAM_NO_FLUSH)) { if ((flush_type == LZHAM_SYNC_FLUSH) || (flush_type == LZHAM_FULL_FLUSH) || (flush_type == LZHAM_TABLE_FLUSH)) { if (!pState->m_compressor.flush(flush_type)) { *pIn_buf_size = 0; *pOut_buf_size = num_bytes_written_to_out_buf; pState->m_status = LZHAM_COMP_STATUS_FAILED; return pState->m_status; } } else if (!pState->m_finished_compression) { if (!pState->m_compressor.put_bytes(NULL, 0)) { *pIn_buf_size = 0; *pOut_buf_size = num_bytes_written_to_out_buf; pState->m_status = LZHAM_COMP_STATUS_FAILED; return pState->m_status; } pState->m_finished_compression = true; } } size_t num_comp_bytes_to_output = LZHAM_MIN(comp_data.size() - pState->m_comp_data_ofs, *pOut_buf_size); if (num_comp_bytes_to_output) { memcpy(pOut_buf, comp_data.get_ptr() + pState->m_comp_data_ofs, num_comp_bytes_to_output); pState->m_comp_data_ofs += num_comp_bytes_to_output; } *pIn_buf_size = bytes_to_put; *pOut_buf_size = num_bytes_written_to_out_buf + num_comp_bytes_to_output; const bool has_no_more_output = (pState->m_comp_data_ofs >= comp_data.size()); if ((has_no_more_output) && (flush_type == LZHAM_FINISH) && (pState->m_finished_compression)) pState->m_status = LZHAM_COMP_STATUS_SUCCESS; else if ((has_no_more_output) && (consumed_entire_input_buf) && (flush_type == LZHAM_NO_FLUSH)) pState->m_status = LZHAM_COMP_STATUS_NEEDS_MORE_INPUT; else pState->m_status = has_no_more_output ? LZHAM_COMP_STATUS_NOT_FINISHED : LZHAM_COMP_STATUS_HAS_MORE_OUTPUT; return pState->m_status; }