Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
26 pmbaty 1
/* n2_99.ch -- implementation of the NRV2[BDE]-99 compression algorithms
2
 
3
   This file is part of the UCL data compression library.
4
 
5
   Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer
6
   All Rights Reserved.
7
 
8
   The UCL library is free software; you can redistribute it and/or
9
   modify it under the terms of the GNU General Public License as
10
   published by the Free Software Foundation; either version 2 of
11
   the License, or (at your option) any later version.
12
 
13
   The UCL library is distributed in the hope that it will be useful,
14
   but WITHOUT ANY WARRANTY; without even the implied warranty of
15
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
   GNU General Public License for more details.
17
 
18
   You should have received a copy of the GNU General Public License
19
   along with the UCL library; see the file COPYING.
20
   If not, write to the Free Software Foundation, Inc.,
21
   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
 
23
   Markus F.X.J. Oberhumer
24
   <markus@oberhumer.com>
25
   http://www.oberhumer.com/opensource/ucl/
26
 */
27
 
28
 
29
 
30
#include "ucl_conf.h"
31
#include <ucl/ucl.h>
32
 
33
 
34
/***********************************************************************
35
//
36
************************************************************************/
37
 
38
#define SWD_USE_MALLOC 1
39
#if (ACC_OS_DOS16)
40
#define SWD_HMASK       (s->hmask)
41
#define HEAD2_VAR
42
#define IF_HEAD2(s)     if (s->use_head2)
43
#else
44
#define SWD_HMASK       (UCL_UINT32_C(65535))
45
#define IF_HEAD2(s)
46
#endif
47
#define SWD_N           (8*1024*1024ul) /* max. size of ring buffer */
48
#define SWD_F           2048            /* upper limit for match length */
49
#define SWD_THRESHOLD   1               /* lower limit for match length */
50
 
51
#if defined(NRV2B)
52
#  define UCL_COMPRESS_T                ucl_nrv2b_t
53
#  define ucl_swd_t                     ucl_nrv2b_swd_t
54
#  define ucl_nrv_99_compress           ucl_nrv2b_99_compress
55
#  define M2_MAX_OFFSET                 0xd00
56
#elif defined(NRV2D)
57
#  define UCL_COMPRESS_T                ucl_nrv2d_t
58
#  define ucl_swd_t                     ucl_nrv2d_swd_t
59
#  define ucl_nrv_99_compress           ucl_nrv2d_99_compress
60
#  define M2_MAX_OFFSET                 0x500
61
#elif defined(NRV2E)
62
#  define UCL_COMPRESS_T                ucl_nrv2e_t
63
#  define ucl_swd_t                     ucl_nrv2e_swd_t
64
#  define ucl_nrv_99_compress           ucl_nrv2e_99_compress
65
#  define M2_MAX_OFFSET                 0x500
66
#else
67
#  error
68
#endif
69
#define ucl_swd_p       ucl_swd_t * __UCL_MMODEL
70
 
71
#include "ucl_mchw.ch"
72
 
73
 
74
/***********************************************************************
75
// start-step-stop prefix coding
76
************************************************************************/
77
 
78
static void code_prefix_ss11(UCL_COMPRESS_T *c, ucl_uint32 i)
79
{
80
    if (i >= 2)
81
    {
82
        ucl_uint32 t = 4;
83
        i += 2;
84
        do {
85
            t <<= 1;
86
        } while (i >= t);
87
        t >>= 1;
88
        do {
89
            t >>= 1;
90
            bbPutBit(c, (i & t) ? 1 : 0);
91
            bbPutBit(c, 0);
92
        } while (t > 2);
93
    }
94
    bbPutBit(c, (unsigned)i & 1);
95
    bbPutBit(c, 1);
96
}
97
 
98
 
99
#if defined(NRV2D) || defined(NRV2E)
100
static void code_prefix_ss12(UCL_COMPRESS_T *c, ucl_uint32 i)
101
{
102
    if (i >= 2)
103
    {
104
        ucl_uint32 t = 2;
105
        do {
106
            i -= t;
107
            t <<= 2;
108
        } while (i >= t);
109
        do {
110
            t >>= 1;
111
            bbPutBit(c, (i & t) ? 1 : 0);
112
            bbPutBit(c, 0);
113
            t >>= 1;
114
            bbPutBit(c, (i & t) ? 1 : 0);
115
        } while (t > 2);
116
    }
117
    bbPutBit(c, (unsigned)i & 1);
118
    bbPutBit(c, 1);
119
}
120
#endif
121
 
122
 
123
static void
124
code_match(UCL_COMPRESS_T *c, ucl_uint m_len, const ucl_uint m_off)
125
{
126
    unsigned m_low = 0;
127
 
128
    while (m_len > c->conf.max_match)
129
    {
130
        code_match(c, c->conf.max_match - 3, m_off);
131
        m_len -= c->conf.max_match - 3;
132
    }
133
 
134
    c->match_bytes += m_len;
135
    if (m_len > c->result[3])
136
        c->result[3] = m_len;
137
    if (m_off > c->result[1])
138
        c->result[1] = m_off;
139
 
140
    bbPutBit(c, 0);
141
 
142
#if defined(NRV2B)
143
    if (m_off == c->last_m_off)
144
    {
145
        bbPutBit(c, 0);
146
        bbPutBit(c, 1);
147
    }
148
    else
149
    {
150
        code_prefix_ss11(c, 1 + ((m_off - 1) >> 8));
151
        bbPutByte(c, (unsigned)m_off - 1);
152
    }
153
    m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
154
    if (m_len >= 4)
155
    {
156
        bbPutBit(c,0);
157
        bbPutBit(c,0);
158
        code_prefix_ss11(c, m_len - 4);
159
    }
160
    else
161
    {
162
        bbPutBit(c, m_len > 1);
163
        bbPutBit(c, (unsigned)m_len & 1);
164
    }
165
#elif defined(NRV2D)
166
    m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
167
    assert(m_len > 0);
168
    m_low = (m_len >= 4) ? 0u : (unsigned) m_len;
169
    if (m_off == c->last_m_off)
170
    {
171
        bbPutBit(c, 0);
172
        bbPutBit(c, 1);
173
        bbPutBit(c, m_low > 1);
174
        bbPutBit(c, m_low & 1);
175
    }
176
    else
177
    {
178
        code_prefix_ss12(c, 1 + ((m_off - 1) >> 7));
179
        bbPutByte(c, ((((unsigned)m_off - 1) & 0x7f) << 1) | ((m_low > 1) ? 0 : 1));
180
        bbPutBit(c, m_low & 1);
181
    }
182
    if (m_len >= 4)
183
        code_prefix_ss11(c, m_len - 4);
184
#elif defined(NRV2E)
185
    m_len = m_len - 1 - (m_off > M2_MAX_OFFSET);
186
    assert(m_len > 0);
187
    m_low = (m_len <= 2);
188
    if (m_off == c->last_m_off)
189
    {
190
        bbPutBit(c, 0);
191
        bbPutBit(c, 1);
192
        bbPutBit(c, m_low);
193
    }
194
    else
195
    {
196
        code_prefix_ss12(c, 1 + ((m_off - 1) >> 7));
197
        bbPutByte(c, ((((unsigned)m_off - 1) & 0x7f) << 1) | (m_low ^ 1));
198
    }
199
    if (m_low)
200
        bbPutBit(c, (unsigned)m_len - 1);
201
    else if (m_len <= 4)
202
    {
203
        bbPutBit(c, 1);
204
        bbPutBit(c, (unsigned)m_len - 3);
205
    }
206
    else
207
    {
208
        bbPutBit(c, 0);
209
        code_prefix_ss11(c, m_len - 5);
210
    }
211
#else
212
#  error
213
#endif
214
 
215
    c->last_m_off = m_off;
216
    ACC_UNUSED(m_low);
217
}
218
 
219
 
220
static void
221
code_run(UCL_COMPRESS_T *c, const ucl_bytep ii, ucl_uint lit)
222
{
223
    if (lit == 0)
224
        return;
225
    c->lit_bytes += lit;
226
    if (lit > c->result[5])
227
        c->result[5] = lit;
228
    do {
229
        bbPutBit(c, 1);
230
        bbPutByte(c, *ii++);
231
    } while (--lit > 0);
232
}
233
 
234
 
235
/***********************************************************************
236
//
237
************************************************************************/
238
 
239
static int
240
len_of_coded_match(UCL_COMPRESS_T *c, ucl_uint m_len, ucl_uint m_off)
241
{
242
    int b;
243
    if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
244
        || m_off > c->conf.max_offset)
245
        return -1;
246
    assert(m_off > 0);
247
 
248
    m_len = m_len - 2 - (m_off > M2_MAX_OFFSET);
249
 
250
    if (m_off == c->last_m_off)
251
        b = 1 + 2;
252
    else
253
    {
254
#if defined(NRV2B)
255
        b = 1 + 10;
256
        m_off = (m_off - 1) >> 8;
257
        while (m_off > 0)
258
        {
259
            b += 2;
260
            m_off >>= 1;
261
        }
262
#elif defined(NRV2D) || defined(NRV2E)
263
        b = 1 + 9;
264
        m_off = (m_off - 1) >> 7;
265
        while (m_off > 0)
266
        {
267
            b += 3;
268
            m_off >>= 2;
269
        }
270
#else
271
#  error
272
#endif
273
    }
274
 
275
#if defined(NRV2B) || defined(NRV2D)
276
    b += 2;
277
    if (m_len < 3)
278
        return b;
279
    m_len -= 3;
280
#elif defined(NRV2E)
281
    b += 2;
282
    if (m_len < 2)
283
        return b;
284
    if (m_len < 4)
285
        return b + 1;
286
    m_len -= 4;
287
#else
288
#  error
289
#endif
290
    do {
291
        b += 2;
292
        m_len >>= 1;
293
    } while (m_len > 0);
294
 
295
    return b;
296
}
297
 
298
 
299
/***********************************************************************
300
//
301
************************************************************************/
302
 
303
#if !defined(NDEBUG)
304
static
305
void assert_match( const ucl_swd_p swd, ucl_uint m_len, ucl_uint m_off )
306
{
307
    const UCL_COMPRESS_T *c = swd->c;
308
    ucl_uint d_off;
309
 
310
    assert(m_len >= 2);
311
    if (m_off <= (ucl_uint) (c->bp - c->in))
312
    {
313
        assert(c->bp - m_off + m_len < c->ip);
314
        assert(ucl_memcmp(c->bp, c->bp - m_off, m_len) == 0);
315
    }
316
    else
317
    {
318
        assert(swd->dict != NULL);
319
        d_off = m_off - (ucl_uint) (c->bp - c->in);
320
        assert(d_off <= swd->dict_len);
321
        if (m_len > d_off)
322
        {
323
            assert(ucl_memcmp(c->bp, swd->dict_end - d_off, d_off) == 0);
324
            assert(c->in + m_len - d_off < c->ip);
325
            assert(ucl_memcmp(c->bp + d_off, c->in, m_len - d_off) == 0);
326
        }
327
        else
328
        {
329
            assert(ucl_memcmp(c->bp, swd->dict_end - d_off, m_len) == 0);
330
        }
331
    }
332
}
333
#else
334
#  define assert_match(a,b,c)   ((void)0)
335
#endif
336
 
337
 
338
#if defined(SWD_BEST_OFF)
339
 
340
static void
341
better_match ( const ucl_swd_p swd, ucl_uint *m_len, ucl_uint *m_off )
342
{
343
}
344
 
345
#endif
346
 
347
 
348
/***********************************************************************
349
//
350
************************************************************************/
351
 
352
UCL_PUBLIC(int)
353
ucl_nrv_99_compress        ( const ucl_bytep in, ucl_uint in_len,
354
                                   ucl_bytep out, ucl_uintp out_len,
355
                                   ucl_progress_callback_p cb,
356
                                   int level,
357
                             const struct ucl_compress_config_p conf,
358
                                   ucl_uintp result)
359
{
360
    const ucl_bytep ii;
361
    ucl_uint lit;
362
    ucl_uint m_len, m_off;
363
    UCL_COMPRESS_T c_buffer;
364
    UCL_COMPRESS_T * const c = &c_buffer;
365
#undef s
366
#if defined(SWD_USE_MALLOC)
367
    ucl_swd_t the_swd;
368
#   define s (&the_swd)
369
#else
370
    ucl_swd_p s;
371
#endif
372
    ucl_uint result_buffer[16];
373
    int r;
374
 
375
    struct swd_config_t
376
    {
377
        unsigned try_lazy;
378
        ucl_uint good_length;
379
        ucl_uint max_lazy;
380
        ucl_uint nice_length;
381
        ucl_uint max_chain;
382
        ucl_uint32 flags;
383
        ucl_uint32 max_offset;
384
    };
385
    const struct swd_config_t *sc;
386
    static const struct swd_config_t swd_config[10] = {
387
#define F SWD_F
388
        /* faster compression */
389
        {   0,   0,   0,   8,    4,   0,  48*1024L },
390
        {   0,   0,   0,  16,    8,   0,  48*1024L },
391
        {   0,   0,   0,  32,   16,   0,  48*1024L },
392
        {   1,   4,   4,  16,   16,   0,  48*1024L },
393
        {   1,   8,  16,  32,   32,   0,  48*1024L },
394
        {   1,   8,  16, 128,  128,   0,  48*1024L },
395
        {   2,   8,  32, 128,  256,   0, 128*1024L },
396
        {   2,  32, 128,   F, 2048,   1, 128*1024L },
397
        {   2,  32, 128,   F, 2048,   1, 256*1024L },
398
        {   2,   F,   F,   F, 4096,   1, SWD_N }
399
        /* max. compression */
400
#undef F
401
    };
402
 
403
    if (level < 1 || level > 10)
404
        return UCL_E_INVALID_ARGUMENT;
405
    sc = &swd_config[level - 1];
406
 
407
    memset(c, 0, sizeof(*c));
408
    memset(&c->conf, 0xff, sizeof(c->conf));
409
    c->ip = c->in = in;
410
    c->in_end = in + in_len;
411
    c->out = out;
412
    if (cb && cb->callback)
413
        c->cb = cb;
414
    cb = NULL;
415
    c->result = result ? result : (ucl_uintp) result_buffer;
416
    result = NULL;
417
    ucl_memset(c->result, 0, 16*sizeof(*c->result));
418
    c->result[0] = c->result[2] = c->result[4] = UCL_UINT_MAX;
419
    if (conf)
420
        ucl_memcpy(&c->conf, conf, sizeof(c->conf));
421
    conf = NULL;
422
    r = bbConfig(c, 0, 8);
423
    if (r == 0)
424
        r = bbConfig(c, c->conf.bb_endian, c->conf.bb_size);
425
    if (r != 0)
426
        return UCL_E_INVALID_ARGUMENT;
427
    c->bb_op = out;
428
 
429
    ii = c->ip;             /* point to start of literal run */
430
    lit = 0;
431
 
432
#if !defined(s)
433
    s = (ucl_swd_p) ucl_malloc(ucl_sizeof(*s));
434
    if (!s)
435
        return UCL_E_OUT_OF_MEMORY;
436
#endif
437
    s->f = UCL_MIN((ucl_uint)SWD_F, c->conf.max_match);
438
    s->n = UCL_MIN((ucl_uint)SWD_N, sc->max_offset);
439
    s->hmask = UCL_UINT32_C(65535);
440
#ifdef HEAD2_VAR
441
    s->use_head2 = 1;
442
#if defined(ACC_MM_AHSHIFT)
443
    if (ACC_MM_AHSHIFT != 3) {
444
        s->hmask = 16 * 1024 - 1;
445
        s->use_head2 = 0;
446
    }
447
#endif
448
#endif
449
    if (c->conf.max_offset != UCL_UINT_MAX)
450
        s->n = UCL_MIN(SWD_N, c->conf.max_offset);
451
    if (in_len < s->n)
452
        s->n = UCL_MAX(in_len, 256);
453
    if (s->f < 8 || s->n < 256)
454
        return UCL_E_INVALID_ARGUMENT;
455
    r = init_match(c,s,NULL,0,sc->flags);
456
    if (r == UCL_E_OK && (SWD_HSIZE - 1 != s->hmask))
457
        r = UCL_E_ERROR;
458
    if (r != UCL_E_OK)
459
    {
460
#if !defined(s)
461
        ucl_free(s);
462
#endif
463
        return r;
464
    }
465
    if (sc->max_chain > 0)
466
        s->max_chain = sc->max_chain;
467
    if (sc->nice_length > 0)
468
        s->nice_length = sc->nice_length;
469
    if (c->conf.max_match < s->nice_length)
470
        s->nice_length = c->conf.max_match;
471
 
472
    if (c->cb)
473
        (*c->cb->callback)(0,0,-1,c->cb->user);
474
 
475
    c->last_m_off = 1;
476
    r = find_match(c,s,0,0);
477
    if (r != UCL_E_OK)
478
        return r;
479
    while (c->look > 0)
480
    {
481
        ucl_uint ahead;
482
        ucl_uint max_ahead;
483
        int l1, l2;
484
 
485
        c->codesize = (ucl_uint) (c->bb_op - out);
486
 
487
        m_len = c->m_len;
488
        m_off = c->m_off;
489
 
490
        assert(c->bp == c->ip - c->look);
491
        assert(c->bp >= in);
492
        if (lit == 0)
493
            ii = c->bp;
494
        assert(ii + lit == c->bp);
495
        assert(s->b_char == *(c->bp));
496
 
497
        if (m_len < 2 || (m_len == 2 && (m_off > M2_MAX_OFFSET))
498
            || m_off > c->conf.max_offset)
499
        {
500
            /* a literal */
501
            lit++;
502
            s->max_chain = sc->max_chain;
503
            r = find_match(c,s,1,0);
504
            assert(r == 0);
505
            continue;
506
        }
507
 
508
    /* a match */
509
#if defined(SWD_BEST_OFF)
510
        if (s->use_best_off)
511
            better_match(s,&m_len,&m_off);
512
#endif
513
        assert_match(s,m_len,m_off);
514
 
515
        /* shall we try a lazy match ? */
516
        ahead = 0;
517
        if (sc->try_lazy <= 0 || m_len >= sc->max_lazy || m_off == c->last_m_off)
518
        {
519
            /* no */
520
            l1 = 0;
521
            max_ahead = 0;
522
        }
523
        else
524
        {
525
            /* yes, try a lazy match */
526
            l1 = len_of_coded_match(c,m_len,m_off);
527
            assert(l1 > 0);
528
            max_ahead = UCL_MIN((ucl_uint)sc->try_lazy, m_len - 1);
529
        }
530
 
531
        while (ahead < max_ahead && c->look > m_len)
532
        {
533
            if (m_len >= sc->good_length)
534
                s->max_chain = sc->max_chain >> 2;
535
            else
536
                s->max_chain = sc->max_chain;
537
            r = find_match(c,s,1,0);
538
            ahead++;
539
 
540
            assert(r == 0);
541
            assert(c->look > 0);
542
            assert(ii + lit + ahead == c->bp);
543
 
544
            if (c->m_len < 2)
545
                continue;
546
#if defined(SWD_BEST_OFF)
547
            if (s->use_best_off)
548
                better_match(s,&c->m_len,&c->m_off);
549
#endif
550
            l2 = len_of_coded_match(c,c->m_len,c->m_off);
551
            if (l2 < 0)
552
                continue;
553
#if 1
554
            if (l1 + (int)(ahead + c->m_len - m_len) * 5 > l2 + (int)(ahead) * 9)
555
#else
556
            if (l1 > l2)
557
#endif
558
            {
559
                c->lazy++;
560
                assert_match(s,c->m_len,c->m_off);
561
 
562
#if 0
563
                if (l3 > 0)
564
                {
565
                    /* code previous run */
566
                    code_run(c,ii,lit);
567
                    lit = 0;
568
                    /* code shortened match */
569
                    code_match(c,ahead,m_off);
570
                }
571
                else
572
#endif
573
                {
574
                    lit += ahead;
575
                    assert(ii + lit == c->bp);
576
                }
577
                goto lazy_match_done;
578
            }
579
        }
580
 
581
        assert(ii + lit + ahead == c->bp);
582
 
583
        /* 1 - code run */
584
        code_run(c,ii,lit);
585
        lit = 0;
586
 
587
        /* 2 - code match */
588
        code_match(c,m_len,m_off);
589
        s->max_chain = sc->max_chain;
590
        r = find_match(c,s,m_len,1+ahead);
591
        assert(r == 0);
592
 
593
lazy_match_done: ;
594
    }
595
 
596
    /* store final run */
597
    code_run(c,ii,lit);
598
 
599
    /* EOF */
600
    bbPutBit(c, 0);
601
#if defined(NRV2B)
602
    code_prefix_ss11(c, UCL_UINT32_C(0x1000000));
603
    bbPutByte(c, 0xff);
604
#elif defined(NRV2D) || defined(NRV2E)
605
    code_prefix_ss12(c, UCL_UINT32_C(0x1000000));
606
    bbPutByte(c, 0xff);
607
#else
608
#  error
609
#endif
610
    bbFlushBits(c, 0);
611
 
612
    assert(c->textsize == in_len);
613
    c->codesize = (ucl_uint) (c->bb_op - out);
614
    *out_len = (ucl_uint) (c->bb_op - out);
615
    if (c->cb)
616
        (*c->cb->callback)(c->textsize,c->codesize,4,c->cb->user);
617
 
618
#if 0
619
    printf("%7ld %7ld -> %7ld   %7ld %7ld   %ld  (max: %d %d %d)\n",
620
          (long) c->textsize, (long) in_len, (long) c->codesize,
621
           c->match_bytes, c->lit_bytes,  c->lazy,
622
           c->result[1], c->result[3], c->result[5]);
623
#endif
624
    assert(c->lit_bytes + c->match_bytes == in_len);
625
 
626
    swd_exit(s);
627
#if !defined(s)
628
    ucl_free(s);
629
#endif
630
    return UCL_E_OK;
631
#undef s
632
}
633
 
634
 
635
/*
636
vi:ts=4:et
637
*/
638