3
0

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. //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. s->ftab = xmalloc(65537 * sizeof(uint32_t));
  85. s->crc32table = crc32_filltable(NULL, 1);
  86. s->state = BZ_S_INPUT;
  87. s->mode = BZ_M_RUNNING;
  88. s->blockSize100k = blockSize100k;
  89. s->nblockMAX = n - 19;
  90. strm->state = s;
  91. /*strm->total_in = 0;*/
  92. strm->total_out = 0;
  93. init_RL(s);
  94. prepare_new_block(s);
  95. }
  96. /*---------------------------------------------------*/
  97. static
  98. void add_pair_to_block(EState* s)
  99. {
  100. int32_t i;
  101. uint8_t ch = (uint8_t)(s->state_in_ch);
  102. for (i = 0; i < s->state_in_len; i++) {
  103. BZ_UPDATE_CRC(s, s->blockCRC, ch);
  104. }
  105. s->inUse[s->state_in_ch] = 1;
  106. switch (s->state_in_len) {
  107. case 3:
  108. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  109. /* fall through */
  110. case 2:
  111. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  112. /* fall through */
  113. case 1:
  114. s->block[s->nblock] = (uint8_t)ch; s->nblock++;
  115. break;
  116. default:
  117. s->inUse[s->state_in_len - 4] = 1;
  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)ch; s->nblock++;
  122. s->block[s->nblock] = (uint8_t)(s->state_in_len - 4);
  123. s->nblock++;
  124. break;
  125. }
  126. }
  127. /*---------------------------------------------------*/
  128. static
  129. void flush_RL(EState* s)
  130. {
  131. if (s->state_in_ch < 256) add_pair_to_block(s);
  132. init_RL(s);
  133. }
  134. /*---------------------------------------------------*/
  135. #define ADD_CHAR_TO_BLOCK(zs, zchh0) \
  136. { \
  137. uint32_t zchh = (uint32_t)(zchh0); \
  138. /*-- fast track the common case --*/ \
  139. if (zchh != zs->state_in_ch && zs->state_in_len == 1) { \
  140. uint8_t ch = (uint8_t)(zs->state_in_ch); \
  141. BZ_UPDATE_CRC(zs, zs->blockCRC, ch); \
  142. zs->inUse[zs->state_in_ch] = 1; \
  143. zs->block[zs->nblock] = (uint8_t)ch; \
  144. zs->nblock++; \
  145. zs->state_in_ch = zchh; \
  146. } \
  147. else \
  148. /*-- general, uncommon cases --*/ \
  149. if (zchh != zs->state_in_ch || zs->state_in_len == 255) { \
  150. if (zs->state_in_ch < 256) \
  151. add_pair_to_block(zs); \
  152. zs->state_in_ch = zchh; \
  153. zs->state_in_len = 1; \
  154. } else { \
  155. zs->state_in_len++; \
  156. } \
  157. }
  158. /*---------------------------------------------------*/
  159. static
  160. void /*Bool*/ copy_input_until_stop(EState* s)
  161. {
  162. /*Bool progress_in = False;*/
  163. #ifdef SAME_CODE_AS_BELOW
  164. if (s->mode == BZ_M_RUNNING) {
  165. /*-- fast track the common case --*/
  166. while (1) {
  167. /*-- no input? --*/
  168. if (s->strm->avail_in == 0) break;
  169. /*-- block full? --*/
  170. if (s->nblock >= s->nblockMAX) break;
  171. /*progress_in = True;*/
  172. ADD_CHAR_TO_BLOCK(s, (uint32_t)(*(uint8_t*)(s->strm->next_in)));
  173. s->strm->next_in++;
  174. s->strm->avail_in--;
  175. /*s->strm->total_in++;*/
  176. }
  177. } else
  178. #endif
  179. {
  180. /*-- general, uncommon case --*/
  181. while (1) {
  182. /*-- no input? --*/
  183. if (s->strm->avail_in == 0) break;
  184. /*-- block full? --*/
  185. if (s->nblock >= s->nblockMAX) break;
  186. //# /*-- flush/finish end? --*/
  187. //# if (s->avail_in_expect == 0) break;
  188. /*progress_in = True;*/
  189. ADD_CHAR_TO_BLOCK(s, *(uint8_t*)(s->strm->next_in));
  190. s->strm->next_in++;
  191. s->strm->avail_in--;
  192. /*s->strm->total_in++;*/
  193. //# s->avail_in_expect--;
  194. }
  195. }
  196. /*return progress_in;*/
  197. }
  198. /*---------------------------------------------------*/
  199. static
  200. void /*Bool*/ copy_output_until_stop(EState* s)
  201. {
  202. /*Bool progress_out = False;*/
  203. while (1) {
  204. /*-- no output space? --*/
  205. if (s->strm->avail_out == 0) break;
  206. /*-- block done? --*/
  207. if (s->state_out_pos >= s->posZ) break;
  208. /*progress_out = True;*/
  209. *(s->strm->next_out) = *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->posZ) 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->posZ)
  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->posZ)
  307. //# return BZ_FINISH_OK;
  308. if (s->strm->avail_in > 0 || !isempty_RL(s) || s->state_out_pos < s->posZ)
  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. static
  317. void BZ2_bzCompressEnd(bz_stream *strm)
  318. {
  319. EState* s;
  320. s = strm->state;
  321. free(s->arr1);
  322. free(s->arr2);
  323. free(s->ftab);
  324. free(s->crc32table);
  325. free(s);
  326. }
  327. /*---------------------------------------------------*/
  328. /*--- Misc convenience stuff ---*/
  329. /*---------------------------------------------------*/
  330. /*---------------------------------------------------*/
  331. #ifdef EXAMPLE_CODE_FOR_MEM_TO_MEM_COMPRESSION
  332. static
  333. int BZ2_bzBuffToBuffCompress(char* dest,
  334. unsigned int* destLen,
  335. char* source,
  336. unsigned int sourceLen,
  337. int blockSize100k)
  338. {
  339. bz_stream strm;
  340. int ret;
  341. if (dest == NULL || destLen == NULL
  342. || source == NULL
  343. || blockSize100k < 1 || blockSize100k > 9
  344. ) {
  345. return BZ_PARAM_ERROR;
  346. }
  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. /*-------------------------------------------------------------*/