lzham_lzdecomp.cpp 59 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527
  1. // File: lzham_lzdecomp.cpp
  2. // See Copyright Notice and license at the end of include/lzham.h
  3. //
  4. // See "Coroutines in C":
  5. // http://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
  6. // Also see "Protothreads - Lightweight, Stackless Threads in C":
  7. // http://www.sics.se/~adam/pt/
  8. #include "lzham_core.h"
  9. #include "lzham_decomp.h"
  10. #include "lzham_symbol_codec.h"
  11. #include "lzham_checksum.h"
  12. #include "lzham_lzdecompbase.h"
  13. using namespace lzham;
  14. namespace lzham
  15. {
  16. static const uint8 s_literal_next_state[24] =
  17. {
  18. 0, 0, 0, 0, 1, 2, 3, // 0-6: literal states
  19. 4, 5, 6, 4, 5, // 7-11: match states
  20. 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 // 12-23: unused
  21. };
  22. static const uint s_huge_match_base_len[4] = { CLZDecompBase::cMaxMatchLen + 1, CLZDecompBase::cMaxMatchLen + 1 + 256, CLZDecompBase::cMaxMatchLen + 1 + 256 + 1024, CLZDecompBase::cMaxMatchLen + 1 + 256 + 1024 + 4096 };
  23. static const uint8 s_huge_match_code_len[4] = { 8, 10, 12, 16 };
  24. struct lzham_decompressor
  25. {
  26. void init();
  27. template<bool unbuffered> lzham_decompress_status_t decompress();
  28. void reset_huff_tables();
  29. void reset_arith_tables();
  30. void reset_all_tables();
  31. void reset_huffman_table_update_rates();
  32. int m_state;
  33. CLZDecompBase m_lzBase;
  34. symbol_codec m_codec;
  35. uint32 m_raw_decomp_buf_size;
  36. uint8 *m_pRaw_decomp_buf;
  37. uint8 *m_pDecomp_buf;
  38. uint32 m_decomp_adler32;
  39. const uint8 *m_pIn_buf;
  40. size_t *m_pIn_buf_size;
  41. uint8 *m_pOut_buf;
  42. size_t *m_pOut_buf_size;
  43. bool m_no_more_input_bytes_flag;
  44. uint8 *m_pOrig_out_buf;
  45. size_t m_orig_out_buf_size;
  46. lzham_decompress_params m_params;
  47. lzham_decompress_status_t m_status;
  48. quasi_adaptive_huffman_data_model m_lit_table;
  49. quasi_adaptive_huffman_data_model m_delta_lit_table;
  50. quasi_adaptive_huffman_data_model m_main_table;
  51. quasi_adaptive_huffman_data_model m_rep_len_table[2];
  52. quasi_adaptive_huffman_data_model m_large_len_table[2];
  53. quasi_adaptive_huffman_data_model m_dist_lsb_table;
  54. adaptive_bit_model m_is_match_model[CLZDecompBase::cNumStates];
  55. adaptive_bit_model m_is_rep_model[CLZDecompBase::cNumStates];
  56. adaptive_bit_model m_is_rep0_model[CLZDecompBase::cNumStates];
  57. adaptive_bit_model m_is_rep0_single_byte_model[CLZDecompBase::cNumStates];
  58. adaptive_bit_model m_is_rep1_model[CLZDecompBase::cNumStates];
  59. adaptive_bit_model m_is_rep2_model[CLZDecompBase::cNumStates];
  60. uint m_dst_ofs;
  61. uint m_dst_highwater_ofs;
  62. uint m_step;
  63. uint m_block_step;
  64. uint m_initial_step;
  65. uint m_block_index;
  66. int m_match_hist0;
  67. int m_match_hist1;
  68. int m_match_hist2;
  69. int m_match_hist3;
  70. uint m_cur_state;
  71. uint m_start_block_dst_ofs;
  72. uint m_block_type;
  73. const uint8 *m_pFlush_src;
  74. size_t m_flush_num_bytes_remaining;
  75. size_t m_flush_n;
  76. uint m_seed_bytes_to_ignore_when_flushing;
  77. uint m_file_src_file_adler32;
  78. uint m_rep_lit0;
  79. uint m_match_len;
  80. uint m_match_slot;
  81. uint m_extra_bits;
  82. uint m_num_extra_bits;
  83. uint m_src_ofs;
  84. const uint8* m_pCopy_src;
  85. uint m_num_raw_bytes_remaining;
  86. uint m_debug_is_match;
  87. uint m_debug_match_len;
  88. uint m_debug_match_dist;
  89. uint m_debug_lit;
  90. lzham_decompress_status_t m_z_last_status;
  91. uint m_z_first_call;
  92. uint m_z_has_flushed;
  93. uint m_z_cmf;
  94. uint m_z_flg;
  95. uint m_z_dict_adler32;
  96. uint m_tmp;
  97. };
  98. // Ordinarily I dislike macros like this, but in this case I think using them makes the decompression function easier to follow.
  99. // Coroutine helpers.
  100. #define LZHAM_CR_INITIAL_STATE 0
  101. #define LZHAM_CR_BEGIN(state) switch( state ) { case LZHAM_CR_INITIAL_STATE:
  102. #define LZHAM_CR_RETURN(state, result) do { state = __LINE__; return (result); case __LINE__:; } while (0)
  103. #define LZHAM_CR_FINISH }
  104. // Helpers to save/restore local variables (hopefully CPU registers) to memory.
  105. #define LZHAM_RESTORE_STATE LZHAM_RESTORE_LOCAL_STATE \
  106. match_hist0 = m_match_hist0; match_hist1 = m_match_hist1; match_hist2 = m_match_hist2; match_hist3 = m_match_hist3; \
  107. cur_state = m_cur_state; dst_ofs = m_dst_ofs;
  108. #define LZHAM_SAVE_STATE LZHAM_SAVE_LOCAL_STATE \
  109. m_match_hist0 = match_hist0; m_match_hist1 = match_hist1; m_match_hist2 = match_hist2; m_match_hist3 = match_hist3; \
  110. m_cur_state = cur_state; m_dst_ofs = dst_ofs;
  111. // Helper that coroutine returns to the caller with a request for more input bytes.
  112. #define LZHAM_DECODE_NEEDS_BYTES \
  113. LZHAM_SAVE_STATE \
  114. for ( ; ; ) \
  115. { \
  116. *m_pIn_buf_size = static_cast<size_t>(m_codec.decode_get_bytes_consumed()); \
  117. *m_pOut_buf_size = 0; \
  118. LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT); \
  119. m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag); \
  120. if ((m_codec.m_decode_buf_eof) || (m_codec.m_decode_buf_size)) break; \
  121. } \
  122. LZHAM_RESTORE_STATE
  123. #if LZHAM_PLATFORM_X360
  124. #define LZHAM_BULK_MEMCPY XMemCpy
  125. #define LZHAM_MEMCPY memcpy
  126. #else
  127. #define LZHAM_BULK_MEMCPY memcpy
  128. #define LZHAM_MEMCPY memcpy
  129. #endif
  130. // Flush the output buffer/dictionary by doing a coroutine return to the caller.
  131. // Buffered mode only.
  132. #define LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_ofs) \
  133. LZHAM_SAVE_STATE \
  134. m_pFlush_src = m_pDecomp_buf + m_seed_bytes_to_ignore_when_flushing + m_dst_highwater_ofs; \
  135. m_flush_num_bytes_remaining = dict_ofs - m_seed_bytes_to_ignore_when_flushing - m_dst_highwater_ofs; \
  136. m_seed_bytes_to_ignore_when_flushing = 0; \
  137. m_dst_highwater_ofs = dict_ofs & dict_size_mask; \
  138. while (m_flush_num_bytes_remaining) \
  139. { \
  140. m_flush_n = LZHAM_MIN(m_flush_num_bytes_remaining, *m_pOut_buf_size); \
  141. if (0 == (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_COMPUTE_ADLER32)) \
  142. { \
  143. LZHAM_BULK_MEMCPY(m_pOut_buf, m_pFlush_src, m_flush_n); \
  144. } \
  145. else \
  146. { \
  147. size_t copy_ofs = 0; \
  148. while (copy_ofs < m_flush_n) \
  149. { \
  150. const uint cBytesToMemCpyPerIteration = 8192U; \
  151. size_t bytes_to_copy = LZHAM_MIN((size_t)(m_flush_n - copy_ofs), cBytesToMemCpyPerIteration); \
  152. LZHAM_MEMCPY(m_pOut_buf + copy_ofs, m_pFlush_src + copy_ofs, bytes_to_copy); \
  153. m_decomp_adler32 = adler32(m_pFlush_src + copy_ofs, bytes_to_copy, m_decomp_adler32); \
  154. copy_ofs += bytes_to_copy; \
  155. } \
  156. } \
  157. *m_pIn_buf_size = static_cast<size_t>(m_codec.decode_get_bytes_consumed()); \
  158. *m_pOut_buf_size = m_flush_n; \
  159. LZHAM_CR_RETURN(m_state, m_flush_n ? LZHAM_DECOMP_STATUS_NOT_FINISHED : LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT); \
  160. m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag); \
  161. m_pFlush_src += m_flush_n; \
  162. m_flush_num_bytes_remaining -= m_flush_n; \
  163. } \
  164. LZHAM_RESTORE_STATE
  165. #define LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, result, model) LZHAM_SYMBOL_CODEC_DECODE_ADAPTIVE_HUFFMAN(codec, result, model)
  166. //------------------------------------------------------------------------------------------------------------------
  167. void lzham_decompressor::init()
  168. {
  169. m_lzBase.init_position_slots(m_params.m_dict_size_log2);
  170. #ifdef LZHAM_LZDEBUG
  171. if (m_pDecomp_buf)
  172. memset(m_pDecomp_buf, 0xCE, 1U << m_params.m_dict_size_log2);
  173. #endif
  174. m_state = LZHAM_CR_INITIAL_STATE;
  175. m_step = 0;
  176. m_block_step = 0;
  177. m_block_index = 0;
  178. m_initial_step = 0;
  179. m_dst_ofs = 0;
  180. m_dst_highwater_ofs = 0;
  181. m_pIn_buf = NULL;
  182. m_pIn_buf_size = NULL;
  183. m_pOut_buf = NULL;
  184. m_pOut_buf_size = NULL;
  185. m_no_more_input_bytes_flag = false;
  186. m_status = LZHAM_DECOMP_STATUS_NOT_FINISHED;
  187. m_pOrig_out_buf = NULL;
  188. m_orig_out_buf_size = 0;
  189. m_decomp_adler32 = cInitAdler32;
  190. m_seed_bytes_to_ignore_when_flushing = 0;
  191. m_z_last_status = LZHAM_DECOMP_STATUS_NOT_FINISHED;
  192. m_z_first_call = 1;
  193. m_z_has_flushed = 0;
  194. m_z_cmf = 0;
  195. m_z_flg = 0;
  196. m_z_dict_adler32 = 0;
  197. m_tmp = 0;
  198. m_match_hist0 = 0;
  199. m_match_hist1 = 0;
  200. m_match_hist2 = 0;
  201. m_match_hist3 = 0;
  202. m_cur_state = 0;
  203. m_start_block_dst_ofs = 0;
  204. m_block_type = 0;
  205. m_flush_num_bytes_remaining = 0;
  206. m_flush_n = 0;
  207. m_file_src_file_adler32 = 0;
  208. m_rep_lit0 = 0;
  209. m_match_len = 0;
  210. m_match_slot = 0;
  211. m_extra_bits = 0;
  212. m_num_extra_bits = 0;
  213. m_src_ofs = 0;
  214. m_pCopy_src = NULL;
  215. m_num_raw_bytes_remaining = 0;
  216. m_codec.clear();
  217. }
  218. void lzham_decompressor::reset_huff_tables()
  219. {
  220. m_lit_table.reset();
  221. m_delta_lit_table.reset();
  222. m_main_table.reset();
  223. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
  224. m_rep_len_table[i].reset();
  225. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
  226. m_large_len_table[i].reset();
  227. m_dist_lsb_table.reset();
  228. }
  229. void lzham_decompressor::reset_arith_tables()
  230. {
  231. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_is_match_model); i++)
  232. m_is_match_model[i].clear();
  233. for (uint i = 0; i < CLZDecompBase::cNumStates; i++)
  234. {
  235. m_is_rep_model[i].clear();
  236. m_is_rep0_model[i].clear();
  237. m_is_rep0_single_byte_model[i].clear();
  238. m_is_rep1_model[i].clear();
  239. m_is_rep2_model[i].clear();
  240. }
  241. }
  242. void lzham_decompressor::reset_all_tables()
  243. {
  244. reset_huff_tables();
  245. reset_arith_tables();
  246. }
  247. void lzham_decompressor::reset_huffman_table_update_rates()
  248. {
  249. m_lit_table.reset_update_rate();
  250. m_delta_lit_table.reset_update_rate();
  251. m_main_table.reset_update_rate();
  252. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_rep_len_table); i++)
  253. m_rep_len_table[i].reset_update_rate();
  254. for (uint i = 0; i < LZHAM_ARRAY_SIZE(m_large_len_table); i++)
  255. m_large_len_table[i].reset_update_rate();
  256. m_dist_lsb_table.reset_update_rate();
  257. }
  258. //------------------------------------------------------------------------------------------------------------------
  259. // Decompression method. Implemented as a coroutine so it can be paused and resumed to support streaming.
  260. //------------------------------------------------------------------------------------------------------------------
  261. template<bool unbuffered>
  262. lzham_decompress_status_t lzham_decompressor::decompress()
  263. {
  264. // Important: This function is a coroutine. ANY locals variables that need to be preserved across coroutine
  265. // returns must be either be a member variable, or a local which is saved/restored to a member variable at
  266. // the right times. (This makes this function difficult to follow and freaking ugly due to the macros of doom - but hey it works.)
  267. // The most often used variables are in locals so the compiler hopefully puts them into CPU registers.
  268. symbol_codec &codec = m_codec;
  269. const uint dict_size = 1U << m_params.m_dict_size_log2;
  270. const uint dict_size_mask = unbuffered ? UINT_MAX : (dict_size - 1);
  271. int match_hist0 = 0, match_hist1 = 0, match_hist2 = 0, match_hist3 = 0;
  272. uint cur_state = 0, dst_ofs = 0;
  273. const size_t out_buf_size = *m_pOut_buf_size;
  274. uint8* pDst = unbuffered ? reinterpret_cast<uint8*>(m_pOut_buf) : reinterpret_cast<uint8*>(m_pDecomp_buf);
  275. uint8* pDst_end = unbuffered ? (reinterpret_cast<uint8*>(m_pOut_buf) + out_buf_size) : (reinterpret_cast<uint8*>(m_pDecomp_buf) + dict_size);
  276. LZHAM_SYMBOL_CODEC_DECODE_DECLARE(codec);
  277. #define LZHAM_SAVE_LOCAL_STATE
  278. #define LZHAM_RESTORE_LOCAL_STATE
  279. // Important: Do not use any switch() statements below here.
  280. LZHAM_CR_BEGIN(m_state)
  281. if ((!unbuffered) && (m_params.m_num_seed_bytes))
  282. {
  283. LZHAM_BULK_MEMCPY(pDst, m_params.m_pSeed_bytes, m_params.m_num_seed_bytes);
  284. dst_ofs += m_params.m_num_seed_bytes;
  285. if (dst_ofs >= dict_size)
  286. dst_ofs = 0;
  287. else
  288. m_seed_bytes_to_ignore_when_flushing = dst_ofs;
  289. }
  290. if (!m_codec.start_decoding(m_pIn_buf, *m_pIn_buf_size, m_no_more_input_bytes_flag, NULL, NULL))
  291. return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
  292. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  293. {
  294. if (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM)
  295. {
  296. uint check;
  297. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_z_cmf, 8);
  298. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_z_flg, 8);
  299. check = ((m_z_cmf << 8) + m_z_flg) % 31;
  300. if ((check != 0) || ((m_z_cmf & 15) != LZHAM_Z_LZHAM))
  301. return LZHAM_DECOMP_STATUS_FAILED_BAD_ZLIB_HEADER;
  302. if (m_z_flg & 32)
  303. {
  304. if ((!m_params.m_pSeed_bytes) || (unbuffered))
  305. return LZHAM_DECOMP_STATUS_FAILED_NEED_SEED_BYTES;
  306. m_z_dict_adler32 = 0;
  307. for (m_tmp = 0; m_tmp < 4; ++m_tmp)
  308. {
  309. uint n; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 8);
  310. m_z_dict_adler32 = (m_z_dict_adler32 << 8) | n;
  311. }
  312. if (adler32(m_params.m_pSeed_bytes, m_params.m_num_seed_bytes) != m_z_dict_adler32)
  313. return LZHAM_DECOMP_STATUS_FAILED_BAD_SEED_BYTES;
  314. }
  315. }
  316. {
  317. // Was written by lzcompressor::send_configuration().
  318. //uint tmp;
  319. //LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, tmp, 2);
  320. }
  321. uint max_update_interval = m_params.m_table_max_update_interval, update_interval_slow_rate = m_params.m_table_update_interval_slow_rate;
  322. if (!max_update_interval && !update_interval_slow_rate)
  323. {
  324. uint rate = m_params.m_table_update_rate;
  325. if (!rate)
  326. rate = LZHAM_DEFAULT_TABLE_UPDATE_RATE;
  327. rate = math::clamp<uint>(rate, 1, LZHAM_FASTEST_TABLE_UPDATE_RATE) - 1;
  328. max_update_interval = g_table_update_settings[rate].m_max_update_interval;
  329. update_interval_slow_rate = g_table_update_settings[rate].m_slow_rate;
  330. }
  331. bool succeeded = m_lit_table.init2(false, 256, max_update_interval, update_interval_slow_rate, NULL);
  332. succeeded = succeeded && m_delta_lit_table.assign(m_lit_table);
  333. succeeded = succeeded && m_main_table.init2(false, CLZDecompBase::cLZXNumSpecialLengths + (m_lzBase.m_num_lzx_slots - CLZDecompBase::cLZXLowestUsableMatchSlot) * 8, max_update_interval, update_interval_slow_rate, NULL);
  334. succeeded = succeeded && m_rep_len_table[0].init2(false, CLZDecompBase::cNumHugeMatchCodes + (CLZDecompBase::cMaxMatchLen - CLZDecompBase::cMinMatchLen + 1), max_update_interval, update_interval_slow_rate, NULL);
  335. succeeded = succeeded && m_rep_len_table[1].assign(m_rep_len_table[0]);
  336. succeeded = succeeded && m_large_len_table[0].init2(false, CLZDecompBase::cNumHugeMatchCodes + CLZDecompBase::cLZXNumSecondaryLengths, max_update_interval, update_interval_slow_rate, NULL);
  337. succeeded = succeeded && m_large_len_table[1].assign(m_large_len_table[0]);
  338. succeeded = succeeded && m_dist_lsb_table.init2(false, 16, max_update_interval, update_interval_slow_rate, NULL);
  339. if (!succeeded)
  340. return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
  341. }
  342. // Output block loop.
  343. do
  344. {
  345. #ifdef LZHAM_LZDEBUG
  346. uint outer_sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, 12);
  347. LZHAM_VERIFY(outer_sync_marker == 166);
  348. #endif
  349. // Decode block type.
  350. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_block_type, CLZDecompBase::cBlockHeaderBits);
  351. if (m_block_type == CLZDecompBase::cSyncBlock)
  352. {
  353. // Sync block
  354. // Reset either the symbol table update rates, or all statistics, then force a coroutine return to give the caller a chance to handle the output right now.
  355. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_tmp, CLZDecompBase::cBlockFlushTypeBits);
  356. // See lzcompressor::send_sync_block() (TODO: make these an enum)
  357. if (m_tmp == 1)
  358. reset_huffman_table_update_rates();
  359. else if (m_tmp == 2)
  360. reset_all_tables();
  361. LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
  362. uint n; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 16);
  363. if (n != 0)
  364. {
  365. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  366. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  367. *m_pOut_buf_size = 0;
  368. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_SYNC_BLOCK); }
  369. }
  370. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, n, 16);
  371. if (n != 0xFFFF)
  372. {
  373. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  374. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  375. *m_pOut_buf_size = 0;
  376. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_SYNC_BLOCK); }
  377. }
  378. // See lzcompressor::send_sync_block() (TODO: make these an enum)
  379. if ((m_tmp == 2) || (m_tmp == 3))
  380. {
  381. // It's a sync or full flush, so immediately give caller whatever output we have. Also gives the caller a chance to reposition the input stream ptr somewhere else before continuing.
  382. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  383. if ((!unbuffered) && (dst_ofs))
  384. {
  385. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dst_ofs);
  386. }
  387. else
  388. {
  389. if (unbuffered)
  390. {
  391. LZHAM_ASSERT(dst_ofs >= m_dst_highwater_ofs);
  392. }
  393. else
  394. {
  395. LZHAM_ASSERT(!m_dst_highwater_ofs);
  396. }
  397. // unbuffered, or dst_ofs==0
  398. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  399. *m_pOut_buf_size = dst_ofs - m_dst_highwater_ofs;
  400. // Partial/sync flushes in unbuffered mode details:
  401. // We assume the caller doesn't move the output buffer between calls AND the pointer to the output buffer input parameter won't change between calls (i.e.
  402. // it *always* points to the beginning of the decompressed stream). The caller will need to track the current output buffer offset.
  403. m_dst_highwater_ofs = dst_ofs;
  404. LZHAM_SAVE_STATE
  405. LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NOT_FINISHED);
  406. LZHAM_RESTORE_STATE
  407. m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag);
  408. }
  409. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  410. }
  411. }
  412. else if (m_block_type == CLZDecompBase::cRawBlock)
  413. {
  414. // Raw block handling is complex because we ultimately want to (safely) handle as many bytes as possible using a small number of memcpy()'s.
  415. uint num_raw_bytes_remaining;
  416. num_raw_bytes_remaining = 0;
  417. #undef LZHAM_SAVE_LOCAL_STATE
  418. #undef LZHAM_RESTORE_LOCAL_STATE
  419. #define LZHAM_SAVE_LOCAL_STATE m_num_raw_bytes_remaining = num_raw_bytes_remaining;
  420. #define LZHAM_RESTORE_LOCAL_STATE num_raw_bytes_remaining = m_num_raw_bytes_remaining;
  421. // Determine how large this raw block is.
  422. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, num_raw_bytes_remaining, 24);
  423. // Get and verify raw block length check bits.
  424. uint num_raw_bytes_check_bits; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, num_raw_bytes_check_bits, 8);
  425. uint raw_bytes_remaining0, raw_bytes_remaining1, raw_bytes_remaining2;
  426. raw_bytes_remaining0 = num_raw_bytes_remaining & 0xFF;
  427. raw_bytes_remaining1 = (num_raw_bytes_remaining >> 8) & 0xFF;
  428. raw_bytes_remaining2 = (num_raw_bytes_remaining >> 16) & 0xFF;
  429. if (num_raw_bytes_check_bits != ((raw_bytes_remaining0 ^ raw_bytes_remaining1) ^ raw_bytes_remaining2))
  430. {
  431. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  432. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  433. *m_pOut_buf_size = 0;
  434. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_RAW_BLOCK); }
  435. }
  436. num_raw_bytes_remaining++;
  437. // Discard any partial bytes from the bit buffer (align up to the next byte).
  438. LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
  439. // Flush any full bytes from the bit buffer.
  440. do
  441. {
  442. int b;
  443. LZHAM_SYMBOL_CODEC_DECODE_REMOVE_BYTE_FROM_BIT_BUF(codec, b);
  444. if (b < 0)
  445. break;
  446. if ((unbuffered) && (dst_ofs >= out_buf_size))
  447. {
  448. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  449. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  450. *m_pOut_buf_size = 0;
  451. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
  452. }
  453. pDst[dst_ofs++] = static_cast<uint8>(b);
  454. if ((!unbuffered) && (dst_ofs > dict_size_mask))
  455. {
  456. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  457. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
  458. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  459. dst_ofs = 0;
  460. }
  461. num_raw_bytes_remaining--;
  462. } while (num_raw_bytes_remaining);
  463. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  464. // Now handle the bulk of the raw data with memcpy().
  465. while (num_raw_bytes_remaining)
  466. {
  467. uint64 in_buf_ofs, in_buf_remaining;
  468. in_buf_ofs = codec.decode_get_bytes_consumed();
  469. in_buf_remaining = *m_pIn_buf_size - in_buf_ofs;
  470. while (!in_buf_remaining)
  471. {
  472. // We need more bytes from the caller.
  473. *m_pIn_buf_size = static_cast<size_t>(in_buf_ofs);
  474. *m_pOut_buf_size = 0;
  475. if (m_no_more_input_bytes_flag)
  476. {
  477. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_EXPECTED_MORE_RAW_BYTES); }
  478. }
  479. LZHAM_SAVE_STATE
  480. LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT);
  481. LZHAM_RESTORE_STATE
  482. m_codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf, m_no_more_input_bytes_flag);
  483. in_buf_ofs = 0;
  484. in_buf_remaining = *m_pIn_buf_size;
  485. }
  486. // Determine how many bytes we can safely memcpy() in a single call.
  487. uint num_bytes_to_copy;
  488. num_bytes_to_copy = static_cast<uint>(LZHAM_MIN(num_raw_bytes_remaining, in_buf_remaining));
  489. if (!unbuffered)
  490. num_bytes_to_copy = LZHAM_MIN(num_bytes_to_copy, dict_size - dst_ofs);
  491. if ((unbuffered) && ((dst_ofs + num_bytes_to_copy) > out_buf_size))
  492. {
  493. // Output buffer is not large enough.
  494. *m_pIn_buf_size = static_cast<size_t>(in_buf_ofs);
  495. *m_pOut_buf_size = 0;
  496. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
  497. }
  498. // Copy the raw bytes.
  499. LZHAM_BULK_MEMCPY(pDst + dst_ofs, m_pIn_buf + in_buf_ofs, num_bytes_to_copy);
  500. in_buf_ofs += num_bytes_to_copy;
  501. num_raw_bytes_remaining -= num_bytes_to_copy;
  502. codec.decode_set_input_buffer(m_pIn_buf, *m_pIn_buf_size, m_pIn_buf + in_buf_ofs, m_no_more_input_bytes_flag);
  503. dst_ofs += num_bytes_to_copy;
  504. if ((!unbuffered) && (dst_ofs > dict_size_mask))
  505. {
  506. LZHAM_ASSERT(dst_ofs == dict_size);
  507. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
  508. dst_ofs = 0;
  509. }
  510. }
  511. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  512. #undef LZHAM_SAVE_LOCAL_STATE
  513. #undef LZHAM_RESTORE_LOCAL_STATE
  514. #define LZHAM_SAVE_LOCAL_STATE
  515. #define LZHAM_RESTORE_LOCAL_STATE
  516. }
  517. else if (m_block_type == CLZDecompBase::cCompBlock)
  518. {
  519. LZHAM_SYMBOL_CODEC_DECODE_ARITH_START(codec)
  520. match_hist0 = 1;
  521. match_hist1 = 1;
  522. match_hist2 = 1;
  523. match_hist3 = 1;
  524. cur_state = 0;
  525. m_start_block_dst_ofs = dst_ofs;
  526. {
  527. uint block_flush_type; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, block_flush_type, CLZDecompBase::cBlockFlushTypeBits);
  528. if (block_flush_type == 1)
  529. reset_huffman_table_update_rates();
  530. else if (block_flush_type == 2)
  531. reset_all_tables();
  532. }
  533. #ifdef LZHAM_LZDEBUG
  534. m_initial_step = m_step;
  535. m_block_step = 0;
  536. for ( ; ; m_step++, m_block_step++)
  537. #else
  538. for ( ; ; )
  539. #endif
  540. {
  541. #ifdef LZHAM_LZDEBUG
  542. uint sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, x, CLZDecompBase::cLZHAMDebugSyncMarkerBits);
  543. LZHAM_VERIFY(sync_marker == CLZDecompBase::cLZHAMDebugSyncMarkerValue);
  544. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_is_match, 1);
  545. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_match_len, 17);
  546. uint debug_cur_state; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, debug_cur_state, 4);
  547. LZHAM_VERIFY(cur_state == debug_cur_state);
  548. #endif
  549. // Read "is match" bit.
  550. uint match_model_index;
  551. match_model_index = LZHAM_IS_MATCH_MODEL_INDEX(cur_state);
  552. LZHAM_ASSERT(match_model_index < LZHAM_ARRAY_SIZE(m_is_match_model));
  553. uint is_match_bit; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_match_bit, m_is_match_model[match_model_index]);
  554. #ifdef LZHAM_LZDEBUG
  555. LZHAM_VERIFY(is_match_bit == m_debug_is_match);
  556. #endif
  557. if (LZHAM_BUILTIN_EXPECT(!is_match_bit, 0))
  558. {
  559. // Handle literal.
  560. #ifdef LZHAM_LZDEBUG
  561. LZHAM_VERIFY(m_debug_match_len == 1);
  562. #endif
  563. #ifdef LZHAM_LZDEBUG
  564. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_lit, 8);
  565. #endif
  566. if ((unbuffered) && (LZHAM_BUILTIN_EXPECT(dst_ofs >= out_buf_size, 0)))
  567. {
  568. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  569. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  570. *m_pOut_buf_size = 0;
  571. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_DEST_BUF_TOO_SMALL); }
  572. }
  573. if (LZHAM_BUILTIN_EXPECT(cur_state < CLZDecompBase::cNumLitStates, 1))
  574. {
  575. // Regular literal
  576. uint r; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, r, m_lit_table);
  577. pDst[dst_ofs] = static_cast<uint8>(r);
  578. #ifdef LZHAM_LZDEBUG
  579. LZHAM_VERIFY(pDst[dst_ofs] == m_debug_lit);
  580. #endif
  581. }
  582. else
  583. {
  584. // Delta literal
  585. uint match_hist0_ofs, rep_lit0;
  586. // Determine delta literal's partial context.
  587. match_hist0_ofs = dst_ofs - match_hist0;
  588. rep_lit0 = pDst[match_hist0_ofs & dict_size_mask];
  589. #undef LZHAM_SAVE_LOCAL_STATE
  590. #undef LZHAM_RESTORE_LOCAL_STATE
  591. #define LZHAM_SAVE_LOCAL_STATE m_rep_lit0 = rep_lit0;
  592. #define LZHAM_RESTORE_LOCAL_STATE rep_lit0 = m_rep_lit0;
  593. #ifdef LZHAM_LZDEBUG
  594. uint debug_rep_lit0; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, debug_rep_lit0, 8);
  595. LZHAM_VERIFY(debug_rep_lit0 == rep_lit0);
  596. #endif
  597. uint r; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, r, m_delta_lit_table);
  598. r ^= rep_lit0;
  599. pDst[dst_ofs] = static_cast<uint8>(r);
  600. #ifdef LZHAM_LZDEBUG
  601. LZHAM_VERIFY(pDst[dst_ofs] == m_debug_lit);
  602. #endif
  603. #undef LZHAM_SAVE_LOCAL_STATE
  604. #undef LZHAM_RESTORE_LOCAL_STATE
  605. #define LZHAM_SAVE_LOCAL_STATE
  606. #define LZHAM_RESTORE_LOCAL_STATE
  607. }
  608. cur_state = s_literal_next_state[cur_state];
  609. dst_ofs++;
  610. if ((!unbuffered) && (LZHAM_BUILTIN_EXPECT(dst_ofs > dict_size_mask, 0)))
  611. {
  612. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  613. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
  614. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  615. dst_ofs = 0;
  616. }
  617. }
  618. else
  619. {
  620. // Handle match.
  621. uint match_len;
  622. match_len = 1;
  623. #undef LZHAM_SAVE_LOCAL_STATE
  624. #undef LZHAM_RESTORE_LOCAL_STATE
  625. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len;
  626. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len;
  627. // Determine if match is a rep_match, and if so what type.
  628. uint is_rep; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep, m_is_rep_model[cur_state]);
  629. if (LZHAM_BUILTIN_EXPECT(is_rep, 1))
  630. {
  631. uint is_rep0; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep0, m_is_rep0_model[cur_state]);
  632. if (LZHAM_BUILTIN_EXPECT(is_rep0, 1))
  633. {
  634. uint is_rep0_len1; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep0_len1, m_is_rep0_single_byte_model[cur_state]);
  635. if (LZHAM_BUILTIN_EXPECT(is_rep0_len1, 1))
  636. {
  637. cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 9 : 11;
  638. }
  639. else
  640. {
  641. LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, match_len, m_rep_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
  642. match_len += CLZDecompBase::cMinMatchLen;
  643. if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
  644. {
  645. // Decode "huge" match length.
  646. match_len = 0;
  647. do
  648. {
  649. uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
  650. if (!b)
  651. break;
  652. match_len++;
  653. } while (match_len < 3);
  654. uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
  655. match_len = s_huge_match_base_len[match_len] + k;
  656. }
  657. cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 8 : 11;
  658. }
  659. }
  660. else
  661. {
  662. LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, match_len, m_rep_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
  663. match_len += CLZDecompBase::cMinMatchLen;
  664. if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
  665. {
  666. // Decode "huge" match length.
  667. match_len = 0;
  668. do
  669. {
  670. uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
  671. if (!b)
  672. break;
  673. match_len++;
  674. } while (match_len < 3);
  675. uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
  676. match_len = s_huge_match_base_len[match_len] + k;
  677. }
  678. uint is_rep1; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep1, m_is_rep1_model[cur_state]);
  679. if (LZHAM_BUILTIN_EXPECT(is_rep1, 1))
  680. {
  681. uint temp = match_hist1;
  682. match_hist1 = match_hist0;
  683. match_hist0 = temp;
  684. }
  685. else
  686. {
  687. uint is_rep2; LZHAM_SYMBOL_CODEC_DECODE_ARITH_BIT(codec, is_rep2, m_is_rep2_model[cur_state]);
  688. if (LZHAM_BUILTIN_EXPECT(is_rep2, 1))
  689. {
  690. // rep2
  691. uint temp = match_hist2;
  692. match_hist2 = match_hist1;
  693. match_hist1 = match_hist0;
  694. match_hist0 = temp;
  695. }
  696. else
  697. {
  698. // rep3
  699. uint temp = match_hist3;
  700. match_hist3 = match_hist2;
  701. match_hist2 = match_hist1;
  702. match_hist1 = match_hist0;
  703. match_hist0 = temp;
  704. }
  705. }
  706. cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? 8 : 11;
  707. }
  708. }
  709. else
  710. {
  711. // Handle normal/full match.
  712. uint sym; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, sym, m_main_table);
  713. sym -= CLZDecompBase::cLZXNumSpecialLengths;
  714. if (LZHAM_BUILTIN_EXPECT(static_cast<int>(sym) < 0, 0))
  715. {
  716. // Handle special symbols.
  717. if (static_cast<int>(sym) == (CLZDecompBase::cLZXSpecialCodeEndOfBlockCode - CLZDecompBase::cLZXNumSpecialLengths))
  718. break;
  719. else
  720. {
  721. // Must be cLZXSpecialCodePartialStateReset.
  722. match_hist0 = 1;
  723. match_hist1 = 1;
  724. match_hist2 = 1;
  725. match_hist3 = 1;
  726. cur_state = 0;
  727. continue;
  728. }
  729. }
  730. // Low 3 bits of symbol = match length category, higher bits = distance category.
  731. match_len = (sym & 7) + 2;
  732. uint match_slot;
  733. match_slot = (sym >> 3) + CLZDecompBase::cLZXLowestUsableMatchSlot;
  734. #undef LZHAM_SAVE_LOCAL_STATE
  735. #undef LZHAM_RESTORE_LOCAL_STATE
  736. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot;
  737. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot;
  738. if (LZHAM_BUILTIN_EXPECT(match_len == 9, 0))
  739. {
  740. // Match is >= 9 bytes, decode the actual length.
  741. uint e; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, e, m_large_len_table[cur_state >= CLZDecompBase::cNumLitStates]);
  742. match_len += e;
  743. if (match_len == (CLZDecompBase::cMaxMatchLen + 1))
  744. {
  745. // Decode "huge" match length.
  746. match_len = 0;
  747. do
  748. {
  749. uint b; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, b, 1);
  750. if (!b)
  751. break;
  752. match_len++;
  753. } while (match_len < 3);
  754. uint k; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, k, s_huge_match_code_len[match_len]);
  755. match_len = s_huge_match_base_len[match_len] + k;
  756. }
  757. }
  758. uint num_extra_bits;
  759. num_extra_bits = m_lzBase.m_lzx_position_extra_bits[match_slot];
  760. uint extra_bits;
  761. #undef LZHAM_SAVE_LOCAL_STATE
  762. #undef LZHAM_RESTORE_LOCAL_STATE
  763. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot; m_num_extra_bits = num_extra_bits;
  764. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot; num_extra_bits = m_num_extra_bits;
  765. if (LZHAM_BUILTIN_EXPECT(num_extra_bits < 3, 0))
  766. {
  767. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, extra_bits, num_extra_bits);
  768. }
  769. else
  770. {
  771. extra_bits = 0;
  772. if (LZHAM_BUILTIN_EXPECT(num_extra_bits > 4, 1))
  773. {
  774. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, extra_bits, num_extra_bits - 4);
  775. extra_bits <<= 4;
  776. }
  777. #undef LZHAM_SAVE_LOCAL_STATE
  778. #undef LZHAM_RESTORE_LOCAL_STATE
  779. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_match_slot = match_slot; m_extra_bits = extra_bits;
  780. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; match_slot = m_match_slot; extra_bits = m_extra_bits;
  781. uint j; LZHAM_DECOMPRESS_DECODE_ADAPTIVE_SYMBOL(codec, j, m_dist_lsb_table);
  782. extra_bits += j;
  783. }
  784. match_hist3 = match_hist2;
  785. match_hist2 = match_hist1;
  786. match_hist1 = match_hist0;
  787. match_hist0 = m_lzBase.m_lzx_position_base[match_slot] + extra_bits;
  788. cur_state = (cur_state < CLZDecompBase::cNumLitStates) ? CLZDecompBase::cNumLitStates : CLZDecompBase::cNumLitStates + 3;
  789. #undef LZHAM_SAVE_LOCAL_STATE
  790. #undef LZHAM_RESTORE_LOCAL_STATE
  791. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len;
  792. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len;
  793. }
  794. // We have the match's length and distance, now do the copy.
  795. #ifdef LZHAM_LZDEBUG
  796. LZHAM_VERIFY(match_len == m_debug_match_len);
  797. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_debug_match_dist, 25);
  798. uint d; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, d, 4);
  799. m_debug_match_dist = (m_debug_match_dist << 4) | d;
  800. LZHAM_VERIFY((uint)match_hist0 == m_debug_match_dist);
  801. #endif
  802. if ( (unbuffered) && LZHAM_BUILTIN_EXPECT((((size_t)match_hist0 > dst_ofs) || ((dst_ofs + match_len) > out_buf_size)), 0) )
  803. {
  804. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  805. *m_pIn_buf_size = static_cast<size_t>(codec.decode_get_bytes_consumed());
  806. *m_pOut_buf_size = 0;
  807. for ( ; ; ) { LZHAM_CR_RETURN(m_state, LZHAM_DECOMP_STATUS_FAILED_BAD_CODE); }
  808. }
  809. uint src_ofs;
  810. const uint8* pCopy_src;
  811. src_ofs = (dst_ofs - match_hist0) & dict_size_mask;
  812. pCopy_src = pDst + src_ofs;
  813. #undef LZHAM_SAVE_LOCAL_STATE
  814. #undef LZHAM_RESTORE_LOCAL_STATE
  815. #define LZHAM_SAVE_LOCAL_STATE m_match_len = match_len; m_src_ofs = src_ofs; m_pCopy_src = pCopy_src;
  816. #define LZHAM_RESTORE_LOCAL_STATE match_len = m_match_len; src_ofs = m_src_ofs; pCopy_src = m_pCopy_src;
  817. if ( (!unbuffered) && LZHAM_BUILTIN_EXPECT( ((LZHAM_MAX(src_ofs, dst_ofs) + match_len) > dict_size_mask), 0) )
  818. {
  819. // Match source or destination wraps around the end of the dictionary to the beginning, so handle the copy one byte at a time.
  820. do
  821. {
  822. pDst[dst_ofs++] = *pCopy_src++;
  823. if (LZHAM_BUILTIN_EXPECT(pCopy_src == pDst_end, 0))
  824. pCopy_src = pDst;
  825. if (LZHAM_BUILTIN_EXPECT(dst_ofs > dict_size_mask, 0))
  826. {
  827. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  828. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dict_size);
  829. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  830. dst_ofs = 0;
  831. }
  832. match_len--;
  833. } while (LZHAM_BUILTIN_EXPECT(match_len > 0, 1));
  834. }
  835. else
  836. {
  837. uint8* pCopy_dst = pDst + dst_ofs;
  838. if (LZHAM_BUILTIN_EXPECT(match_hist0 == 1, 0))
  839. {
  840. // Handle byte runs.
  841. uint8 c = *pCopy_src;
  842. if (LZHAM_BUILTIN_EXPECT(match_len < 8, 1))
  843. {
  844. for (int i = match_len; i > 0; i--)
  845. *pCopy_dst++ = c;
  846. }
  847. else
  848. {
  849. memset(pCopy_dst, c, match_len);
  850. }
  851. }
  852. else
  853. {
  854. // Handle matches of length 2 or higher.
  855. if (LZHAM_BUILTIN_EXPECT(((match_len < 8) || ((int)match_len > match_hist0)), 1))
  856. {
  857. for (int i = match_len; i > 0; i--)
  858. *pCopy_dst++ = *pCopy_src++;
  859. }
  860. else
  861. {
  862. LZHAM_MEMCPY(pCopy_dst, pCopy_src, match_len);
  863. }
  864. }
  865. dst_ofs += match_len;
  866. }
  867. } // lit or match
  868. #undef LZHAM_SAVE_LOCAL_STATE
  869. #undef LZHAM_RESTORE_LOCAL_STATE
  870. #define LZHAM_SAVE_LOCAL_STATE
  871. #define LZHAM_RESTORE_LOCAL_STATE
  872. } // for ( ; ; )
  873. #ifdef LZHAM_LZDEBUG
  874. uint end_sync_marker; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, end_sync_marker, 12);
  875. LZHAM_VERIFY(end_sync_marker == 366);
  876. #endif
  877. LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
  878. }
  879. else if (m_block_type == CLZDecompBase::cEOFBlock)
  880. {
  881. // Received EOF.
  882. m_status = LZHAM_DECOMP_STATUS_SUCCESS;
  883. }
  884. else
  885. {
  886. // This block type is currently undefined.
  887. m_status = LZHAM_DECOMP_STATUS_FAILED_BAD_CODE;
  888. }
  889. m_block_index++;
  890. } while (m_status == LZHAM_DECOMP_STATUS_NOT_FINISHED);
  891. if ((!unbuffered) && (dst_ofs))
  892. {
  893. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  894. LZHAM_FLUSH_DICT_TO_OUTPUT_BUFFER(dst_ofs);
  895. LZHAM_SYMBOL_CODEC_DECODE_BEGIN(codec);
  896. }
  897. if (m_status == LZHAM_DECOMP_STATUS_SUCCESS)
  898. {
  899. LZHAM_SYMBOL_CODEC_DECODE_ALIGN_TO_BYTE(codec);
  900. LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, m_file_src_file_adler32, 16);
  901. uint l; LZHAM_SYMBOL_CODEC_DECODE_GET_BITS(codec, l, 16);
  902. m_file_src_file_adler32 = (m_file_src_file_adler32 << 16) | l;
  903. if (m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_COMPUTE_ADLER32)
  904. {
  905. if (unbuffered)
  906. {
  907. m_decomp_adler32 = adler32(pDst, dst_ofs, cInitAdler32);
  908. }
  909. if (m_file_src_file_adler32 != m_decomp_adler32)
  910. {
  911. m_status = LZHAM_DECOMP_STATUS_FAILED_ADLER32;
  912. }
  913. }
  914. else
  915. {
  916. m_decomp_adler32 = m_file_src_file_adler32;
  917. }
  918. }
  919. LZHAM_SYMBOL_CODEC_DECODE_END(codec);
  920. *m_pIn_buf_size = static_cast<size_t>(codec.stop_decoding());
  921. *m_pOut_buf_size = unbuffered ? (dst_ofs - m_dst_highwater_ofs) : 0;
  922. m_dst_highwater_ofs = dst_ofs;
  923. LZHAM_CR_RETURN(m_state, m_status);
  924. for ( ; ; )
  925. {
  926. *m_pIn_buf_size = 0;
  927. *m_pOut_buf_size = 0;
  928. LZHAM_CR_RETURN(m_state, m_status);
  929. }
  930. LZHAM_CR_FINISH
  931. return m_status;
  932. }
  933. static bool check_params(const lzham_decompress_params *pParams)
  934. {
  935. if ((!pParams) || (pParams->m_struct_size != sizeof(lzham_decompress_params)))
  936. return false;
  937. if ((pParams->m_dict_size_log2 < CLZDecompBase::cMinDictSizeLog2) || (pParams->m_dict_size_log2 > CLZDecompBase::cMaxDictSizeLog2))
  938. return false;
  939. if (pParams->m_num_seed_bytes)
  940. {
  941. if (((pParams->m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED) != 0) || (!pParams->m_pSeed_bytes))
  942. return false;
  943. if (pParams->m_num_seed_bytes > (1U << pParams->m_dict_size_log2))
  944. return false;
  945. }
  946. return true;
  947. }
  948. lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_init(const lzham_decompress_params *pParams)
  949. {
  950. LZHAM_ASSUME(CLZDecompBase::cMinDictSizeLog2 == LZHAM_MIN_DICT_SIZE_LOG2);
  951. LZHAM_ASSUME(CLZDecompBase::cMaxDictSizeLog2 == LZHAM_MAX_DICT_SIZE_LOG2_X64);
  952. if (!check_params(pParams))
  953. return NULL;
  954. lzham_decompressor *pState = lzham_new<lzham_decompressor>();
  955. if (!pState)
  956. return NULL;
  957. pState->m_params = *pParams;
  958. if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
  959. {
  960. pState->m_pRaw_decomp_buf = NULL;
  961. pState->m_raw_decomp_buf_size = 0;
  962. pState->m_pDecomp_buf = NULL;
  963. }
  964. else
  965. {
  966. uint32 decomp_buf_size = 1U << pState->m_params.m_dict_size_log2;
  967. pState->m_pRaw_decomp_buf = static_cast<uint8*>(lzham_malloc(decomp_buf_size + 15));
  968. if (!pState->m_pRaw_decomp_buf)
  969. {
  970. lzham_delete(pState);
  971. return NULL;
  972. }
  973. pState->m_raw_decomp_buf_size = decomp_buf_size;
  974. pState->m_pDecomp_buf = math::align_up_pointer(pState->m_pRaw_decomp_buf, 16);
  975. }
  976. pState->init();
  977. return pState;
  978. }
  979. lzham_decompress_state_ptr LZHAM_CDECL lzham_lib_decompress_reinit(lzham_decompress_state_ptr p, const lzham_decompress_params *pParams)
  980. {
  981. if (!p)
  982. return lzham_lib_decompress_init(pParams);
  983. lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
  984. if (!check_params(pParams))
  985. return NULL;
  986. if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
  987. {
  988. lzham_free(pState->m_pRaw_decomp_buf);
  989. pState->m_pRaw_decomp_buf = NULL;
  990. pState->m_raw_decomp_buf_size = 0;
  991. pState->m_pDecomp_buf = NULL;
  992. }
  993. else
  994. {
  995. uint32 new_dict_size = 1U << pState->m_params.m_dict_size_log2;
  996. if ((!pState->m_pRaw_decomp_buf) || (pState->m_raw_decomp_buf_size < new_dict_size))
  997. {
  998. uint8 *pNew_dict = static_cast<uint8*>(lzham_realloc(pState->m_pRaw_decomp_buf, new_dict_size + 15));
  999. if (!pNew_dict)
  1000. return NULL;
  1001. pState->m_pRaw_decomp_buf = pNew_dict;
  1002. pState->m_raw_decomp_buf_size = new_dict_size;
  1003. pState->m_pDecomp_buf = math::align_up_pointer(pState->m_pRaw_decomp_buf, 16);
  1004. }
  1005. }
  1006. pState->m_params = *pParams;
  1007. pState->init();
  1008. pState->reset_arith_tables();
  1009. return pState;
  1010. }
  1011. uint32 LZHAM_CDECL lzham_lib_decompress_deinit(lzham_decompress_state_ptr p)
  1012. {
  1013. lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
  1014. if (!pState)
  1015. return 0;
  1016. uint32 adler32 = pState->m_decomp_adler32;
  1017. lzham_free(pState->m_pRaw_decomp_buf);
  1018. lzham_delete(pState);
  1019. return adler32;
  1020. }
  1021. lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress(
  1022. lzham_decompress_state_ptr p,
  1023. const lzham_uint8 *pIn_buf, size_t *pIn_buf_size,
  1024. lzham_uint8 *pOut_buf, size_t *pOut_buf_size,
  1025. lzham_bool no_more_input_bytes_flag)
  1026. {
  1027. lzham_decompressor *pState = static_cast<lzham_decompressor *>(p);
  1028. if ((!pState) || (!pState->m_params.m_dict_size_log2) || (!pIn_buf_size) || (!pOut_buf_size))
  1029. {
  1030. return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
  1031. }
  1032. if ((*pIn_buf_size) && (!pIn_buf))
  1033. {
  1034. return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
  1035. }
  1036. if ((*pOut_buf_size) && (!pOut_buf))
  1037. {
  1038. return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
  1039. }
  1040. pState->m_pIn_buf = pIn_buf;
  1041. pState->m_pIn_buf_size = pIn_buf_size;
  1042. pState->m_pOut_buf = pOut_buf;
  1043. pState->m_pOut_buf_size = pOut_buf_size;
  1044. pState->m_no_more_input_bytes_flag = (no_more_input_bytes_flag != 0);
  1045. if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
  1046. {
  1047. if (!pState->m_pOrig_out_buf)
  1048. {
  1049. pState->m_pOrig_out_buf = pOut_buf;
  1050. pState->m_orig_out_buf_size = *pOut_buf_size;
  1051. }
  1052. else
  1053. {
  1054. // In unbuffered mode, the caller is not allowed to move the output buffer and the output pointer MUST always point to the beginning of the output buffer.
  1055. // Also, the output buffer size must indicate the full size of the output buffer. The decompressor will track the current output offset, and during partial/sync
  1056. // flushes it'll report how many bytes it has written since the call.
  1057. if ((pState->m_pOrig_out_buf != pOut_buf) || (pState->m_orig_out_buf_size != *pOut_buf_size))
  1058. {
  1059. return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
  1060. }
  1061. }
  1062. }
  1063. lzham_decompress_status_t status;
  1064. if (pState->m_params.m_decompress_flags & LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED)
  1065. status = pState->decompress<true>();
  1066. else
  1067. status = pState->decompress<false>();
  1068. return status;
  1069. }
  1070. lzham_decompress_status_t LZHAM_CDECL lzham_lib_decompress_memory(const lzham_decompress_params *pParams, lzham_uint8* pDst_buf, size_t *pDst_len, const lzham_uint8* pSrc_buf, size_t src_len, lzham_uint32 *pAdler32)
  1071. {
  1072. if (!pParams)
  1073. return LZHAM_DECOMP_STATUS_INVALID_PARAMETER;
  1074. lzham_decompress_params params(*pParams);
  1075. params.m_decompress_flags |= LZHAM_DECOMP_FLAG_OUTPUT_UNBUFFERED;
  1076. lzham_decompress_state_ptr pState = lzham_lib_decompress_init(&params);
  1077. if (!pState)
  1078. return LZHAM_DECOMP_STATUS_FAILED_INITIALIZING;
  1079. lzham_decompress_status_t status = lzham_lib_decompress(pState, pSrc_buf, &src_len, pDst_buf, pDst_len, true);
  1080. uint32 adler32 = lzham_lib_decompress_deinit(pState);
  1081. if (pAdler32)
  1082. *pAdler32 = adler32;
  1083. return status;
  1084. }
  1085. // ----------------- zlib-style API's
  1086. int LZHAM_CDECL lzham_lib_z_inflateInit(lzham_z_streamp pStream)
  1087. {
  1088. return lzham_lib_z_inflateInit2(pStream, LZHAM_Z_DEFAULT_WINDOW_BITS);
  1089. }
  1090. int LZHAM_CDECL lzham_lib_z_inflateInit2(lzham_z_streamp pStream, int window_bits)
  1091. {
  1092. if (!pStream)
  1093. return LZHAM_Z_STREAM_ERROR;
  1094. #ifdef LZHAM_Z_API_FORCE_WINDOW_BITS
  1095. window_bits = LZHAM_Z_API_FORCE_WINDOW_BITS;
  1096. #endif
  1097. int max_window_bits = LZHAM_64BIT_POINTERS ? LZHAM_MAX_DICT_SIZE_LOG2_X64 : LZHAM_MAX_DICT_SIZE_LOG2_X86;
  1098. if (labs(window_bits) > max_window_bits)
  1099. return LZHAM_Z_PARAM_ERROR;
  1100. if (labs(window_bits) < LZHAM_MIN_DICT_SIZE_LOG2)
  1101. window_bits = (window_bits < 0) ? -LZHAM_MIN_DICT_SIZE_LOG2 : LZHAM_MIN_DICT_SIZE_LOG2;
  1102. lzham_decompress_params params;
  1103. utils::zero_object(params);
  1104. params.m_struct_size = sizeof(lzham_decompress_params);
  1105. params.m_dict_size_log2 = static_cast<lzham_uint32>(labs(window_bits));
  1106. params.m_decompress_flags = LZHAM_DECOMP_FLAG_COMPUTE_ADLER32;
  1107. if (window_bits > 0)
  1108. params.m_decompress_flags |= LZHAM_DECOMP_FLAG_READ_ZLIB_STREAM;
  1109. lzham_decompress_state_ptr pState = lzham_lib_decompress_init(&params);
  1110. if (!pState)
  1111. return LZHAM_Z_MEM_ERROR;
  1112. pStream->state = static_cast<lzham_z_internal_state *>(pState);
  1113. pStream->data_type = 0;
  1114. pStream->adler = LZHAM_Z_ADLER32_INIT;
  1115. pStream->msg = NULL;
  1116. pStream->total_in = 0;
  1117. pStream->total_out = 0;
  1118. pStream->reserved = 0;
  1119. return LZHAM_Z_OK;
  1120. }
  1121. int LZHAM_CDECL lzham_lib_z_inflateReset(lzham_z_streamp pStream)
  1122. {
  1123. if ((!pStream) || (!pStream->state))
  1124. return LZHAM_Z_STREAM_ERROR;
  1125. lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
  1126. lzham_decompressor *pDecomp = static_cast<lzham_decompressor *>(pState);
  1127. lzham_decompress_params params(pDecomp->m_params);
  1128. if (!lzham_lib_decompress_reinit(pState, &params))
  1129. return LZHAM_Z_STREAM_ERROR;
  1130. return LZHAM_Z_OK;
  1131. }
  1132. int LZHAM_CDECL lzham_lib_z_inflate(lzham_z_streamp pStream, int flush)
  1133. {
  1134. if ((!pStream) || (!pStream->state))
  1135. return LZHAM_Z_STREAM_ERROR;
  1136. if ((flush == LZHAM_Z_PARTIAL_FLUSH) || (flush == LZHAM_Z_FULL_FLUSH))
  1137. flush = LZHAM_Z_SYNC_FLUSH;
  1138. if (flush)
  1139. {
  1140. if ((flush != LZHAM_Z_SYNC_FLUSH) && (flush != LZHAM_Z_FINISH))
  1141. return LZHAM_Z_STREAM_ERROR;
  1142. }
  1143. size_t orig_avail_in = pStream->avail_in;
  1144. lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
  1145. lzham_decompressor *pDecomp = static_cast<lzham_decompressor *>(pState);
  1146. if (pDecomp->m_z_last_status >= LZHAM_DECOMP_STATUS_FIRST_SUCCESS_OR_FAILURE_CODE)
  1147. return LZHAM_Z_DATA_ERROR;
  1148. if (pDecomp->m_z_has_flushed && (flush != LZHAM_Z_FINISH))
  1149. return LZHAM_Z_STREAM_ERROR;
  1150. pDecomp->m_z_has_flushed |= (flush == LZHAM_Z_FINISH);
  1151. lzham_decompress_status_t status;
  1152. for ( ; ; )
  1153. {
  1154. size_t in_bytes = pStream->avail_in;
  1155. size_t out_bytes = pStream->avail_out;
  1156. lzham_bool no_more_input_bytes_flag = (flush == LZHAM_Z_FINISH);
  1157. status = lzham_lib_decompress(pState, pStream->next_in, &in_bytes, pStream->next_out, &out_bytes, no_more_input_bytes_flag);
  1158. pDecomp->m_z_last_status = status;
  1159. pStream->next_in += (uint)in_bytes;
  1160. pStream->avail_in -= (uint)in_bytes;
  1161. pStream->total_in += (uint)in_bytes;
  1162. pStream->adler = pDecomp->m_decomp_adler32;
  1163. pStream->next_out += (uint)out_bytes;
  1164. pStream->avail_out -= (uint)out_bytes;
  1165. pStream->total_out += (uint)out_bytes;
  1166. if (status >= LZHAM_DECOMP_STATUS_FIRST_FAILURE_CODE)
  1167. {
  1168. if (status == LZHAM_DECOMP_STATUS_FAILED_NEED_SEED_BYTES)
  1169. return LZHAM_Z_NEED_DICT;
  1170. else
  1171. return LZHAM_Z_DATA_ERROR; // Stream is corrupted (there could be some uncompressed data left in the output dictionary - oh well).
  1172. }
  1173. if ((status == LZHAM_DECOMP_STATUS_NEEDS_MORE_INPUT) && (!orig_avail_in))
  1174. return LZHAM_Z_BUF_ERROR; // Signal caller that we can't make forward progress without supplying more input, or by setting flush to LZHAM_Z_FINISH.
  1175. else if (flush == LZHAM_Z_FINISH)
  1176. {
  1177. // Caller has indicated that all remaining input was at next_in, and all remaining output will fit entirely in next_out.
  1178. // (The output buffer at next_out MUST be large to hold the remaining uncompressed data when flush==LZHAM_Z_FINISH).
  1179. if (status == LZHAM_DECOMP_STATUS_SUCCESS)
  1180. return LZHAM_Z_STREAM_END;
  1181. // If status is LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT, there must be at least 1 more byte on the way but the caller to lzham_decompress() supplied an empty output buffer.
  1182. // Something is wrong because the caller's output buffer should be large enough to hold the entire decompressed stream when flush==LZHAM_Z_FINISH.
  1183. else if (status == LZHAM_DECOMP_STATUS_HAS_MORE_OUTPUT)
  1184. return LZHAM_Z_BUF_ERROR;
  1185. }
  1186. else if ((status == LZHAM_DECOMP_STATUS_SUCCESS) || (!pStream->avail_in) || (!pStream->avail_out))
  1187. break;
  1188. }
  1189. return (status == LZHAM_DECOMP_STATUS_SUCCESS) ? LZHAM_Z_STREAM_END : LZHAM_Z_OK;
  1190. }
  1191. int LZHAM_CDECL lzham_lib_z_inflateEnd(lzham_z_streamp pStream)
  1192. {
  1193. if (!pStream)
  1194. return LZHAM_Z_STREAM_ERROR;
  1195. lzham_decompress_state_ptr pState = static_cast<lzham_decompress_state_ptr>(pStream->state);
  1196. if (pState)
  1197. {
  1198. pStream->adler = lzham_lib_decompress_deinit(pState);
  1199. pStream->state = NULL;
  1200. }
  1201. return LZHAM_Z_OK;
  1202. }
  1203. int LZHAM_CDECL lzham_lib_z_uncompress(unsigned char *pDest, lzham_z_ulong *pDest_len, const unsigned char *pSource, lzham_z_ulong source_len)
  1204. {
  1205. lzham_z_stream stream;
  1206. int status;
  1207. memset(&stream, 0, sizeof(stream));
  1208. // In case lzham_z_ulong is 64-bits (argh I hate longs).
  1209. if ((source_len | *pDest_len) > 0xFFFFFFFFU)
  1210. return LZHAM_Z_PARAM_ERROR;
  1211. stream.next_in = pSource;
  1212. stream.avail_in = (uint)source_len;
  1213. stream.next_out = pDest;
  1214. stream.avail_out = (uint)*pDest_len;
  1215. status = lzham_lib_z_inflateInit(&stream);
  1216. if (status != LZHAM_Z_OK)
  1217. return status;
  1218. status = lzham_lib_z_inflate(&stream, LZHAM_Z_FINISH);
  1219. if (status != LZHAM_Z_STREAM_END)
  1220. {
  1221. lzham_lib_z_inflateEnd(&stream);
  1222. return ((status == LZHAM_Z_BUF_ERROR) && (!stream.avail_in)) ? LZHAM_Z_DATA_ERROR : status;
  1223. }
  1224. *pDest_len = stream.total_out;
  1225. return lzham_lib_z_inflateEnd(&stream);
  1226. }
  1227. const char * LZHAM_CDECL lzham_lib_z_error(int err)
  1228. {
  1229. static struct
  1230. {
  1231. int m_err;
  1232. const char *m_pDesc;
  1233. }
  1234. s_error_descs[] =
  1235. {
  1236. { LZHAM_Z_OK, "" },
  1237. { LZHAM_Z_STREAM_END, "stream end" },
  1238. { LZHAM_Z_NEED_DICT, "need dictionary" },
  1239. { LZHAM_Z_ERRNO, "file error" },
  1240. { LZHAM_Z_STREAM_ERROR, "stream error" },
  1241. { LZHAM_Z_DATA_ERROR, "data error" },
  1242. { LZHAM_Z_MEM_ERROR, "out of memory" },
  1243. { LZHAM_Z_BUF_ERROR, "buf error" },
  1244. { LZHAM_Z_VERSION_ERROR, "version error" },
  1245. { LZHAM_Z_PARAM_ERROR, "parameter error" }
  1246. };
  1247. for (uint i = 0; i < sizeof(s_error_descs) / sizeof(s_error_descs[0]); ++i)
  1248. if (s_error_descs[i].m_err == err)
  1249. return s_error_descs[i].m_pDesc;
  1250. return NULL;
  1251. }
  1252. lzham_z_ulong lzham_lib_z_adler32(lzham_z_ulong adler, const unsigned char *ptr, size_t buf_len)
  1253. {
  1254. return adler32(ptr, buf_len, static_cast<uint>(adler));
  1255. }
  1256. lzham_z_ulong LZHAM_CDECL lzham_lib_z_crc32(lzham_z_ulong crc, const lzham_uint8 *ptr, size_t buf_len)
  1257. {
  1258. return crc32(static_cast<uint>(crc), ptr, buf_len);
  1259. }
  1260. } // namespace lzham