Basic gzip/gunzip in memory buffer examples using zlib code.

Dependencies:   mbed-rtos mbed

There are small changes needed to the zconf.h file in the zlib distribution (I used 1.2.7). The zlib license applies to the zlib code - I have only imported a subset of the source.

The MBED has limited memory, so we need the following (near the top of zconf.h) to restrict memory allocation sizes:

#define    MAX_MEM_LEVEL    3
#define    MAX_WBITS        10

Because MAX_MEM_LEVEL and MAX_WBITS are so much lower than the default, there is a danger that the mbed cannot gunzip data compressed by a 'normal' zlib build. My use-case is to gzip on the mbed more than gunzip on the mbed so I have not given much time to this issue.

I also included this (also near the top of zconf.h) to prefix defines with Z_

#define    Z_PREFIX

In zconf.h, in the zlib distribution, the includes for <fcntl.h> and <sys/types.h> need commenting out when using the online compiler. No need when using GCC4MBED.

I also looked at miniz. I chose zlib because I needed the gzip headers and miniz does not implement them.

The sample main.cpp reads source data, compresses it, decompresses it, and finally compares the input data with the output data to confirm they are the same.

    unsigned char input_data[2048];
    unsigned long input_data_length = 0;
    FILE *ifp = fopen("/local/src.txt", "r");
    if (ifp) {
        int br = fread(input_data, 1, sizeof(input_data), ifp);
        fclose(ifp);
        input_data_length = br;
    }
    printf("%s:%d: input_data_length:%lu%s", __FILE__, __LINE__, input_data_length, newline);
 
 
    unsigned char gzip_data[2048];
    unsigned long gzip_data_length = 0;
    if (input_data_length > 0) {
        gzip_data_length = sizeof(gzip_data);
        int rv = gzip(gzip_data, &gzip_data_length, input_data, input_data_length);
        if (Z_OK == rv) {
            FILE *ofp = fopen("/local/dst.gz", "w");
            if (ofp) {
                int bw = fwrite(gzip_data, 1, gzip_data_length, ofp);
                fclose(ofp);
            }
        } else {
            printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
        }
    }
    printf("%s:%d: gzip_data_length:%lu%s", __FILE__, __LINE__, gzip_data_length, newline);
 
 
    unsigned char output_data[2048];
    unsigned long output_data_length = 0;
    if (gzip_data_length > 0) {
        output_data_length = sizeof(output_data);
        int rv = gunzip(output_data, &output_data_length, gzip_data, gzip_data_length);
        if (Z_OK != rv) {
            printf("%s:%d: %d%s", __FILE__, __LINE__, rv, newline);
        }
    }
    printf("%s:%d: output_data_length:%lu%s", __FILE__, __LINE__, output_data_length, newline);
 
 
    if (input_data_length > 0 and input_data_length > 0) {
        bool input_matches_output = false;
        if (input_data_length == output_data_length) {
            input_matches_output = true;
            for ( size_t i = 0 ; input_matches_output && i < input_data_length ; i++ ) {
                if (input_data[i] != output_data[i]) {
                    input_matches_output = false;
                }
            }
        }
        printf("%s:%d: input (%lu bytes) %s output (%lu bytes)%s", __FILE__, __LINE__, input_data_length, input_matches_output?"matches":"does not match", output_data_length, newline);
    } else {
        printf("%s:%d: input and/or output length is 0%s", __FILE__, __LINE__, newline);
    }
Committer:
jonathonfletcher
Date:
Sun Oct 21 07:46:41 2012 +0000
Revision:
0:54f5be781526
initial checkin

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jonathonfletcher 0:54f5be781526 1 /* inflate.h -- internal inflate state definition
jonathonfletcher 0:54f5be781526 2 * Copyright (C) 1995-2009 Mark Adler
jonathonfletcher 0:54f5be781526 3 * For conditions of distribution and use, see copyright notice in zlib.h
jonathonfletcher 0:54f5be781526 4 */
jonathonfletcher 0:54f5be781526 5
jonathonfletcher 0:54f5be781526 6 /* WARNING: this file should *not* be used by applications. It is
jonathonfletcher 0:54f5be781526 7 part of the implementation of the compression library and is
jonathonfletcher 0:54f5be781526 8 subject to change. Applications should only use zlib.h.
jonathonfletcher 0:54f5be781526 9 */
jonathonfletcher 0:54f5be781526 10
jonathonfletcher 0:54f5be781526 11 /* define NO_GZIP when compiling if you want to disable gzip header and
jonathonfletcher 0:54f5be781526 12 trailer decoding by inflate(). NO_GZIP would be used to avoid linking in
jonathonfletcher 0:54f5be781526 13 the crc code when it is not needed. For shared libraries, gzip decoding
jonathonfletcher 0:54f5be781526 14 should be left enabled. */
jonathonfletcher 0:54f5be781526 15 #ifndef NO_GZIP
jonathonfletcher 0:54f5be781526 16 # define GUNZIP
jonathonfletcher 0:54f5be781526 17 #endif
jonathonfletcher 0:54f5be781526 18
jonathonfletcher 0:54f5be781526 19 /* Possible inflate modes between inflate() calls */
jonathonfletcher 0:54f5be781526 20 typedef enum {
jonathonfletcher 0:54f5be781526 21 HEAD, /* i: waiting for magic header */
jonathonfletcher 0:54f5be781526 22 FLAGS, /* i: waiting for method and flags (gzip) */
jonathonfletcher 0:54f5be781526 23 TIME, /* i: waiting for modification time (gzip) */
jonathonfletcher 0:54f5be781526 24 OS, /* i: waiting for extra flags and operating system (gzip) */
jonathonfletcher 0:54f5be781526 25 EXLEN, /* i: waiting for extra length (gzip) */
jonathonfletcher 0:54f5be781526 26 EXTRA, /* i: waiting for extra bytes (gzip) */
jonathonfletcher 0:54f5be781526 27 NAME, /* i: waiting for end of file name (gzip) */
jonathonfletcher 0:54f5be781526 28 COMMENT, /* i: waiting for end of comment (gzip) */
jonathonfletcher 0:54f5be781526 29 HCRC, /* i: waiting for header crc (gzip) */
jonathonfletcher 0:54f5be781526 30 DICTID, /* i: waiting for dictionary check value */
jonathonfletcher 0:54f5be781526 31 DICT, /* waiting for inflateSetDictionary() call */
jonathonfletcher 0:54f5be781526 32 TYPE, /* i: waiting for type bits, including last-flag bit */
jonathonfletcher 0:54f5be781526 33 TYPEDO, /* i: same, but skip check to exit inflate on new block */
jonathonfletcher 0:54f5be781526 34 STORED, /* i: waiting for stored size (length and complement) */
jonathonfletcher 0:54f5be781526 35 COPY_, /* i/o: same as COPY below, but only first time in */
jonathonfletcher 0:54f5be781526 36 COPY, /* i/o: waiting for input or output to copy stored block */
jonathonfletcher 0:54f5be781526 37 TABLE, /* i: waiting for dynamic block table lengths */
jonathonfletcher 0:54f5be781526 38 LENLENS, /* i: waiting for code length code lengths */
jonathonfletcher 0:54f5be781526 39 CODELENS, /* i: waiting for length/lit and distance code lengths */
jonathonfletcher 0:54f5be781526 40 LEN_, /* i: same as LEN below, but only first time in */
jonathonfletcher 0:54f5be781526 41 LEN, /* i: waiting for length/lit/eob code */
jonathonfletcher 0:54f5be781526 42 LENEXT, /* i: waiting for length extra bits */
jonathonfletcher 0:54f5be781526 43 DIST, /* i: waiting for distance code */
jonathonfletcher 0:54f5be781526 44 DISTEXT, /* i: waiting for distance extra bits */
jonathonfletcher 0:54f5be781526 45 MATCH, /* o: waiting for output space to copy string */
jonathonfletcher 0:54f5be781526 46 LIT, /* o: waiting for output space to write literal */
jonathonfletcher 0:54f5be781526 47 CHECK, /* i: waiting for 32-bit check value */
jonathonfletcher 0:54f5be781526 48 LENGTH, /* i: waiting for 32-bit length (gzip) */
jonathonfletcher 0:54f5be781526 49 DONE, /* finished check, done -- remain here until reset */
jonathonfletcher 0:54f5be781526 50 BAD, /* got a data error -- remain here until reset */
jonathonfletcher 0:54f5be781526 51 MEM, /* got an inflate() memory error -- remain here until reset */
jonathonfletcher 0:54f5be781526 52 SYNC /* looking for synchronization bytes to restart inflate() */
jonathonfletcher 0:54f5be781526 53 } inflate_mode;
jonathonfletcher 0:54f5be781526 54
jonathonfletcher 0:54f5be781526 55 /*
jonathonfletcher 0:54f5be781526 56 State transitions between above modes -
jonathonfletcher 0:54f5be781526 57
jonathonfletcher 0:54f5be781526 58 (most modes can go to BAD or MEM on error -- not shown for clarity)
jonathonfletcher 0:54f5be781526 59
jonathonfletcher 0:54f5be781526 60 Process header:
jonathonfletcher 0:54f5be781526 61 HEAD -> (gzip) or (zlib) or (raw)
jonathonfletcher 0:54f5be781526 62 (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
jonathonfletcher 0:54f5be781526 63 HCRC -> TYPE
jonathonfletcher 0:54f5be781526 64 (zlib) -> DICTID or TYPE
jonathonfletcher 0:54f5be781526 65 DICTID -> DICT -> TYPE
jonathonfletcher 0:54f5be781526 66 (raw) -> TYPEDO
jonathonfletcher 0:54f5be781526 67 Read deflate blocks:
jonathonfletcher 0:54f5be781526 68 TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
jonathonfletcher 0:54f5be781526 69 STORED -> COPY_ -> COPY -> TYPE
jonathonfletcher 0:54f5be781526 70 TABLE -> LENLENS -> CODELENS -> LEN_
jonathonfletcher 0:54f5be781526 71 LEN_ -> LEN
jonathonfletcher 0:54f5be781526 72 Read deflate codes in fixed or dynamic block:
jonathonfletcher 0:54f5be781526 73 LEN -> LENEXT or LIT or TYPE
jonathonfletcher 0:54f5be781526 74 LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
jonathonfletcher 0:54f5be781526 75 LIT -> LEN
jonathonfletcher 0:54f5be781526 76 Process trailer:
jonathonfletcher 0:54f5be781526 77 CHECK -> LENGTH -> DONE
jonathonfletcher 0:54f5be781526 78 */
jonathonfletcher 0:54f5be781526 79
jonathonfletcher 0:54f5be781526 80 /* state maintained between inflate() calls. Approximately 10K bytes. */
jonathonfletcher 0:54f5be781526 81 struct inflate_state {
jonathonfletcher 0:54f5be781526 82 inflate_mode mode; /* current inflate mode */
jonathonfletcher 0:54f5be781526 83 int last; /* true if processing last block */
jonathonfletcher 0:54f5be781526 84 int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
jonathonfletcher 0:54f5be781526 85 int havedict; /* true if dictionary provided */
jonathonfletcher 0:54f5be781526 86 int flags; /* gzip header method and flags (0 if zlib) */
jonathonfletcher 0:54f5be781526 87 unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
jonathonfletcher 0:54f5be781526 88 unsigned long check; /* protected copy of check value */
jonathonfletcher 0:54f5be781526 89 unsigned long total; /* protected copy of output count */
jonathonfletcher 0:54f5be781526 90 gz_headerp head; /* where to save gzip header information */
jonathonfletcher 0:54f5be781526 91 /* sliding window */
jonathonfletcher 0:54f5be781526 92 unsigned wbits; /* log base 2 of requested window size */
jonathonfletcher 0:54f5be781526 93 unsigned wsize; /* window size or zero if not using window */
jonathonfletcher 0:54f5be781526 94 unsigned whave; /* valid bytes in the window */
jonathonfletcher 0:54f5be781526 95 unsigned wnext; /* window write index */
jonathonfletcher 0:54f5be781526 96 unsigned char FAR *window; /* allocated sliding window, if needed */
jonathonfletcher 0:54f5be781526 97 /* bit accumulator */
jonathonfletcher 0:54f5be781526 98 unsigned long hold; /* input bit accumulator */
jonathonfletcher 0:54f5be781526 99 unsigned bits; /* number of bits in "in" */
jonathonfletcher 0:54f5be781526 100 /* for string and stored block copying */
jonathonfletcher 0:54f5be781526 101 unsigned length; /* literal or length of data to copy */
jonathonfletcher 0:54f5be781526 102 unsigned offset; /* distance back to copy string from */
jonathonfletcher 0:54f5be781526 103 /* for table and code decoding */
jonathonfletcher 0:54f5be781526 104 unsigned extra; /* extra bits needed */
jonathonfletcher 0:54f5be781526 105 /* fixed and dynamic code tables */
jonathonfletcher 0:54f5be781526 106 code const FAR *lencode; /* starting table for length/literal codes */
jonathonfletcher 0:54f5be781526 107 code const FAR *distcode; /* starting table for distance codes */
jonathonfletcher 0:54f5be781526 108 unsigned lenbits; /* index bits for lencode */
jonathonfletcher 0:54f5be781526 109 unsigned distbits; /* index bits for distcode */
jonathonfletcher 0:54f5be781526 110 /* dynamic table building */
jonathonfletcher 0:54f5be781526 111 unsigned ncode; /* number of code length code lengths */
jonathonfletcher 0:54f5be781526 112 unsigned nlen; /* number of length code lengths */
jonathonfletcher 0:54f5be781526 113 unsigned ndist; /* number of distance code lengths */
jonathonfletcher 0:54f5be781526 114 unsigned have; /* number of code lengths in lens[] */
jonathonfletcher 0:54f5be781526 115 code FAR *next; /* next available space in codes[] */
jonathonfletcher 0:54f5be781526 116 unsigned short lens[320]; /* temporary storage for code lengths */
jonathonfletcher 0:54f5be781526 117 unsigned short work[288]; /* work area for code table building */
jonathonfletcher 0:54f5be781526 118 code codes[ENOUGH]; /* space for code tables */
jonathonfletcher 0:54f5be781526 119 int sane; /* if false, allow invalid distance too far */
jonathonfletcher 0:54f5be781526 120 int back; /* bits back of last unprocessed length/lit */
jonathonfletcher 0:54f5be781526 121 unsigned was; /* initial length of match */
jonathonfletcher 0:54f5be781526 122 };