Changeset 64bad829 in rtems


Ignore:
Timestamp:
Jul 27, 2008, 6:58:53 PM (11 years ago)
Author:
Ralf Corsepius <ralf.corsepius@…>
Branches:
4.10, 4.11, master
Children:
ced3e37
Parents:
d42bd2f
Message:

Import from zlib-1.2.4

File:
1 edited

Legend:

Unmodified
Added
Removed
  • cpukit/zlib/contrib/puff/puff.c

    rd42bd2f r64bad829  
    11/*
    22 * puff.c
    3  * Copyright (C) 2002-2004 Mark Adler
     3 * Copyright (C) 2002-2008 Mark Adler
    44 * For conditions of distribution and use, see copyright notice in puff.h
    5  * version 1.8, 9 Jan 2004
     5 * version 2.0, 25 Jul 2008
    66 *
    77 * puff.c is a simple inflate written to be an unambiguous way to specify the
     
    6262 *                      - Added zlib-like license
    6363 * 1.8   9 Jan 2004     - Added some comments on no distance codes case
     64 * 1.9  21 Feb 2008     - Fix bug on 16-bit integer architectures [Pohland]
     65 *                      - Catch missing end-of-block symbol error
     66 * 2.0  25 Jul 2008     - Add #define to permit distance too far back
     67 *                      - Add option in TEST code for puff to write the data
     68 *                      - Add option in TEST code to skip input bytes
     69 *                      - Allow TEST code to read from piped stdin
    6470 */
    6571
     
    195201 * a negative value if there is an error.  If all of the lengths are zero, i.e.
    196202 * an empty code, or if the code is incomplete and an invalid code is received,
    197  * then -9 is returned after reading MAXBITS bits.
     203 * then -10 is returned after reading MAXBITS bits.
    198204 *
    199205 * Format notes:
     
    227233        code |= bits(s, 1);             /* get next bit */
    228234        count = h->count[len];
    229         if (code < first + count)       /* if length len, return symbol */
     235        if (code - count < first)       /* if length len, return symbol */
    230236            return h->symbol[index + (code - first)];
    231237        index += count;                 /* else update for next length */
     
    234240        code <<= 1;
    235241    }
    236     return -9;                          /* ran out of codes */
     242    return -10;                         /* ran out of codes */
    237243}
    238244
     
    264270            bitbuf >>= 1;
    265271            count = *next++;
    266             if (code < first + count) { /* if length len, return symbol */
     272            if (code - count < first) { /* if length len, return symbol */
    267273                s->bitbuf = bitbuf;
    268274                s->bitcnt = (s->bitcnt - len) & 7;
     
    281287        if (left > 8) left = 8;
    282288    }
    283     return -9;                          /* ran out of codes */
     289    return -10;                         /* ran out of codes */
    284290}
    285291#endif /* SLOW */
     
    449455            /* get and compute length */
    450456            symbol -= 257;
    451             if (symbol >= 29) return -9;        /* invalid fixed code */
     457            if (symbol >= 29) return -10;       /* invalid fixed code */
    452458            len = lens[symbol] + bits(s, lext[symbol]);
    453459
     
    456462            if (symbol < 0) return symbol;      /* invalid symbol */
    457463            dist = dists[symbol] + bits(s, dext[symbol]);
     464#ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
    458465            if (dist > s->outcnt)
    459                 return -10;     /* distance too far back */
     466                return -11;     /* distance too far back */
     467#endif
    460468
    461469            /* copy length bytes from distance bytes back */
     
    463471                if (s->outcnt + len > s->outlen) return 1;
    464472                while (len--) {
    465                     s->out[s->outcnt] = s->out[s->outcnt - dist];
     473                    s->out[s->outcnt] =
     474#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
     475                        dist > s->outcnt ? 0 :
     476#endif
     477                        s->out[s->outcnt - dist];
    466478                    s->outcnt++;
    467479                }
     
    681693    }
    682694
     695    /* check for end-of-block code -- there better be one! */
     696    if (lengths[256] == 0)
     697        return -9;
     698
    683699    /* build huffman table for literal/length codes */
    684700    err = construct(&lencode, lengths, nlen);
     
    725741 *  -7:  dynamic block code description: invalid literal/length code lengths
    726742 *  -8:  dynamic block code description: invalid distance code lengths
    727  *  -9:  invalid literal/length or distance code in fixed or dynamic block
    728  * -10:  distance is too far back in fixed or dynamic block
     743 *  -9:  dynamic block code description: missing end-of-block code
     744 * -10:  invalid literal/length or distance code in fixed or dynamic block
     745 * -11:  distance is too far back in fixed or dynamic block
    729746 *
    730747 * Format notes:
     
    784801
    785802#ifdef TEST
    786 /* Example of how to use puff() */
     803/* Examples of how to use puff().
     804
     805   Usage: puff [-w] [-nnn] file
     806          ... | puff [-w] [-nnn]
     807
     808   where file is the input file with deflate data, nnn is the number of bytes
     809   of input to skip before inflating (e.g. to skip a zlib or gzip header), and
     810   -w is used to write the decompressed data to stdout */
     811
    787812#include <stdio.h>
    788813#include <stdlib.h>
    789 #include <sys/types.h>
    790 #include <sys/stat.h>
    791 
    792 local unsigned char *yank(char *name, unsigned long *len)
    793 {
    794     unsigned long size;
    795     unsigned char *buf;
     814
     815/* Return size times approximately the cube root of 2, keeping the result as 1,
     816   3, or 5 times a power of 2 -- the result is always > size, until the result
     817   is the maximum value of an unsigned long, where it remains.  This is useful
     818   to keep reallocations less than ~33% over the actual data. */
     819local size_t bythirds(size_t size)
     820{
     821    int n;
     822    size_t m;
     823
     824    m = size;
     825    for (n = 0; m; n++)
     826        m >>= 1;
     827    if (n < 3)
     828        return size + 1;
     829    n -= 3;
     830    m = size >> n;
     831    m += m == 6 ? 2 : 1;
     832    m <<= n;
     833    return m > size ? m : (size_t)(-1);
     834}
     835
     836/* Read the input file *name, or stdin if name is NULL, into allocated memory.
     837   Reallocate to larger buffers until the entire file is read in.  Return a
     838   pointer to the allocated data, or NULL if there was a memory allocation
     839   failure.  *len is the number of bytes of data read from the input file (even
     840   if load() returns NULL).  If the input file was empty or could not be opened
     841   or read, *len is zero. */
     842local void *load(char *name, size_t *len)
     843{
     844    size_t size;
     845    void *buf, *swap;
    796846    FILE *in;
    797     struct stat s;
    798847
    799848    *len = 0;
    800     if (stat(name, &s)) return NULL;
    801     if ((s.st_mode & S_IFMT) != S_IFREG) return NULL;
    802     size = (unsigned long)(s.st_size);
    803     if (size == 0 || (off_t)size != s.st_size) return NULL;
    804     in = fopen(name, "r");
    805     if (in == NULL) return NULL;
    806     buf = malloc(size);
    807     if (buf != NULL && fread(buf, 1, size, in) != size) {
    808         free(buf);
    809         buf = NULL;
    810     }
    811     fclose(in);
    812     *len = size;
     849    buf = malloc(size = 4096);
     850    if (buf == NULL)
     851        return NULL;
     852    in = name == NULL ? stdin : fopen(name, "rb");
     853    if (in != NULL) {
     854        for (;;) {
     855            *len += fread((char *)buf + *len, 1, size - *len, in);
     856            if (*len < size) break;
     857            size = bythirds(size);
     858            if (size == *len || (swap = realloc(buf, size)) == NULL) {
     859                free(buf);
     860                buf = NULL;
     861                break;
     862            }
     863            buf = swap;
     864        }
     865        fclose(in);
     866    }
    813867    return buf;
    814868}
     
    816870int main(int argc, char **argv)
    817871{
    818     int ret;
    819     unsigned char *source;
    820     unsigned long len, sourcelen, destlen;
    821 
    822     if (argc < 2) return 2;
    823     source = yank(argv[1], &len);
    824     if (source == NULL) return 2;
    825     sourcelen = len;
    826     ret = puff(NIL, &destlen, source, &sourcelen);
     872    int ret, skip = 0, put = 0;
     873    char *arg, *name = NULL;
     874    unsigned char *source = NULL, *dest;
     875    size_t len = 0;
     876    unsigned long sourcelen, destlen;
     877
     878    /* process arguments */
     879    while (arg = *++argv, --argc)
     880        if (arg[0] == '-') {
     881            if (arg[1] == 'w' && arg[2] == 0)
     882                put = 1;
     883            else if (arg[1] >= '0' && arg[1] <= '9')
     884                skip = atoi(arg + 1);
     885            else {
     886                fprintf(stderr, "invalid option %s\n", arg);
     887                return 3;
     888            }
     889        }
     890        else if (name != NULL) {
     891            fprintf(stderr, "only one file name allowed\n");
     892            return 3;
     893        }
     894        else
     895            name = arg;
     896    source = load(name, &len);
     897    if (source == NULL) {
     898        fprintf(stderr, "memory allocation failure\n");
     899        return 4;
     900    }
     901    if (len == 0) {
     902        fprintf(stderr, "could not read %s, or it was empty\n",
     903                name == NULL ? "<stdin>" : name);
     904        free(source);
     905        return 3;
     906    }
     907    if (skip >= len) {
     908        fprintf(stderr, "skip request of %d leaves no input\n", skip);
     909        free(source);
     910        return 3;
     911    }
     912
     913    /* test inflate data with offset skip */
     914    len -= skip;
     915    sourcelen = (unsigned long)len;
     916    ret = puff(NIL, &destlen, source + skip, &sourcelen);
    827917    if (ret)
    828         printf("puff() failed with return code %d\n", ret);
     918        fprintf(stderr, "puff() failed with return code %d\n", ret);
    829919    else {
    830         printf("puff() succeeded uncompressing %lu bytes\n", destlen);
    831         if (sourcelen < len) printf("%lu compressed bytes unused\n",
    832                                     len - sourcelen);
    833     }
     920        fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen);
     921        if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n",
     922                                     len - sourcelen);
     923    }
     924
     925    /* if requested, inflate again and write decompressd data to stdout */
     926    if (put) {
     927        dest = malloc(destlen);
     928        if (dest == NULL) {
     929            fprintf(stderr, "memory allocation failure\n");
     930            free(source);
     931            return 4;
     932        }
     933        puff(dest, &destlen, source + skip, &sourcelen);
     934        fwrite(dest, 1, destlen, stdout);
     935        free(dest);
     936    }
     937
     938    /* clean up */
    834939    free(source);
    835940    return ret;
Note: See TracChangeset for help on using the changeset viewer.