1 /* $NetBSD: compress.c,v 1.1.1.3 2019/07/21 11:35:30 maya Exp $ */
2
3
4 /*-------------------------------------------------------------*/
5 /*--- Compression machinery (not incl block sorting) ---*/
6 /*--- compress.c ---*/
7 /*-------------------------------------------------------------*/
8
9 /* ------------------------------------------------------------------
10 This file is part of bzip2/libbzip2, a program and library for
11 lossless, block-sorting data compression.
12
13 bzip2/libbzip2 version 1.0.8 of 13 July 2019
14 Copyright (C) 1996-2019 Julian Seward <jseward@acm.org>
15
16 Please read the WARNING, DISCLAIMER and PATENTS sections in the
17 README file.
18
19 This program is released under the terms of the license contained
20 in the file LICENSE.
21 ------------------------------------------------------------------ */
22
23
24 /* CHANGES
25 0.9.0 -- original version.
26 0.9.0a/b -- no changes in this file.
27 0.9.0c -- changed setting of nGroups in sendMTFValues()
28 so as to do a bit better on small files
29 */
30
31 #include "bzlib_private.h"
32
33
34 /*---------------------------------------------------*/
35 /*--- Bit stream I/O ---*/
36 /*---------------------------------------------------*/
37
38 /*---------------------------------------------------*/
BZ2_bsInitWrite(EState * s)39 void BZ2_bsInitWrite ( EState* s )
40 {
41 s->bsLive = 0;
42 s->bsBuff = 0;
43 }
44
45
46 /*---------------------------------------------------*/
47 static
bsFinishWrite(EState * s)48 void bsFinishWrite ( EState* s )
49 {
50 while (s->bsLive > 0) {
51 s->zbits[s->numZ] = (UChar)(s->bsBuff >> 24);
52 s->numZ++;
53 s->bsBuff <<= 8;
54 s->bsLive -= 8;
55 }
56 }
57
58
59 /*---------------------------------------------------*/
60 #define bsNEEDW(nz) \
61 { \
62 while (s->bsLive >= 8) { \
63 s->zbits[s->numZ] \
64 = (UChar)(s->bsBuff >> 24); \
65 s->numZ++; \
66 s->bsBuff <<= 8; \
67 s->bsLive -= 8; \
68 } \
69 }
70
71
72 /*---------------------------------------------------*/
73 static
74 __inline__
bsW(EState * s,Int32 n,UInt32 v)75 void bsW ( EState* s, Int32 n, UInt32 v )
76 {
77 bsNEEDW ( n );
78 s->bsBuff |= (v << (32 - s->bsLive - n));
79 s->bsLive += n;
80 }
81
82
83 /*---------------------------------------------------*/
84 static
bsPutUInt32(EState * s,UInt32 u)85 void bsPutUInt32 ( EState* s, UInt32 u )
86 {
87 bsW ( s, 8, (u >> 24) & 0xffL );
88 bsW ( s, 8, (u >> 16) & 0xffL );
89 bsW ( s, 8, (u >> 8) & 0xffL );
90 bsW ( s, 8, u & 0xffL );
91 }
92
93
94 /*---------------------------------------------------*/
95 static
bsPutUChar(EState * s,UChar c)96 void bsPutUChar ( EState* s, UChar c )
97 {
98 bsW( s, 8, (UInt32)c );
99 }
100
101
102 /*---------------------------------------------------*/
103 /*--- The back end proper ---*/
104 /*---------------------------------------------------*/
105
106 /*---------------------------------------------------*/
107 static
makeMaps_e(EState * s)108 void makeMaps_e ( EState* s )
109 {
110 Int32 i;
111 s->nInUse = 0;
112 for (i = 0; i < 256; i++)
113 if (s->inUse[i]) {
114 s->unseqToSeq[i] = s->nInUse;
115 s->nInUse++;
116 }
117 }
118
119
120 /*---------------------------------------------------*/
121 static
generateMTFValues(EState * s)122 void generateMTFValues ( EState* s )
123 {
124 UChar yy[256];
125 Int32 i, j;
126 Int32 zPend;
127 Int32 wr;
128 Int32 EOB;
129
130 /*
131 After sorting (eg, here),
132 s->arr1 [ 0 .. s->nblock-1 ] holds sorted order,
133 and
134 ((UChar*)s->arr2) [ 0 .. s->nblock-1 ]
135 holds the original block data.
136
137 The first thing to do is generate the MTF values,
138 and put them in
139 ((UInt16*)s->arr1) [ 0 .. s->nblock-1 ].
140 Because there are strictly fewer or equal MTF values
141 than block values, ptr values in this area are overwritten
142 with MTF values only when they are no longer needed.
143
144 The final compressed bitstream is generated into the
145 area starting at
146 (UChar*) (&((UChar*)s->arr2)[s->nblock])
147
148 These storage aliases are set up in bzCompressInit(),
149 except for the last one, which is arranged in
150 compressBlock().
151 */
152 UInt32* ptr = s->ptr;
153 UChar* block = s->block;
154 UInt16* mtfv = s->mtfv;
155
156 makeMaps_e ( s );
157 EOB = s->nInUse+1;
158
159 for (i = 0; i <= EOB; i++) s->mtfFreq[i] = 0;
160
161 wr = 0;
162 zPend = 0;
163 for (i = 0; i < s->nInUse; i++) yy[i] = (UChar) i;
164
165 for (i = 0; i < s->nblock; i++) {
166 UChar ll_i;
167 AssertD ( wr <= i, "generateMTFValues(1)" );
168 j = ptr[i]-1; if (j < 0) j += s->nblock;
169 ll_i = s->unseqToSeq[block[j]];
170 AssertD ( ll_i < s->nInUse, "generateMTFValues(2a)" );
171
172 if (yy[0] == ll_i) {
173 zPend++;
174 } else {
175
176 if (zPend > 0) {
177 zPend--;
178 while (True) {
179 if (zPend & 1) {
180 mtfv[wr] = BZ_RUNB; wr++;
181 s->mtfFreq[BZ_RUNB]++;
182 } else {
183 mtfv[wr] = BZ_RUNA; wr++;
184 s->mtfFreq[BZ_RUNA]++;
185 }
186 if (zPend < 2) break;
187 zPend = (zPend - 2) / 2;
188 };
189 zPend = 0;
190 }
191 {
192 register UChar rtmp;
193 register UChar* ryy_j;
194 register UChar rll_i;
195 rtmp = yy[1];
196 yy[1] = yy[0];
197 ryy_j = &(yy[1]);
198 rll_i = ll_i;
199 while ( rll_i != rtmp ) {
200 register UChar rtmp2;
201 ryy_j++;
202 rtmp2 = rtmp;
203 rtmp = *ryy_j;
204 *ryy_j = rtmp2;
205 };
206 yy[0] = rtmp;
207 j = ryy_j - &(yy[0]);
208 mtfv[wr] = j+1; wr++; s->mtfFreq[j+1]++;
209 }
210
211 }
212 }
213
214 if (zPend > 0) {
215 zPend--;
216 while (True) {
217 if (zPend & 1) {
218 mtfv[wr] = BZ_RUNB; wr++;
219 s->mtfFreq[BZ_RUNB]++;
220 } else {
221 mtfv[wr] = BZ_RUNA; wr++;
222 s->mtfFreq[BZ_RUNA]++;
223 }
224 if (zPend < 2) break;
225 zPend = (zPend - 2) / 2;
226 };
227 zPend = 0;
228 }
229
230 mtfv[wr] = EOB; wr++; s->mtfFreq[EOB]++;
231
232 s->nMTF = wr;
233 }
234
235
236 /*---------------------------------------------------*/
237 #define BZ_LESSER_ICOST 0
238 #define BZ_GREATER_ICOST 15
239
240 static
sendMTFValues(EState * s)241 void sendMTFValues ( EState* s )
242 {
243 Int32 v, t, i, j, gs, ge, totc, bt, bc, iter;
244 Int32 nSelectors, alphaSize, minLen, maxLen, selCtr;
245 Int32 nGroups, nBytes;
246
247 /*--
248 UChar len [BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
249 is a global since the decoder also needs it.
250
251 Int32 code[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
252 Int32 rfreq[BZ_N_GROUPS][BZ_MAX_ALPHA_SIZE];
253 are also globals only used in this proc.
254 Made global to keep stack frame size small.
255 --*/
256
257
258 UInt16 cost[BZ_N_GROUPS];
259 Int32 fave[BZ_N_GROUPS];
260
261 UInt16* mtfv = s->mtfv;
262
263 if (s->verbosity >= 3)
264 VPrintf3( " %d in block, %d after MTF & 1-2 coding, "
265 "%d+2 syms in use\n",
266 s->nblock, s->nMTF, s->nInUse );
267
268 alphaSize = s->nInUse+2;
269 for (t = 0; t < BZ_N_GROUPS; t++)
270 for (v = 0; v < alphaSize; v++)
271 s->len[t][v] = BZ_GREATER_ICOST;
272
273 /*--- Decide how many coding tables to use ---*/
274 AssertH ( s->nMTF > 0, 3001 );
275 if (s->nMTF < 200) nGroups = 2; else
276 if (s->nMTF < 600) nGroups = 3; else
277 if (s->nMTF < 1200) nGroups = 4; else
278 if (s->nMTF < 2400) nGroups = 5; else
279 nGroups = 6;
280
281 /*--- Generate an initial set of coding tables ---*/
282 {
283 Int32 nPart, remF, tFreq, aFreq;
284
285 nPart = nGroups;
286 remF = s->nMTF;
287 gs = 0;
288 while (nPart > 0) {
289 tFreq = remF / nPart;
290 ge = gs-1;
291 aFreq = 0;
292 while (aFreq < tFreq && ge < alphaSize-1) {
293 ge++;
294 aFreq += s->mtfFreq[ge];
295 }
296
297 if (ge > gs
298 && nPart != nGroups && nPart != 1
299 && ((nGroups-nPart) % 2 == 1)) {
300 aFreq -= s->mtfFreq[ge];
301 ge--;
302 }
303
304 if (s->verbosity >= 3)
305 VPrintf5( " initial group %d, [%d .. %d], "
306 "has %d syms (%4.1f%%)\n",
307 nPart, gs, ge, aFreq,
308 (100.0 * (float)aFreq) / (float)(s->nMTF) );
309
310 for (v = 0; v < alphaSize; v++)
311 if (v >= gs && v <= ge)
312 s->len[nPart-1][v] = BZ_LESSER_ICOST; else
313 s->len[nPart-1][v] = BZ_GREATER_ICOST;
314
315 nPart--;
316 gs = ge+1;
317 remF -= aFreq;
318 }
319 }
320
321 /*---
322 Iterate up to BZ_N_ITERS times to improve the tables.
323 ---*/
324 for (iter = 0; iter < BZ_N_ITERS; iter++) {
325
326 for (t = 0; t < nGroups; t++) fave[t] = 0;
327
328 for (t = 0; t < nGroups; t++)
329 for (v = 0; v < alphaSize; v++)
330 s->rfreq[t][v] = 0;
331
332 /*---
333 Set up an auxiliary length table which is used to fast-track
334 the common case (nGroups == 6).
335 ---*/
336 if (nGroups == 6) {
337 for (v = 0; v < alphaSize; v++) {
338 s->len_pack[v][0] = (s->len[1][v] << 16) | s->len[0][v];
339 s->len_pack[v][1] = (s->len[3][v] << 16) | s->len[2][v];
340 s->len_pack[v][2] = (s->len[5][v] << 16) | s->len[4][v];
341 }
342 }
343
344 nSelectors = 0;
345 totc = 0;
346 gs = 0;
347 while (True) {
348
349 /*--- Set group start & end marks. --*/
350 if (gs >= s->nMTF) break;
351 ge = gs + BZ_G_SIZE - 1;
352 if (ge >= s->nMTF) ge = s->nMTF-1;
353
354 /*--
355 Calculate the cost of this group as coded
356 by each of the coding tables.
357 --*/
358 for (t = 0; t < nGroups; t++) cost[t] = 0;
359
360 if (nGroups == 6 && 50 == ge-gs+1) {
361 /*--- fast track the common case ---*/
362 register UInt32 cost01, cost23, cost45;
363 register UInt16 icv;
364 cost01 = cost23 = cost45 = 0;
365
366 # define BZ_ITER(nn) \
367 icv = mtfv[gs+(nn)]; \
368 cost01 += s->len_pack[icv][0]; \
369 cost23 += s->len_pack[icv][1]; \
370 cost45 += s->len_pack[icv][2]; \
371
372 BZ_ITER(0); BZ_ITER(1); BZ_ITER(2); BZ_ITER(3); BZ_ITER(4);
373 BZ_ITER(5); BZ_ITER(6); BZ_ITER(7); BZ_ITER(8); BZ_ITER(9);
374 BZ_ITER(10); BZ_ITER(11); BZ_ITER(12); BZ_ITER(13); BZ_ITER(14);
375 BZ_ITER(15); BZ_ITER(16); BZ_ITER(17); BZ_ITER(18); BZ_ITER(19);
376 BZ_ITER(20); BZ_ITER(21); BZ_ITER(22); BZ_ITER(23); BZ_ITER(24);
377 BZ_ITER(25); BZ_ITER(26); BZ_ITER(27); BZ_ITER(28); BZ_ITER(29);
378 BZ_ITER(30); BZ_ITER(31); BZ_ITER(32); BZ_ITER(33); BZ_ITER(34);
379 BZ_ITER(35); BZ_ITER(36); BZ_ITER(37); BZ_ITER(38); BZ_ITER(39);
380 BZ_ITER(40); BZ_ITER(41); BZ_ITER(42); BZ_ITER(43); BZ_ITER(44);
381 BZ_ITER(45); BZ_ITER(46); BZ_ITER(47); BZ_ITER(48); BZ_ITER(49);
382
383 # undef BZ_ITER
384
385 cost[0] = cost01 & 0xffff; cost[1] = cost01 >> 16;
386 cost[2] = cost23 & 0xffff; cost[3] = cost23 >> 16;
387 cost[4] = cost45 & 0xffff; cost[5] = cost45 >> 16;
388
389 } else {
390 /*--- slow version which correctly handles all situations ---*/
391 for (i = gs; i <= ge; i++) {
392 UInt16 icv = mtfv[i];
393 for (t = 0; t < nGroups; t++) cost[t] += s->len[t][icv];
394 }
395 }
396
397 /*--
398 Find the coding table which is best for this group,
399 and record its identity in the selector table.
400 --*/
401 bc = 999999999; bt = -1;
402 for (t = 0; t < nGroups; t++)
403 if (cost[t] < bc) { bc = cost[t]; bt = t; };
404 totc += bc;
405 fave[bt]++;
406 s->selector[nSelectors] = bt;
407 nSelectors++;
408
409 /*--
410 Increment the symbol frequencies for the selected table.
411 --*/
412 if (nGroups == 6 && 50 == ge-gs+1) {
413 /*--- fast track the common case ---*/
414
415 # define BZ_ITUR(nn) s->rfreq[bt][ mtfv[gs+(nn)] ]++
416
417 BZ_ITUR(0); BZ_ITUR(1); BZ_ITUR(2); BZ_ITUR(3); BZ_ITUR(4);
418 BZ_ITUR(5); BZ_ITUR(6); BZ_ITUR(7); BZ_ITUR(8); BZ_ITUR(9);
419 BZ_ITUR(10); BZ_ITUR(11); BZ_ITUR(12); BZ_ITUR(13); BZ_ITUR(14);
420 BZ_ITUR(15); BZ_ITUR(16); BZ_ITUR(17); BZ_ITUR(18); BZ_ITUR(19);
421 BZ_ITUR(20); BZ_ITUR(21); BZ_ITUR(22); BZ_ITUR(23); BZ_ITUR(24);
422 BZ_ITUR(25); BZ_ITUR(26); BZ_ITUR(27); BZ_ITUR(28); BZ_ITUR(29);
423 BZ_ITUR(30); BZ_ITUR(31); BZ_ITUR(32); BZ_ITUR(33); BZ_ITUR(34);
424 BZ_ITUR(35); BZ_ITUR(36); BZ_ITUR(37); BZ_ITUR(38); BZ_ITUR(39);
425 BZ_ITUR(40); BZ_ITUR(41); BZ_ITUR(42); BZ_ITUR(43); BZ_ITUR(44);
426 BZ_ITUR(45); BZ_ITUR(46); BZ_ITUR(47); BZ_ITUR(48); BZ_ITUR(49);
427
428 # undef BZ_ITUR
429
430 } else {
431 /*--- slow version which correctly handles all situations ---*/
432 for (i = gs; i <= ge; i++)
433 s->rfreq[bt][ mtfv[i] ]++;
434 }
435
436 gs = ge+1;
437 }
438 if (s->verbosity >= 3) {
439 VPrintf2 ( " pass %d: size is %d, grp uses are ",
440 iter+1, totc/8 );
441 for (t = 0; t < nGroups; t++)
442 VPrintf1 ( "%d ", fave[t] );
443 VPrintf0 ( "\n" );
444 }
445
446 /*--
447 Recompute the tables based on the accumulated frequencies.
448 --*/
449 /* maxLen was changed from 20 to 17 in bzip2-1.0.3. See
450 comment in huffman.c for details. */
451 for (t = 0; t < nGroups; t++)
452 BZ2_hbMakeCodeLengths ( &(s->len[t][0]), &(s->rfreq[t][0]),
453 alphaSize, 17 /*20*/ );
454 }
455
456
457 AssertH( nGroups < 8, 3002 );
458 AssertH( nSelectors < 32768 &&
459 nSelectors <= BZ_MAX_SELECTORS,
460 3003 );
461
462
463 /*--- Compute MTF values for the selectors. ---*/
464 {
465 UChar pos[BZ_N_GROUPS], ll_i, tmp2, tmp;
466 for (i = 0; i < nGroups; i++) pos[i] = i;
467 for (i = 0; i < nSelectors; i++) {
468 ll_i = s->selector[i];
469 j = 0;
470 tmp = pos[j];
471 while ( ll_i != tmp ) {
472 j++;
473 tmp2 = tmp;
474 tmp = pos[j];
475 pos[j] = tmp2;
476 };
477 pos[0] = tmp;
478 s->selectorMtf[i] = j;
479 }
480 };
481
482 /*--- Assign actual codes for the tables. --*/
483 for (t = 0; t < nGroups; t++) {
484 minLen = 32;
485 maxLen = 0;
486 for (i = 0; i < alphaSize; i++) {
487 if (s->len[t][i] > maxLen) maxLen = s->len[t][i];
488 if (s->len[t][i] < minLen) minLen = s->len[t][i];
489 }
490 AssertH ( !(maxLen > 17 /*20*/ ), 3004 );
491 AssertH ( !(minLen < 1), 3005 );
492 BZ2_hbAssignCodes ( &(s->code[t][0]), &(s->len[t][0]),
493 minLen, maxLen, alphaSize );
494 }
495
496 /*--- Transmit the mapping table. ---*/
497 {
498 Bool inUse16[16];
499 for (i = 0; i < 16; i++) {
500 inUse16[i] = False;
501 for (j = 0; j < 16; j++)
502 if (s->inUse[i * 16 + j]) inUse16[i] = True;
503 }
504
505 nBytes = s->numZ;
506 for (i = 0; i < 16; i++)
507 if (inUse16[i]) bsW(s,1,1); else bsW(s,1,0);
508
509 for (i = 0; i < 16; i++)
510 if (inUse16[i])
511 for (j = 0; j < 16; j++) {
512 if (s->inUse[i * 16 + j]) bsW(s,1,1); else bsW(s,1,0);
513 }
514
515 if (s->verbosity >= 3)
516 VPrintf1( " bytes: mapping %d, ", s->numZ-nBytes );
517 }
518
519 /*--- Now the selectors. ---*/
520 nBytes = s->numZ;
521 bsW ( s, 3, nGroups );
522 bsW ( s, 15, nSelectors );
523 for (i = 0; i < nSelectors; i++) {
524 for (j = 0; j < s->selectorMtf[i]; j++) bsW(s,1,1);
525 bsW(s,1,0);
526 }
527 if (s->verbosity >= 3)
528 VPrintf1( "selectors %d, ", s->numZ-nBytes );
529
530 /*--- Now the coding tables. ---*/
531 nBytes = s->numZ;
532
533 for (t = 0; t < nGroups; t++) {
534 Int32 curr = s->len[t][0];
535 bsW ( s, 5, curr );
536 for (i = 0; i < alphaSize; i++) {
537 while (curr < s->len[t][i]) { bsW(s,2,2); curr++; /* 10 */ };
538 while (curr > s->len[t][i]) { bsW(s,2,3); curr--; /* 11 */ };
539 bsW ( s, 1, 0 );
540 }
541 }
542
543 if (s->verbosity >= 3)
544 VPrintf1 ( "code lengths %d, ", s->numZ-nBytes );
545
546 /*--- And finally, the block data proper ---*/
547 nBytes = s->numZ;
548 selCtr = 0;
549 gs = 0;
550 while (True) {
551 if (gs >= s->nMTF) break;
552 ge = gs + BZ_G_SIZE - 1;
553 if (ge >= s->nMTF) ge = s->nMTF-1;
554 AssertH ( s->selector[selCtr] < nGroups, 3006 );
555
556 if (nGroups == 6 && 50 == ge-gs+1) {
557 /*--- fast track the common case ---*/
558 UInt16 mtfv_i;
559 UChar* s_len_sel_selCtr
560 = &(s->len[s->selector[selCtr]][0]);
561 Int32* s_code_sel_selCtr
562 = &(s->code[s->selector[selCtr]][0]);
563
564 # define BZ_ITAH(nn) \
565 mtfv_i = mtfv[gs+(nn)]; \
566 bsW ( s, \
567 s_len_sel_selCtr[mtfv_i], \
568 s_code_sel_selCtr[mtfv_i] )
569
570 BZ_ITAH(0); BZ_ITAH(1); BZ_ITAH(2); BZ_ITAH(3); BZ_ITAH(4);
571 BZ_ITAH(5); BZ_ITAH(6); BZ_ITAH(7); BZ_ITAH(8); BZ_ITAH(9);
572 BZ_ITAH(10); BZ_ITAH(11); BZ_ITAH(12); BZ_ITAH(13); BZ_ITAH(14);
573 BZ_ITAH(15); BZ_ITAH(16); BZ_ITAH(17); BZ_ITAH(18); BZ_ITAH(19);
574 BZ_ITAH(20); BZ_ITAH(21); BZ_ITAH(22); BZ_ITAH(23); BZ_ITAH(24);
575 BZ_ITAH(25); BZ_ITAH(26); BZ_ITAH(27); BZ_ITAH(28); BZ_ITAH(29);
576 BZ_ITAH(30); BZ_ITAH(31); BZ_ITAH(32); BZ_ITAH(33); BZ_ITAH(34);
577 BZ_ITAH(35); BZ_ITAH(36); BZ_ITAH(37); BZ_ITAH(38); BZ_ITAH(39);
578 BZ_ITAH(40); BZ_ITAH(41); BZ_ITAH(42); BZ_ITAH(43); BZ_ITAH(44);
579 BZ_ITAH(45); BZ_ITAH(46); BZ_ITAH(47); BZ_ITAH(48); BZ_ITAH(49);
580
581 # undef BZ_ITAH
582
583 } else {
584 /*--- slow version which correctly handles all situations ---*/
585 for (i = gs; i <= ge; i++) {
586 bsW ( s,
587 s->len [s->selector[selCtr]] [mtfv[i]],
588 s->code [s->selector[selCtr]] [mtfv[i]] );
589 }
590 }
591
592
593 gs = ge+1;
594 selCtr++;
595 }
596 AssertH( selCtr == nSelectors, 3007 );
597
598 if (s->verbosity >= 3)
599 VPrintf1( "codes %d\n", s->numZ-nBytes );
600 }
601
602
603 /*---------------------------------------------------*/
BZ2_compressBlock(EState * s,Bool is_last_block)604 void BZ2_compressBlock ( EState* s, Bool is_last_block )
605 {
606 if (s->nblock > 0) {
607
608 BZ_FINALISE_CRC ( s->blockCRC );
609 s->combinedCRC = (s->combinedCRC << 1) | (s->combinedCRC >> 31);
610 s->combinedCRC ^= s->blockCRC;
611 if (s->blockNo > 1) s->numZ = 0;
612
613 if (s->verbosity >= 2)
614 VPrintf4( " block %d: crc = 0x%08x, "
615 "combined CRC = 0x%08x, size = %d\n",
616 s->blockNo, s->blockCRC, s->combinedCRC, s->nblock );
617
618 BZ2_blockSort ( s );
619 }
620
621 s->zbits = (UChar*) (&((UChar*)s->arr2)[s->nblock]);
622
623 /*-- If this is the first block, create the stream header. --*/
624 if (s->blockNo == 1) {
625 BZ2_bsInitWrite ( s );
626 bsPutUChar ( s, BZ_HDR_B );
627 bsPutUChar ( s, BZ_HDR_Z );
628 bsPutUChar ( s, BZ_HDR_h );
629 bsPutUChar ( s, (UChar)(BZ_HDR_0 + s->blockSize100k) );
630 }
631
632 if (s->nblock > 0) {
633
634 bsPutUChar ( s, 0x31 ); bsPutUChar ( s, 0x41 );
635 bsPutUChar ( s, 0x59 ); bsPutUChar ( s, 0x26 );
636 bsPutUChar ( s, 0x53 ); bsPutUChar ( s, 0x59 );
637
638 /*-- Now the block's CRC, so it is in a known place. --*/
639 bsPutUInt32 ( s, s->blockCRC );
640
641 /*--
642 Now a single bit indicating (non-)randomisation.
643 As of version 0.9.5, we use a better sorting algorithm
644 which makes randomisation unnecessary. So always set
645 the randomised bit to 'no'. Of course, the decoder
646 still needs to be able to handle randomised blocks
647 so as to maintain backwards compatibility with
648 older versions of bzip2.
649 --*/
650 bsW(s,1,0);
651
652 bsW ( s, 24, s->origPtr );
653 generateMTFValues ( s );
654 sendMTFValues ( s );
655 }
656
657
658 /*-- If this is the last block, add the stream trailer. --*/
659 if (is_last_block) {
660
661 bsPutUChar ( s, 0x17 ); bsPutUChar ( s, 0x72 );
662 bsPutUChar ( s, 0x45 ); bsPutUChar ( s, 0x38 );
663 bsPutUChar ( s, 0x50 ); bsPutUChar ( s, 0x90 );
664 bsPutUInt32 ( s, s->combinedCRC );
665 if (s->verbosity >= 2)
666 VPrintf1( " final combined CRC = 0x%08x\n ", s->combinedCRC );
667 bsFinishWrite ( s );
668 }
669 }
670
671
672 /*-------------------------------------------------------------*/
673 /*--- end compress.c ---*/
674 /*-------------------------------------------------------------*/
675