bzlib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428
  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. //indexes into s->zbits[], initialzation moved to init of s->zbits
  49. //s->posZ = s->zbits; // was: s->numZ = 0;
  50. //s->state_out_pos = s->zbits;
  51. BZ_INITIALISE_CRC(s->blockCRC);
  52. /* inlined memset would be nice to have here */
  53. for (i = 0; i < 256; i++)
  54. s->inUse[i] = 0;
  55. s->blockNo++;
  56. }
  57. /*---------------------------------------------------*/
  58. static
  59. ALWAYS_INLINE
  60. void init_RL(EState* s)
  61. {
  62. s->state_in_ch = 256;
  63. s->state_in_len = 0;
  64. }
  65. static
  66. int isempty_RL(EState* s)
  67. {
  68. return (s->state_in_ch >= 256 || s->state_in_len <= 0);
  69. }
  70. /*---------------------------------------------------*/
  71. static
  72. void BZ2_bzCompressInit(bz_stream *strm, int blockSize100k)
  73. {
  74. unsigned n;
  75. EState* s;
  76. s = xzalloc(sizeof(EState));
  77. s->strm = strm;
  78. n = 100000 * blockSize100k;
  79. s->arr1 = xmalloc(n * sizeof(uint32_t));
  80. s->mtfv = (uint16_t*)s->arr1;
  81. s->ptr = (uint32_t*)s->arr1;
  82. s->arr2 = xmalloc((n + BZ_N_OVERSHOOT) * sizeof(uint32_t));
  83. s->block = (uint8_t*)s->arr2;
  84. crc32_filltable(s->crc32table, 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->posZ) break;
  207. /*progress_out = True;*/
  208. *(s->strm->next_out) = *s->state_out_pos++;
  209. s->strm->avail_out--;
  210. s->strm->next_out++;
  211. s->strm->total_out++;
  212. }
  213. /*return progress_out;*/
  214. }
  215. /*---------------------------------------------------*/
  216. static
  217. void /*Bool*/ handle_compress(bz_stream *strm)
  218. {
  219. /*Bool progress_in = False;*/
  220. /*Bool progress_out = False;*/
  221. EState* s = strm->state;
  222. while (1) {
  223. if (s->state == BZ_S_OUTPUT) {
  224. /*progress_out |=*/ copy_output_until_stop(s);
  225. if (s->state_out_pos < s->posZ) break;
  226. if (s->mode == BZ_M_FINISHING
  227. //# && s->avail_in_expect == 0
  228. && s->strm->avail_in == 0
  229. && isempty_RL(s))
  230. break;
  231. prepare_new_block(s);
  232. s->state = BZ_S_INPUT;
  233. #ifdef FLUSH_IS_UNUSED
  234. if (s->mode == BZ_M_FLUSHING
  235. && s->avail_in_expect == 0
  236. && isempty_RL(s))
  237. break;
  238. #endif
  239. }
  240. if (s->state == BZ_S_INPUT) {
  241. /*progress_in |=*/ copy_input_until_stop(s);
  242. //#if (s->mode != BZ_M_RUNNING && s->avail_in_expect == 0) {
  243. if (s->mode != BZ_M_RUNNING && s->strm->avail_in == 0) {
  244. flush_RL(s);
  245. BZ2_compressBlock(s, (s->mode == BZ_M_FINISHING));
  246. s->state = BZ_S_OUTPUT;
  247. } else
  248. if (s->nblock >= s->nblockMAX) {
  249. BZ2_compressBlock(s, 0);
  250. s->state = BZ_S_OUTPUT;
  251. } else
  252. if (s->strm->avail_in == 0) {
  253. break;
  254. }
  255. }
  256. }
  257. /*return progress_in || progress_out;*/
  258. }
  259. /*---------------------------------------------------*/
  260. static
  261. int BZ2_bzCompress(bz_stream *strm, int action)
  262. {
  263. /*Bool progress;*/
  264. EState* s;
  265. s = strm->state;
  266. switch (s->mode) {
  267. case BZ_M_RUNNING:
  268. if (action == BZ_RUN) {
  269. /*progress =*/ handle_compress(strm);
  270. /*return progress ? BZ_RUN_OK : BZ_PARAM_ERROR;*/
  271. return BZ_RUN_OK;
  272. }
  273. #ifdef FLUSH_IS_UNUSED
  274. else
  275. if (action == BZ_FLUSH) {
  276. //#s->avail_in_expect = strm->avail_in;
  277. s->mode = BZ_M_FLUSHING;
  278. goto case_BZ_M_FLUSHING;
  279. }
  280. #endif
  281. else
  282. /*if (action == BZ_FINISH)*/ {
  283. //#s->avail_in_expect = strm->avail_in;
  284. s->mode = BZ_M_FINISHING;
  285. goto case_BZ_M_FINISHING;
  286. }
  287. #ifdef FLUSH_IS_UNUSED
  288. case_BZ_M_FLUSHING:
  289. case BZ_M_FLUSHING:
  290. /*if (s->avail_in_expect != s->strm->avail_in)
  291. return BZ_SEQUENCE_ERROR;*/
  292. /*progress =*/ handle_compress(strm);
  293. if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ)
  294. return BZ_FLUSH_OK;
  295. s->mode = BZ_M_RUNNING;
  296. return BZ_RUN_OK;
  297. #endif
  298. case_BZ_M_FINISHING:
  299. /*case BZ_M_FINISHING:*/
  300. default:
  301. /*if (s->avail_in_expect != s->strm->avail_in)
  302. return BZ_SEQUENCE_ERROR;*/
  303. /*progress =*/ handle_compress(strm);
  304. /*if (!progress) return BZ_SEQUENCE_ERROR;*/
  305. //#if (s->avail_in_expect > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ)
  306. //# return BZ_FINISH_OK;
  307. if (s->strm->avail_in > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ)
  308. return BZ_FINISH_OK;
  309. /*s->mode = BZ_M_IDLE;*/
  310. return BZ_STREAM_END;
  311. }
  312. /* return BZ_OK; --not reached--*/
  313. }
  314. /*---------------------------------------------------*/
  315. static
  316. void BZ2_bzCompressEnd(bz_stream *strm)
  317. {
  318. EState* s;
  319. s = strm->state;
  320. free(s->arr1);
  321. free(s->arr2);
  322. //free(s->ftab); // made it array member of s
  323. //free(s->crc32table); // ditto
  324. free(s);
  325. }
  326. /*---------------------------------------------------*/
  327. /*--- Misc convenience stuff ---*/
  328. /*---------------------------------------------------*/
  329. /*---------------------------------------------------*/
  330. #ifdef EXAMPLE_CODE_FOR_MEM_TO_MEM_COMPRESSION
  331. static
  332. int BZ2_bzBuffToBuffCompress(char* dest,
  333. unsigned int* destLen,
  334. char* source,
  335. unsigned int sourceLen,
  336. int blockSize100k)
  337. {
  338. bz_stream strm;
  339. int ret;
  340. if (dest == NULL || destLen == NULL
  341. || source == NULL
  342. || blockSize100k < 1 || blockSize100k > 9
  343. ) {
  344. return BZ_PARAM_ERROR;
  345. }
  346. BZ2_bzCompressInit(&strm, blockSize100k);
  347. strm.next_in = source;
  348. strm.next_out = dest;
  349. strm.avail_in = sourceLen;
  350. strm.avail_out = *destLen;
  351. ret = BZ2_bzCompress(&strm, BZ_FINISH);
  352. if (ret == BZ_FINISH_OK) goto output_overflow;
  353. if (ret != BZ_STREAM_END) goto errhandler;
  354. /* normal termination */
  355. *destLen -= strm.avail_out;
  356. BZ2_bzCompressEnd(&strm);
  357. return BZ_OK;
  358. output_overflow:
  359. BZ2_bzCompressEnd(&strm);
  360. return BZ_OUTBUFF_FULL;
  361. errhandler:
  362. BZ2_bzCompressEnd(&strm);
  363. return ret;
  364. }
  365. #endif
  366. /*-------------------------------------------------------------*/
  367. /*--- end bzlib.c ---*/
  368. /*-------------------------------------------------------------*/