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