summaryrefslogtreecommitdiffstats
path: root/main/zlib/infutil.c
blob: 856a1970bba3850548b32de08c0e57fe8a9a342c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/* inflate_util.c -- data and routines common to blocks and codes
 * Copyright (C) 1995-1998 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"

extern int memcpy(char *,char *, int);
struct inflate_codes_state {
    int dummy;
}; /* for buggy compilers */

/* And'ing with mask[n] masks the lower n bits */
uInt inflate_mask[17] = {
    0x0000,
    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
};


/* copy as much as possible from the sliding window to the output area */
int inflate_flush(s, z, r)
inflate_blocks_statef *s;
z_streamp z;
int r;
{
    uInt n;
    Bytef *p;
    Bytef *q;

    /* local copies of source and destination pointers */
    p = z->next_out;
    q = s->read;

    /* compute number of bytes to copy as far as end of window */
    n = (uInt)((q <= s->write ? s->write : s->end) - q);
    if(n > z->avail_out) {
        n = z->avail_out;
    }
    if(n && r == Z_BUF_ERROR) {
        r = Z_OK;
    }

    /* update counters */
    z->avail_out -= n;
    z->total_out += n;

    /* update check information */
    if(s->checkfn != Z_NULL) {
        z->adler = s->check = (*s->checkfn)(s->check, q, n);
    }

    /* copy as far as end of window */
    zmemcpy((char *)p, (char *)q, n);
    p += n;
    q += n;

    /* see if more to copy at beginning of window */
    if(q == s->end) {
        /* wrap pointers */
        q = s->window;
        if(s->write == s->end) {
            s->write = s->window;
        }

        /* compute bytes to copy */
        n = (uInt)(s->write - q);
        if(n > z->avail_out) {
            n = z->avail_out;
        }
        if(n && r == Z_BUF_ERROR) {
            r = Z_OK;
        }

        /* update counters */
        z->avail_out -= n;
        z->total_out += n;

        /* update check information */
        if(s->checkfn != Z_NULL) {
            z->adler = s->check = (*s->checkfn)(s->check, q, n);
        }

        /* copy */
        zmemcpy((char *)p, (char *)q, n);
        p += n;
        q += n;
    }

    /* update pointers */
    z->next_out = p;
    s->read = q;

    /* done */
    return r;
}