Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
26 pmbaty 1
/* ucl_swd.c -- sliding window dictionary
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
#if (UCL_UINT_MAX < UCL_0xffffffffL)
30
#  error "UCL_UINT_MAX"
31
#endif
32
 
33
 
34
/***********************************************************************
35
//
36
************************************************************************/
37
 
38
/* unsigned type for dictionary access - don't waste memory here */
39
#if (0UL + SWD_N + SWD_F + SWD_F < 0UL + USHRT_MAX)
40
   typedef unsigned short   swd_uint;
41
#  define SWD_UINT_MAX      USHRT_MAX
42
#else
43
   typedef ucl_uint         swd_uint;
44
#  define SWD_UINT_MAX      UCL_UINT_MAX
45
#endif
46
#define swd_uintp           swd_uint __UCL_MMODEL *
47
#define SWD_UINT(x)         ((swd_uint)(x))
48
 
49
 
50
#ifndef SWD_MAX_CHAIN
51
#  define SWD_MAX_CHAIN     2048
52
#endif
53
#define SWD_HSIZE           (SWD_HMASK + 1)
54
 
55
#if !defined(HEAD3)
56
#if 1
57
#  define HEAD3(b,p) \
58
    (((0x9f5f*(((((ucl_uint32)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & SWD_HMASK)
59
#else
60
#  define HEAD3(b,p) \
61
    (((0x9f5f*(((((ucl_uint32)b[p+2]<<5)^b[p+1])<<5)^b[p]))>>5) & SWD_HMASK)
62
#endif
63
#endif
64
 
65
#if !defined(HEAD2)
66
#if (SWD_THRESHOLD == 1)
67
#  if 1 && defined(UA_GET2)
68
#    define HEAD2(b,p)      UA_GET2(&(b[p]))
69
#  else
70
#    define HEAD2(b,p)      (b[p] ^ ((unsigned)b[p+1]<<8))
71
#  endif
72
#  define NIL2              SWD_UINT_MAX
73
#endif
74
#endif
75
 
76
 
77
#if defined(__UCL_CHECKER)
78
   /* malloc arrays of the exact size to detect any overrun */
79
#  ifndef SWD_USE_MALLOC
80
#    define SWD_USE_MALLOC
81
#  endif
82
#endif
83
 
84
 
85
typedef struct
86
{
87
/* public - "built-in" */
88
    ucl_uint n;
89
    ucl_uint f;
90
    ucl_uint threshold;
91
    ucl_uint hmask;
92
 
93
/* public - configuration */
94
    ucl_uint max_chain;
95
    ucl_uint nice_length;
96
    ucl_bool use_best_off;
97
    ucl_uint lazy_insert;
98
 
99
/* public - output */
100
    ucl_uint m_len;
101
    ucl_uint m_off;
102
    ucl_uint look;
103
    int b_char;
104
#if defined(SWD_BEST_OFF)
105
    ucl_uint best_off[ SWD_BEST_OFF ];
106
#endif
107
 
108
/* semi public */
109
    UCL_COMPRESS_T *c;
110
    ucl_uint m_pos;
111
#if defined(SWD_BEST_OFF)
112
    ucl_uint best_pos[ SWD_BEST_OFF ];
113
#endif
114
 
115
/* private */
116
    const ucl_bytep dict;
117
    const ucl_bytep dict_end;
118
    ucl_uint dict_len;
119
 
120
/* private */
121
    ucl_uint ip;                /* input pointer (lookahead) */
122
    ucl_uint bp;                /* buffer pointer */
123
    ucl_uint rp;                /* remove pointer */
124
    ucl_uint b_size;
125
 
126
    ucl_bytep b_wrap;
127
 
128
    ucl_uint node_count;
129
    ucl_uint first_rp;
130
 
131
#if defined(SWD_USE_MALLOC)
132
    ucl_bytep b;
133
    swd_uintp head3;
134
    swd_uintp succ3;
135
    swd_uintp best3;
136
    swd_uintp llen3;
137
#ifdef HEAD2
138
    swd_uintp head2;
139
#ifdef HEAD2_VAR
140
    int use_head2;
141
#endif
142
#endif
143
#else
144
    unsigned char b [ SWD_N + SWD_F + SWD_F ];
145
    swd_uint head3 [ SWD_HSIZE ];
146
    swd_uint succ3 [ SWD_N + SWD_F ];
147
    swd_uint best3 [ SWD_N + SWD_F ];
148
    swd_uint llen3 [ SWD_HSIZE ];
149
#ifdef HEAD2
150
    swd_uint head2 [ UCL_UINT32_C(65536) ];
151
#endif
152
#endif
153
}
154
ucl_swd_t;
155
 
156
 
157
/* Access macro for head3.
158
 * head3[key] may be uninitialized if the list is emtpy,
159
 * but then its value will never be used.
160
 */
161
#if defined(__UCL_CHECKER)
162
#  define s_get_head3(s,key) \
163
        ((s->llen3[key] == 0) ? SWD_UINT_MAX : s->head3[key])
164
#else
165
#  define s_get_head3(s,key)    s->head3[key]
166
#endif
167
 
168
 
169
/***********************************************************************
170
//
171
************************************************************************/
172
 
173
static
174
void swd_initdict(ucl_swd_t *s, const ucl_bytep dict, ucl_uint dict_len)
175
{
176
    s->dict = s->dict_end = NULL;
177
    s->dict_len = 0;
178
 
179
    if (!dict || dict_len <= 0)
180
        return;
181
    if (dict_len > s->n)
182
    {
183
        dict += dict_len - s->n;
184
        dict_len = s->n;
185
    }
186
 
187
    s->dict = dict;
188
    s->dict_len = dict_len;
189
    s->dict_end = dict + dict_len;
190
    ucl_memcpy(s->b,dict,dict_len);
191
    s->ip = dict_len;
192
}
193
 
194
 
195
static
196
void swd_insertdict(ucl_swd_t *s, ucl_uint node, ucl_uint len)
197
{
198
    ucl_uint key;
199
 
200
    s->node_count = s->n - len;
201
    s->first_rp = node;
202
 
203
    while (len-- > 0)
204
    {
205
        key = HEAD3(s->b,node);
206
        s->succ3[node] = s_get_head3(s,key);
207
        s->head3[key] = SWD_UINT(node);
208
        s->best3[node] = SWD_UINT(s->f + 1);
209
        s->llen3[key]++;
210
        assert(s->llen3[key] <= s->n);
211
 
212
#ifdef HEAD2
213
        IF_HEAD2(s) {
214
            key = HEAD2(s->b,node);
215
            s->head2[key] = SWD_UINT(node);
216
        }
217
#endif
218
 
219
        node++;
220
    }
221
}
222
 
223
 
224
/***********************************************************************
225
//
226
************************************************************************/
227
 
228
static
229
int swd_init(ucl_swd_t *s, const ucl_bytep dict, ucl_uint dict_len)
230
{
231
#if defined(SWD_USE_MALLOC)
232
    s->b = NULL;
233
    s->head3 = NULL;
234
    s->succ3 = NULL;
235
    s->best3 = NULL;
236
    s->llen3 = NULL;
237
#ifdef HEAD2
238
    s->head2 = NULL;
239
#endif
240
#endif
241
 
242
    if (s->n == 0)
243
        s->n = SWD_N;
244
    if (s->f == 0)
245
        s->f = SWD_F;
246
    s->threshold = SWD_THRESHOLD;
247
    if (s->n > SWD_N || s->f > SWD_F)
248
        return UCL_E_INVALID_ARGUMENT;
249
 
250
#if defined(SWD_USE_MALLOC)
251
    s->b = (ucl_bytep) ucl_malloc(s->n + s->f + s->f);
252
    s->head3 = (swd_uintp) ucl_alloc(SWD_HSIZE, sizeof(*s->head3));
253
    s->succ3 = (swd_uintp) ucl_alloc(s->n + s->f, sizeof(*s->succ3));
254
    s->best3 = (swd_uintp) ucl_alloc(s->n + s->f, sizeof(*s->best3));
255
    s->llen3 = (swd_uintp) ucl_alloc(SWD_HSIZE, sizeof(*s->llen3));
256
    if (!s->b || !s->head3  || !s->succ3 || !s->best3 || !s->llen3)
257
        return UCL_E_OUT_OF_MEMORY;
258
#ifdef HEAD2
259
    IF_HEAD2(s) {
260
        s->head2 = (swd_uintp) ucl_alloc(UCL_UINT32_C(65536), sizeof(*s->head2));
261
        if (!s->head2)
262
            return UCL_E_OUT_OF_MEMORY;
263
    }
264
#endif
265
#endif
266
 
267
    /* defaults */
268
    s->max_chain = SWD_MAX_CHAIN;
269
    s->nice_length = s->f;
270
    s->use_best_off = 0;
271
    s->lazy_insert = 0;
272
 
273
    s->b_size = s->n + s->f;
274
    if (s->b_size + s->f >= SWD_UINT_MAX)
275
        return UCL_E_ERROR;
276
    s->b_wrap = s->b + s->b_size;
277
    s->node_count = s->n;
278
 
279
    ucl_memset(s->llen3, 0, (ucl_uint)sizeof(s->llen3[0]) * SWD_HSIZE);
280
#ifdef HEAD2
281
    IF_HEAD2(s) {
282
#if 1
283
        ucl_memset(s->head2, 0xff, (ucl_uint)sizeof(s->head2[0]) * UCL_UINT32_C(65536));
284
        assert(s->head2[0] == NIL2);
285
#else
286
        ucl_uint32 i;
287
        for (i = 0; i < UCL_UINT32_C(65536); i++)
288
            s->head2[i] = NIL2;
289
#endif
290
    }
291
#endif
292
 
293
    s->ip = 0;
294
    swd_initdict(s,dict,dict_len);
295
    s->bp = s->ip;
296
    s->first_rp = s->ip;
297
 
298
    assert(s->ip + s->f <= s->b_size);
299
#if 1
300
    s->look = (ucl_uint) (s->c->in_end - s->c->ip);
301
    if (s->look > 0)
302
    {
303
        if (s->look > s->f)
304
            s->look = s->f;
305
        ucl_memcpy(&s->b[s->ip],s->c->ip,s->look);
306
        s->c->ip += s->look;
307
        s->ip += s->look;
308
    }
309
#else
310
    s->look = 0;
311
    while (s->look < s->f)
312
    {
313
        int c;
314
        if ((c = getbyte(*(s->c))) < 0)
315
            break;
316
        s->b[s->ip] = UCL_BYTE(c);
317
        s->ip++;
318
        s->look++;
319
    }
320
#endif
321
    if (s->ip == s->b_size)
322
        s->ip = 0;
323
 
324
    if (s->look >= 2 && s->dict_len > 0)
325
        swd_insertdict(s,0,s->dict_len);
326
 
327
    s->rp = s->first_rp;
328
    if (s->rp >= s->node_count)
329
        s->rp -= s->node_count;
330
    else
331
        s->rp += s->b_size - s->node_count;
332
 
333
#if defined(__UCL_CHECKER)
334
    /* initialize memory for the first few HEAD3 (if s->ip is not far
335
     * enough ahead to do this job for us). The value doesn't matter. */
336
    if (s->look < 3)
337
        ucl_memset(&s->b[s->bp+s->look],0,3);
338
#endif
339
 
340
    return UCL_E_OK;
341
}
342
 
343
 
344
static
345
void swd_exit(ucl_swd_t *s)
346
{
347
#if defined(SWD_USE_MALLOC)
348
    /* free in reverse order of allocations */
349
#ifdef HEAD2
350
    ucl_free(s->head2); s->head2 = NULL;
351
#endif
352
    ucl_free(s->llen3); s->llen3 = NULL;
353
    ucl_free(s->best3); s->best3 = NULL;
354
    ucl_free(s->succ3); s->succ3 = NULL;
355
    ucl_free(s->head3); s->head3 = NULL;
356
    ucl_free(s->b); s->b = NULL;
357
#else
358
    ACC_UNUSED(s);
359
#endif
360
}
361
 
362
 
363
#define swd_pos2off(s,pos) \
364
    (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
365
 
366
 
367
/***********************************************************************
368
//
369
************************************************************************/
370
 
371
static
372
void swd_getbyte(ucl_swd_t *s)
373
{
374
    int c;
375
 
376
    if ((c = getbyte(*(s->c))) < 0)
377
    {
378
        if (s->look > 0)
379
            --s->look;
380
#if defined(__UCL_CHECKER)
381
        /* initialize memory - value doesn't matter */
382
        s->b[s->ip] = 0;
383
        if (s->ip < s->f)
384
            s->b_wrap[s->ip] = 0;
385
#endif
386
    }
387
    else
388
    {
389
        s->b[s->ip] = UCL_BYTE(c);
390
        if (s->ip < s->f)
391
            s->b_wrap[s->ip] = UCL_BYTE(c);
392
    }
393
    if (++s->ip == s->b_size)
394
        s->ip = 0;
395
    if (++s->bp == s->b_size)
396
        s->bp = 0;
397
    if (++s->rp == s->b_size)
398
        s->rp = 0;
399
}
400
 
401
 
402
/***********************************************************************
403
// remove node from lists
404
************************************************************************/
405
 
406
static
407
void swd_remove_node(ucl_swd_t *s, ucl_uint node)
408
{
409
    if (s->node_count == 0)
410
    {
411
        ucl_uint key;
412
 
413
#ifdef UCL_DEBUG
414
        if (s->first_rp != UCL_UINT_MAX)
415
        {
416
            if (node != s->first_rp)
417
                printf("Remove %5u: %5u %5u %5u %5u  %6u %6u\n",
418
                        node, s->rp, s->ip, s->bp, s->first_rp,
419
                        s->ip - node, s->ip - s->bp);
420
            assert(node == s->first_rp);
421
            s->first_rp = UCL_UINT_MAX;
422
        }
423
#endif
424
 
425
        key = HEAD3(s->b,node);
426
        assert(s->llen3[key] > 0);
427
        --s->llen3[key];
428
 
429
#ifdef HEAD2
430
        IF_HEAD2(s) {
431
            key = HEAD2(s->b,node);
432
            assert(s->head2[key] != NIL2);
433
            if ((ucl_uint) s->head2[key] == node)
434
                s->head2[key] = NIL2;
435
        }
436
#endif
437
    }
438
    else
439
        --s->node_count;
440
}
441
 
442
 
443
/***********************************************************************
444
//
445
************************************************************************/
446
 
447
static
448
void swd_accept(ucl_swd_t *s, ucl_uint n)
449
{
450
    assert(n <= s->look);
451
 
452
    if (n > 0) do
453
    {
454
        ucl_uint key;
455
 
456
        swd_remove_node(s,s->rp);
457
 
458
        /* add bp into HEAD3 */
459
        key = HEAD3(s->b,s->bp);
460
        s->succ3[s->bp] = s_get_head3(s,key);
461
        s->head3[key] = SWD_UINT(s->bp);
462
        s->best3[s->bp] = SWD_UINT(s->f + 1);
463
        s->llen3[key]++;
464
        assert(s->llen3[key] <= s->n);
465
 
466
#ifdef HEAD2
467
        IF_HEAD2(s) {
468
            /* add bp into HEAD2 */
469
            key = HEAD2(s->b,s->bp);
470
            s->head2[key] = SWD_UINT(s->bp);
471
        }
472
#endif
473
 
474
        swd_getbyte(s);
475
    } while (--n > 0);
476
}
477
 
478
 
479
/***********************************************************************
480
//
481
************************************************************************/
482
 
483
static
484
void swd_search(ucl_swd_t *s, ucl_uint node, ucl_uint cnt)
485
{
486
    const ucl_bytep p1;
487
    const ucl_bytep p2;
488
    const ucl_bytep px;
489
    ucl_uint m_len = s->m_len;
490
    const ucl_bytep b  = s->b;
491
    const ucl_bytep bp = s->b + s->bp;
492
    const ucl_bytep bx = s->b + s->bp + s->look;
493
    unsigned char scan_end1;
494
 
495
    assert(s->m_len > 0);
496
 
497
    scan_end1 = bp[m_len - 1];
498
    for ( ; cnt-- > 0; node = s->succ3[node])
499
    {
500
        p1 = bp;
501
        p2 = b + node;
502
        px = bx;
503
 
504
        assert(m_len < s->look);
505
 
506
        if (
507
#if 1
508
            p2[m_len - 1] == scan_end1 &&
509
            p2[m_len] == p1[m_len] &&
510
#endif
511
            p2[0] == p1[0] &&
512
            p2[1] == p1[1])
513
        {
514
            ucl_uint i;
515
            assert(ucl_memcmp(bp,&b[node],3) == 0);
516
 
517
#if 0 && defined(UA_GET4)
518
            p1 += 3; p2 += 3;
519
            while (p1 < px && UA_GET4(p1) == UA_GET4(p2))
520
                p1 += 4, p2 += 4;
521
            while (p1 < px && *p1 == *p2)
522
                p1 += 1, p2 += 1;
523
#else
524
            p1 += 2; p2 += 2;
525
            do {} while (++p1 < px && *p1 == *++p2);
526
#endif
527
            i = (ucl_uint) (p1 - bp);
528
 
529
#ifdef UCL_DEBUG
530
            if (ucl_memcmp(bp,&b[node],i) != 0)
531
                printf("%5ld %5ld %02x%02x %02x%02x\n",
532
                        (long)s->bp, (long) node,
533
                        bp[0], bp[1], b[node], b[node+1]);
534
#endif
535
            assert(ucl_memcmp(bp,&b[node],i) == 0);
536
 
537
#if defined(SWD_BEST_OFF)
538
            if (i < SWD_BEST_OFF)
539
            {
540
                if (s->best_pos[i] == 0)
541
                    s->best_pos[i] = node + 1;
542
            }
543
#endif
544
            if (i > m_len)
545
            {
546
                s->m_len = m_len = i;
547
                s->m_pos = node;
548
                if (m_len == s->look)
549
                    return;
550
                if (m_len >= s->nice_length)
551
                    return;
552
                if (m_len > (ucl_uint) s->best3[node])
553
                    return;
554
                scan_end1 = bp[m_len - 1];
555
            }
556
        }
557
    }
558
}
559
 
560
 
561
/***********************************************************************
562
//
563
************************************************************************/
564
 
565
#ifdef HEAD2
566
 
567
static
568
ucl_bool swd_search2(ucl_swd_t *s)
569
{
570
    ucl_uint key;
571
 
572
    assert(s->look >= 2);
573
    assert(s->m_len > 0);
574
 
575
    key = s->head2[ HEAD2(s->b,s->bp) ];
576
    if (key == NIL2)
577
        return 0;
578
#ifdef UCL_DEBUG
579
    if (ucl_memcmp(&s->b[s->bp],&s->b[key],2) != 0)
580
        printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key,
581
                s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]);
582
#endif
583
    assert(ucl_memcmp(&s->b[s->bp],&s->b[key],2) == 0);
584
#if defined(SWD_BEST_OFF)
585
    if (s->best_pos[2] == 0)
586
        s->best_pos[2] = key + 1;
587
#endif
588
 
589
    if (s->m_len < 2)
590
    {
591
        s->m_len = 2;
592
        s->m_pos = key;
593
    }
594
    return 1;
595
}
596
 
597
#endif
598
 
599
 
600
/***********************************************************************
601
//
602
************************************************************************/
603
 
604
static
605
void swd_findbest(ucl_swd_t *s)
606
{
607
    ucl_uint key;
608
    ucl_uint cnt, node;
609
    ucl_uint len;
610
 
611
    assert(s->m_len > 0);
612
 
613
    /* get current head, add bp into HEAD3 */
614
    key = HEAD3(s->b,s->bp);
615
    node = s->succ3[s->bp] = s_get_head3(s,key);
616
    cnt = s->llen3[key]++;
617
    assert(s->llen3[key] <= s->n + s->f);
618
    if (cnt > s->max_chain && s->max_chain > 0)
619
        cnt = s->max_chain;
620
    s->head3[key] = SWD_UINT(s->bp);
621
 
622
    s->b_char = s->b[s->bp];
623
    len = s->m_len;
624
    if (s->m_len >= s->look)
625
    {
626
        if (s->look == 0)
627
            s->b_char = -1;
628
        s->m_off = 0;
629
        s->best3[s->bp] = SWD_UINT(s->f + 1);
630
    }
631
    else
632
    {
633
#if defined(HEAD2_VAR)
634
        if (s->use_head2) {
635
            if (swd_search2(s) && s->look >= 3)
636
                swd_search(s,node,cnt);
637
        } else {
638
            if (s->look >= 3)
639
                swd_search(s,node,cnt);
640
        }
641
#elif defined(HEAD2)
642
        if (swd_search2(s) && s->look >= 3)
643
            swd_search(s,node,cnt);
644
#else
645
        if (s->look >= 3)
646
            swd_search(s,node,cnt);
647
#endif
648
        if (s->m_len > len)
649
            s->m_off = swd_pos2off(s,s->m_pos);
650
        s->best3[s->bp] = SWD_UINT(s->m_len);
651
 
652
#if defined(SWD_BEST_OFF)
653
        if (s->use_best_off)
654
        {
655
            int i;
656
            for (i = 2; i < SWD_BEST_OFF; i++)
657
                if (s->best_pos[i] > 0)
658
                    s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1);
659
                else
660
                    s->best_off[i] = 0;
661
        }
662
#endif
663
    }
664
 
665
    swd_remove_node(s,s->rp);
666
 
667
#ifdef HEAD2
668
    /* add bp into HEAD2 */
669
    IF_HEAD2(s) {
670
        key = HEAD2(s->b,s->bp);
671
        s->head2[key] = SWD_UINT(s->bp);
672
    }
673
#endif
674
}
675
 
676
 
677
#undef HEAD3
678
#undef HEAD2
679
#undef IF_HEAD2
680
#undef s_get_head3
681
 
682
 
683
/*
684
vi:ts=4:et
685
*/
686