bzlib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*
  2. * bzip2 is written by Julian Seward <jseward@bzip.org>.
  3. * Adapted for busybox by Denys Vlasenko <vda.linux@googlemail.com>.
  4. * See README and LICENSE files in this directory for more information.
  5. */
  6. /*-------------------------------------------------------------*/
  7. /*--- Library top-level functions. ---*/
  8. /*--- bzlib.c ---*/
  9. /*-------------------------------------------------------------*/
  10. /* ------------------------------------------------------------------
  11. This file is part of bzip2/libbzip2, a program and library for
  12. lossless, block-sorting data compression.
  13. bzip2/libbzip2 version 1.0.4 of 20 December 2006
  14. Copyright (C) 1996-2006 Julian Seward <jseward@bzip.org>
  15. Please read the WARNING, DISCLAIMER and PATENTS sections in the
  16. README file.
  17. This program is released under the terms of the license contained
  18. in the file LICENSE.
  19. ------------------------------------------------------------------ */
  20. /* CHANGES
  21. * 0.9.0 -- original version.
  22. * 0.9.0a/b -- no changes in this file.
  23. * 0.9.0c -- made zero-length BZ_FLUSH work correctly in bzCompress().
  24. * fixed bzWrite/bzRead to ignore zero-length requests.
  25. * fixed bzread to correctly handle read requests after EOF.
  26. * wrong parameter order in call to bzDecompressInit in
  27. * bzBuffToBuffDecompress. Fixed.
  28. */
  29. /* #include "bzlib_private.h" */
  30. /*---------------------------------------------------*/
  31. /*--- Compression stuff ---*/
  32. /*---------------------------------------------------*/
  33. /*---------------------------------------------------*/
  34. #if BZ_LIGHT_DEBUG
  35. static
  36. void bz_assert_fail(int errcode)
  37. {
  38. /* if (errcode == 1007) bb_error_msg_and_die("probably bad RAM"); */
  39. bb_error_msg_and_die("internal error %d", errcode);
  40. }
  41. #endif
  42. /*---------------------------------------------------*/
  43. static
  44. void prepare_new_block(EState* s)
  45. {
  46. int i;
  47. s->nblock = 0;
  48. s->numZ = 0;
  49. s->state_out_pos = 0;
  50. BZ_INITIALISE_CRC(s->blockCRC);
  51. /* inlined memset would be nice to have here */
  52. for (i = 0; i < 256; i++)
  53. s->inUse[i] = 0;
  54. s->blockNo++;
  55. }
  56. /*---------------------------------------------------*/
  57. static
  58. ALWAYS_INLINE
  59. void init_RL(EState* s)
  60. {
  61. s->state_in_ch = 256;
  62. s->state_in_len = 0;
  63. }
  64. static
  65. int isempty_RL(EState* s)
  66. {
  67. return (s->state_in_ch >= 256 || s->state_in_len <= 0);
  68. }
  69. /*---------------------------------------------------*/
  70. static
  71. void BZ2_bzCompressInit(bz_stream *strm, int blockSize100k)
  72. {
  73. int32_t n;
  74. EState* s;
  75. s = xzalloc(sizeof(EState));
  76. s->strm = strm;
  77. n = 100000 * blockSize100k;
  78. s->arr1 = xmalloc(n * sizeof(uint32_t));
  79. s->mtfv = (uint16_t*)s->arr1;
  80. s->ptr = (uint32_t*)s->arr1;
  81. s->arr2 = xmalloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t));
  82. s->block = (uint8_t*)s->arr2;
  83. s->ftab = xmalloc(65537 * sizeof(uint32_t));
  84. s->crc32table = crc32_filltable(NULL, 1);
  85. s->state = BZ_S_INPUT;
  86. s->mode = BZ_M_RUNNING;
  87. s->blockSize100k = blockSize100k;
  88. s->nblockMAX = n - 19;
  89. strm->state = s;
  90. /*strm->total_in = 0;*/
  91. strm->total_out = 0;
  92. init_RL(s);
  93. prepare_new_block(s);
  94. }
  95. /*---------------------------------------------------*/
  96. static
  97. void add_pair_to_block(EState* s)
  98. {
  99. int32_t i;
  100. uint8_t ch = (uint8_t)(s->state_in_ch);
  101. for (i = 0; i < s->state_in_len; i++) {
  102. BZ_UPDATE_CRC(s, s->blockCRC, ch);
  103. }
  104. s->inUse[s->state_in_ch] = 1;
  105. switch (s->state_in_len) {
  106. case 3:
  107. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  108. /* fall through */
  109. case 2:
  110. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  111. /* fall through */
  112. case 1:
  113. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  114. break;
  115. default:
  116. s->inUse[s->state_in_len - 4] = 1;
  117. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  118. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  119. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  120. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  121. s->block[s->nblock] = (uint8_t)(s->state_in_len - 4);
  122. s->nblock++;
  123. break;
  124. }
  125. }
  126. /*---------------------------------------------------*/
  127. static
  128. void flush_RL(EState* s)
  129. {
  130. if (s->state_in_ch < 256) add_pair_to_block(s);
  131. init_RL(s);
  132. }
  133. /*---------------------------------------------------*/
  134. #define ADD_CHAR_TO_BLOCK(zs, zchh0) \
  135. { \
  136. uint32_t zchh = (uint32_t)(zchh0); \
  137. /*-- fast track the common case --*/ \
  138. if (zchh != zs->state_in_ch && zs->state_in_len == 1) { \
  139. uint8_t ch = (uint8_t)(zs->state_in_ch); \
  140. BZ_UPDATE_CRC(zs, zs->blockCRC, ch); \
  141. zs->inUse[zs->state_in_ch] = 1; \
  142. zs->block[zs->nblock] = (uint8_t)ch; \
  143. zs->nblock++; \
  144. zs->state_in_ch = zchh; \
  145. } \
  146. else \
  147. /*-- general, uncommon cases --*/ \
  148. if (zchh != zs->state_in_ch || zs->state_in_len == 255) { \
  149. if (zs->state_in_ch < 256) \
  150. add_pair_to_block(zs); \
  151. zs->state_in_ch = zchh; \
  152. zs->state_in_len = 1; \
  153. } else { \
  154. zs->state_in_len++; \
  155. } \
  156. }
  157. /*---------------------------------------------------*/
  158. static
  159. void /*Bool*/ copy_input_until_stop(EState* s)
  160. {
  161. /*Bool progress_in = False;*/
  162. #ifdef SAME_CODE_AS_BELOW
  163. if (s->mode == BZ_M_RUNNING) {
  164. /*-- fast track the common case --*/
  165. while (1) {
  166. /*-- no input? --*/
  167. if (s->strm->avail_in == 0) break;
  168. /*-- block full? --*/
  169. if (s->nblock >= s->nblockMAX) break;
  170. /*progress_in = True;*/
  171. ADD_CHAR_TO_BLOCK(s, (uint32_t)(*(uint8_t*)(s->strm->next_in)));
  172. s->strm->next_in++;
  173. s->strm->avail_in--;
  174. /*s->strm->total_in++;*/
  175. }
  176. } else
  177. #endif
  178. {
  179. /*-- general, uncommon case --*/
  180. while (1) {
  181. /*-- no input? --*/
  182. if (s->strm->avail_in == 0) break;
  183. /*-- block full? --*/
  184. if (s->nblock >= s->nblockMAX) break;
  185. //# /*-- flush/finish end? --*/
  186. //# if (s->avail_in_expect == 0) break;
  187. /*progress_in = True;*/
  188. ADD_CHAR_TO_BLOCK(s, *(uint8_t*)(s->strm->next_in));
  189. s->strm->next_in++;
  190. s->strm->avail_in--;
  191. /*s->strm->total_in++;*/
  192. //# s->avail_in_expect--;
  193. }
  194. }
  195. /*return progress_in;*/
  196. }
  197. /*---------------------------------------------------*/
  198. static
  199. void /*Bool*/ copy_output_until_stop(EState* s)
  200. {
  201. /*Bool progress_out = False;*/
  202. while (1) {
  203. /*-- no output space? --*/
  204. if (s->strm->avail_out == 0) break;
  205. /*-- block done? --*/
  206. if (s->state_out_pos >= s->numZ) break;
  207. /*progress_out = True;*/
  208. *(s->strm->next_out) = s->zbits[s->state_out_pos];
  209. s->state_out_pos++;
  210. s->strm->avail_out--;
  211. s->strm->next_out++;
  212. s->strm->total_out++;
  213. }
  214. /*return progress_out;*/
  215. }
  216. /*---------------------------------------------------*/
  217. static
  218. void /*Bool*/ handle_compress(bz_stream *strm)
  219. {
  220. /*Bool progress_in = False;*/
  221. /*Bool progress_out = False;*/
  222. EState* s = strm->state;
  223. while (1) {
  224. if (s->state == BZ_S_OUTPUT) {
  225. /*progress_out |=*/ copy_output_until_stop(s);
  226. if (s->state_out_pos < s->numZ) break;
  227. if (s->mode == BZ_M_FINISHING
  228. //# && s->avail_in_expect == 0
  229. && s->strm->avail_in == 0
  230. && isempty_RL(s))
  231. break;
  232. prepare_new_block(s);
  233. s->state = BZ_S_INPUT;
  234. #ifdef FLUSH_IS_UNUSED
  235. if (s->mode == BZ_M_FLUSHING
  236. && s->avail_in_expect == 0
  237. && isempty_RL(s))
  238. break;
  239. #endif
  240. }
  241. if (s->state == BZ_S_INPUT) {
  242. /*progress_in |=*/ copy_input_until_stop(s);
  243. //#if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
  244. if (s->mode != BZ_M_RUNNING && s->strm->avail_in == 0) {
  245. flush_RL(s);
  246. BZ2_compressBlock(s, (s->mode == BZ_M_FINISHING));
  247. s->state = BZ_S_OUTPUT;
  248. } else
  249. if (s->nblock >= s->nblockMAX) {
  250. BZ2_compressBlock(s, 0);
  251. s->state = BZ_S_OUTPUT;
  252. } else
  253. if (s->strm->avail_in == 0) {
  254. break;
  255. }
  256. }
  257. }
  258. /*return progress_in || progress_out;*/
  259. }
  260. /*---------------------------------------------------*/
  261. static
  262. int BZ2_bzCompress(bz_stream *strm, int action)
  263. {
  264. /*Bool progress;*/
  265. EState* s;
  266. s = strm->state;
  267. switch (s->mode) {
  268. case BZ_M_RUNNING:
  269. if (action == BZ_RUN) {
  270. /*progress =*/ handle_compress(strm);
  271. /*return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;*/
  272. return BZ_RUN_OK;
  273. }
  274. #ifdef FLUSH_IS_UNUSED
  275. else
  276. if (action == BZ_FLUSH) {
  277. //#s->avail_in_expect = strm->avail_in;
  278. s->mode = BZ_M_FLUSHING;
  279. goto case_BZ_M_FLUSHING;
  280. }
  281. #endif
  282. else
  283. /*if (action == BZ_FINISH)*/ {
  284. //#s->avail_in_expect = strm->avail_in;
  285. s->mode = BZ_M_FINISHING;
  286. goto case_BZ_M_FINISHING;
  287. }
  288. #ifdef FLUSH_IS_UNUSED
  289. case_BZ_M_FLUSHING:
  290. case BZ_M_FLUSHING:
  291. /*if (s->avail_in_expect != s->strm->avail_in)
  292. return BZ_SEQUENCE_ERROR;*/
  293. /*progress =*/ handle_compress(strm);
  294. if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ)
  295. return BZ_FLUSH_OK;
  296. s->mode = BZ_M_RUNNING;
  297. return BZ_RUN_OK;
  298. #endif
  299. case_BZ_M_FINISHING:
  300. /*case BZ_M_FINISHING:*/
  301. default:
  302. /*if (s->avail_in_expect != s->strm->avail_in)
  303. return BZ_SEQUENCE_ERROR;*/
  304. /*progress =*/ handle_compress(strm);
  305. /*if (!progress) return BZ_SEQUENCE_ERROR;*/
  306. //#if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ)
  307. //# return BZ_FINISH_OK;
  308. if (s->strm->avail_in > 0 || !isempty_RL(s) || s->state_out_pos < s->numZ)
  309. return BZ_FINISH_OK;
  310. /*s->mode = BZ_M_IDLE;*/
  311. return BZ_STREAM_END;
  312. }
  313. /* return BZ_OK; --not reached--*/
  314. }
  315. /*---------------------------------------------------*/
  316. #if ENABLE_FEATURE_CLEAN_UP
  317. static
  318. void BZ2_bzCompressEnd(bz_stream *strm)
  319. {
  320. EState* s;
  321. s = strm->state;
  322. free(s->arr1);
  323. free(s->arr2);
  324. free(s->ftab);
  325. free(s->crc32table);
  326. free(strm->state);
  327. }
  328. #endif
  329. /*---------------------------------------------------*/
  330. /*--- Misc convenience stuff ---*/
  331. /*---------------------------------------------------*/
  332. /*---------------------------------------------------*/
  333. #ifdef EXAMPLE_CODE_FOR_MEM_TO_MEM_COMPRESSION
  334. static
  335. int BZ2_bzBuffToBuffCompress(char* dest,
  336. unsigned int* destLen,
  337. char* source,
  338. unsigned int sourceLen,
  339. int blockSize100k)
  340. {
  341. bz_stream strm;
  342. int ret;
  343. if (dest == NULL || destLen == NULL ||
  344. source == NULL ||
  345. blockSize100k < 1 || blockSize100k > 9)
  346. return BZ_PARAM_ERROR;
  347. BZ2_bzCompressInit(&strm, blockSize100k);
  348. strm.next_in = source;
  349. strm.next_out = dest;
  350. strm.avail_in = sourceLen;
  351. strm.avail_out = *destLen;
  352. ret = BZ2_bzCompress(&strm, BZ_FINISH);
  353. if (ret == BZ_FINISH_OK) goto output_overflow;
  354. if (ret != BZ_STREAM_END) goto errhandler;
  355. /* normal termination */
  356. *destLen -= strm.avail_out;
  357. BZ2_bzCompressEnd(&strm);
  358. return BZ_OK;
  359. output_overflow:
  360. BZ2_bzCompressEnd(&strm);
  361. return BZ_OUTBUFF_FULL;
  362. errhandler:
  363. BZ2_bzCompressEnd(&strm);
  364. return ret;
  365. }
  366. #endif
  367. /*-------------------------------------------------------------*/
  368. /*--- end bzlib.c ---*/
  369. /*-------------------------------------------------------------*/